1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "Debug.hpp"
16*03ce13f7SAndroid Build Coastguard Worker #include "Print.hpp"
17*03ce13f7SAndroid Build Coastguard Worker #include "Reactor.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "ReactorDebugInfo.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "SIMD.hpp"
20*03ce13f7SAndroid Build Coastguard Worker
21*03ce13f7SAndroid Build Coastguard Worker #include "ExecutableMemory.hpp"
22*03ce13f7SAndroid Build Coastguard Worker #include "Optimizer.hpp"
23*03ce13f7SAndroid Build Coastguard Worker #include "PragmaInternals.hpp"
24*03ce13f7SAndroid Build Coastguard Worker
25*03ce13f7SAndroid Build Coastguard Worker #include "src/IceCfg.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "src/IceCfgNode.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "src/IceELFObjectWriter.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "src/IceELFStreamer.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "src/IceGlobalContext.h"
30*03ce13f7SAndroid Build Coastguard Worker #include "src/IceGlobalInits.h"
31*03ce13f7SAndroid Build Coastguard Worker #include "src/IceTypes.h"
32*03ce13f7SAndroid Build Coastguard Worker
33*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Compiler.h"
34*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
35*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
36*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/raw_os_ostream.h"
37*03ce13f7SAndroid Build Coastguard Worker
38*03ce13f7SAndroid Build Coastguard Worker #include "marl/event.h"
39*03ce13f7SAndroid Build Coastguard Worker
40*03ce13f7SAndroid Build Coastguard Worker #if __has_feature(memory_sanitizer)
41*03ce13f7SAndroid Build Coastguard Worker # include <sanitizer/msan_interface.h>
42*03ce13f7SAndroid Build Coastguard Worker #endif
43*03ce13f7SAndroid Build Coastguard Worker
44*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
45*03ce13f7SAndroid Build Coastguard Worker # ifndef WIN32_LEAN_AND_MEAN
46*03ce13f7SAndroid Build Coastguard Worker # define WIN32_LEAN_AND_MEAN
47*03ce13f7SAndroid Build Coastguard Worker # endif // !WIN32_LEAN_AND_MEAN
48*03ce13f7SAndroid Build Coastguard Worker # ifndef NOMINMAX
49*03ce13f7SAndroid Build Coastguard Worker # define NOMINMAX
50*03ce13f7SAndroid Build Coastguard Worker # endif // !NOMINMAX
51*03ce13f7SAndroid Build Coastguard Worker # include <Windows.h>
52*03ce13f7SAndroid Build Coastguard Worker #endif
53*03ce13f7SAndroid Build Coastguard Worker
54*03ce13f7SAndroid Build Coastguard Worker #include <array>
55*03ce13f7SAndroid Build Coastguard Worker #include <cmath>
56*03ce13f7SAndroid Build Coastguard Worker #include <iostream>
57*03ce13f7SAndroid Build Coastguard Worker #include <limits>
58*03ce13f7SAndroid Build Coastguard Worker #include <mutex>
59*03ce13f7SAndroid Build Coastguard Worker
60*03ce13f7SAndroid Build Coastguard Worker // Subzero utility functions
61*03ce13f7SAndroid Build Coastguard Worker // These functions only accept and return Subzero (Ice) types, and do not access any globals.
62*03ce13f7SAndroid Build Coastguard Worker namespace {
63*03ce13f7SAndroid Build Coastguard Worker namespace sz {
64*03ce13f7SAndroid Build Coastguard Worker
createFunction(Ice::GlobalContext * context,Ice::Type returnType,const std::vector<Ice::Type> & paramTypes)65*03ce13f7SAndroid Build Coastguard Worker Ice::Cfg *createFunction(Ice::GlobalContext *context, Ice::Type returnType, const std::vector<Ice::Type> ¶mTypes)
66*03ce13f7SAndroid Build Coastguard Worker {
67*03ce13f7SAndroid Build Coastguard Worker uint32_t sequenceNumber = 0;
68*03ce13f7SAndroid Build Coastguard Worker auto *function = Ice::Cfg::create(context, sequenceNumber).release();
69*03ce13f7SAndroid Build Coastguard Worker
70*03ce13f7SAndroid Build Coastguard Worker function->setStackSizeLimit(512 * 1024); // 512 KiB
71*03ce13f7SAndroid Build Coastguard Worker
72*03ce13f7SAndroid Build Coastguard Worker Ice::CfgLocalAllocatorScope allocScope{ function };
73*03ce13f7SAndroid Build Coastguard Worker
74*03ce13f7SAndroid Build Coastguard Worker for(auto type : paramTypes)
75*03ce13f7SAndroid Build Coastguard Worker {
76*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *arg = function->makeVariable(type);
77*03ce13f7SAndroid Build Coastguard Worker function->addArg(arg);
78*03ce13f7SAndroid Build Coastguard Worker }
79*03ce13f7SAndroid Build Coastguard Worker
80*03ce13f7SAndroid Build Coastguard Worker Ice::CfgNode *node = function->makeNode();
81*03ce13f7SAndroid Build Coastguard Worker function->setEntryNode(node);
82*03ce13f7SAndroid Build Coastguard Worker
83*03ce13f7SAndroid Build Coastguard Worker return function;
84*03ce13f7SAndroid Build Coastguard Worker }
85*03ce13f7SAndroid Build Coastguard Worker
getPointerType(Ice::Type elementType)86*03ce13f7SAndroid Build Coastguard Worker Ice::Type getPointerType(Ice::Type elementType)
87*03ce13f7SAndroid Build Coastguard Worker {
88*03ce13f7SAndroid Build Coastguard Worker if(sizeof(void *) == 8)
89*03ce13f7SAndroid Build Coastguard Worker {
90*03ce13f7SAndroid Build Coastguard Worker return Ice::IceType_i64;
91*03ce13f7SAndroid Build Coastguard Worker }
92*03ce13f7SAndroid Build Coastguard Worker else
93*03ce13f7SAndroid Build Coastguard Worker {
94*03ce13f7SAndroid Build Coastguard Worker return Ice::IceType_i32;
95*03ce13f7SAndroid Build Coastguard Worker }
96*03ce13f7SAndroid Build Coastguard Worker }
97*03ce13f7SAndroid Build Coastguard Worker
allocateStackVariable(Ice::Cfg * function,Ice::Type type,int arraySize=0)98*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *allocateStackVariable(Ice::Cfg *function, Ice::Type type, int arraySize = 0)
99*03ce13f7SAndroid Build Coastguard Worker {
100*03ce13f7SAndroid Build Coastguard Worker int typeSize = Ice::typeWidthInBytes(type);
101*03ce13f7SAndroid Build Coastguard Worker int totalSize = typeSize * (arraySize ? arraySize : 1);
102*03ce13f7SAndroid Build Coastguard Worker
103*03ce13f7SAndroid Build Coastguard Worker auto bytes = Ice::ConstantInteger32::create(function->getContext(), Ice::IceType_i32, totalSize);
104*03ce13f7SAndroid Build Coastguard Worker auto address = function->makeVariable(getPointerType(type));
105*03ce13f7SAndroid Build Coastguard Worker auto alloca = Ice::InstAlloca::create(function, address, bytes, typeSize); // SRoA depends on the alignment to match the type size.
106*03ce13f7SAndroid Build Coastguard Worker function->getEntryNode()->getInsts().push_front(alloca);
107*03ce13f7SAndroid Build Coastguard Worker
108*03ce13f7SAndroid Build Coastguard Worker ASSERT(!rr::getPragmaState(rr::InitializeLocalVariables) && "Subzero does not support initializing local variables");
109*03ce13f7SAndroid Build Coastguard Worker
110*03ce13f7SAndroid Build Coastguard Worker return address;
111*03ce13f7SAndroid Build Coastguard Worker }
112*03ce13f7SAndroid Build Coastguard Worker
getConstantPointer(Ice::GlobalContext * context,const void * ptr)113*03ce13f7SAndroid Build Coastguard Worker Ice::Constant *getConstantPointer(Ice::GlobalContext *context, const void *ptr)
114*03ce13f7SAndroid Build Coastguard Worker {
115*03ce13f7SAndroid Build Coastguard Worker if(sizeof(void *) == 8)
116*03ce13f7SAndroid Build Coastguard Worker {
117*03ce13f7SAndroid Build Coastguard Worker return context->getConstantInt64(reinterpret_cast<intptr_t>(ptr));
118*03ce13f7SAndroid Build Coastguard Worker }
119*03ce13f7SAndroid Build Coastguard Worker else
120*03ce13f7SAndroid Build Coastguard Worker {
121*03ce13f7SAndroid Build Coastguard Worker return context->getConstantInt32(reinterpret_cast<intptr_t>(ptr));
122*03ce13f7SAndroid Build Coastguard Worker }
123*03ce13f7SAndroid Build Coastguard Worker }
124*03ce13f7SAndroid Build Coastguard Worker
125*03ce13f7SAndroid Build Coastguard Worker // TODO(amaiorano): remove this prototype once these are moved to separate header/cpp
126*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *createTruncate(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Operand *from, Ice::Type toType);
127*03ce13f7SAndroid Build Coastguard Worker
128*03ce13f7SAndroid Build Coastguard Worker // Wrapper for calls on C functions with Ice types
Call(Ice::Cfg * function,Ice::CfgNode * basicBlock,Ice::Type retTy,Ice::Operand * callTarget,const std::vector<Ice::Operand * > & iceArgs,bool isVariadic)129*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Type retTy, Ice::Operand *callTarget, const std::vector<Ice::Operand *> &iceArgs, bool isVariadic)
130*03ce13f7SAndroid Build Coastguard Worker {
131*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *ret = nullptr;
132*03ce13f7SAndroid Build Coastguard Worker
133*03ce13f7SAndroid Build Coastguard Worker // Subzero doesn't support boolean return values. Replace with an i32 temporarily,
134*03ce13f7SAndroid Build Coastguard Worker // then truncate result to bool.
135*03ce13f7SAndroid Build Coastguard Worker // TODO(b/151158858): Add support to Subzero's InstCall for bool-returning functions
136*03ce13f7SAndroid Build Coastguard Worker const bool returningBool = (retTy == Ice::IceType_i1);
137*03ce13f7SAndroid Build Coastguard Worker if(returningBool)
138*03ce13f7SAndroid Build Coastguard Worker {
139*03ce13f7SAndroid Build Coastguard Worker ret = function->makeVariable(Ice::IceType_i32);
140*03ce13f7SAndroid Build Coastguard Worker }
141*03ce13f7SAndroid Build Coastguard Worker else if(retTy != Ice::IceType_void)
142*03ce13f7SAndroid Build Coastguard Worker {
143*03ce13f7SAndroid Build Coastguard Worker ret = function->makeVariable(retTy);
144*03ce13f7SAndroid Build Coastguard Worker }
145*03ce13f7SAndroid Build Coastguard Worker
146*03ce13f7SAndroid Build Coastguard Worker auto call = Ice::InstCall::create(function, iceArgs.size(), ret, callTarget, false, false, isVariadic);
147*03ce13f7SAndroid Build Coastguard Worker for(auto arg : iceArgs)
148*03ce13f7SAndroid Build Coastguard Worker {
149*03ce13f7SAndroid Build Coastguard Worker call->addArg(arg);
150*03ce13f7SAndroid Build Coastguard Worker }
151*03ce13f7SAndroid Build Coastguard Worker
152*03ce13f7SAndroid Build Coastguard Worker basicBlock->appendInst(call);
153*03ce13f7SAndroid Build Coastguard Worker
154*03ce13f7SAndroid Build Coastguard Worker if(returningBool)
155*03ce13f7SAndroid Build Coastguard Worker {
156*03ce13f7SAndroid Build Coastguard Worker // Truncate result to bool so that if any (lsb) bits were set, result will be true
157*03ce13f7SAndroid Build Coastguard Worker ret = createTruncate(function, basicBlock, ret, Ice::IceType_i1);
158*03ce13f7SAndroid Build Coastguard Worker }
159*03ce13f7SAndroid Build Coastguard Worker
160*03ce13f7SAndroid Build Coastguard Worker return ret;
161*03ce13f7SAndroid Build Coastguard Worker }
162*03ce13f7SAndroid Build Coastguard Worker
Call(Ice::Cfg * function,Ice::CfgNode * basicBlock,Ice::Type retTy,const void * fptr,const std::vector<Ice::Operand * > & iceArgs,bool isVariadic)163*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Type retTy, const void *fptr, const std::vector<Ice::Operand *> &iceArgs, bool isVariadic)
164*03ce13f7SAndroid Build Coastguard Worker {
165*03ce13f7SAndroid Build Coastguard Worker Ice::Operand *callTarget = getConstantPointer(function->getContext(), fptr);
166*03ce13f7SAndroid Build Coastguard Worker return Call(function, basicBlock, retTy, callTarget, iceArgs, isVariadic);
167*03ce13f7SAndroid Build Coastguard Worker }
168*03ce13f7SAndroid Build Coastguard Worker
169*03ce13f7SAndroid Build Coastguard Worker // Wrapper for calls on C functions with Ice types
170*03ce13f7SAndroid Build Coastguard Worker template<typename Return, typename... CArgs, typename... RArgs>
Call(Ice::Cfg * function,Ice::CfgNode * basicBlock,Return (fptr)(CArgs...),RArgs &&...args)171*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Return(fptr)(CArgs...), RArgs &&...args)
172*03ce13f7SAndroid Build Coastguard Worker {
173*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof...(CArgs) == sizeof...(RArgs), "Expected number of args don't match");
174*03ce13f7SAndroid Build Coastguard Worker
175*03ce13f7SAndroid Build Coastguard Worker Ice::Type retTy = T(rr::CToReactorT<Return>::type());
176*03ce13f7SAndroid Build Coastguard Worker std::vector<Ice::Operand *> iceArgs{ std::forward<RArgs>(args)... };
177*03ce13f7SAndroid Build Coastguard Worker return Call(function, basicBlock, retTy, reinterpret_cast<const void *>(fptr), iceArgs, false);
178*03ce13f7SAndroid Build Coastguard Worker }
179*03ce13f7SAndroid Build Coastguard Worker
createTruncate(Ice::Cfg * function,Ice::CfgNode * basicBlock,Ice::Operand * from,Ice::Type toType)180*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *createTruncate(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Operand *from, Ice::Type toType)
181*03ce13f7SAndroid Build Coastguard Worker {
182*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *to = function->makeVariable(toType);
183*03ce13f7SAndroid Build Coastguard Worker Ice::InstCast *cast = Ice::InstCast::create(function, Ice::InstCast::Trunc, to, from);
184*03ce13f7SAndroid Build Coastguard Worker basicBlock->appendInst(cast);
185*03ce13f7SAndroid Build Coastguard Worker return to;
186*03ce13f7SAndroid Build Coastguard Worker }
187*03ce13f7SAndroid Build Coastguard Worker
createLoad(Ice::Cfg * function,Ice::CfgNode * basicBlock,Ice::Operand * ptr,Ice::Type type,unsigned int align)188*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *createLoad(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Operand *ptr, Ice::Type type, unsigned int align)
189*03ce13f7SAndroid Build Coastguard Worker {
190*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = function->makeVariable(type);
191*03ce13f7SAndroid Build Coastguard Worker auto load = Ice::InstLoad::create(function, result, ptr, align);
192*03ce13f7SAndroid Build Coastguard Worker basicBlock->appendInst(load);
193*03ce13f7SAndroid Build Coastguard Worker
194*03ce13f7SAndroid Build Coastguard Worker return result;
195*03ce13f7SAndroid Build Coastguard Worker }
196*03ce13f7SAndroid Build Coastguard Worker
197*03ce13f7SAndroid Build Coastguard Worker } // namespace sz
198*03ce13f7SAndroid Build Coastguard Worker } // namespace
199*03ce13f7SAndroid Build Coastguard Worker
200*03ce13f7SAndroid Build Coastguard Worker namespace rr {
201*03ce13f7SAndroid Build Coastguard Worker class ELFMemoryStreamer;
202*03ce13f7SAndroid Build Coastguard Worker class CoroutineGenerator;
203*03ce13f7SAndroid Build Coastguard Worker } // namespace rr
204*03ce13f7SAndroid Build Coastguard Worker
205*03ce13f7SAndroid Build Coastguard Worker namespace {
206*03ce13f7SAndroid Build Coastguard Worker
207*03ce13f7SAndroid Build Coastguard Worker // Used to automatically invoke llvm_shutdown() when driver is unloaded
208*03ce13f7SAndroid Build Coastguard Worker llvm::llvm_shutdown_obj llvmShutdownObj;
209*03ce13f7SAndroid Build Coastguard Worker
210*03ce13f7SAndroid Build Coastguard Worker Ice::GlobalContext *context = nullptr;
211*03ce13f7SAndroid Build Coastguard Worker Ice::Cfg *function = nullptr;
212*03ce13f7SAndroid Build Coastguard Worker Ice::CfgNode *entryBlock = nullptr;
213*03ce13f7SAndroid Build Coastguard Worker Ice::CfgNode *basicBlockTop = nullptr;
214*03ce13f7SAndroid Build Coastguard Worker Ice::CfgNode *basicBlock = nullptr;
215*03ce13f7SAndroid Build Coastguard Worker Ice::CfgLocalAllocatorScope *allocator = nullptr;
216*03ce13f7SAndroid Build Coastguard Worker rr::ELFMemoryStreamer *routine = nullptr;
217*03ce13f7SAndroid Build Coastguard Worker
218*03ce13f7SAndroid Build Coastguard Worker std::mutex codegenMutex;
219*03ce13f7SAndroid Build Coastguard Worker
220*03ce13f7SAndroid Build Coastguard Worker Ice::ELFFileStreamer *elfFile = nullptr;
221*03ce13f7SAndroid Build Coastguard Worker Ice::Fdstream *out = nullptr;
222*03ce13f7SAndroid Build Coastguard Worker
223*03ce13f7SAndroid Build Coastguard Worker // Coroutine globals
224*03ce13f7SAndroid Build Coastguard Worker rr::Type *coroYieldType = nullptr;
225*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<rr::CoroutineGenerator> coroGen;
getOrCreateScheduler()226*03ce13f7SAndroid Build Coastguard Worker marl::Scheduler &getOrCreateScheduler()
227*03ce13f7SAndroid Build Coastguard Worker {
228*03ce13f7SAndroid Build Coastguard Worker static auto scheduler = [] {
229*03ce13f7SAndroid Build Coastguard Worker marl::Scheduler::Config cfg;
230*03ce13f7SAndroid Build Coastguard Worker cfg.setWorkerThreadCount(8);
231*03ce13f7SAndroid Build Coastguard Worker return std::make_unique<marl::Scheduler>(cfg);
232*03ce13f7SAndroid Build Coastguard Worker }();
233*03ce13f7SAndroid Build Coastguard Worker
234*03ce13f7SAndroid Build Coastguard Worker return *scheduler;
235*03ce13f7SAndroid Build Coastguard Worker }
236*03ce13f7SAndroid Build Coastguard Worker
237*03ce13f7SAndroid Build Coastguard Worker rr::Nucleus::OptimizerCallback *optimizerCallback = nullptr;
238*03ce13f7SAndroid Build Coastguard Worker
239*03ce13f7SAndroid Build Coastguard Worker } // Anonymous namespace
240*03ce13f7SAndroid Build Coastguard Worker
241*03ce13f7SAndroid Build Coastguard Worker namespace {
242*03ce13f7SAndroid Build Coastguard Worker
243*03ce13f7SAndroid Build Coastguard Worker #if !defined(__i386__) && defined(_M_IX86)
244*03ce13f7SAndroid Build Coastguard Worker # define __i386__ 1
245*03ce13f7SAndroid Build Coastguard Worker #endif
246*03ce13f7SAndroid Build Coastguard Worker
247*03ce13f7SAndroid Build Coastguard Worker #if !defined(__x86_64__) && (defined(_M_AMD64) || defined(_M_X64))
248*03ce13f7SAndroid Build Coastguard Worker # define __x86_64__ 1
249*03ce13f7SAndroid Build Coastguard Worker #endif
250*03ce13f7SAndroid Build Coastguard Worker
toIce(int level)251*03ce13f7SAndroid Build Coastguard Worker Ice::OptLevel toIce(int level)
252*03ce13f7SAndroid Build Coastguard Worker {
253*03ce13f7SAndroid Build Coastguard Worker switch(level)
254*03ce13f7SAndroid Build Coastguard Worker {
255*03ce13f7SAndroid Build Coastguard Worker // Note that O0 and O1 are not implemented by Subzero
256*03ce13f7SAndroid Build Coastguard Worker case 0: return Ice::Opt_m1;
257*03ce13f7SAndroid Build Coastguard Worker case 1: return Ice::Opt_m1;
258*03ce13f7SAndroid Build Coastguard Worker case 2: return Ice::Opt_2;
259*03ce13f7SAndroid Build Coastguard Worker case 3: return Ice::Opt_2;
260*03ce13f7SAndroid Build Coastguard Worker default: UNREACHABLE("Unknown Optimization Level %d", int(level));
261*03ce13f7SAndroid Build Coastguard Worker }
262*03ce13f7SAndroid Build Coastguard Worker return Ice::Opt_2;
263*03ce13f7SAndroid Build Coastguard Worker }
264*03ce13f7SAndroid Build Coastguard Worker
stdToIceMemoryOrder(std::memory_order memoryOrder)265*03ce13f7SAndroid Build Coastguard Worker Ice::Intrinsics::MemoryOrder stdToIceMemoryOrder(std::memory_order memoryOrder)
266*03ce13f7SAndroid Build Coastguard Worker {
267*03ce13f7SAndroid Build Coastguard Worker switch(memoryOrder)
268*03ce13f7SAndroid Build Coastguard Worker {
269*03ce13f7SAndroid Build Coastguard Worker case std::memory_order_relaxed: return Ice::Intrinsics::MemoryOrderRelaxed;
270*03ce13f7SAndroid Build Coastguard Worker case std::memory_order_consume: return Ice::Intrinsics::MemoryOrderConsume;
271*03ce13f7SAndroid Build Coastguard Worker case std::memory_order_acquire: return Ice::Intrinsics::MemoryOrderAcquire;
272*03ce13f7SAndroid Build Coastguard Worker case std::memory_order_release: return Ice::Intrinsics::MemoryOrderRelease;
273*03ce13f7SAndroid Build Coastguard Worker case std::memory_order_acq_rel: return Ice::Intrinsics::MemoryOrderAcquireRelease;
274*03ce13f7SAndroid Build Coastguard Worker case std::memory_order_seq_cst: return Ice::Intrinsics::MemoryOrderSequentiallyConsistent;
275*03ce13f7SAndroid Build Coastguard Worker }
276*03ce13f7SAndroid Build Coastguard Worker return Ice::Intrinsics::MemoryOrderInvalid;
277*03ce13f7SAndroid Build Coastguard Worker }
278*03ce13f7SAndroid Build Coastguard Worker
279*03ce13f7SAndroid Build Coastguard Worker class CPUID
280*03ce13f7SAndroid Build Coastguard Worker {
281*03ce13f7SAndroid Build Coastguard Worker public:
282*03ce13f7SAndroid Build Coastguard Worker const static bool ARM;
283*03ce13f7SAndroid Build Coastguard Worker const static bool SSE4_1;
284*03ce13f7SAndroid Build Coastguard Worker
285*03ce13f7SAndroid Build Coastguard Worker private:
cpuid(int registers[4],int info)286*03ce13f7SAndroid Build Coastguard Worker static void cpuid(int registers[4], int info)
287*03ce13f7SAndroid Build Coastguard Worker {
288*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
289*03ce13f7SAndroid Build Coastguard Worker # if defined(_WIN32)
290*03ce13f7SAndroid Build Coastguard Worker __cpuid(registers, info);
291*03ce13f7SAndroid Build Coastguard Worker # else
292*03ce13f7SAndroid Build Coastguard Worker __asm volatile("cpuid"
293*03ce13f7SAndroid Build Coastguard Worker : "=a"(registers[0]), "=b"(registers[1]), "=c"(registers[2]), "=d"(registers[3])
294*03ce13f7SAndroid Build Coastguard Worker : "a"(info));
295*03ce13f7SAndroid Build Coastguard Worker # endif
296*03ce13f7SAndroid Build Coastguard Worker #else
297*03ce13f7SAndroid Build Coastguard Worker registers[0] = 0;
298*03ce13f7SAndroid Build Coastguard Worker registers[1] = 0;
299*03ce13f7SAndroid Build Coastguard Worker registers[2] = 0;
300*03ce13f7SAndroid Build Coastguard Worker registers[3] = 0;
301*03ce13f7SAndroid Build Coastguard Worker #endif
302*03ce13f7SAndroid Build Coastguard Worker }
303*03ce13f7SAndroid Build Coastguard Worker
detectARM()304*03ce13f7SAndroid Build Coastguard Worker constexpr static bool detectARM()
305*03ce13f7SAndroid Build Coastguard Worker {
306*03ce13f7SAndroid Build Coastguard Worker #if defined(__arm__) || defined(__aarch64__)
307*03ce13f7SAndroid Build Coastguard Worker return true;
308*03ce13f7SAndroid Build Coastguard Worker #elif defined(__i386__) || defined(__x86_64__)
309*03ce13f7SAndroid Build Coastguard Worker return false;
310*03ce13f7SAndroid Build Coastguard Worker #elif defined(__mips__)
311*03ce13f7SAndroid Build Coastguard Worker return false;
312*03ce13f7SAndroid Build Coastguard Worker #else
313*03ce13f7SAndroid Build Coastguard Worker # error "Unknown architecture"
314*03ce13f7SAndroid Build Coastguard Worker #endif
315*03ce13f7SAndroid Build Coastguard Worker }
316*03ce13f7SAndroid Build Coastguard Worker
detectSSE4_1()317*03ce13f7SAndroid Build Coastguard Worker static bool detectSSE4_1()
318*03ce13f7SAndroid Build Coastguard Worker {
319*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
320*03ce13f7SAndroid Build Coastguard Worker int registers[4];
321*03ce13f7SAndroid Build Coastguard Worker cpuid(registers, 1);
322*03ce13f7SAndroid Build Coastguard Worker return (registers[2] & 0x00080000) != 0;
323*03ce13f7SAndroid Build Coastguard Worker #else
324*03ce13f7SAndroid Build Coastguard Worker return false;
325*03ce13f7SAndroid Build Coastguard Worker #endif
326*03ce13f7SAndroid Build Coastguard Worker }
327*03ce13f7SAndroid Build Coastguard Worker };
328*03ce13f7SAndroid Build Coastguard Worker
329*03ce13f7SAndroid Build Coastguard Worker constexpr bool CPUID::ARM = CPUID::detectARM();
330*03ce13f7SAndroid Build Coastguard Worker const bool CPUID::SSE4_1 = CPUID::detectSSE4_1();
331*03ce13f7SAndroid Build Coastguard Worker constexpr bool emulateIntrinsics = false;
332*03ce13f7SAndroid Build Coastguard Worker constexpr bool emulateMismatchedBitCast = CPUID::ARM;
333*03ce13f7SAndroid Build Coastguard Worker
334*03ce13f7SAndroid Build Coastguard Worker constexpr bool subzeroDumpEnabled = false;
335*03ce13f7SAndroid Build Coastguard Worker constexpr bool subzeroEmitTextAsm = false;
336*03ce13f7SAndroid Build Coastguard Worker
337*03ce13f7SAndroid Build Coastguard Worker #if !ALLOW_DUMP
338*03ce13f7SAndroid Build Coastguard Worker static_assert(!subzeroDumpEnabled, "Compile Subzero with ALLOW_DUMP=1 for subzeroDumpEnabled");
339*03ce13f7SAndroid Build Coastguard Worker static_assert(!subzeroEmitTextAsm, "Compile Subzero with ALLOW_DUMP=1 for subzeroEmitTextAsm");
340*03ce13f7SAndroid Build Coastguard Worker #endif
341*03ce13f7SAndroid Build Coastguard Worker
342*03ce13f7SAndroid Build Coastguard Worker } // anonymous namespace
343*03ce13f7SAndroid Build Coastguard Worker
344*03ce13f7SAndroid Build Coastguard Worker namespace rr {
345*03ce13f7SAndroid Build Coastguard Worker
346*03ce13f7SAndroid Build Coastguard Worker const int SIMD::Width = 4;
347*03ce13f7SAndroid Build Coastguard Worker
backendName()348*03ce13f7SAndroid Build Coastguard Worker std::string Caps::backendName()
349*03ce13f7SAndroid Build Coastguard Worker {
350*03ce13f7SAndroid Build Coastguard Worker return "Subzero";
351*03ce13f7SAndroid Build Coastguard Worker }
352*03ce13f7SAndroid Build Coastguard Worker
coroutinesSupported()353*03ce13f7SAndroid Build Coastguard Worker bool Caps::coroutinesSupported()
354*03ce13f7SAndroid Build Coastguard Worker {
355*03ce13f7SAndroid Build Coastguard Worker return true;
356*03ce13f7SAndroid Build Coastguard Worker }
357*03ce13f7SAndroid Build Coastguard Worker
fmaIsFast()358*03ce13f7SAndroid Build Coastguard Worker bool Caps::fmaIsFast()
359*03ce13f7SAndroid Build Coastguard Worker {
360*03ce13f7SAndroid Build Coastguard Worker // TODO(b/214591655): Subzero currently never emits FMA instructions. std::fma() is called instead.
361*03ce13f7SAndroid Build Coastguard Worker return false;
362*03ce13f7SAndroid Build Coastguard Worker }
363*03ce13f7SAndroid Build Coastguard Worker
364*03ce13f7SAndroid Build Coastguard Worker enum EmulatedType
365*03ce13f7SAndroid Build Coastguard Worker {
366*03ce13f7SAndroid Build Coastguard Worker EmulatedShift = 16,
367*03ce13f7SAndroid Build Coastguard Worker EmulatedV2 = 2 << EmulatedShift,
368*03ce13f7SAndroid Build Coastguard Worker EmulatedV4 = 4 << EmulatedShift,
369*03ce13f7SAndroid Build Coastguard Worker EmulatedV8 = 8 << EmulatedShift,
370*03ce13f7SAndroid Build Coastguard Worker EmulatedBits = EmulatedV2 | EmulatedV4 | EmulatedV8,
371*03ce13f7SAndroid Build Coastguard Worker
372*03ce13f7SAndroid Build Coastguard Worker Type_v2i32 = Ice::IceType_v4i32 | EmulatedV2,
373*03ce13f7SAndroid Build Coastguard Worker Type_v4i16 = Ice::IceType_v8i16 | EmulatedV4,
374*03ce13f7SAndroid Build Coastguard Worker Type_v2i16 = Ice::IceType_v8i16 | EmulatedV2,
375*03ce13f7SAndroid Build Coastguard Worker Type_v8i8 = Ice::IceType_v16i8 | EmulatedV8,
376*03ce13f7SAndroid Build Coastguard Worker Type_v4i8 = Ice::IceType_v16i8 | EmulatedV4,
377*03ce13f7SAndroid Build Coastguard Worker Type_v2f32 = Ice::IceType_v4f32 | EmulatedV2,
378*03ce13f7SAndroid Build Coastguard Worker };
379*03ce13f7SAndroid Build Coastguard Worker
380*03ce13f7SAndroid Build Coastguard Worker class Value : public Ice::Operand
381*03ce13f7SAndroid Build Coastguard Worker {};
382*03ce13f7SAndroid Build Coastguard Worker class SwitchCases : public Ice::InstSwitch
383*03ce13f7SAndroid Build Coastguard Worker {};
384*03ce13f7SAndroid Build Coastguard Worker class BasicBlock : public Ice::CfgNode
385*03ce13f7SAndroid Build Coastguard Worker {};
386*03ce13f7SAndroid Build Coastguard Worker
T(Type * t)387*03ce13f7SAndroid Build Coastguard Worker Ice::Type T(Type *t)
388*03ce13f7SAndroid Build Coastguard Worker {
389*03ce13f7SAndroid Build Coastguard Worker static_assert(static_cast<unsigned int>(Ice::IceType_NUM) < static_cast<unsigned int>(EmulatedBits), "Ice::Type overlaps with our emulated types!");
390*03ce13f7SAndroid Build Coastguard Worker return (Ice::Type)(reinterpret_cast<std::intptr_t>(t) & ~EmulatedBits);
391*03ce13f7SAndroid Build Coastguard Worker }
392*03ce13f7SAndroid Build Coastguard Worker
T(Ice::Type t)393*03ce13f7SAndroid Build Coastguard Worker Type *T(Ice::Type t)
394*03ce13f7SAndroid Build Coastguard Worker {
395*03ce13f7SAndroid Build Coastguard Worker return reinterpret_cast<Type *>(t);
396*03ce13f7SAndroid Build Coastguard Worker }
397*03ce13f7SAndroid Build Coastguard Worker
T(EmulatedType t)398*03ce13f7SAndroid Build Coastguard Worker Type *T(EmulatedType t)
399*03ce13f7SAndroid Build Coastguard Worker {
400*03ce13f7SAndroid Build Coastguard Worker return reinterpret_cast<Type *>(t);
401*03ce13f7SAndroid Build Coastguard Worker }
402*03ce13f7SAndroid Build Coastguard Worker
T(const std::vector<Type * > & types)403*03ce13f7SAndroid Build Coastguard Worker std::vector<Ice::Type> T(const std::vector<Type *> &types)
404*03ce13f7SAndroid Build Coastguard Worker {
405*03ce13f7SAndroid Build Coastguard Worker std::vector<Ice::Type> result;
406*03ce13f7SAndroid Build Coastguard Worker result.reserve(types.size());
407*03ce13f7SAndroid Build Coastguard Worker for(auto &t : types)
408*03ce13f7SAndroid Build Coastguard Worker {
409*03ce13f7SAndroid Build Coastguard Worker result.push_back(T(t));
410*03ce13f7SAndroid Build Coastguard Worker }
411*03ce13f7SAndroid Build Coastguard Worker return result;
412*03ce13f7SAndroid Build Coastguard Worker }
413*03ce13f7SAndroid Build Coastguard Worker
V(Ice::Operand * v)414*03ce13f7SAndroid Build Coastguard Worker Value *V(Ice::Operand *v)
415*03ce13f7SAndroid Build Coastguard Worker {
416*03ce13f7SAndroid Build Coastguard Worker return reinterpret_cast<Value *>(v);
417*03ce13f7SAndroid Build Coastguard Worker }
418*03ce13f7SAndroid Build Coastguard Worker
V(Value * v)419*03ce13f7SAndroid Build Coastguard Worker Ice::Operand *V(Value *v)
420*03ce13f7SAndroid Build Coastguard Worker {
421*03ce13f7SAndroid Build Coastguard Worker return reinterpret_cast<Ice::Operand *>(v);
422*03ce13f7SAndroid Build Coastguard Worker }
423*03ce13f7SAndroid Build Coastguard Worker
V(const std::vector<Value * > & values)424*03ce13f7SAndroid Build Coastguard Worker std::vector<Ice::Operand *> V(const std::vector<Value *> &values)
425*03ce13f7SAndroid Build Coastguard Worker {
426*03ce13f7SAndroid Build Coastguard Worker std::vector<Ice::Operand *> result;
427*03ce13f7SAndroid Build Coastguard Worker result.reserve(values.size());
428*03ce13f7SAndroid Build Coastguard Worker for(auto &v : values)
429*03ce13f7SAndroid Build Coastguard Worker {
430*03ce13f7SAndroid Build Coastguard Worker result.push_back(V(v));
431*03ce13f7SAndroid Build Coastguard Worker }
432*03ce13f7SAndroid Build Coastguard Worker return result;
433*03ce13f7SAndroid Build Coastguard Worker }
434*03ce13f7SAndroid Build Coastguard Worker
B(Ice::CfgNode * b)435*03ce13f7SAndroid Build Coastguard Worker BasicBlock *B(Ice::CfgNode *b)
436*03ce13f7SAndroid Build Coastguard Worker {
437*03ce13f7SAndroid Build Coastguard Worker return reinterpret_cast<BasicBlock *>(b);
438*03ce13f7SAndroid Build Coastguard Worker }
439*03ce13f7SAndroid Build Coastguard Worker
typeSize(Type * type)440*03ce13f7SAndroid Build Coastguard Worker static size_t typeSize(Type *type)
441*03ce13f7SAndroid Build Coastguard Worker {
442*03ce13f7SAndroid Build Coastguard Worker if(reinterpret_cast<std::intptr_t>(type) & EmulatedBits)
443*03ce13f7SAndroid Build Coastguard Worker {
444*03ce13f7SAndroid Build Coastguard Worker switch(reinterpret_cast<std::intptr_t>(type))
445*03ce13f7SAndroid Build Coastguard Worker {
446*03ce13f7SAndroid Build Coastguard Worker case Type_v2i32: return 8;
447*03ce13f7SAndroid Build Coastguard Worker case Type_v4i16: return 8;
448*03ce13f7SAndroid Build Coastguard Worker case Type_v2i16: return 4;
449*03ce13f7SAndroid Build Coastguard Worker case Type_v8i8: return 8;
450*03ce13f7SAndroid Build Coastguard Worker case Type_v4i8: return 4;
451*03ce13f7SAndroid Build Coastguard Worker case Type_v2f32: return 8;
452*03ce13f7SAndroid Build Coastguard Worker default: ASSERT(false);
453*03ce13f7SAndroid Build Coastguard Worker }
454*03ce13f7SAndroid Build Coastguard Worker }
455*03ce13f7SAndroid Build Coastguard Worker
456*03ce13f7SAndroid Build Coastguard Worker return Ice::typeWidthInBytes(T(type));
457*03ce13f7SAndroid Build Coastguard Worker }
458*03ce13f7SAndroid Build Coastguard Worker
finalizeFunction()459*03ce13f7SAndroid Build Coastguard Worker static void finalizeFunction()
460*03ce13f7SAndroid Build Coastguard Worker {
461*03ce13f7SAndroid Build Coastguard Worker // Create a return if none was added
462*03ce13f7SAndroid Build Coastguard Worker if(::basicBlock->getInsts().empty() || ::basicBlock->getInsts().back().getKind() != Ice::Inst::Ret)
463*03ce13f7SAndroid Build Coastguard Worker {
464*03ce13f7SAndroid Build Coastguard Worker Nucleus::createRetVoid();
465*03ce13f7SAndroid Build Coastguard Worker }
466*03ce13f7SAndroid Build Coastguard Worker
467*03ce13f7SAndroid Build Coastguard Worker // Connect the entry block to the top of the initial basic block
468*03ce13f7SAndroid Build Coastguard Worker auto br = Ice::InstBr::create(::function, ::basicBlockTop);
469*03ce13f7SAndroid Build Coastguard Worker ::entryBlock->appendInst(br);
470*03ce13f7SAndroid Build Coastguard Worker }
471*03ce13f7SAndroid Build Coastguard Worker
472*03ce13f7SAndroid Build Coastguard Worker using ElfHeader = std::conditional<sizeof(void *) == 8, Elf64_Ehdr, Elf32_Ehdr>::type;
473*03ce13f7SAndroid Build Coastguard Worker using SectionHeader = std::conditional<sizeof(void *) == 8, Elf64_Shdr, Elf32_Shdr>::type;
474*03ce13f7SAndroid Build Coastguard Worker
sectionHeader(const ElfHeader * elfHeader)475*03ce13f7SAndroid Build Coastguard Worker inline const SectionHeader *sectionHeader(const ElfHeader *elfHeader)
476*03ce13f7SAndroid Build Coastguard Worker {
477*03ce13f7SAndroid Build Coastguard Worker return reinterpret_cast<const SectionHeader *>((intptr_t)elfHeader + elfHeader->e_shoff);
478*03ce13f7SAndroid Build Coastguard Worker }
479*03ce13f7SAndroid Build Coastguard Worker
elfSection(const ElfHeader * elfHeader,int index)480*03ce13f7SAndroid Build Coastguard Worker inline const SectionHeader *elfSection(const ElfHeader *elfHeader, int index)
481*03ce13f7SAndroid Build Coastguard Worker {
482*03ce13f7SAndroid Build Coastguard Worker return §ionHeader(elfHeader)[index];
483*03ce13f7SAndroid Build Coastguard Worker }
484*03ce13f7SAndroid Build Coastguard Worker
relocateSymbol(const ElfHeader * elfHeader,const Elf32_Rel & relocation,const SectionHeader & relocationTable)485*03ce13f7SAndroid Build Coastguard Worker static void *relocateSymbol(const ElfHeader *elfHeader, const Elf32_Rel &relocation, const SectionHeader &relocationTable)
486*03ce13f7SAndroid Build Coastguard Worker {
487*03ce13f7SAndroid Build Coastguard Worker const SectionHeader *target = elfSection(elfHeader, relocationTable.sh_info);
488*03ce13f7SAndroid Build Coastguard Worker
489*03ce13f7SAndroid Build Coastguard Worker uint32_t index = relocation.getSymbol();
490*03ce13f7SAndroid Build Coastguard Worker int table = relocationTable.sh_link;
491*03ce13f7SAndroid Build Coastguard Worker void *symbolValue = nullptr;
492*03ce13f7SAndroid Build Coastguard Worker
493*03ce13f7SAndroid Build Coastguard Worker if(index != SHN_UNDEF)
494*03ce13f7SAndroid Build Coastguard Worker {
495*03ce13f7SAndroid Build Coastguard Worker if(table == SHN_UNDEF) return nullptr;
496*03ce13f7SAndroid Build Coastguard Worker const SectionHeader *symbolTable = elfSection(elfHeader, table);
497*03ce13f7SAndroid Build Coastguard Worker
498*03ce13f7SAndroid Build Coastguard Worker uint32_t symtab_entries = symbolTable->sh_size / symbolTable->sh_entsize;
499*03ce13f7SAndroid Build Coastguard Worker if(index >= symtab_entries)
500*03ce13f7SAndroid Build Coastguard Worker {
501*03ce13f7SAndroid Build Coastguard Worker ASSERT(index < symtab_entries && "Symbol Index out of range");
502*03ce13f7SAndroid Build Coastguard Worker return nullptr;
503*03ce13f7SAndroid Build Coastguard Worker }
504*03ce13f7SAndroid Build Coastguard Worker
505*03ce13f7SAndroid Build Coastguard Worker intptr_t symbolAddress = (intptr_t)elfHeader + symbolTable->sh_offset;
506*03ce13f7SAndroid Build Coastguard Worker Elf32_Sym &symbol = ((Elf32_Sym *)symbolAddress)[index];
507*03ce13f7SAndroid Build Coastguard Worker uint16_t section = symbol.st_shndx;
508*03ce13f7SAndroid Build Coastguard Worker
509*03ce13f7SAndroid Build Coastguard Worker if(section != SHN_UNDEF && section < SHN_LORESERVE)
510*03ce13f7SAndroid Build Coastguard Worker {
511*03ce13f7SAndroid Build Coastguard Worker const SectionHeader *target = elfSection(elfHeader, symbol.st_shndx);
512*03ce13f7SAndroid Build Coastguard Worker symbolValue = reinterpret_cast<void *>((intptr_t)elfHeader + symbol.st_value + target->sh_offset);
513*03ce13f7SAndroid Build Coastguard Worker }
514*03ce13f7SAndroid Build Coastguard Worker else
515*03ce13f7SAndroid Build Coastguard Worker {
516*03ce13f7SAndroid Build Coastguard Worker return nullptr;
517*03ce13f7SAndroid Build Coastguard Worker }
518*03ce13f7SAndroid Build Coastguard Worker }
519*03ce13f7SAndroid Build Coastguard Worker
520*03ce13f7SAndroid Build Coastguard Worker intptr_t address = (intptr_t)elfHeader + target->sh_offset;
521*03ce13f7SAndroid Build Coastguard Worker unaligned_ptr<int32_t> patchSite = (void *)(address + relocation.r_offset);
522*03ce13f7SAndroid Build Coastguard Worker
523*03ce13f7SAndroid Build Coastguard Worker if(CPUID::ARM)
524*03ce13f7SAndroid Build Coastguard Worker {
525*03ce13f7SAndroid Build Coastguard Worker switch(relocation.getType())
526*03ce13f7SAndroid Build Coastguard Worker {
527*03ce13f7SAndroid Build Coastguard Worker case R_ARM_NONE:
528*03ce13f7SAndroid Build Coastguard Worker // No relocation
529*03ce13f7SAndroid Build Coastguard Worker break;
530*03ce13f7SAndroid Build Coastguard Worker case R_ARM_MOVW_ABS_NC:
531*03ce13f7SAndroid Build Coastguard Worker {
532*03ce13f7SAndroid Build Coastguard Worker uint32_t thumb = 0; // Calls to Thumb code not supported.
533*03ce13f7SAndroid Build Coastguard Worker uint32_t lo = (uint32_t)(intptr_t)symbolValue | thumb;
534*03ce13f7SAndroid Build Coastguard Worker *patchSite = (*patchSite & 0xFFF0F000) | ((lo & 0xF000) << 4) | (lo & 0x0FFF);
535*03ce13f7SAndroid Build Coastguard Worker }
536*03ce13f7SAndroid Build Coastguard Worker break;
537*03ce13f7SAndroid Build Coastguard Worker case R_ARM_MOVT_ABS:
538*03ce13f7SAndroid Build Coastguard Worker {
539*03ce13f7SAndroid Build Coastguard Worker uint32_t hi = (uint32_t)(intptr_t)(symbolValue) >> 16;
540*03ce13f7SAndroid Build Coastguard Worker *patchSite = (*patchSite & 0xFFF0F000) | ((hi & 0xF000) << 4) | (hi & 0x0FFF);
541*03ce13f7SAndroid Build Coastguard Worker }
542*03ce13f7SAndroid Build Coastguard Worker break;
543*03ce13f7SAndroid Build Coastguard Worker default:
544*03ce13f7SAndroid Build Coastguard Worker ASSERT(false && "Unsupported relocation type");
545*03ce13f7SAndroid Build Coastguard Worker return nullptr;
546*03ce13f7SAndroid Build Coastguard Worker }
547*03ce13f7SAndroid Build Coastguard Worker }
548*03ce13f7SAndroid Build Coastguard Worker else
549*03ce13f7SAndroid Build Coastguard Worker {
550*03ce13f7SAndroid Build Coastguard Worker switch(relocation.getType())
551*03ce13f7SAndroid Build Coastguard Worker {
552*03ce13f7SAndroid Build Coastguard Worker case R_386_NONE:
553*03ce13f7SAndroid Build Coastguard Worker // No relocation
554*03ce13f7SAndroid Build Coastguard Worker break;
555*03ce13f7SAndroid Build Coastguard Worker case R_386_32:
556*03ce13f7SAndroid Build Coastguard Worker *patchSite = (int32_t)((intptr_t)symbolValue + *patchSite);
557*03ce13f7SAndroid Build Coastguard Worker break;
558*03ce13f7SAndroid Build Coastguard Worker case R_386_PC32:
559*03ce13f7SAndroid Build Coastguard Worker *patchSite = (int32_t)((intptr_t)symbolValue + *patchSite - (intptr_t)patchSite);
560*03ce13f7SAndroid Build Coastguard Worker break;
561*03ce13f7SAndroid Build Coastguard Worker default:
562*03ce13f7SAndroid Build Coastguard Worker ASSERT(false && "Unsupported relocation type");
563*03ce13f7SAndroid Build Coastguard Worker return nullptr;
564*03ce13f7SAndroid Build Coastguard Worker }
565*03ce13f7SAndroid Build Coastguard Worker }
566*03ce13f7SAndroid Build Coastguard Worker
567*03ce13f7SAndroid Build Coastguard Worker return symbolValue;
568*03ce13f7SAndroid Build Coastguard Worker }
569*03ce13f7SAndroid Build Coastguard Worker
relocateSymbol(const ElfHeader * elfHeader,const Elf64_Rela & relocation,const SectionHeader & relocationTable)570*03ce13f7SAndroid Build Coastguard Worker static void *relocateSymbol(const ElfHeader *elfHeader, const Elf64_Rela &relocation, const SectionHeader &relocationTable)
571*03ce13f7SAndroid Build Coastguard Worker {
572*03ce13f7SAndroid Build Coastguard Worker const SectionHeader *target = elfSection(elfHeader, relocationTable.sh_info);
573*03ce13f7SAndroid Build Coastguard Worker
574*03ce13f7SAndroid Build Coastguard Worker uint32_t index = relocation.getSymbol();
575*03ce13f7SAndroid Build Coastguard Worker int table = relocationTable.sh_link;
576*03ce13f7SAndroid Build Coastguard Worker void *symbolValue = nullptr;
577*03ce13f7SAndroid Build Coastguard Worker
578*03ce13f7SAndroid Build Coastguard Worker if(index != SHN_UNDEF)
579*03ce13f7SAndroid Build Coastguard Worker {
580*03ce13f7SAndroid Build Coastguard Worker if(table == SHN_UNDEF) return nullptr;
581*03ce13f7SAndroid Build Coastguard Worker const SectionHeader *symbolTable = elfSection(elfHeader, table);
582*03ce13f7SAndroid Build Coastguard Worker
583*03ce13f7SAndroid Build Coastguard Worker uint32_t symtab_entries = symbolTable->sh_size / symbolTable->sh_entsize;
584*03ce13f7SAndroid Build Coastguard Worker if(index >= symtab_entries)
585*03ce13f7SAndroid Build Coastguard Worker {
586*03ce13f7SAndroid Build Coastguard Worker ASSERT(index < symtab_entries && "Symbol Index out of range");
587*03ce13f7SAndroid Build Coastguard Worker return nullptr;
588*03ce13f7SAndroid Build Coastguard Worker }
589*03ce13f7SAndroid Build Coastguard Worker
590*03ce13f7SAndroid Build Coastguard Worker intptr_t symbolAddress = (intptr_t)elfHeader + symbolTable->sh_offset;
591*03ce13f7SAndroid Build Coastguard Worker Elf64_Sym &symbol = ((Elf64_Sym *)symbolAddress)[index];
592*03ce13f7SAndroid Build Coastguard Worker uint16_t section = symbol.st_shndx;
593*03ce13f7SAndroid Build Coastguard Worker
594*03ce13f7SAndroid Build Coastguard Worker if(section != SHN_UNDEF && section < SHN_LORESERVE)
595*03ce13f7SAndroid Build Coastguard Worker {
596*03ce13f7SAndroid Build Coastguard Worker const SectionHeader *target = elfSection(elfHeader, symbol.st_shndx);
597*03ce13f7SAndroid Build Coastguard Worker symbolValue = reinterpret_cast<void *>((intptr_t)elfHeader + symbol.st_value + target->sh_offset);
598*03ce13f7SAndroid Build Coastguard Worker }
599*03ce13f7SAndroid Build Coastguard Worker else
600*03ce13f7SAndroid Build Coastguard Worker {
601*03ce13f7SAndroid Build Coastguard Worker return nullptr;
602*03ce13f7SAndroid Build Coastguard Worker }
603*03ce13f7SAndroid Build Coastguard Worker }
604*03ce13f7SAndroid Build Coastguard Worker
605*03ce13f7SAndroid Build Coastguard Worker intptr_t address = (intptr_t)elfHeader + target->sh_offset;
606*03ce13f7SAndroid Build Coastguard Worker unaligned_ptr<int32_t> patchSite32 = (void *)(address + relocation.r_offset);
607*03ce13f7SAndroid Build Coastguard Worker unaligned_ptr<int64_t> patchSite64 = (void *)(address + relocation.r_offset);
608*03ce13f7SAndroid Build Coastguard Worker
609*03ce13f7SAndroid Build Coastguard Worker switch(relocation.getType())
610*03ce13f7SAndroid Build Coastguard Worker {
611*03ce13f7SAndroid Build Coastguard Worker case R_X86_64_NONE:
612*03ce13f7SAndroid Build Coastguard Worker // No relocation
613*03ce13f7SAndroid Build Coastguard Worker break;
614*03ce13f7SAndroid Build Coastguard Worker case R_X86_64_64:
615*03ce13f7SAndroid Build Coastguard Worker *patchSite64 = (int64_t)((intptr_t)symbolValue + *patchSite64 + relocation.r_addend);
616*03ce13f7SAndroid Build Coastguard Worker break;
617*03ce13f7SAndroid Build Coastguard Worker case R_X86_64_PC32:
618*03ce13f7SAndroid Build Coastguard Worker *patchSite32 = (int32_t)((intptr_t)symbolValue + *patchSite32 - (intptr_t)patchSite32 + relocation.r_addend);
619*03ce13f7SAndroid Build Coastguard Worker break;
620*03ce13f7SAndroid Build Coastguard Worker case R_X86_64_32S:
621*03ce13f7SAndroid Build Coastguard Worker *patchSite32 = (int32_t)((intptr_t)symbolValue + *patchSite32 + relocation.r_addend);
622*03ce13f7SAndroid Build Coastguard Worker break;
623*03ce13f7SAndroid Build Coastguard Worker default:
624*03ce13f7SAndroid Build Coastguard Worker ASSERT(false && "Unsupported relocation type");
625*03ce13f7SAndroid Build Coastguard Worker return nullptr;
626*03ce13f7SAndroid Build Coastguard Worker }
627*03ce13f7SAndroid Build Coastguard Worker
628*03ce13f7SAndroid Build Coastguard Worker return symbolValue;
629*03ce13f7SAndroid Build Coastguard Worker }
630*03ce13f7SAndroid Build Coastguard Worker
631*03ce13f7SAndroid Build Coastguard Worker struct EntryPoint
632*03ce13f7SAndroid Build Coastguard Worker {
633*03ce13f7SAndroid Build Coastguard Worker const void *entry;
634*03ce13f7SAndroid Build Coastguard Worker size_t codeSize = 0;
635*03ce13f7SAndroid Build Coastguard Worker };
636*03ce13f7SAndroid Build Coastguard Worker
loadImage(uint8_t * const elfImage,const std::vector<const char * > & functionNames)637*03ce13f7SAndroid Build Coastguard Worker std::vector<EntryPoint> loadImage(uint8_t *const elfImage, const std::vector<const char *> &functionNames)
638*03ce13f7SAndroid Build Coastguard Worker {
639*03ce13f7SAndroid Build Coastguard Worker ASSERT(functionNames.size() > 0);
640*03ce13f7SAndroid Build Coastguard Worker std::vector<EntryPoint> entryPoints(functionNames.size());
641*03ce13f7SAndroid Build Coastguard Worker
642*03ce13f7SAndroid Build Coastguard Worker ElfHeader *elfHeader = (ElfHeader *)elfImage;
643*03ce13f7SAndroid Build Coastguard Worker
644*03ce13f7SAndroid Build Coastguard Worker // TODO: assert?
645*03ce13f7SAndroid Build Coastguard Worker if(!elfHeader->checkMagic())
646*03ce13f7SAndroid Build Coastguard Worker {
647*03ce13f7SAndroid Build Coastguard Worker return {};
648*03ce13f7SAndroid Build Coastguard Worker }
649*03ce13f7SAndroid Build Coastguard Worker
650*03ce13f7SAndroid Build Coastguard Worker // Expect ELF bitness to match platform
651*03ce13f7SAndroid Build Coastguard Worker ASSERT(sizeof(void *) == 8 ? elfHeader->getFileClass() == ELFCLASS64 : elfHeader->getFileClass() == ELFCLASS32);
652*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__)
653*03ce13f7SAndroid Build Coastguard Worker ASSERT(sizeof(void *) == 4 && elfHeader->e_machine == EM_386);
654*03ce13f7SAndroid Build Coastguard Worker #elif defined(__x86_64__)
655*03ce13f7SAndroid Build Coastguard Worker ASSERT(sizeof(void *) == 8 && elfHeader->e_machine == EM_X86_64);
656*03ce13f7SAndroid Build Coastguard Worker #elif defined(__arm__)
657*03ce13f7SAndroid Build Coastguard Worker ASSERT(sizeof(void *) == 4 && elfHeader->e_machine == EM_ARM);
658*03ce13f7SAndroid Build Coastguard Worker #elif defined(__aarch64__)
659*03ce13f7SAndroid Build Coastguard Worker ASSERT(sizeof(void *) == 8 && elfHeader->e_machine == EM_AARCH64);
660*03ce13f7SAndroid Build Coastguard Worker #elif defined(__mips__)
661*03ce13f7SAndroid Build Coastguard Worker ASSERT(sizeof(void *) == 4 && elfHeader->e_machine == EM_MIPS);
662*03ce13f7SAndroid Build Coastguard Worker #else
663*03ce13f7SAndroid Build Coastguard Worker # error "Unsupported platform"
664*03ce13f7SAndroid Build Coastguard Worker #endif
665*03ce13f7SAndroid Build Coastguard Worker
666*03ce13f7SAndroid Build Coastguard Worker SectionHeader *sectionHeader = (SectionHeader *)(elfImage + elfHeader->e_shoff);
667*03ce13f7SAndroid Build Coastguard Worker
668*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < elfHeader->e_shnum; i++)
669*03ce13f7SAndroid Build Coastguard Worker {
670*03ce13f7SAndroid Build Coastguard Worker if(sectionHeader[i].sh_type == SHT_PROGBITS)
671*03ce13f7SAndroid Build Coastguard Worker {
672*03ce13f7SAndroid Build Coastguard Worker if(sectionHeader[i].sh_flags & SHF_EXECINSTR)
673*03ce13f7SAndroid Build Coastguard Worker {
674*03ce13f7SAndroid Build Coastguard Worker auto findSectionNameEntryIndex = [&]() -> size_t {
675*03ce13f7SAndroid Build Coastguard Worker auto sectionNameOffset = sectionHeader[elfHeader->e_shstrndx].sh_offset + sectionHeader[i].sh_name;
676*03ce13f7SAndroid Build Coastguard Worker const char *sectionName = reinterpret_cast<const char *>(elfImage + sectionNameOffset);
677*03ce13f7SAndroid Build Coastguard Worker
678*03ce13f7SAndroid Build Coastguard Worker for(size_t j = 0; j < functionNames.size(); ++j)
679*03ce13f7SAndroid Build Coastguard Worker {
680*03ce13f7SAndroid Build Coastguard Worker if(strstr(sectionName, functionNames[j]) != nullptr)
681*03ce13f7SAndroid Build Coastguard Worker {
682*03ce13f7SAndroid Build Coastguard Worker return j;
683*03ce13f7SAndroid Build Coastguard Worker }
684*03ce13f7SAndroid Build Coastguard Worker }
685*03ce13f7SAndroid Build Coastguard Worker
686*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("Failed to find executable section that matches input function names");
687*03ce13f7SAndroid Build Coastguard Worker return static_cast<size_t>(-1);
688*03ce13f7SAndroid Build Coastguard Worker };
689*03ce13f7SAndroid Build Coastguard Worker
690*03ce13f7SAndroid Build Coastguard Worker size_t index = findSectionNameEntryIndex();
691*03ce13f7SAndroid Build Coastguard Worker entryPoints[index].entry = elfImage + sectionHeader[i].sh_offset;
692*03ce13f7SAndroid Build Coastguard Worker entryPoints[index].codeSize = sectionHeader[i].sh_size;
693*03ce13f7SAndroid Build Coastguard Worker }
694*03ce13f7SAndroid Build Coastguard Worker }
695*03ce13f7SAndroid Build Coastguard Worker else if(sectionHeader[i].sh_type == SHT_REL)
696*03ce13f7SAndroid Build Coastguard Worker {
697*03ce13f7SAndroid Build Coastguard Worker ASSERT(sizeof(void *) == 4 && "UNIMPLEMENTED"); // Only expected/implemented for 32-bit code
698*03ce13f7SAndroid Build Coastguard Worker
699*03ce13f7SAndroid Build Coastguard Worker for(Elf32_Word index = 0; index < sectionHeader[i].sh_size / sectionHeader[i].sh_entsize; index++)
700*03ce13f7SAndroid Build Coastguard Worker {
701*03ce13f7SAndroid Build Coastguard Worker const Elf32_Rel &relocation = ((const Elf32_Rel *)(elfImage + sectionHeader[i].sh_offset))[index];
702*03ce13f7SAndroid Build Coastguard Worker relocateSymbol(elfHeader, relocation, sectionHeader[i]);
703*03ce13f7SAndroid Build Coastguard Worker }
704*03ce13f7SAndroid Build Coastguard Worker }
705*03ce13f7SAndroid Build Coastguard Worker else if(sectionHeader[i].sh_type == SHT_RELA)
706*03ce13f7SAndroid Build Coastguard Worker {
707*03ce13f7SAndroid Build Coastguard Worker ASSERT(sizeof(void *) == 8 && "UNIMPLEMENTED"); // Only expected/implemented for 64-bit code
708*03ce13f7SAndroid Build Coastguard Worker
709*03ce13f7SAndroid Build Coastguard Worker for(Elf32_Word index = 0; index < sectionHeader[i].sh_size / sectionHeader[i].sh_entsize; index++)
710*03ce13f7SAndroid Build Coastguard Worker {
711*03ce13f7SAndroid Build Coastguard Worker const Elf64_Rela &relocation = ((const Elf64_Rela *)(elfImage + sectionHeader[i].sh_offset))[index];
712*03ce13f7SAndroid Build Coastguard Worker relocateSymbol(elfHeader, relocation, sectionHeader[i]);
713*03ce13f7SAndroid Build Coastguard Worker }
714*03ce13f7SAndroid Build Coastguard Worker }
715*03ce13f7SAndroid Build Coastguard Worker }
716*03ce13f7SAndroid Build Coastguard Worker
717*03ce13f7SAndroid Build Coastguard Worker return entryPoints;
718*03ce13f7SAndroid Build Coastguard Worker }
719*03ce13f7SAndroid Build Coastguard Worker
720*03ce13f7SAndroid Build Coastguard Worker template<typename T>
721*03ce13f7SAndroid Build Coastguard Worker struct ExecutableAllocator
722*03ce13f7SAndroid Build Coastguard Worker {
ExecutableAllocatorrr::ExecutableAllocator723*03ce13f7SAndroid Build Coastguard Worker ExecutableAllocator() {}
724*03ce13f7SAndroid Build Coastguard Worker template<class U>
ExecutableAllocatorrr::ExecutableAllocator725*03ce13f7SAndroid Build Coastguard Worker ExecutableAllocator(const ExecutableAllocator<U> &other)
726*03ce13f7SAndroid Build Coastguard Worker {}
727*03ce13f7SAndroid Build Coastguard Worker
728*03ce13f7SAndroid Build Coastguard Worker using value_type = T;
729*03ce13f7SAndroid Build Coastguard Worker using size_type = std::size_t;
730*03ce13f7SAndroid Build Coastguard Worker
allocaterr::ExecutableAllocator731*03ce13f7SAndroid Build Coastguard Worker T *allocate(size_type n)
732*03ce13f7SAndroid Build Coastguard Worker {
733*03ce13f7SAndroid Build Coastguard Worker return (T *)allocateMemoryPages(
734*03ce13f7SAndroid Build Coastguard Worker sizeof(T) * n, PERMISSION_READ | PERMISSION_WRITE, true);
735*03ce13f7SAndroid Build Coastguard Worker }
736*03ce13f7SAndroid Build Coastguard Worker
deallocaterr::ExecutableAllocator737*03ce13f7SAndroid Build Coastguard Worker void deallocate(T *p, size_type n)
738*03ce13f7SAndroid Build Coastguard Worker {
739*03ce13f7SAndroid Build Coastguard Worker deallocateMemoryPages(p, sizeof(T) * n);
740*03ce13f7SAndroid Build Coastguard Worker }
741*03ce13f7SAndroid Build Coastguard Worker };
742*03ce13f7SAndroid Build Coastguard Worker
743*03ce13f7SAndroid Build Coastguard Worker class ELFMemoryStreamer : public Ice::ELFStreamer, public Routine
744*03ce13f7SAndroid Build Coastguard Worker {
745*03ce13f7SAndroid Build Coastguard Worker ELFMemoryStreamer(const ELFMemoryStreamer &) = delete;
746*03ce13f7SAndroid Build Coastguard Worker ELFMemoryStreamer &operator=(const ELFMemoryStreamer &) = delete;
747*03ce13f7SAndroid Build Coastguard Worker
748*03ce13f7SAndroid Build Coastguard Worker public:
ELFMemoryStreamer()749*03ce13f7SAndroid Build Coastguard Worker ELFMemoryStreamer()
750*03ce13f7SAndroid Build Coastguard Worker : Routine()
751*03ce13f7SAndroid Build Coastguard Worker {
752*03ce13f7SAndroid Build Coastguard Worker position = 0;
753*03ce13f7SAndroid Build Coastguard Worker buffer.reserve(0x1000);
754*03ce13f7SAndroid Build Coastguard Worker }
755*03ce13f7SAndroid Build Coastguard Worker
~ELFMemoryStreamer()756*03ce13f7SAndroid Build Coastguard Worker ~ELFMemoryStreamer() override
757*03ce13f7SAndroid Build Coastguard Worker {
758*03ce13f7SAndroid Build Coastguard Worker }
759*03ce13f7SAndroid Build Coastguard Worker
write8(uint8_t Value)760*03ce13f7SAndroid Build Coastguard Worker void write8(uint8_t Value) override
761*03ce13f7SAndroid Build Coastguard Worker {
762*03ce13f7SAndroid Build Coastguard Worker if(position == (uint64_t)buffer.size())
763*03ce13f7SAndroid Build Coastguard Worker {
764*03ce13f7SAndroid Build Coastguard Worker buffer.push_back(Value);
765*03ce13f7SAndroid Build Coastguard Worker position++;
766*03ce13f7SAndroid Build Coastguard Worker }
767*03ce13f7SAndroid Build Coastguard Worker else if(position < (uint64_t)buffer.size())
768*03ce13f7SAndroid Build Coastguard Worker {
769*03ce13f7SAndroid Build Coastguard Worker buffer[position] = Value;
770*03ce13f7SAndroid Build Coastguard Worker position++;
771*03ce13f7SAndroid Build Coastguard Worker }
772*03ce13f7SAndroid Build Coastguard Worker else
773*03ce13f7SAndroid Build Coastguard Worker ASSERT(false && "UNIMPLEMENTED");
774*03ce13f7SAndroid Build Coastguard Worker }
775*03ce13f7SAndroid Build Coastguard Worker
writeBytes(llvm::StringRef Bytes)776*03ce13f7SAndroid Build Coastguard Worker void writeBytes(llvm::StringRef Bytes) override
777*03ce13f7SAndroid Build Coastguard Worker {
778*03ce13f7SAndroid Build Coastguard Worker std::size_t oldSize = buffer.size();
779*03ce13f7SAndroid Build Coastguard Worker buffer.resize(oldSize + Bytes.size());
780*03ce13f7SAndroid Build Coastguard Worker memcpy(&buffer[oldSize], Bytes.begin(), Bytes.size());
781*03ce13f7SAndroid Build Coastguard Worker position += Bytes.size();
782*03ce13f7SAndroid Build Coastguard Worker }
783*03ce13f7SAndroid Build Coastguard Worker
tell() const784*03ce13f7SAndroid Build Coastguard Worker uint64_t tell() const override
785*03ce13f7SAndroid Build Coastguard Worker {
786*03ce13f7SAndroid Build Coastguard Worker return position;
787*03ce13f7SAndroid Build Coastguard Worker }
788*03ce13f7SAndroid Build Coastguard Worker
seek(uint64_t Off)789*03ce13f7SAndroid Build Coastguard Worker void seek(uint64_t Off) override
790*03ce13f7SAndroid Build Coastguard Worker {
791*03ce13f7SAndroid Build Coastguard Worker position = Off;
792*03ce13f7SAndroid Build Coastguard Worker }
793*03ce13f7SAndroid Build Coastguard Worker
loadImageAndGetEntryPoints(const std::vector<const char * > & functionNames)794*03ce13f7SAndroid Build Coastguard Worker std::vector<EntryPoint> loadImageAndGetEntryPoints(const std::vector<const char *> &functionNames)
795*03ce13f7SAndroid Build Coastguard Worker {
796*03ce13f7SAndroid Build Coastguard Worker auto entryPoints = loadImage(&buffer[0], functionNames);
797*03ce13f7SAndroid Build Coastguard Worker
798*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
799*03ce13f7SAndroid Build Coastguard Worker FlushInstructionCache(GetCurrentProcess(), NULL, 0);
800*03ce13f7SAndroid Build Coastguard Worker #else
801*03ce13f7SAndroid Build Coastguard Worker for(auto &entryPoint : entryPoints)
802*03ce13f7SAndroid Build Coastguard Worker {
803*03ce13f7SAndroid Build Coastguard Worker __builtin___clear_cache((char *)entryPoint.entry, (char *)entryPoint.entry + entryPoint.codeSize);
804*03ce13f7SAndroid Build Coastguard Worker }
805*03ce13f7SAndroid Build Coastguard Worker #endif
806*03ce13f7SAndroid Build Coastguard Worker
807*03ce13f7SAndroid Build Coastguard Worker return entryPoints;
808*03ce13f7SAndroid Build Coastguard Worker }
809*03ce13f7SAndroid Build Coastguard Worker
finalize()810*03ce13f7SAndroid Build Coastguard Worker void finalize()
811*03ce13f7SAndroid Build Coastguard Worker {
812*03ce13f7SAndroid Build Coastguard Worker position = std::numeric_limits<std::size_t>::max(); // Can't stream more data after this
813*03ce13f7SAndroid Build Coastguard Worker
814*03ce13f7SAndroid Build Coastguard Worker protectMemoryPages(&buffer[0], buffer.size(), PERMISSION_READ | PERMISSION_EXECUTE);
815*03ce13f7SAndroid Build Coastguard Worker }
816*03ce13f7SAndroid Build Coastguard Worker
setEntry(int index,const void * func)817*03ce13f7SAndroid Build Coastguard Worker void setEntry(int index, const void *func)
818*03ce13f7SAndroid Build Coastguard Worker {
819*03ce13f7SAndroid Build Coastguard Worker ASSERT(func);
820*03ce13f7SAndroid Build Coastguard Worker funcs[index] = func;
821*03ce13f7SAndroid Build Coastguard Worker }
822*03ce13f7SAndroid Build Coastguard Worker
getEntry(int index) const823*03ce13f7SAndroid Build Coastguard Worker const void *getEntry(int index) const override
824*03ce13f7SAndroid Build Coastguard Worker {
825*03ce13f7SAndroid Build Coastguard Worker ASSERT(funcs[index]);
826*03ce13f7SAndroid Build Coastguard Worker return funcs[index];
827*03ce13f7SAndroid Build Coastguard Worker }
828*03ce13f7SAndroid Build Coastguard Worker
addConstantData(const void * data,size_t size,size_t alignment=1)829*03ce13f7SAndroid Build Coastguard Worker const void *addConstantData(const void *data, size_t size, size_t alignment = 1)
830*03ce13f7SAndroid Build Coastguard Worker {
831*03ce13f7SAndroid Build Coastguard Worker // Check if we already have a suitable constant.
832*03ce13f7SAndroid Build Coastguard Worker for(const auto &c : constantsPool)
833*03ce13f7SAndroid Build Coastguard Worker {
834*03ce13f7SAndroid Build Coastguard Worker void *ptr = c.data.get();
835*03ce13f7SAndroid Build Coastguard Worker size_t space = c.space;
836*03ce13f7SAndroid Build Coastguard Worker
837*03ce13f7SAndroid Build Coastguard Worker void *alignedPtr = std::align(alignment, size, ptr, space);
838*03ce13f7SAndroid Build Coastguard Worker
839*03ce13f7SAndroid Build Coastguard Worker if(space < size)
840*03ce13f7SAndroid Build Coastguard Worker {
841*03ce13f7SAndroid Build Coastguard Worker continue;
842*03ce13f7SAndroid Build Coastguard Worker }
843*03ce13f7SAndroid Build Coastguard Worker
844*03ce13f7SAndroid Build Coastguard Worker if(memcmp(data, alignedPtr, size) == 0)
845*03ce13f7SAndroid Build Coastguard Worker {
846*03ce13f7SAndroid Build Coastguard Worker return alignedPtr;
847*03ce13f7SAndroid Build Coastguard Worker }
848*03ce13f7SAndroid Build Coastguard Worker }
849*03ce13f7SAndroid Build Coastguard Worker
850*03ce13f7SAndroid Build Coastguard Worker // TODO(b/148086935): Replace with a buffer allocator.
851*03ce13f7SAndroid Build Coastguard Worker size_t space = size + alignment;
852*03ce13f7SAndroid Build Coastguard Worker auto buf = std::unique_ptr<uint8_t[]>(new uint8_t[space]);
853*03ce13f7SAndroid Build Coastguard Worker void *ptr = buf.get();
854*03ce13f7SAndroid Build Coastguard Worker void *alignedPtr = std::align(alignment, size, ptr, space);
855*03ce13f7SAndroid Build Coastguard Worker ASSERT(alignedPtr);
856*03ce13f7SAndroid Build Coastguard Worker memcpy(alignedPtr, data, size);
857*03ce13f7SAndroid Build Coastguard Worker constantsPool.emplace_back(std::move(buf), space);
858*03ce13f7SAndroid Build Coastguard Worker
859*03ce13f7SAndroid Build Coastguard Worker return alignedPtr;
860*03ce13f7SAndroid Build Coastguard Worker }
861*03ce13f7SAndroid Build Coastguard Worker
862*03ce13f7SAndroid Build Coastguard Worker private:
863*03ce13f7SAndroid Build Coastguard Worker struct Constant
864*03ce13f7SAndroid Build Coastguard Worker {
Constantrr::ELFMemoryStreamer::Constant865*03ce13f7SAndroid Build Coastguard Worker Constant(std::unique_ptr<uint8_t[]> data, size_t space)
866*03ce13f7SAndroid Build Coastguard Worker : data(std::move(data))
867*03ce13f7SAndroid Build Coastguard Worker , space(space)
868*03ce13f7SAndroid Build Coastguard Worker {}
869*03ce13f7SAndroid Build Coastguard Worker
870*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> data;
871*03ce13f7SAndroid Build Coastguard Worker size_t space;
872*03ce13f7SAndroid Build Coastguard Worker };
873*03ce13f7SAndroid Build Coastguard Worker
874*03ce13f7SAndroid Build Coastguard Worker std::array<const void *, Nucleus::CoroutineEntryCount> funcs = {};
875*03ce13f7SAndroid Build Coastguard Worker std::vector<uint8_t, ExecutableAllocator<uint8_t>> buffer;
876*03ce13f7SAndroid Build Coastguard Worker std::size_t position;
877*03ce13f7SAndroid Build Coastguard Worker std::vector<Constant> constantsPool;
878*03ce13f7SAndroid Build Coastguard Worker };
879*03ce13f7SAndroid Build Coastguard Worker
880*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_PRINT
VPrintf(const std::vector<Value * > & vals)881*03ce13f7SAndroid Build Coastguard Worker void VPrintf(const std::vector<Value *> &vals)
882*03ce13f7SAndroid Build Coastguard Worker {
883*03ce13f7SAndroid Build Coastguard Worker sz::Call(::function, ::basicBlock, Ice::IceType_i32, reinterpret_cast<const void *>(rr::DebugPrintf), V(vals), true);
884*03ce13f7SAndroid Build Coastguard Worker }
885*03ce13f7SAndroid Build Coastguard Worker #endif // ENABLE_RR_PRINT
886*03ce13f7SAndroid Build Coastguard Worker
Nucleus()887*03ce13f7SAndroid Build Coastguard Worker Nucleus::Nucleus()
888*03ce13f7SAndroid Build Coastguard Worker {
889*03ce13f7SAndroid Build Coastguard Worker ::codegenMutex.lock(); // SubzeroReactor is currently not thread safe
890*03ce13f7SAndroid Build Coastguard Worker
891*03ce13f7SAndroid Build Coastguard Worker Ice::ClFlags &Flags = Ice::ClFlags::Flags;
892*03ce13f7SAndroid Build Coastguard Worker Ice::ClFlags::getParsedClFlags(Flags);
893*03ce13f7SAndroid Build Coastguard Worker
894*03ce13f7SAndroid Build Coastguard Worker #if defined(__arm__)
895*03ce13f7SAndroid Build Coastguard Worker Flags.setTargetArch(Ice::Target_ARM32);
896*03ce13f7SAndroid Build Coastguard Worker Flags.setTargetInstructionSet(Ice::ARM32InstructionSet_HWDivArm);
897*03ce13f7SAndroid Build Coastguard Worker #elif defined(__mips__)
898*03ce13f7SAndroid Build Coastguard Worker Flags.setTargetArch(Ice::Target_MIPS32);
899*03ce13f7SAndroid Build Coastguard Worker Flags.setTargetInstructionSet(Ice::BaseInstructionSet);
900*03ce13f7SAndroid Build Coastguard Worker #else // x86
901*03ce13f7SAndroid Build Coastguard Worker Flags.setTargetArch(sizeof(void *) == 8 ? Ice::Target_X8664 : Ice::Target_X8632);
902*03ce13f7SAndroid Build Coastguard Worker Flags.setTargetInstructionSet(CPUID::SSE4_1 ? Ice::X86InstructionSet_SSE4_1 : Ice::X86InstructionSet_SSE2);
903*03ce13f7SAndroid Build Coastguard Worker #endif
904*03ce13f7SAndroid Build Coastguard Worker Flags.setOutFileType(Ice::FT_Elf);
905*03ce13f7SAndroid Build Coastguard Worker Flags.setOptLevel(toIce(rr::getPragmaState(rr::OptimizationLevel)));
906*03ce13f7SAndroid Build Coastguard Worker Flags.setVerbose(subzeroDumpEnabled ? Ice::IceV_Most : Ice::IceV_None);
907*03ce13f7SAndroid Build Coastguard Worker Flags.setDisableHybridAssembly(true);
908*03ce13f7SAndroid Build Coastguard Worker
909*03ce13f7SAndroid Build Coastguard Worker // Emit functions into separate sections in the ELF so we can find them by name
910*03ce13f7SAndroid Build Coastguard Worker Flags.setFunctionSections(true);
911*03ce13f7SAndroid Build Coastguard Worker
912*03ce13f7SAndroid Build Coastguard Worker static llvm::raw_os_ostream cout(std::cout);
913*03ce13f7SAndroid Build Coastguard Worker static llvm::raw_os_ostream cerr(std::cerr);
914*03ce13f7SAndroid Build Coastguard Worker
915*03ce13f7SAndroid Build Coastguard Worker if(subzeroEmitTextAsm)
916*03ce13f7SAndroid Build Coastguard Worker {
917*03ce13f7SAndroid Build Coastguard Worker // Decorate text asm with liveness info
918*03ce13f7SAndroid Build Coastguard Worker Flags.setDecorateAsm(true);
919*03ce13f7SAndroid Build Coastguard Worker }
920*03ce13f7SAndroid Build Coastguard Worker
921*03ce13f7SAndroid Build Coastguard Worker if(false) // Write out to a file
922*03ce13f7SAndroid Build Coastguard Worker {
923*03ce13f7SAndroid Build Coastguard Worker std::error_code errorCode;
924*03ce13f7SAndroid Build Coastguard Worker ::out = new Ice::Fdstream("out.o", errorCode, llvm::sys::fs::F_None);
925*03ce13f7SAndroid Build Coastguard Worker ::elfFile = new Ice::ELFFileStreamer(*out);
926*03ce13f7SAndroid Build Coastguard Worker ::context = new Ice::GlobalContext(&cout, &cout, &cerr, elfFile);
927*03ce13f7SAndroid Build Coastguard Worker }
928*03ce13f7SAndroid Build Coastguard Worker else
929*03ce13f7SAndroid Build Coastguard Worker {
930*03ce13f7SAndroid Build Coastguard Worker ELFMemoryStreamer *elfMemory = new ELFMemoryStreamer();
931*03ce13f7SAndroid Build Coastguard Worker ::context = new Ice::GlobalContext(&cout, &cout, &cerr, elfMemory);
932*03ce13f7SAndroid Build Coastguard Worker ::routine = elfMemory;
933*03ce13f7SAndroid Build Coastguard Worker }
934*03ce13f7SAndroid Build Coastguard Worker
935*03ce13f7SAndroid Build Coastguard Worker #if !__has_feature(memory_sanitizer)
936*03ce13f7SAndroid Build Coastguard Worker // thread_local variables in shared libraries are initialized at load-time,
937*03ce13f7SAndroid Build Coastguard Worker // but this is not observed by MemorySanitizer if the loader itself was not
938*03ce13f7SAndroid Build Coastguard Worker // instrumented, leading to false-positive uninitialized variable errors.
939*03ce13f7SAndroid Build Coastguard Worker ASSERT(Variable::unmaterializedVariables == nullptr);
940*03ce13f7SAndroid Build Coastguard Worker #endif
941*03ce13f7SAndroid Build Coastguard Worker Variable::unmaterializedVariables = new Variable::UnmaterializedVariables{};
942*03ce13f7SAndroid Build Coastguard Worker }
943*03ce13f7SAndroid Build Coastguard Worker
~Nucleus()944*03ce13f7SAndroid Build Coastguard Worker Nucleus::~Nucleus()
945*03ce13f7SAndroid Build Coastguard Worker {
946*03ce13f7SAndroid Build Coastguard Worker delete Variable::unmaterializedVariables;
947*03ce13f7SAndroid Build Coastguard Worker Variable::unmaterializedVariables = nullptr;
948*03ce13f7SAndroid Build Coastguard Worker
949*03ce13f7SAndroid Build Coastguard Worker delete ::routine;
950*03ce13f7SAndroid Build Coastguard Worker ::routine = nullptr;
951*03ce13f7SAndroid Build Coastguard Worker
952*03ce13f7SAndroid Build Coastguard Worker delete ::allocator;
953*03ce13f7SAndroid Build Coastguard Worker ::allocator = nullptr;
954*03ce13f7SAndroid Build Coastguard Worker
955*03ce13f7SAndroid Build Coastguard Worker delete ::function;
956*03ce13f7SAndroid Build Coastguard Worker ::function = nullptr;
957*03ce13f7SAndroid Build Coastguard Worker
958*03ce13f7SAndroid Build Coastguard Worker delete ::context;
959*03ce13f7SAndroid Build Coastguard Worker ::context = nullptr;
960*03ce13f7SAndroid Build Coastguard Worker
961*03ce13f7SAndroid Build Coastguard Worker delete ::elfFile;
962*03ce13f7SAndroid Build Coastguard Worker ::elfFile = nullptr;
963*03ce13f7SAndroid Build Coastguard Worker
964*03ce13f7SAndroid Build Coastguard Worker delete ::out;
965*03ce13f7SAndroid Build Coastguard Worker ::out = nullptr;
966*03ce13f7SAndroid Build Coastguard Worker
967*03ce13f7SAndroid Build Coastguard Worker ::entryBlock = nullptr;
968*03ce13f7SAndroid Build Coastguard Worker ::basicBlock = nullptr;
969*03ce13f7SAndroid Build Coastguard Worker ::basicBlockTop = nullptr;
970*03ce13f7SAndroid Build Coastguard Worker
971*03ce13f7SAndroid Build Coastguard Worker ::codegenMutex.unlock();
972*03ce13f7SAndroid Build Coastguard Worker }
973*03ce13f7SAndroid Build Coastguard Worker
974*03ce13f7SAndroid Build Coastguard Worker // This function lowers and produces executable binary code in memory for the input functions,
975*03ce13f7SAndroid Build Coastguard Worker // and returns a Routine with the entry points to these functions.
976*03ce13f7SAndroid Build Coastguard Worker template<size_t Count>
acquireRoutine(Ice::Cfg * const (& functions)[Count],const char * const (& names)[Count])977*03ce13f7SAndroid Build Coastguard Worker static std::shared_ptr<Routine> acquireRoutine(Ice::Cfg *const (&functions)[Count], const char *const (&names)[Count])
978*03ce13f7SAndroid Build Coastguard Worker {
979*03ce13f7SAndroid Build Coastguard Worker // This logic is modeled after the IceCompiler, as well as GlobalContext::translateFunctions
980*03ce13f7SAndroid Build Coastguard Worker // and GlobalContext::emitItems.
981*03ce13f7SAndroid Build Coastguard Worker
982*03ce13f7SAndroid Build Coastguard Worker if(subzeroDumpEnabled)
983*03ce13f7SAndroid Build Coastguard Worker {
984*03ce13f7SAndroid Build Coastguard Worker // Output dump strings immediately, rather than once buffer is full. Useful for debugging.
985*03ce13f7SAndroid Build Coastguard Worker ::context->getStrDump().SetUnbuffered();
986*03ce13f7SAndroid Build Coastguard Worker }
987*03ce13f7SAndroid Build Coastguard Worker
988*03ce13f7SAndroid Build Coastguard Worker ::context->emitFileHeader();
989*03ce13f7SAndroid Build Coastguard Worker
990*03ce13f7SAndroid Build Coastguard Worker // Translate
991*03ce13f7SAndroid Build Coastguard Worker
992*03ce13f7SAndroid Build Coastguard Worker for(size_t i = 0; i < Count; ++i)
993*03ce13f7SAndroid Build Coastguard Worker {
994*03ce13f7SAndroid Build Coastguard Worker Ice::Cfg *currFunc = functions[i];
995*03ce13f7SAndroid Build Coastguard Worker
996*03ce13f7SAndroid Build Coastguard Worker // Install function allocator in TLS for Cfg-specific container allocators
997*03ce13f7SAndroid Build Coastguard Worker Ice::CfgLocalAllocatorScope allocScope(currFunc);
998*03ce13f7SAndroid Build Coastguard Worker
999*03ce13f7SAndroid Build Coastguard Worker currFunc->setFunctionName(Ice::GlobalString::createWithString(::context, names[i]));
1000*03ce13f7SAndroid Build Coastguard Worker
1001*03ce13f7SAndroid Build Coastguard Worker if(::optimizerCallback)
1002*03ce13f7SAndroid Build Coastguard Worker {
1003*03ce13f7SAndroid Build Coastguard Worker Nucleus::OptimizerReport report;
1004*03ce13f7SAndroid Build Coastguard Worker rr::optimize(currFunc, &report);
1005*03ce13f7SAndroid Build Coastguard Worker ::optimizerCallback(&report);
1006*03ce13f7SAndroid Build Coastguard Worker ::optimizerCallback = nullptr;
1007*03ce13f7SAndroid Build Coastguard Worker }
1008*03ce13f7SAndroid Build Coastguard Worker else
1009*03ce13f7SAndroid Build Coastguard Worker {
1010*03ce13f7SAndroid Build Coastguard Worker rr::optimize(currFunc);
1011*03ce13f7SAndroid Build Coastguard Worker }
1012*03ce13f7SAndroid Build Coastguard Worker
1013*03ce13f7SAndroid Build Coastguard Worker currFunc->computeInOutEdges();
1014*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(!currFunc->hasError(), "%s", currFunc->getError().c_str());
1015*03ce13f7SAndroid Build Coastguard Worker
1016*03ce13f7SAndroid Build Coastguard Worker currFunc->translate();
1017*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(!currFunc->hasError(), "%s", currFunc->getError().c_str());
1018*03ce13f7SAndroid Build Coastguard Worker
1019*03ce13f7SAndroid Build Coastguard Worker currFunc->getAssembler<>()->setInternal(currFunc->getInternal());
1020*03ce13f7SAndroid Build Coastguard Worker
1021*03ce13f7SAndroid Build Coastguard Worker if(subzeroEmitTextAsm)
1022*03ce13f7SAndroid Build Coastguard Worker {
1023*03ce13f7SAndroid Build Coastguard Worker currFunc->emit();
1024*03ce13f7SAndroid Build Coastguard Worker }
1025*03ce13f7SAndroid Build Coastguard Worker
1026*03ce13f7SAndroid Build Coastguard Worker currFunc->emitIAS();
1027*03ce13f7SAndroid Build Coastguard Worker
1028*03ce13f7SAndroid Build Coastguard Worker if(currFunc->hasError())
1029*03ce13f7SAndroid Build Coastguard Worker {
1030*03ce13f7SAndroid Build Coastguard Worker return nullptr;
1031*03ce13f7SAndroid Build Coastguard Worker }
1032*03ce13f7SAndroid Build Coastguard Worker }
1033*03ce13f7SAndroid Build Coastguard Worker
1034*03ce13f7SAndroid Build Coastguard Worker // Emit items
1035*03ce13f7SAndroid Build Coastguard Worker
1036*03ce13f7SAndroid Build Coastguard Worker ::context->lowerGlobals("");
1037*03ce13f7SAndroid Build Coastguard Worker
1038*03ce13f7SAndroid Build Coastguard Worker auto objectWriter = ::context->getObjectWriter();
1039*03ce13f7SAndroid Build Coastguard Worker
1040*03ce13f7SAndroid Build Coastguard Worker for(size_t i = 0; i < Count; ++i)
1041*03ce13f7SAndroid Build Coastguard Worker {
1042*03ce13f7SAndroid Build Coastguard Worker Ice::Cfg *currFunc = functions[i];
1043*03ce13f7SAndroid Build Coastguard Worker
1044*03ce13f7SAndroid Build Coastguard Worker // Accumulate globals from functions to emit into the "last" section at the end
1045*03ce13f7SAndroid Build Coastguard Worker auto globals = currFunc->getGlobalInits();
1046*03ce13f7SAndroid Build Coastguard Worker if(globals && !globals->empty())
1047*03ce13f7SAndroid Build Coastguard Worker {
1048*03ce13f7SAndroid Build Coastguard Worker ::context->getGlobals()->merge(globals.get());
1049*03ce13f7SAndroid Build Coastguard Worker }
1050*03ce13f7SAndroid Build Coastguard Worker
1051*03ce13f7SAndroid Build Coastguard Worker auto assembler = currFunc->releaseAssembler();
1052*03ce13f7SAndroid Build Coastguard Worker assembler->alignFunction();
1053*03ce13f7SAndroid Build Coastguard Worker objectWriter->writeFunctionCode(currFunc->getFunctionName(), currFunc->getInternal(), assembler.get());
1054*03ce13f7SAndroid Build Coastguard Worker }
1055*03ce13f7SAndroid Build Coastguard Worker
1056*03ce13f7SAndroid Build Coastguard Worker ::context->lowerGlobals("last");
1057*03ce13f7SAndroid Build Coastguard Worker ::context->lowerConstants();
1058*03ce13f7SAndroid Build Coastguard Worker ::context->lowerJumpTables();
1059*03ce13f7SAndroid Build Coastguard Worker
1060*03ce13f7SAndroid Build Coastguard Worker objectWriter->setUndefinedSyms(::context->getConstantExternSyms());
1061*03ce13f7SAndroid Build Coastguard Worker ::context->emitTargetRODataSections();
1062*03ce13f7SAndroid Build Coastguard Worker objectWriter->writeNonUserSections();
1063*03ce13f7SAndroid Build Coastguard Worker
1064*03ce13f7SAndroid Build Coastguard Worker // Done compiling functions, get entry pointers to each of them
1065*03ce13f7SAndroid Build Coastguard Worker auto entryPoints = ::routine->loadImageAndGetEntryPoints({ names, names + Count });
1066*03ce13f7SAndroid Build Coastguard Worker ASSERT(entryPoints.size() == Count);
1067*03ce13f7SAndroid Build Coastguard Worker for(size_t i = 0; i < entryPoints.size(); ++i)
1068*03ce13f7SAndroid Build Coastguard Worker {
1069*03ce13f7SAndroid Build Coastguard Worker ::routine->setEntry(i, entryPoints[i].entry);
1070*03ce13f7SAndroid Build Coastguard Worker }
1071*03ce13f7SAndroid Build Coastguard Worker
1072*03ce13f7SAndroid Build Coastguard Worker ::routine->finalize();
1073*03ce13f7SAndroid Build Coastguard Worker
1074*03ce13f7SAndroid Build Coastguard Worker Routine *handoffRoutine = ::routine;
1075*03ce13f7SAndroid Build Coastguard Worker ::routine = nullptr;
1076*03ce13f7SAndroid Build Coastguard Worker
1077*03ce13f7SAndroid Build Coastguard Worker return std::shared_ptr<Routine>(handoffRoutine);
1078*03ce13f7SAndroid Build Coastguard Worker }
1079*03ce13f7SAndroid Build Coastguard Worker
acquireRoutine(const char * name)1080*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Routine> Nucleus::acquireRoutine(const char *name)
1081*03ce13f7SAndroid Build Coastguard Worker {
1082*03ce13f7SAndroid Build Coastguard Worker finalizeFunction();
1083*03ce13f7SAndroid Build Coastguard Worker return rr::acquireRoutine({ ::function }, { name });
1084*03ce13f7SAndroid Build Coastguard Worker }
1085*03ce13f7SAndroid Build Coastguard Worker
allocateStackVariable(Type * t,int arraySize)1086*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::allocateStackVariable(Type *t, int arraySize)
1087*03ce13f7SAndroid Build Coastguard Worker {
1088*03ce13f7SAndroid Build Coastguard Worker Ice::Type type = T(t);
1089*03ce13f7SAndroid Build Coastguard Worker int typeSize = Ice::typeWidthInBytes(type);
1090*03ce13f7SAndroid Build Coastguard Worker int totalSize = typeSize * (arraySize ? arraySize : 1);
1091*03ce13f7SAndroid Build Coastguard Worker
1092*03ce13f7SAndroid Build Coastguard Worker auto bytes = Ice::ConstantInteger32::create(::context, Ice::IceType_i32, totalSize);
1093*03ce13f7SAndroid Build Coastguard Worker auto address = ::function->makeVariable(T(getPointerType(t)));
1094*03ce13f7SAndroid Build Coastguard Worker auto alloca = Ice::InstAlloca::create(::function, address, bytes, typeSize); // SRoA depends on the alignment to match the type size.
1095*03ce13f7SAndroid Build Coastguard Worker ::function->getEntryNode()->getInsts().push_front(alloca);
1096*03ce13f7SAndroid Build Coastguard Worker
1097*03ce13f7SAndroid Build Coastguard Worker return V(address);
1098*03ce13f7SAndroid Build Coastguard Worker }
1099*03ce13f7SAndroid Build Coastguard Worker
createBasicBlock()1100*03ce13f7SAndroid Build Coastguard Worker BasicBlock *Nucleus::createBasicBlock()
1101*03ce13f7SAndroid Build Coastguard Worker {
1102*03ce13f7SAndroid Build Coastguard Worker return B(::function->makeNode());
1103*03ce13f7SAndroid Build Coastguard Worker }
1104*03ce13f7SAndroid Build Coastguard Worker
getInsertBlock()1105*03ce13f7SAndroid Build Coastguard Worker BasicBlock *Nucleus::getInsertBlock()
1106*03ce13f7SAndroid Build Coastguard Worker {
1107*03ce13f7SAndroid Build Coastguard Worker return B(::basicBlock);
1108*03ce13f7SAndroid Build Coastguard Worker }
1109*03ce13f7SAndroid Build Coastguard Worker
setInsertBlock(BasicBlock * basicBlock)1110*03ce13f7SAndroid Build Coastguard Worker void Nucleus::setInsertBlock(BasicBlock *basicBlock)
1111*03ce13f7SAndroid Build Coastguard Worker {
1112*03ce13f7SAndroid Build Coastguard Worker // ASSERT(::basicBlock->getInsts().back().getTerminatorEdges().size() >= 0 && "Previous basic block must have a terminator");
1113*03ce13f7SAndroid Build Coastguard Worker
1114*03ce13f7SAndroid Build Coastguard Worker ::basicBlock = basicBlock;
1115*03ce13f7SAndroid Build Coastguard Worker }
1116*03ce13f7SAndroid Build Coastguard Worker
createFunction(Type * returnType,const std::vector<Type * > & paramTypes)1117*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createFunction(Type *returnType, const std::vector<Type *> ¶mTypes)
1118*03ce13f7SAndroid Build Coastguard Worker {
1119*03ce13f7SAndroid Build Coastguard Worker ASSERT(::function == nullptr);
1120*03ce13f7SAndroid Build Coastguard Worker ASSERT(::allocator == nullptr);
1121*03ce13f7SAndroid Build Coastguard Worker ASSERT(::entryBlock == nullptr);
1122*03ce13f7SAndroid Build Coastguard Worker ASSERT(::basicBlock == nullptr);
1123*03ce13f7SAndroid Build Coastguard Worker ASSERT(::basicBlockTop == nullptr);
1124*03ce13f7SAndroid Build Coastguard Worker
1125*03ce13f7SAndroid Build Coastguard Worker ::function = sz::createFunction(::context, T(returnType), T(paramTypes));
1126*03ce13f7SAndroid Build Coastguard Worker
1127*03ce13f7SAndroid Build Coastguard Worker // NOTE: The scoped allocator sets the TLS allocator to the one in the function. This global one
1128*03ce13f7SAndroid Build Coastguard Worker // becomes invalid if another one is created; for example, when creating await and destroy functions
1129*03ce13f7SAndroid Build Coastguard Worker // for coroutines, in which case, we must make sure to create a new scoped allocator for ::function again.
1130*03ce13f7SAndroid Build Coastguard Worker // TODO: Get rid of this as a global, and create scoped allocs in every Nucleus function instead.
1131*03ce13f7SAndroid Build Coastguard Worker ::allocator = new Ice::CfgLocalAllocatorScope(::function);
1132*03ce13f7SAndroid Build Coastguard Worker
1133*03ce13f7SAndroid Build Coastguard Worker ::entryBlock = ::function->getEntryNode();
1134*03ce13f7SAndroid Build Coastguard Worker ::basicBlock = ::function->makeNode();
1135*03ce13f7SAndroid Build Coastguard Worker ::basicBlockTop = ::basicBlock;
1136*03ce13f7SAndroid Build Coastguard Worker }
1137*03ce13f7SAndroid Build Coastguard Worker
getArgument(unsigned int index)1138*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::getArgument(unsigned int index)
1139*03ce13f7SAndroid Build Coastguard Worker {
1140*03ce13f7SAndroid Build Coastguard Worker return V(::function->getArgs()[index]);
1141*03ce13f7SAndroid Build Coastguard Worker }
1142*03ce13f7SAndroid Build Coastguard Worker
createRetVoid()1143*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createRetVoid()
1144*03ce13f7SAndroid Build Coastguard Worker {
1145*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1146*03ce13f7SAndroid Build Coastguard Worker
1147*03ce13f7SAndroid Build Coastguard Worker // Code generated after this point is unreachable, so any variables
1148*03ce13f7SAndroid Build Coastguard Worker // being read can safely return an undefined value. We have to avoid
1149*03ce13f7SAndroid Build Coastguard Worker // materializing variables after the terminator ret instruction.
1150*03ce13f7SAndroid Build Coastguard Worker Variable::killUnmaterialized();
1151*03ce13f7SAndroid Build Coastguard Worker
1152*03ce13f7SAndroid Build Coastguard Worker Ice::InstRet *ret = Ice::InstRet::create(::function);
1153*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(ret);
1154*03ce13f7SAndroid Build Coastguard Worker }
1155*03ce13f7SAndroid Build Coastguard Worker
createRet(Value * v)1156*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createRet(Value *v)
1157*03ce13f7SAndroid Build Coastguard Worker {
1158*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1159*03ce13f7SAndroid Build Coastguard Worker
1160*03ce13f7SAndroid Build Coastguard Worker // Code generated after this point is unreachable, so any variables
1161*03ce13f7SAndroid Build Coastguard Worker // being read can safely return an undefined value. We have to avoid
1162*03ce13f7SAndroid Build Coastguard Worker // materializing variables after the terminator ret instruction.
1163*03ce13f7SAndroid Build Coastguard Worker Variable::killUnmaterialized();
1164*03ce13f7SAndroid Build Coastguard Worker
1165*03ce13f7SAndroid Build Coastguard Worker Ice::InstRet *ret = Ice::InstRet::create(::function, v);
1166*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(ret);
1167*03ce13f7SAndroid Build Coastguard Worker }
1168*03ce13f7SAndroid Build Coastguard Worker
createBr(BasicBlock * dest)1169*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createBr(BasicBlock *dest)
1170*03ce13f7SAndroid Build Coastguard Worker {
1171*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1172*03ce13f7SAndroid Build Coastguard Worker Variable::materializeAll();
1173*03ce13f7SAndroid Build Coastguard Worker
1174*03ce13f7SAndroid Build Coastguard Worker auto br = Ice::InstBr::create(::function, dest);
1175*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(br);
1176*03ce13f7SAndroid Build Coastguard Worker }
1177*03ce13f7SAndroid Build Coastguard Worker
createCondBr(Value * cond,BasicBlock * ifTrue,BasicBlock * ifFalse)1178*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createCondBr(Value *cond, BasicBlock *ifTrue, BasicBlock *ifFalse)
1179*03ce13f7SAndroid Build Coastguard Worker {
1180*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1181*03ce13f7SAndroid Build Coastguard Worker Variable::materializeAll();
1182*03ce13f7SAndroid Build Coastguard Worker
1183*03ce13f7SAndroid Build Coastguard Worker auto br = Ice::InstBr::create(::function, cond, ifTrue, ifFalse);
1184*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(br);
1185*03ce13f7SAndroid Build Coastguard Worker }
1186*03ce13f7SAndroid Build Coastguard Worker
isCommutative(Ice::InstArithmetic::OpKind op)1187*03ce13f7SAndroid Build Coastguard Worker static bool isCommutative(Ice::InstArithmetic::OpKind op)
1188*03ce13f7SAndroid Build Coastguard Worker {
1189*03ce13f7SAndroid Build Coastguard Worker switch(op)
1190*03ce13f7SAndroid Build Coastguard Worker {
1191*03ce13f7SAndroid Build Coastguard Worker case Ice::InstArithmetic::Add:
1192*03ce13f7SAndroid Build Coastguard Worker case Ice::InstArithmetic::Fadd:
1193*03ce13f7SAndroid Build Coastguard Worker case Ice::InstArithmetic::Mul:
1194*03ce13f7SAndroid Build Coastguard Worker case Ice::InstArithmetic::Fmul:
1195*03ce13f7SAndroid Build Coastguard Worker case Ice::InstArithmetic::And:
1196*03ce13f7SAndroid Build Coastguard Worker case Ice::InstArithmetic::Or:
1197*03ce13f7SAndroid Build Coastguard Worker case Ice::InstArithmetic::Xor:
1198*03ce13f7SAndroid Build Coastguard Worker return true;
1199*03ce13f7SAndroid Build Coastguard Worker default:
1200*03ce13f7SAndroid Build Coastguard Worker return false;
1201*03ce13f7SAndroid Build Coastguard Worker }
1202*03ce13f7SAndroid Build Coastguard Worker }
1203*03ce13f7SAndroid Build Coastguard Worker
createArithmetic(Ice::InstArithmetic::OpKind op,Value * lhs,Value * rhs)1204*03ce13f7SAndroid Build Coastguard Worker static Value *createArithmetic(Ice::InstArithmetic::OpKind op, Value *lhs, Value *rhs)
1205*03ce13f7SAndroid Build Coastguard Worker {
1206*03ce13f7SAndroid Build Coastguard Worker ASSERT(lhs->getType() == rhs->getType() || llvm::isa<Ice::Constant>(rhs));
1207*03ce13f7SAndroid Build Coastguard Worker
1208*03ce13f7SAndroid Build Coastguard Worker bool swapOperands = llvm::isa<Ice::Constant>(lhs) && isCommutative(op);
1209*03ce13f7SAndroid Build Coastguard Worker
1210*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(lhs->getType());
1211*03ce13f7SAndroid Build Coastguard Worker Ice::InstArithmetic *arithmetic = Ice::InstArithmetic::create(::function, op, result, swapOperands ? rhs : lhs, swapOperands ? lhs : rhs);
1212*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(arithmetic);
1213*03ce13f7SAndroid Build Coastguard Worker
1214*03ce13f7SAndroid Build Coastguard Worker return V(result);
1215*03ce13f7SAndroid Build Coastguard Worker }
1216*03ce13f7SAndroid Build Coastguard Worker
createAdd(Value * lhs,Value * rhs)1217*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAdd(Value *lhs, Value *rhs)
1218*03ce13f7SAndroid Build Coastguard Worker {
1219*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1220*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Add, lhs, rhs);
1221*03ce13f7SAndroid Build Coastguard Worker }
1222*03ce13f7SAndroid Build Coastguard Worker
createSub(Value * lhs,Value * rhs)1223*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSub(Value *lhs, Value *rhs)
1224*03ce13f7SAndroid Build Coastguard Worker {
1225*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1226*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Sub, lhs, rhs);
1227*03ce13f7SAndroid Build Coastguard Worker }
1228*03ce13f7SAndroid Build Coastguard Worker
createMul(Value * lhs,Value * rhs)1229*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createMul(Value *lhs, Value *rhs)
1230*03ce13f7SAndroid Build Coastguard Worker {
1231*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1232*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Mul, lhs, rhs);
1233*03ce13f7SAndroid Build Coastguard Worker }
1234*03ce13f7SAndroid Build Coastguard Worker
createUDiv(Value * lhs,Value * rhs)1235*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createUDiv(Value *lhs, Value *rhs)
1236*03ce13f7SAndroid Build Coastguard Worker {
1237*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1238*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Udiv, lhs, rhs);
1239*03ce13f7SAndroid Build Coastguard Worker }
1240*03ce13f7SAndroid Build Coastguard Worker
createSDiv(Value * lhs,Value * rhs)1241*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSDiv(Value *lhs, Value *rhs)
1242*03ce13f7SAndroid Build Coastguard Worker {
1243*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1244*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Sdiv, lhs, rhs);
1245*03ce13f7SAndroid Build Coastguard Worker }
1246*03ce13f7SAndroid Build Coastguard Worker
createFAdd(Value * lhs,Value * rhs)1247*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFAdd(Value *lhs, Value *rhs)
1248*03ce13f7SAndroid Build Coastguard Worker {
1249*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1250*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Fadd, lhs, rhs);
1251*03ce13f7SAndroid Build Coastguard Worker }
1252*03ce13f7SAndroid Build Coastguard Worker
createFSub(Value * lhs,Value * rhs)1253*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFSub(Value *lhs, Value *rhs)
1254*03ce13f7SAndroid Build Coastguard Worker {
1255*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1256*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Fsub, lhs, rhs);
1257*03ce13f7SAndroid Build Coastguard Worker }
1258*03ce13f7SAndroid Build Coastguard Worker
createFMul(Value * lhs,Value * rhs)1259*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFMul(Value *lhs, Value *rhs)
1260*03ce13f7SAndroid Build Coastguard Worker {
1261*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1262*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Fmul, lhs, rhs);
1263*03ce13f7SAndroid Build Coastguard Worker }
1264*03ce13f7SAndroid Build Coastguard Worker
createFDiv(Value * lhs,Value * rhs)1265*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFDiv(Value *lhs, Value *rhs)
1266*03ce13f7SAndroid Build Coastguard Worker {
1267*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1268*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Fdiv, lhs, rhs);
1269*03ce13f7SAndroid Build Coastguard Worker }
1270*03ce13f7SAndroid Build Coastguard Worker
createURem(Value * lhs,Value * rhs)1271*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createURem(Value *lhs, Value *rhs)
1272*03ce13f7SAndroid Build Coastguard Worker {
1273*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1274*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Urem, lhs, rhs);
1275*03ce13f7SAndroid Build Coastguard Worker }
1276*03ce13f7SAndroid Build Coastguard Worker
createSRem(Value * lhs,Value * rhs)1277*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSRem(Value *lhs, Value *rhs)
1278*03ce13f7SAndroid Build Coastguard Worker {
1279*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1280*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Srem, lhs, rhs);
1281*03ce13f7SAndroid Build Coastguard Worker }
1282*03ce13f7SAndroid Build Coastguard Worker
createFRem(Value * lhs,Value * rhs)1283*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFRem(Value *lhs, Value *rhs)
1284*03ce13f7SAndroid Build Coastguard Worker {
1285*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1286*03ce13f7SAndroid Build Coastguard Worker // TODO(b/148139679) Fix Subzero generating invalid code for FRem on vector types
1287*03ce13f7SAndroid Build Coastguard Worker // createArithmetic(Ice::InstArithmetic::Frem, lhs, rhs);
1288*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED("b/148139679 Nucleus::createFRem");
1289*03ce13f7SAndroid Build Coastguard Worker return nullptr;
1290*03ce13f7SAndroid Build Coastguard Worker }
1291*03ce13f7SAndroid Build Coastguard Worker
createShl(Value * lhs,Value * rhs)1292*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createShl(Value *lhs, Value *rhs)
1293*03ce13f7SAndroid Build Coastguard Worker {
1294*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1295*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Shl, lhs, rhs);
1296*03ce13f7SAndroid Build Coastguard Worker }
1297*03ce13f7SAndroid Build Coastguard Worker
createLShr(Value * lhs,Value * rhs)1298*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createLShr(Value *lhs, Value *rhs)
1299*03ce13f7SAndroid Build Coastguard Worker {
1300*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1301*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Lshr, lhs, rhs);
1302*03ce13f7SAndroid Build Coastguard Worker }
1303*03ce13f7SAndroid Build Coastguard Worker
createAShr(Value * lhs,Value * rhs)1304*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAShr(Value *lhs, Value *rhs)
1305*03ce13f7SAndroid Build Coastguard Worker {
1306*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1307*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Ashr, lhs, rhs);
1308*03ce13f7SAndroid Build Coastguard Worker }
1309*03ce13f7SAndroid Build Coastguard Worker
createAnd(Value * lhs,Value * rhs)1310*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAnd(Value *lhs, Value *rhs)
1311*03ce13f7SAndroid Build Coastguard Worker {
1312*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1313*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::And, lhs, rhs);
1314*03ce13f7SAndroid Build Coastguard Worker }
1315*03ce13f7SAndroid Build Coastguard Worker
createOr(Value * lhs,Value * rhs)1316*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createOr(Value *lhs, Value *rhs)
1317*03ce13f7SAndroid Build Coastguard Worker {
1318*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1319*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Or, lhs, rhs);
1320*03ce13f7SAndroid Build Coastguard Worker }
1321*03ce13f7SAndroid Build Coastguard Worker
createXor(Value * lhs,Value * rhs)1322*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createXor(Value *lhs, Value *rhs)
1323*03ce13f7SAndroid Build Coastguard Worker {
1324*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1325*03ce13f7SAndroid Build Coastguard Worker return createArithmetic(Ice::InstArithmetic::Xor, lhs, rhs);
1326*03ce13f7SAndroid Build Coastguard Worker }
1327*03ce13f7SAndroid Build Coastguard Worker
createNeg(Value * v)1328*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createNeg(Value *v)
1329*03ce13f7SAndroid Build Coastguard Worker {
1330*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1331*03ce13f7SAndroid Build Coastguard Worker return createSub(createNullValue(T(v->getType())), v);
1332*03ce13f7SAndroid Build Coastguard Worker }
1333*03ce13f7SAndroid Build Coastguard Worker
createFNeg(Value * v)1334*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFNeg(Value *v)
1335*03ce13f7SAndroid Build Coastguard Worker {
1336*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1337*03ce13f7SAndroid Build Coastguard Worker std::vector<double> c = { -0.0 };
1338*03ce13f7SAndroid Build Coastguard Worker Value *negativeZero = Ice::isVectorType(v->getType()) ? createConstantVector(c, T(v->getType())) : V(::context->getConstantFloat(-0.0f));
1339*03ce13f7SAndroid Build Coastguard Worker
1340*03ce13f7SAndroid Build Coastguard Worker return createFSub(negativeZero, v);
1341*03ce13f7SAndroid Build Coastguard Worker }
1342*03ce13f7SAndroid Build Coastguard Worker
createNot(Value * v)1343*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createNot(Value *v)
1344*03ce13f7SAndroid Build Coastguard Worker {
1345*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1346*03ce13f7SAndroid Build Coastguard Worker if(Ice::isScalarIntegerType(v->getType()))
1347*03ce13f7SAndroid Build Coastguard Worker {
1348*03ce13f7SAndroid Build Coastguard Worker return createXor(v, V(::context->getConstantInt(v->getType(), -1)));
1349*03ce13f7SAndroid Build Coastguard Worker }
1350*03ce13f7SAndroid Build Coastguard Worker else // Vector
1351*03ce13f7SAndroid Build Coastguard Worker {
1352*03ce13f7SAndroid Build Coastguard Worker std::vector<int64_t> c = { -1 };
1353*03ce13f7SAndroid Build Coastguard Worker return createXor(v, createConstantVector(c, T(v->getType())));
1354*03ce13f7SAndroid Build Coastguard Worker }
1355*03ce13f7SAndroid Build Coastguard Worker }
1356*03ce13f7SAndroid Build Coastguard Worker
validateAtomicAndMemoryOrderArgs(bool atomic,std::memory_order memoryOrder)1357*03ce13f7SAndroid Build Coastguard Worker static void validateAtomicAndMemoryOrderArgs(bool atomic, std::memory_order memoryOrder)
1358*03ce13f7SAndroid Build Coastguard Worker {
1359*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1360*03ce13f7SAndroid Build Coastguard Worker // We're good, atomics and strictest memory order (except seq_cst) are guaranteed.
1361*03ce13f7SAndroid Build Coastguard Worker // Note that sequential memory ordering could be guaranteed by using x86's LOCK prefix.
1362*03ce13f7SAndroid Build Coastguard Worker // Note also that relaxed memory order could be implemented using MOVNTPS and friends.
1363*03ce13f7SAndroid Build Coastguard Worker #else
1364*03ce13f7SAndroid Build Coastguard Worker if(atomic)
1365*03ce13f7SAndroid Build Coastguard Worker {
1366*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED("b/150475088 Atomic load/store not implemented for current platform");
1367*03ce13f7SAndroid Build Coastguard Worker }
1368*03ce13f7SAndroid Build Coastguard Worker if(memoryOrder != std::memory_order_relaxed)
1369*03ce13f7SAndroid Build Coastguard Worker {
1370*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED("b/150475088 Memory order other than memory_order_relaxed not implemented for current platform");
1371*03ce13f7SAndroid Build Coastguard Worker }
1372*03ce13f7SAndroid Build Coastguard Worker #endif
1373*03ce13f7SAndroid Build Coastguard Worker
1374*03ce13f7SAndroid Build Coastguard Worker // Vulkan doesn't allow sequential memory order
1375*03ce13f7SAndroid Build Coastguard Worker ASSERT(memoryOrder != std::memory_order_seq_cst);
1376*03ce13f7SAndroid Build Coastguard Worker }
1377*03ce13f7SAndroid Build Coastguard Worker
createLoad(Value * ptr,Type * type,bool isVolatile,unsigned int align,bool atomic,std::memory_order memoryOrder)1378*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createLoad(Value *ptr, Type *type, bool isVolatile, unsigned int align, bool atomic, std::memory_order memoryOrder)
1379*03ce13f7SAndroid Build Coastguard Worker {
1380*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1381*03ce13f7SAndroid Build Coastguard Worker validateAtomicAndMemoryOrderArgs(atomic, memoryOrder);
1382*03ce13f7SAndroid Build Coastguard Worker
1383*03ce13f7SAndroid Build Coastguard Worker int valueType = (int)reinterpret_cast<intptr_t>(type);
1384*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = nullptr;
1385*03ce13f7SAndroid Build Coastguard Worker
1386*03ce13f7SAndroid Build Coastguard Worker if((valueType & EmulatedBits) && (align != 0)) // Narrow vector not stored on stack.
1387*03ce13f7SAndroid Build Coastguard Worker {
1388*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
1389*03ce13f7SAndroid Build Coastguard Worker {
1390*03ce13f7SAndroid Build Coastguard Worker if(typeSize(type) == 4)
1391*03ce13f7SAndroid Build Coastguard Worker {
1392*03ce13f7SAndroid Build Coastguard Worker auto pointer = RValue<Pointer<Byte>>(ptr);
1393*03ce13f7SAndroid Build Coastguard Worker Int x = *Pointer<Int>(pointer);
1394*03ce13f7SAndroid Build Coastguard Worker
1395*03ce13f7SAndroid Build Coastguard Worker Int4 vector;
1396*03ce13f7SAndroid Build Coastguard Worker vector = Insert(vector, x, 0);
1397*03ce13f7SAndroid Build Coastguard Worker
1398*03ce13f7SAndroid Build Coastguard Worker result = ::function->makeVariable(T(type));
1399*03ce13f7SAndroid Build Coastguard Worker auto bitcast = Ice::InstCast::create(::function, Ice::InstCast::Bitcast, result, vector.loadValue());
1400*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(bitcast);
1401*03ce13f7SAndroid Build Coastguard Worker }
1402*03ce13f7SAndroid Build Coastguard Worker else if(typeSize(type) == 8)
1403*03ce13f7SAndroid Build Coastguard Worker {
1404*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(!atomic, "Emulated 64-bit loads are not atomic");
1405*03ce13f7SAndroid Build Coastguard Worker auto pointer = RValue<Pointer<Byte>>(ptr);
1406*03ce13f7SAndroid Build Coastguard Worker Int x = *Pointer<Int>(pointer);
1407*03ce13f7SAndroid Build Coastguard Worker Int y = *Pointer<Int>(pointer + 4);
1408*03ce13f7SAndroid Build Coastguard Worker
1409*03ce13f7SAndroid Build Coastguard Worker Int4 vector;
1410*03ce13f7SAndroid Build Coastguard Worker vector = Insert(vector, x, 0);
1411*03ce13f7SAndroid Build Coastguard Worker vector = Insert(vector, y, 1);
1412*03ce13f7SAndroid Build Coastguard Worker
1413*03ce13f7SAndroid Build Coastguard Worker result = ::function->makeVariable(T(type));
1414*03ce13f7SAndroid Build Coastguard Worker auto bitcast = Ice::InstCast::create(::function, Ice::InstCast::Bitcast, result, vector.loadValue());
1415*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(bitcast);
1416*03ce13f7SAndroid Build Coastguard Worker }
1417*03ce13f7SAndroid Build Coastguard Worker else
1418*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("typeSize(type): %d", int(typeSize(type)));
1419*03ce13f7SAndroid Build Coastguard Worker }
1420*03ce13f7SAndroid Build Coastguard Worker else
1421*03ce13f7SAndroid Build Coastguard Worker {
1422*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::LoadSubVector, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
1423*03ce13f7SAndroid Build Coastguard Worker result = ::function->makeVariable(T(type));
1424*03ce13f7SAndroid Build Coastguard Worker auto load = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
1425*03ce13f7SAndroid Build Coastguard Worker load->addArg(ptr);
1426*03ce13f7SAndroid Build Coastguard Worker load->addArg(::context->getConstantInt32(typeSize(type)));
1427*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(load);
1428*03ce13f7SAndroid Build Coastguard Worker }
1429*03ce13f7SAndroid Build Coastguard Worker }
1430*03ce13f7SAndroid Build Coastguard Worker else
1431*03ce13f7SAndroid Build Coastguard Worker {
1432*03ce13f7SAndroid Build Coastguard Worker result = sz::createLoad(::function, ::basicBlock, V(ptr), T(type), align);
1433*03ce13f7SAndroid Build Coastguard Worker }
1434*03ce13f7SAndroid Build Coastguard Worker
1435*03ce13f7SAndroid Build Coastguard Worker ASSERT(result);
1436*03ce13f7SAndroid Build Coastguard Worker return V(result);
1437*03ce13f7SAndroid Build Coastguard Worker }
1438*03ce13f7SAndroid Build Coastguard Worker
createStore(Value * value,Value * ptr,Type * type,bool isVolatile,unsigned int align,bool atomic,std::memory_order memoryOrder)1439*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatile, unsigned int align, bool atomic, std::memory_order memoryOrder)
1440*03ce13f7SAndroid Build Coastguard Worker {
1441*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1442*03ce13f7SAndroid Build Coastguard Worker validateAtomicAndMemoryOrderArgs(atomic, memoryOrder);
1443*03ce13f7SAndroid Build Coastguard Worker
1444*03ce13f7SAndroid Build Coastguard Worker #if __has_feature(memory_sanitizer)
1445*03ce13f7SAndroid Build Coastguard Worker // Mark all (non-stack) memory writes as initialized by calling __msan_unpoison
1446*03ce13f7SAndroid Build Coastguard Worker if(align != 0)
1447*03ce13f7SAndroid Build Coastguard Worker {
1448*03ce13f7SAndroid Build Coastguard Worker auto call = Ice::InstCall::create(::function, 2, nullptr, ::context->getConstantInt64(reinterpret_cast<intptr_t>(__msan_unpoison)), false);
1449*03ce13f7SAndroid Build Coastguard Worker call->addArg(ptr);
1450*03ce13f7SAndroid Build Coastguard Worker call->addArg(::context->getConstantInt64(typeSize(type)));
1451*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(call);
1452*03ce13f7SAndroid Build Coastguard Worker }
1453*03ce13f7SAndroid Build Coastguard Worker #endif
1454*03ce13f7SAndroid Build Coastguard Worker
1455*03ce13f7SAndroid Build Coastguard Worker int valueType = (int)reinterpret_cast<intptr_t>(type);
1456*03ce13f7SAndroid Build Coastguard Worker
1457*03ce13f7SAndroid Build Coastguard Worker if((valueType & EmulatedBits) && (align != 0)) // Narrow vector not stored on stack.
1458*03ce13f7SAndroid Build Coastguard Worker {
1459*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
1460*03ce13f7SAndroid Build Coastguard Worker {
1461*03ce13f7SAndroid Build Coastguard Worker if(typeSize(type) == 4)
1462*03ce13f7SAndroid Build Coastguard Worker {
1463*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *vector = ::function->makeVariable(Ice::IceType_v4i32);
1464*03ce13f7SAndroid Build Coastguard Worker auto bitcast = Ice::InstCast::create(::function, Ice::InstCast::Bitcast, vector, value);
1465*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(bitcast);
1466*03ce13f7SAndroid Build Coastguard Worker
1467*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> v(V(vector));
1468*03ce13f7SAndroid Build Coastguard Worker
1469*03ce13f7SAndroid Build Coastguard Worker auto pointer = RValue<Pointer<Byte>>(ptr);
1470*03ce13f7SAndroid Build Coastguard Worker Int x = Extract(v, 0);
1471*03ce13f7SAndroid Build Coastguard Worker *Pointer<Int>(pointer) = x;
1472*03ce13f7SAndroid Build Coastguard Worker }
1473*03ce13f7SAndroid Build Coastguard Worker else if(typeSize(type) == 8)
1474*03ce13f7SAndroid Build Coastguard Worker {
1475*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(!atomic, "Emulated 64-bit stores are not atomic");
1476*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *vector = ::function->makeVariable(Ice::IceType_v4i32);
1477*03ce13f7SAndroid Build Coastguard Worker auto bitcast = Ice::InstCast::create(::function, Ice::InstCast::Bitcast, vector, value);
1478*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(bitcast);
1479*03ce13f7SAndroid Build Coastguard Worker
1480*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> v(V(vector));
1481*03ce13f7SAndroid Build Coastguard Worker
1482*03ce13f7SAndroid Build Coastguard Worker auto pointer = RValue<Pointer<Byte>>(ptr);
1483*03ce13f7SAndroid Build Coastguard Worker Int x = Extract(v, 0);
1484*03ce13f7SAndroid Build Coastguard Worker *Pointer<Int>(pointer) = x;
1485*03ce13f7SAndroid Build Coastguard Worker Int y = Extract(v, 1);
1486*03ce13f7SAndroid Build Coastguard Worker *Pointer<Int>(pointer + 4) = y;
1487*03ce13f7SAndroid Build Coastguard Worker }
1488*03ce13f7SAndroid Build Coastguard Worker else
1489*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("typeSize(type): %d", int(typeSize(type)));
1490*03ce13f7SAndroid Build Coastguard Worker }
1491*03ce13f7SAndroid Build Coastguard Worker else
1492*03ce13f7SAndroid Build Coastguard Worker {
1493*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::StoreSubVector, Ice::Intrinsics::SideEffects_T, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_T };
1494*03ce13f7SAndroid Build Coastguard Worker auto store = Ice::InstIntrinsic::create(::function, 3, nullptr, intrinsic);
1495*03ce13f7SAndroid Build Coastguard Worker store->addArg(value);
1496*03ce13f7SAndroid Build Coastguard Worker store->addArg(ptr);
1497*03ce13f7SAndroid Build Coastguard Worker store->addArg(::context->getConstantInt32(typeSize(type)));
1498*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(store);
1499*03ce13f7SAndroid Build Coastguard Worker }
1500*03ce13f7SAndroid Build Coastguard Worker }
1501*03ce13f7SAndroid Build Coastguard Worker else
1502*03ce13f7SAndroid Build Coastguard Worker {
1503*03ce13f7SAndroid Build Coastguard Worker ASSERT(value->getType() == T(type));
1504*03ce13f7SAndroid Build Coastguard Worker
1505*03ce13f7SAndroid Build Coastguard Worker auto store = Ice::InstStore::create(::function, V(value), V(ptr), align);
1506*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(store);
1507*03ce13f7SAndroid Build Coastguard Worker }
1508*03ce13f7SAndroid Build Coastguard Worker
1509*03ce13f7SAndroid Build Coastguard Worker return value;
1510*03ce13f7SAndroid Build Coastguard Worker }
1511*03ce13f7SAndroid Build Coastguard Worker
createGEP(Value * ptr,Type * type,Value * index,bool unsignedIndex)1512*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex)
1513*03ce13f7SAndroid Build Coastguard Worker {
1514*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1515*03ce13f7SAndroid Build Coastguard Worker ASSERT(index->getType() == Ice::IceType_i32);
1516*03ce13f7SAndroid Build Coastguard Worker
1517*03ce13f7SAndroid Build Coastguard Worker if(auto *constant = llvm::dyn_cast<Ice::ConstantInteger32>(index))
1518*03ce13f7SAndroid Build Coastguard Worker {
1519*03ce13f7SAndroid Build Coastguard Worker int32_t offset = constant->getValue() * (int)typeSize(type);
1520*03ce13f7SAndroid Build Coastguard Worker
1521*03ce13f7SAndroid Build Coastguard Worker if(offset == 0)
1522*03ce13f7SAndroid Build Coastguard Worker {
1523*03ce13f7SAndroid Build Coastguard Worker return ptr;
1524*03ce13f7SAndroid Build Coastguard Worker }
1525*03ce13f7SAndroid Build Coastguard Worker
1526*03ce13f7SAndroid Build Coastguard Worker return createAdd(ptr, createConstantInt(offset));
1527*03ce13f7SAndroid Build Coastguard Worker }
1528*03ce13f7SAndroid Build Coastguard Worker
1529*03ce13f7SAndroid Build Coastguard Worker if(!Ice::isByteSizedType(T(type)))
1530*03ce13f7SAndroid Build Coastguard Worker {
1531*03ce13f7SAndroid Build Coastguard Worker index = createMul(index, createConstantInt((int)typeSize(type)));
1532*03ce13f7SAndroid Build Coastguard Worker }
1533*03ce13f7SAndroid Build Coastguard Worker
1534*03ce13f7SAndroid Build Coastguard Worker if(sizeof(void *) == 8)
1535*03ce13f7SAndroid Build Coastguard Worker {
1536*03ce13f7SAndroid Build Coastguard Worker if(unsignedIndex)
1537*03ce13f7SAndroid Build Coastguard Worker {
1538*03ce13f7SAndroid Build Coastguard Worker index = createZExt(index, T(Ice::IceType_i64));
1539*03ce13f7SAndroid Build Coastguard Worker }
1540*03ce13f7SAndroid Build Coastguard Worker else
1541*03ce13f7SAndroid Build Coastguard Worker {
1542*03ce13f7SAndroid Build Coastguard Worker index = createSExt(index, T(Ice::IceType_i64));
1543*03ce13f7SAndroid Build Coastguard Worker }
1544*03ce13f7SAndroid Build Coastguard Worker }
1545*03ce13f7SAndroid Build Coastguard Worker
1546*03ce13f7SAndroid Build Coastguard Worker return createAdd(ptr, index);
1547*03ce13f7SAndroid Build Coastguard Worker }
1548*03ce13f7SAndroid Build Coastguard Worker
createAtomicRMW(Ice::Intrinsics::AtomicRMWOperation rmwOp,Value * ptr,Value * value,std::memory_order memoryOrder)1549*03ce13f7SAndroid Build Coastguard Worker static Value *createAtomicRMW(Ice::Intrinsics::AtomicRMWOperation rmwOp, Value *ptr, Value *value, std::memory_order memoryOrder)
1550*03ce13f7SAndroid Build Coastguard Worker {
1551*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(value->getType());
1552*03ce13f7SAndroid Build Coastguard Worker
1553*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::AtomicRMW, Ice::Intrinsics::SideEffects_T, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_T };
1554*03ce13f7SAndroid Build Coastguard Worker auto inst = Ice::InstIntrinsic::create(::function, 0, result, intrinsic);
1555*03ce13f7SAndroid Build Coastguard Worker auto op = ::context->getConstantInt32(rmwOp);
1556*03ce13f7SAndroid Build Coastguard Worker auto order = ::context->getConstantInt32(stdToIceMemoryOrder(memoryOrder));
1557*03ce13f7SAndroid Build Coastguard Worker inst->addArg(op);
1558*03ce13f7SAndroid Build Coastguard Worker inst->addArg(ptr);
1559*03ce13f7SAndroid Build Coastguard Worker inst->addArg(value);
1560*03ce13f7SAndroid Build Coastguard Worker inst->addArg(order);
1561*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(inst);
1562*03ce13f7SAndroid Build Coastguard Worker
1563*03ce13f7SAndroid Build Coastguard Worker return V(result);
1564*03ce13f7SAndroid Build Coastguard Worker }
1565*03ce13f7SAndroid Build Coastguard Worker
createAtomicAdd(Value * ptr,Value * value,std::memory_order memoryOrder)1566*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicAdd(Value *ptr, Value *value, std::memory_order memoryOrder)
1567*03ce13f7SAndroid Build Coastguard Worker {
1568*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1569*03ce13f7SAndroid Build Coastguard Worker return createAtomicRMW(Ice::Intrinsics::AtomicAdd, ptr, value, memoryOrder);
1570*03ce13f7SAndroid Build Coastguard Worker }
1571*03ce13f7SAndroid Build Coastguard Worker
createAtomicSub(Value * ptr,Value * value,std::memory_order memoryOrder)1572*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicSub(Value *ptr, Value *value, std::memory_order memoryOrder)
1573*03ce13f7SAndroid Build Coastguard Worker {
1574*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1575*03ce13f7SAndroid Build Coastguard Worker return createAtomicRMW(Ice::Intrinsics::AtomicSub, ptr, value, memoryOrder);
1576*03ce13f7SAndroid Build Coastguard Worker }
1577*03ce13f7SAndroid Build Coastguard Worker
createAtomicAnd(Value * ptr,Value * value,std::memory_order memoryOrder)1578*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicAnd(Value *ptr, Value *value, std::memory_order memoryOrder)
1579*03ce13f7SAndroid Build Coastguard Worker {
1580*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1581*03ce13f7SAndroid Build Coastguard Worker return createAtomicRMW(Ice::Intrinsics::AtomicAnd, ptr, value, memoryOrder);
1582*03ce13f7SAndroid Build Coastguard Worker }
1583*03ce13f7SAndroid Build Coastguard Worker
createAtomicOr(Value * ptr,Value * value,std::memory_order memoryOrder)1584*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicOr(Value *ptr, Value *value, std::memory_order memoryOrder)
1585*03ce13f7SAndroid Build Coastguard Worker {
1586*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1587*03ce13f7SAndroid Build Coastguard Worker return createAtomicRMW(Ice::Intrinsics::AtomicOr, ptr, value, memoryOrder);
1588*03ce13f7SAndroid Build Coastguard Worker }
1589*03ce13f7SAndroid Build Coastguard Worker
createAtomicXor(Value * ptr,Value * value,std::memory_order memoryOrder)1590*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicXor(Value *ptr, Value *value, std::memory_order memoryOrder)
1591*03ce13f7SAndroid Build Coastguard Worker {
1592*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1593*03ce13f7SAndroid Build Coastguard Worker return createAtomicRMW(Ice::Intrinsics::AtomicXor, ptr, value, memoryOrder);
1594*03ce13f7SAndroid Build Coastguard Worker }
1595*03ce13f7SAndroid Build Coastguard Worker
createAtomicExchange(Value * ptr,Value * value,std::memory_order memoryOrder)1596*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicExchange(Value *ptr, Value *value, std::memory_order memoryOrder)
1597*03ce13f7SAndroid Build Coastguard Worker {
1598*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1599*03ce13f7SAndroid Build Coastguard Worker return createAtomicRMW(Ice::Intrinsics::AtomicExchange, ptr, value, memoryOrder);
1600*03ce13f7SAndroid Build Coastguard Worker }
1601*03ce13f7SAndroid Build Coastguard Worker
createAtomicCompareExchange(Value * ptr,Value * value,Value * compare,std::memory_order memoryOrderEqual,std::memory_order memoryOrderUnequal)1602*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicCompareExchange(Value *ptr, Value *value, Value *compare, std::memory_order memoryOrderEqual, std::memory_order memoryOrderUnequal)
1603*03ce13f7SAndroid Build Coastguard Worker {
1604*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1605*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(value->getType());
1606*03ce13f7SAndroid Build Coastguard Worker
1607*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::AtomicCmpxchg, Ice::Intrinsics::SideEffects_T, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_T };
1608*03ce13f7SAndroid Build Coastguard Worker auto inst = Ice::InstIntrinsic::create(::function, 0, result, intrinsic);
1609*03ce13f7SAndroid Build Coastguard Worker auto orderEq = ::context->getConstantInt32(stdToIceMemoryOrder(memoryOrderEqual));
1610*03ce13f7SAndroid Build Coastguard Worker auto orderNeq = ::context->getConstantInt32(stdToIceMemoryOrder(memoryOrderUnequal));
1611*03ce13f7SAndroid Build Coastguard Worker inst->addArg(ptr);
1612*03ce13f7SAndroid Build Coastguard Worker inst->addArg(compare);
1613*03ce13f7SAndroid Build Coastguard Worker inst->addArg(value);
1614*03ce13f7SAndroid Build Coastguard Worker inst->addArg(orderEq);
1615*03ce13f7SAndroid Build Coastguard Worker inst->addArg(orderNeq);
1616*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(inst);
1617*03ce13f7SAndroid Build Coastguard Worker
1618*03ce13f7SAndroid Build Coastguard Worker return V(result);
1619*03ce13f7SAndroid Build Coastguard Worker }
1620*03ce13f7SAndroid Build Coastguard Worker
createCast(Ice::InstCast::OpKind op,Value * v,Type * destType)1621*03ce13f7SAndroid Build Coastguard Worker static Value *createCast(Ice::InstCast::OpKind op, Value *v, Type *destType)
1622*03ce13f7SAndroid Build Coastguard Worker {
1623*03ce13f7SAndroid Build Coastguard Worker if(v->getType() == T(destType))
1624*03ce13f7SAndroid Build Coastguard Worker {
1625*03ce13f7SAndroid Build Coastguard Worker return v;
1626*03ce13f7SAndroid Build Coastguard Worker }
1627*03ce13f7SAndroid Build Coastguard Worker
1628*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(T(destType));
1629*03ce13f7SAndroid Build Coastguard Worker Ice::InstCast *cast = Ice::InstCast::create(::function, op, result, v);
1630*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cast);
1631*03ce13f7SAndroid Build Coastguard Worker
1632*03ce13f7SAndroid Build Coastguard Worker return V(result);
1633*03ce13f7SAndroid Build Coastguard Worker }
1634*03ce13f7SAndroid Build Coastguard Worker
createTrunc(Value * v,Type * destType)1635*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createTrunc(Value *v, Type *destType)
1636*03ce13f7SAndroid Build Coastguard Worker {
1637*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1638*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Trunc, v, destType);
1639*03ce13f7SAndroid Build Coastguard Worker }
1640*03ce13f7SAndroid Build Coastguard Worker
createZExt(Value * v,Type * destType)1641*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createZExt(Value *v, Type *destType)
1642*03ce13f7SAndroid Build Coastguard Worker {
1643*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1644*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Zext, v, destType);
1645*03ce13f7SAndroid Build Coastguard Worker }
1646*03ce13f7SAndroid Build Coastguard Worker
createSExt(Value * v,Type * destType)1647*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSExt(Value *v, Type *destType)
1648*03ce13f7SAndroid Build Coastguard Worker {
1649*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1650*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Sext, v, destType);
1651*03ce13f7SAndroid Build Coastguard Worker }
1652*03ce13f7SAndroid Build Coastguard Worker
createFPToUI(Value * v,Type * destType)1653*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFPToUI(Value *v, Type *destType)
1654*03ce13f7SAndroid Build Coastguard Worker {
1655*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1656*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Fptoui, v, destType);
1657*03ce13f7SAndroid Build Coastguard Worker }
1658*03ce13f7SAndroid Build Coastguard Worker
createFPToSI(Value * v,Type * destType)1659*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFPToSI(Value *v, Type *destType)
1660*03ce13f7SAndroid Build Coastguard Worker {
1661*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1662*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Fptosi, v, destType);
1663*03ce13f7SAndroid Build Coastguard Worker }
1664*03ce13f7SAndroid Build Coastguard Worker
createSIToFP(Value * v,Type * destType)1665*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSIToFP(Value *v, Type *destType)
1666*03ce13f7SAndroid Build Coastguard Worker {
1667*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1668*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Sitofp, v, destType);
1669*03ce13f7SAndroid Build Coastguard Worker }
1670*03ce13f7SAndroid Build Coastguard Worker
createFPTrunc(Value * v,Type * destType)1671*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFPTrunc(Value *v, Type *destType)
1672*03ce13f7SAndroid Build Coastguard Worker {
1673*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1674*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Fptrunc, v, destType);
1675*03ce13f7SAndroid Build Coastguard Worker }
1676*03ce13f7SAndroid Build Coastguard Worker
createFPExt(Value * v,Type * destType)1677*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFPExt(Value *v, Type *destType)
1678*03ce13f7SAndroid Build Coastguard Worker {
1679*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1680*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Fpext, v, destType);
1681*03ce13f7SAndroid Build Coastguard Worker }
1682*03ce13f7SAndroid Build Coastguard Worker
createBitCast(Value * v,Type * destType)1683*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createBitCast(Value *v, Type *destType)
1684*03ce13f7SAndroid Build Coastguard Worker {
1685*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1686*03ce13f7SAndroid Build Coastguard Worker // Bitcasts must be between types of the same logical size. But with emulated narrow vectors we need
1687*03ce13f7SAndroid Build Coastguard Worker // support for casting between scalars and wide vectors. For platforms where this is not supported,
1688*03ce13f7SAndroid Build Coastguard Worker // emulate them by writing to the stack and reading back as the destination type.
1689*03ce13f7SAndroid Build Coastguard Worker if(emulateMismatchedBitCast || (v->getType() == Ice::Type::IceType_i64))
1690*03ce13f7SAndroid Build Coastguard Worker {
1691*03ce13f7SAndroid Build Coastguard Worker if(!Ice::isVectorType(v->getType()) && Ice::isVectorType(T(destType)))
1692*03ce13f7SAndroid Build Coastguard Worker {
1693*03ce13f7SAndroid Build Coastguard Worker Value *address = allocateStackVariable(destType);
1694*03ce13f7SAndroid Build Coastguard Worker createStore(v, address, T(v->getType()));
1695*03ce13f7SAndroid Build Coastguard Worker return createLoad(address, destType);
1696*03ce13f7SAndroid Build Coastguard Worker }
1697*03ce13f7SAndroid Build Coastguard Worker else if(Ice::isVectorType(v->getType()) && !Ice::isVectorType(T(destType)))
1698*03ce13f7SAndroid Build Coastguard Worker {
1699*03ce13f7SAndroid Build Coastguard Worker Value *address = allocateStackVariable(T(v->getType()));
1700*03ce13f7SAndroid Build Coastguard Worker createStore(v, address, T(v->getType()));
1701*03ce13f7SAndroid Build Coastguard Worker return createLoad(address, destType);
1702*03ce13f7SAndroid Build Coastguard Worker }
1703*03ce13f7SAndroid Build Coastguard Worker }
1704*03ce13f7SAndroid Build Coastguard Worker
1705*03ce13f7SAndroid Build Coastguard Worker return createCast(Ice::InstCast::Bitcast, v, destType);
1706*03ce13f7SAndroid Build Coastguard Worker }
1707*03ce13f7SAndroid Build Coastguard Worker
createIntCompare(Ice::InstIcmp::ICond condition,Value * lhs,Value * rhs)1708*03ce13f7SAndroid Build Coastguard Worker static Value *createIntCompare(Ice::InstIcmp::ICond condition, Value *lhs, Value *rhs)
1709*03ce13f7SAndroid Build Coastguard Worker {
1710*03ce13f7SAndroid Build Coastguard Worker ASSERT(lhs->getType() == rhs->getType());
1711*03ce13f7SAndroid Build Coastguard Worker
1712*03ce13f7SAndroid Build Coastguard Worker auto result = ::function->makeVariable(Ice::isScalarIntegerType(lhs->getType()) ? Ice::IceType_i1 : lhs->getType());
1713*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, condition, result, lhs, rhs);
1714*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
1715*03ce13f7SAndroid Build Coastguard Worker
1716*03ce13f7SAndroid Build Coastguard Worker return V(result);
1717*03ce13f7SAndroid Build Coastguard Worker }
1718*03ce13f7SAndroid Build Coastguard Worker
createICmpEQ(Value * lhs,Value * rhs)1719*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpEQ(Value *lhs, Value *rhs)
1720*03ce13f7SAndroid Build Coastguard Worker {
1721*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1722*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Eq, lhs, rhs);
1723*03ce13f7SAndroid Build Coastguard Worker }
1724*03ce13f7SAndroid Build Coastguard Worker
createICmpNE(Value * lhs,Value * rhs)1725*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpNE(Value *lhs, Value *rhs)
1726*03ce13f7SAndroid Build Coastguard Worker {
1727*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1728*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Ne, lhs, rhs);
1729*03ce13f7SAndroid Build Coastguard Worker }
1730*03ce13f7SAndroid Build Coastguard Worker
createICmpUGT(Value * lhs,Value * rhs)1731*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpUGT(Value *lhs, Value *rhs)
1732*03ce13f7SAndroid Build Coastguard Worker {
1733*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1734*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Ugt, lhs, rhs);
1735*03ce13f7SAndroid Build Coastguard Worker }
1736*03ce13f7SAndroid Build Coastguard Worker
createICmpUGE(Value * lhs,Value * rhs)1737*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpUGE(Value *lhs, Value *rhs)
1738*03ce13f7SAndroid Build Coastguard Worker {
1739*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1740*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Uge, lhs, rhs);
1741*03ce13f7SAndroid Build Coastguard Worker }
1742*03ce13f7SAndroid Build Coastguard Worker
createICmpULT(Value * lhs,Value * rhs)1743*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpULT(Value *lhs, Value *rhs)
1744*03ce13f7SAndroid Build Coastguard Worker {
1745*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1746*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Ult, lhs, rhs);
1747*03ce13f7SAndroid Build Coastguard Worker }
1748*03ce13f7SAndroid Build Coastguard Worker
createICmpULE(Value * lhs,Value * rhs)1749*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpULE(Value *lhs, Value *rhs)
1750*03ce13f7SAndroid Build Coastguard Worker {
1751*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1752*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Ule, lhs, rhs);
1753*03ce13f7SAndroid Build Coastguard Worker }
1754*03ce13f7SAndroid Build Coastguard Worker
createICmpSGT(Value * lhs,Value * rhs)1755*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpSGT(Value *lhs, Value *rhs)
1756*03ce13f7SAndroid Build Coastguard Worker {
1757*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1758*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Sgt, lhs, rhs);
1759*03ce13f7SAndroid Build Coastguard Worker }
1760*03ce13f7SAndroid Build Coastguard Worker
createICmpSGE(Value * lhs,Value * rhs)1761*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpSGE(Value *lhs, Value *rhs)
1762*03ce13f7SAndroid Build Coastguard Worker {
1763*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1764*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Sge, lhs, rhs);
1765*03ce13f7SAndroid Build Coastguard Worker }
1766*03ce13f7SAndroid Build Coastguard Worker
createICmpSLT(Value * lhs,Value * rhs)1767*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpSLT(Value *lhs, Value *rhs)
1768*03ce13f7SAndroid Build Coastguard Worker {
1769*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1770*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Slt, lhs, rhs);
1771*03ce13f7SAndroid Build Coastguard Worker }
1772*03ce13f7SAndroid Build Coastguard Worker
createICmpSLE(Value * lhs,Value * rhs)1773*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpSLE(Value *lhs, Value *rhs)
1774*03ce13f7SAndroid Build Coastguard Worker {
1775*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1776*03ce13f7SAndroid Build Coastguard Worker return createIntCompare(Ice::InstIcmp::Sle, lhs, rhs);
1777*03ce13f7SAndroid Build Coastguard Worker }
1778*03ce13f7SAndroid Build Coastguard Worker
createFloatCompare(Ice::InstFcmp::FCond condition,Value * lhs,Value * rhs)1779*03ce13f7SAndroid Build Coastguard Worker static Value *createFloatCompare(Ice::InstFcmp::FCond condition, Value *lhs, Value *rhs)
1780*03ce13f7SAndroid Build Coastguard Worker {
1781*03ce13f7SAndroid Build Coastguard Worker ASSERT(lhs->getType() == rhs->getType());
1782*03ce13f7SAndroid Build Coastguard Worker ASSERT(Ice::isScalarFloatingType(lhs->getType()) || lhs->getType() == Ice::IceType_v4f32);
1783*03ce13f7SAndroid Build Coastguard Worker
1784*03ce13f7SAndroid Build Coastguard Worker auto result = ::function->makeVariable(Ice::isScalarFloatingType(lhs->getType()) ? Ice::IceType_i1 : Ice::IceType_v4i32);
1785*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstFcmp::create(::function, condition, result, lhs, rhs);
1786*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
1787*03ce13f7SAndroid Build Coastguard Worker
1788*03ce13f7SAndroid Build Coastguard Worker return V(result);
1789*03ce13f7SAndroid Build Coastguard Worker }
1790*03ce13f7SAndroid Build Coastguard Worker
createFCmpOEQ(Value * lhs,Value * rhs)1791*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOEQ(Value *lhs, Value *rhs)
1792*03ce13f7SAndroid Build Coastguard Worker {
1793*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1794*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Oeq, lhs, rhs);
1795*03ce13f7SAndroid Build Coastguard Worker }
1796*03ce13f7SAndroid Build Coastguard Worker
createFCmpOGT(Value * lhs,Value * rhs)1797*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOGT(Value *lhs, Value *rhs)
1798*03ce13f7SAndroid Build Coastguard Worker {
1799*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1800*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Ogt, lhs, rhs);
1801*03ce13f7SAndroid Build Coastguard Worker }
1802*03ce13f7SAndroid Build Coastguard Worker
createFCmpOGE(Value * lhs,Value * rhs)1803*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOGE(Value *lhs, Value *rhs)
1804*03ce13f7SAndroid Build Coastguard Worker {
1805*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1806*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Oge, lhs, rhs);
1807*03ce13f7SAndroid Build Coastguard Worker }
1808*03ce13f7SAndroid Build Coastguard Worker
createFCmpOLT(Value * lhs,Value * rhs)1809*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOLT(Value *lhs, Value *rhs)
1810*03ce13f7SAndroid Build Coastguard Worker {
1811*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1812*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Olt, lhs, rhs);
1813*03ce13f7SAndroid Build Coastguard Worker }
1814*03ce13f7SAndroid Build Coastguard Worker
createFCmpOLE(Value * lhs,Value * rhs)1815*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOLE(Value *lhs, Value *rhs)
1816*03ce13f7SAndroid Build Coastguard Worker {
1817*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1818*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Ole, lhs, rhs);
1819*03ce13f7SAndroid Build Coastguard Worker }
1820*03ce13f7SAndroid Build Coastguard Worker
createFCmpONE(Value * lhs,Value * rhs)1821*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpONE(Value *lhs, Value *rhs)
1822*03ce13f7SAndroid Build Coastguard Worker {
1823*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1824*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::One, lhs, rhs);
1825*03ce13f7SAndroid Build Coastguard Worker }
1826*03ce13f7SAndroid Build Coastguard Worker
createFCmpORD(Value * lhs,Value * rhs)1827*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpORD(Value *lhs, Value *rhs)
1828*03ce13f7SAndroid Build Coastguard Worker {
1829*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1830*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Ord, lhs, rhs);
1831*03ce13f7SAndroid Build Coastguard Worker }
1832*03ce13f7SAndroid Build Coastguard Worker
createFCmpUNO(Value * lhs,Value * rhs)1833*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUNO(Value *lhs, Value *rhs)
1834*03ce13f7SAndroid Build Coastguard Worker {
1835*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1836*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Uno, lhs, rhs);
1837*03ce13f7SAndroid Build Coastguard Worker }
1838*03ce13f7SAndroid Build Coastguard Worker
createFCmpUEQ(Value * lhs,Value * rhs)1839*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUEQ(Value *lhs, Value *rhs)
1840*03ce13f7SAndroid Build Coastguard Worker {
1841*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1842*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Ueq, lhs, rhs);
1843*03ce13f7SAndroid Build Coastguard Worker }
1844*03ce13f7SAndroid Build Coastguard Worker
createFCmpUGT(Value * lhs,Value * rhs)1845*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUGT(Value *lhs, Value *rhs)
1846*03ce13f7SAndroid Build Coastguard Worker {
1847*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1848*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Ugt, lhs, rhs);
1849*03ce13f7SAndroid Build Coastguard Worker }
1850*03ce13f7SAndroid Build Coastguard Worker
createFCmpUGE(Value * lhs,Value * rhs)1851*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUGE(Value *lhs, Value *rhs)
1852*03ce13f7SAndroid Build Coastguard Worker {
1853*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1854*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Uge, lhs, rhs);
1855*03ce13f7SAndroid Build Coastguard Worker }
1856*03ce13f7SAndroid Build Coastguard Worker
createFCmpULT(Value * lhs,Value * rhs)1857*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpULT(Value *lhs, Value *rhs)
1858*03ce13f7SAndroid Build Coastguard Worker {
1859*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1860*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Ult, lhs, rhs);
1861*03ce13f7SAndroid Build Coastguard Worker }
1862*03ce13f7SAndroid Build Coastguard Worker
createFCmpULE(Value * lhs,Value * rhs)1863*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpULE(Value *lhs, Value *rhs)
1864*03ce13f7SAndroid Build Coastguard Worker {
1865*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1866*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Ule, lhs, rhs);
1867*03ce13f7SAndroid Build Coastguard Worker }
1868*03ce13f7SAndroid Build Coastguard Worker
createFCmpUNE(Value * lhs,Value * rhs)1869*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUNE(Value *lhs, Value *rhs)
1870*03ce13f7SAndroid Build Coastguard Worker {
1871*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1872*03ce13f7SAndroid Build Coastguard Worker return createFloatCompare(Ice::InstFcmp::Une, lhs, rhs);
1873*03ce13f7SAndroid Build Coastguard Worker }
1874*03ce13f7SAndroid Build Coastguard Worker
createExtractElement(Value * vector,Type * type,int index)1875*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createExtractElement(Value *vector, Type *type, int index)
1876*03ce13f7SAndroid Build Coastguard Worker {
1877*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1878*03ce13f7SAndroid Build Coastguard Worker auto result = ::function->makeVariable(T(type));
1879*03ce13f7SAndroid Build Coastguard Worker auto extract = Ice::InstExtractElement::create(::function, result, V(vector), ::context->getConstantInt32(index));
1880*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(extract);
1881*03ce13f7SAndroid Build Coastguard Worker
1882*03ce13f7SAndroid Build Coastguard Worker return V(result);
1883*03ce13f7SAndroid Build Coastguard Worker }
1884*03ce13f7SAndroid Build Coastguard Worker
createInsertElement(Value * vector,Value * element,int index)1885*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createInsertElement(Value *vector, Value *element, int index)
1886*03ce13f7SAndroid Build Coastguard Worker {
1887*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1888*03ce13f7SAndroid Build Coastguard Worker auto result = ::function->makeVariable(vector->getType());
1889*03ce13f7SAndroid Build Coastguard Worker auto insert = Ice::InstInsertElement::create(::function, result, vector, element, ::context->getConstantInt32(index));
1890*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(insert);
1891*03ce13f7SAndroid Build Coastguard Worker
1892*03ce13f7SAndroid Build Coastguard Worker return V(result);
1893*03ce13f7SAndroid Build Coastguard Worker }
1894*03ce13f7SAndroid Build Coastguard Worker
createShuffleVector(Value * V1,Value * V2,std::vector<int> select)1895*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createShuffleVector(Value *V1, Value *V2, std::vector<int> select)
1896*03ce13f7SAndroid Build Coastguard Worker {
1897*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1898*03ce13f7SAndroid Build Coastguard Worker ASSERT(V1->getType() == V2->getType());
1899*03ce13f7SAndroid Build Coastguard Worker
1900*03ce13f7SAndroid Build Coastguard Worker size_t size = Ice::typeNumElements(V1->getType());
1901*03ce13f7SAndroid Build Coastguard Worker auto result = ::function->makeVariable(V1->getType());
1902*03ce13f7SAndroid Build Coastguard Worker auto shuffle = Ice::InstShuffleVector::create(::function, result, V1, V2);
1903*03ce13f7SAndroid Build Coastguard Worker
1904*03ce13f7SAndroid Build Coastguard Worker const size_t selectSize = select.size();
1905*03ce13f7SAndroid Build Coastguard Worker for(size_t i = 0; i < size; i++)
1906*03ce13f7SAndroid Build Coastguard Worker {
1907*03ce13f7SAndroid Build Coastguard Worker shuffle->addIndex(llvm::cast<Ice::ConstantInteger32>(::context->getConstantInt32(select[i % selectSize])));
1908*03ce13f7SAndroid Build Coastguard Worker }
1909*03ce13f7SAndroid Build Coastguard Worker
1910*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(shuffle);
1911*03ce13f7SAndroid Build Coastguard Worker
1912*03ce13f7SAndroid Build Coastguard Worker return V(result);
1913*03ce13f7SAndroid Build Coastguard Worker }
1914*03ce13f7SAndroid Build Coastguard Worker
createSelect(Value * C,Value * ifTrue,Value * ifFalse)1915*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSelect(Value *C, Value *ifTrue, Value *ifFalse)
1916*03ce13f7SAndroid Build Coastguard Worker {
1917*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1918*03ce13f7SAndroid Build Coastguard Worker ASSERT(ifTrue->getType() == ifFalse->getType());
1919*03ce13f7SAndroid Build Coastguard Worker
1920*03ce13f7SAndroid Build Coastguard Worker auto result = ::function->makeVariable(ifTrue->getType());
1921*03ce13f7SAndroid Build Coastguard Worker auto *select = Ice::InstSelect::create(::function, result, C, ifTrue, ifFalse);
1922*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
1923*03ce13f7SAndroid Build Coastguard Worker
1924*03ce13f7SAndroid Build Coastguard Worker return V(result);
1925*03ce13f7SAndroid Build Coastguard Worker }
1926*03ce13f7SAndroid Build Coastguard Worker
createSwitch(Value * control,BasicBlock * defaultBranch,unsigned numCases)1927*03ce13f7SAndroid Build Coastguard Worker SwitchCases *Nucleus::createSwitch(Value *control, BasicBlock *defaultBranch, unsigned numCases)
1928*03ce13f7SAndroid Build Coastguard Worker {
1929*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1930*03ce13f7SAndroid Build Coastguard Worker auto switchInst = Ice::InstSwitch::create(::function, numCases, control, defaultBranch);
1931*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(switchInst);
1932*03ce13f7SAndroid Build Coastguard Worker
1933*03ce13f7SAndroid Build Coastguard Worker return reinterpret_cast<SwitchCases *>(switchInst);
1934*03ce13f7SAndroid Build Coastguard Worker }
1935*03ce13f7SAndroid Build Coastguard Worker
addSwitchCase(SwitchCases * switchCases,int label,BasicBlock * branch)1936*03ce13f7SAndroid Build Coastguard Worker void Nucleus::addSwitchCase(SwitchCases *switchCases, int label, BasicBlock *branch)
1937*03ce13f7SAndroid Build Coastguard Worker {
1938*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1939*03ce13f7SAndroid Build Coastguard Worker switchCases->addBranch(label, label, branch);
1940*03ce13f7SAndroid Build Coastguard Worker }
1941*03ce13f7SAndroid Build Coastguard Worker
createUnreachable()1942*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createUnreachable()
1943*03ce13f7SAndroid Build Coastguard Worker {
1944*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
1945*03ce13f7SAndroid Build Coastguard Worker Ice::InstUnreachable *unreachable = Ice::InstUnreachable::create(::function);
1946*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(unreachable);
1947*03ce13f7SAndroid Build Coastguard Worker }
1948*03ce13f7SAndroid Build Coastguard Worker
getType(Value * value)1949*03ce13f7SAndroid Build Coastguard Worker Type *Nucleus::getType(Value *value)
1950*03ce13f7SAndroid Build Coastguard Worker {
1951*03ce13f7SAndroid Build Coastguard Worker return T(V(value)->getType());
1952*03ce13f7SAndroid Build Coastguard Worker }
1953*03ce13f7SAndroid Build Coastguard Worker
getContainedType(Type * vectorType)1954*03ce13f7SAndroid Build Coastguard Worker Type *Nucleus::getContainedType(Type *vectorType)
1955*03ce13f7SAndroid Build Coastguard Worker {
1956*03ce13f7SAndroid Build Coastguard Worker Ice::Type vecTy = T(vectorType);
1957*03ce13f7SAndroid Build Coastguard Worker switch(vecTy)
1958*03ce13f7SAndroid Build Coastguard Worker {
1959*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v4i1: return T(Ice::IceType_i1);
1960*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v8i1: return T(Ice::IceType_i1);
1961*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v16i1: return T(Ice::IceType_i1);
1962*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v16i8: return T(Ice::IceType_i8);
1963*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v8i16: return T(Ice::IceType_i16);
1964*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v4i32: return T(Ice::IceType_i32);
1965*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v4f32: return T(Ice::IceType_f32);
1966*03ce13f7SAndroid Build Coastguard Worker default:
1967*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(false, "getContainedType: input type is not a vector type");
1968*03ce13f7SAndroid Build Coastguard Worker return {};
1969*03ce13f7SAndroid Build Coastguard Worker }
1970*03ce13f7SAndroid Build Coastguard Worker }
1971*03ce13f7SAndroid Build Coastguard Worker
getPointerType(Type * ElementType)1972*03ce13f7SAndroid Build Coastguard Worker Type *Nucleus::getPointerType(Type *ElementType)
1973*03ce13f7SAndroid Build Coastguard Worker {
1974*03ce13f7SAndroid Build Coastguard Worker return T(sz::getPointerType(T(ElementType)));
1975*03ce13f7SAndroid Build Coastguard Worker }
1976*03ce13f7SAndroid Build Coastguard Worker
getNaturalIntType()1977*03ce13f7SAndroid Build Coastguard Worker static constexpr Ice::Type getNaturalIntType()
1978*03ce13f7SAndroid Build Coastguard Worker {
1979*03ce13f7SAndroid Build Coastguard Worker constexpr size_t intSize = sizeof(int);
1980*03ce13f7SAndroid Build Coastguard Worker static_assert(intSize == 4 || intSize == 8, "");
1981*03ce13f7SAndroid Build Coastguard Worker return intSize == 4 ? Ice::IceType_i32 : Ice::IceType_i64;
1982*03ce13f7SAndroid Build Coastguard Worker }
1983*03ce13f7SAndroid Build Coastguard Worker
getPrintfStorageType(Type * valueType)1984*03ce13f7SAndroid Build Coastguard Worker Type *Nucleus::getPrintfStorageType(Type *valueType)
1985*03ce13f7SAndroid Build Coastguard Worker {
1986*03ce13f7SAndroid Build Coastguard Worker Ice::Type valueTy = T(valueType);
1987*03ce13f7SAndroid Build Coastguard Worker switch(valueTy)
1988*03ce13f7SAndroid Build Coastguard Worker {
1989*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_i32:
1990*03ce13f7SAndroid Build Coastguard Worker return T(getNaturalIntType());
1991*03ce13f7SAndroid Build Coastguard Worker
1992*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_f32:
1993*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_f64);
1994*03ce13f7SAndroid Build Coastguard Worker
1995*03ce13f7SAndroid Build Coastguard Worker default:
1996*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("getPrintfStorageType: add more cases as needed");
1997*03ce13f7SAndroid Build Coastguard Worker return {};
1998*03ce13f7SAndroid Build Coastguard Worker }
1999*03ce13f7SAndroid Build Coastguard Worker }
2000*03ce13f7SAndroid Build Coastguard Worker
createNullValue(Type * Ty)2001*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createNullValue(Type *Ty)
2002*03ce13f7SAndroid Build Coastguard Worker {
2003*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2004*03ce13f7SAndroid Build Coastguard Worker if(Ice::isVectorType(T(Ty)))
2005*03ce13f7SAndroid Build Coastguard Worker {
2006*03ce13f7SAndroid Build Coastguard Worker ASSERT(Ice::typeNumElements(T(Ty)) <= 16);
2007*03ce13f7SAndroid Build Coastguard Worker std::vector<int64_t> c = { 0 };
2008*03ce13f7SAndroid Build Coastguard Worker return createConstantVector(c, Ty);
2009*03ce13f7SAndroid Build Coastguard Worker }
2010*03ce13f7SAndroid Build Coastguard Worker else
2011*03ce13f7SAndroid Build Coastguard Worker {
2012*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantZero(T(Ty)));
2013*03ce13f7SAndroid Build Coastguard Worker }
2014*03ce13f7SAndroid Build Coastguard Worker }
2015*03ce13f7SAndroid Build Coastguard Worker
createConstantLong(int64_t i)2016*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantLong(int64_t i)
2017*03ce13f7SAndroid Build Coastguard Worker {
2018*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2019*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantInt64(i));
2020*03ce13f7SAndroid Build Coastguard Worker }
2021*03ce13f7SAndroid Build Coastguard Worker
createConstantInt(int i)2022*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantInt(int i)
2023*03ce13f7SAndroid Build Coastguard Worker {
2024*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2025*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantInt32(i));
2026*03ce13f7SAndroid Build Coastguard Worker }
2027*03ce13f7SAndroid Build Coastguard Worker
createConstantInt(unsigned int i)2028*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantInt(unsigned int i)
2029*03ce13f7SAndroid Build Coastguard Worker {
2030*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2031*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantInt32(i));
2032*03ce13f7SAndroid Build Coastguard Worker }
2033*03ce13f7SAndroid Build Coastguard Worker
createConstantBool(bool b)2034*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantBool(bool b)
2035*03ce13f7SAndroid Build Coastguard Worker {
2036*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2037*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantInt1(b));
2038*03ce13f7SAndroid Build Coastguard Worker }
2039*03ce13f7SAndroid Build Coastguard Worker
createConstantByte(signed char i)2040*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantByte(signed char i)
2041*03ce13f7SAndroid Build Coastguard Worker {
2042*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2043*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantInt8(i));
2044*03ce13f7SAndroid Build Coastguard Worker }
2045*03ce13f7SAndroid Build Coastguard Worker
createConstantByte(unsigned char i)2046*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantByte(unsigned char i)
2047*03ce13f7SAndroid Build Coastguard Worker {
2048*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2049*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantInt8(i));
2050*03ce13f7SAndroid Build Coastguard Worker }
2051*03ce13f7SAndroid Build Coastguard Worker
createConstantShort(short i)2052*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantShort(short i)
2053*03ce13f7SAndroid Build Coastguard Worker {
2054*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2055*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantInt16(i));
2056*03ce13f7SAndroid Build Coastguard Worker }
2057*03ce13f7SAndroid Build Coastguard Worker
createConstantShort(unsigned short i)2058*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantShort(unsigned short i)
2059*03ce13f7SAndroid Build Coastguard Worker {
2060*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2061*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantInt16(i));
2062*03ce13f7SAndroid Build Coastguard Worker }
2063*03ce13f7SAndroid Build Coastguard Worker
createConstantFloat(float x)2064*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantFloat(float x)
2065*03ce13f7SAndroid Build Coastguard Worker {
2066*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2067*03ce13f7SAndroid Build Coastguard Worker return V(::context->getConstantFloat(x));
2068*03ce13f7SAndroid Build Coastguard Worker }
2069*03ce13f7SAndroid Build Coastguard Worker
createNullPointer(Type * Ty)2070*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createNullPointer(Type *Ty)
2071*03ce13f7SAndroid Build Coastguard Worker {
2072*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2073*03ce13f7SAndroid Build Coastguard Worker return createNullValue(T(sizeof(void *) == 8 ? Ice::IceType_i64 : Ice::IceType_i32));
2074*03ce13f7SAndroid Build Coastguard Worker }
2075*03ce13f7SAndroid Build Coastguard Worker
IceConstantData(const void * data,size_t size,size_t alignment=1)2076*03ce13f7SAndroid Build Coastguard Worker static Ice::Constant *IceConstantData(const void *data, size_t size, size_t alignment = 1)
2077*03ce13f7SAndroid Build Coastguard Worker {
2078*03ce13f7SAndroid Build Coastguard Worker return sz::getConstantPointer(::context, ::routine->addConstantData(data, size, alignment));
2079*03ce13f7SAndroid Build Coastguard Worker }
2080*03ce13f7SAndroid Build Coastguard Worker
createConstantVector(std::vector<int64_t> constants,Type * type)2081*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantVector(std::vector<int64_t> constants, Type *type)
2082*03ce13f7SAndroid Build Coastguard Worker {
2083*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2084*03ce13f7SAndroid Build Coastguard Worker const int vectorSize = 16;
2085*03ce13f7SAndroid Build Coastguard Worker ASSERT(Ice::typeWidthInBytes(T(type)) == vectorSize);
2086*03ce13f7SAndroid Build Coastguard Worker const int alignment = vectorSize;
2087*03ce13f7SAndroid Build Coastguard Worker
2088*03ce13f7SAndroid Build Coastguard Worker const auto &i = constants;
2089*03ce13f7SAndroid Build Coastguard Worker const size_t s = constants.size();
2090*03ce13f7SAndroid Build Coastguard Worker
2091*03ce13f7SAndroid Build Coastguard Worker // TODO(b/148082873): Fix global variable constants when generating multiple functions
2092*03ce13f7SAndroid Build Coastguard Worker Ice::Constant *ptr = nullptr;
2093*03ce13f7SAndroid Build Coastguard Worker
2094*03ce13f7SAndroid Build Coastguard Worker switch((int)reinterpret_cast<intptr_t>(type))
2095*03ce13f7SAndroid Build Coastguard Worker {
2096*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v4i32:
2097*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v4i1:
2098*03ce13f7SAndroid Build Coastguard Worker {
2099*03ce13f7SAndroid Build Coastguard Worker const int initializer[4] = { (int)i[0 % s], (int)i[1 % s], (int)i[2 % s], (int)i[3 % s] };
2100*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2101*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2102*03ce13f7SAndroid Build Coastguard Worker }
2103*03ce13f7SAndroid Build Coastguard Worker break;
2104*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v8i16:
2105*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v8i1:
2106*03ce13f7SAndroid Build Coastguard Worker {
2107*03ce13f7SAndroid Build Coastguard Worker const short initializer[8] = { (short)i[0 % s], (short)i[1 % s], (short)i[2 % s], (short)i[3 % s], (short)i[4 % s], (short)i[5 % s], (short)i[6 % s], (short)i[7 % s] };
2108*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2109*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2110*03ce13f7SAndroid Build Coastguard Worker }
2111*03ce13f7SAndroid Build Coastguard Worker break;
2112*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v16i8:
2113*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v16i1:
2114*03ce13f7SAndroid Build Coastguard Worker {
2115*03ce13f7SAndroid Build Coastguard Worker const char initializer[16] = { (char)i[0 % s], (char)i[1 % s], (char)i[2 % s], (char)i[3 % s], (char)i[4 % s], (char)i[5 % s], (char)i[6 % s], (char)i[7 % s],
2116*03ce13f7SAndroid Build Coastguard Worker (char)i[8 % s], (char)i[9 % s], (char)i[10 % s], (char)i[11 % s], (char)i[12 % s], (char)i[13 % s], (char)i[14 % s], (char)i[15 % s] };
2117*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2118*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2119*03ce13f7SAndroid Build Coastguard Worker }
2120*03ce13f7SAndroid Build Coastguard Worker break;
2121*03ce13f7SAndroid Build Coastguard Worker case Type_v2i32:
2122*03ce13f7SAndroid Build Coastguard Worker {
2123*03ce13f7SAndroid Build Coastguard Worker const int initializer[4] = { (int)i[0 % s], (int)i[1 % s], (int)i[0 % s], (int)i[1 % s] };
2124*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2125*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2126*03ce13f7SAndroid Build Coastguard Worker }
2127*03ce13f7SAndroid Build Coastguard Worker break;
2128*03ce13f7SAndroid Build Coastguard Worker case Type_v4i16:
2129*03ce13f7SAndroid Build Coastguard Worker {
2130*03ce13f7SAndroid Build Coastguard Worker const short initializer[8] = { (short)i[0 % s], (short)i[1 % s], (short)i[2 % s], (short)i[3 % s], (short)i[0 % s], (short)i[1 % s], (short)i[2 % s], (short)i[3 % s] };
2131*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2132*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2133*03ce13f7SAndroid Build Coastguard Worker }
2134*03ce13f7SAndroid Build Coastguard Worker break;
2135*03ce13f7SAndroid Build Coastguard Worker case Type_v8i8:
2136*03ce13f7SAndroid Build Coastguard Worker {
2137*03ce13f7SAndroid Build Coastguard Worker const char initializer[16] = { (char)i[0 % s], (char)i[1 % s], (char)i[2 % s], (char)i[3 % s], (char)i[4 % s], (char)i[5 % s], (char)i[6 % s], (char)i[7 % s], (char)i[0 % s], (char)i[1 % s], (char)i[2 % s], (char)i[3 % s], (char)i[4 % s], (char)i[5 % s], (char)i[6 % s], (char)i[7 % s] };
2138*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2139*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2140*03ce13f7SAndroid Build Coastguard Worker }
2141*03ce13f7SAndroid Build Coastguard Worker break;
2142*03ce13f7SAndroid Build Coastguard Worker case Type_v4i8:
2143*03ce13f7SAndroid Build Coastguard Worker {
2144*03ce13f7SAndroid Build Coastguard Worker const char initializer[16] = { (char)i[0 % s], (char)i[1 % s], (char)i[2 % s], (char)i[3 % s], (char)i[0 % s], (char)i[1 % s], (char)i[2 % s], (char)i[3 % s], (char)i[0 % s], (char)i[1 % s], (char)i[2 % s], (char)i[3 % s], (char)i[0 % s], (char)i[1 % s], (char)i[2 % s], (char)i[3 % s] };
2145*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2146*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2147*03ce13f7SAndroid Build Coastguard Worker }
2148*03ce13f7SAndroid Build Coastguard Worker break;
2149*03ce13f7SAndroid Build Coastguard Worker default:
2150*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("Unknown constant vector type: %d", (int)reinterpret_cast<intptr_t>(type));
2151*03ce13f7SAndroid Build Coastguard Worker }
2152*03ce13f7SAndroid Build Coastguard Worker
2153*03ce13f7SAndroid Build Coastguard Worker ASSERT(ptr);
2154*03ce13f7SAndroid Build Coastguard Worker
2155*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = sz::createLoad(::function, ::basicBlock, ptr, T(type), alignment);
2156*03ce13f7SAndroid Build Coastguard Worker return V(result);
2157*03ce13f7SAndroid Build Coastguard Worker }
2158*03ce13f7SAndroid Build Coastguard Worker
createConstantVector(std::vector<double> constants,Type * type)2159*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantVector(std::vector<double> constants, Type *type)
2160*03ce13f7SAndroid Build Coastguard Worker {
2161*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2162*03ce13f7SAndroid Build Coastguard Worker const int vectorSize = 16;
2163*03ce13f7SAndroid Build Coastguard Worker ASSERT(Ice::typeWidthInBytes(T(type)) == vectorSize);
2164*03ce13f7SAndroid Build Coastguard Worker const int alignment = vectorSize;
2165*03ce13f7SAndroid Build Coastguard Worker
2166*03ce13f7SAndroid Build Coastguard Worker const auto &f = constants;
2167*03ce13f7SAndroid Build Coastguard Worker const size_t s = constants.size();
2168*03ce13f7SAndroid Build Coastguard Worker
2169*03ce13f7SAndroid Build Coastguard Worker // TODO(b/148082873): Fix global variable constants when generating multiple functions
2170*03ce13f7SAndroid Build Coastguard Worker Ice::Constant *ptr = nullptr;
2171*03ce13f7SAndroid Build Coastguard Worker
2172*03ce13f7SAndroid Build Coastguard Worker switch((int)reinterpret_cast<intptr_t>(type))
2173*03ce13f7SAndroid Build Coastguard Worker {
2174*03ce13f7SAndroid Build Coastguard Worker case Ice::IceType_v4f32:
2175*03ce13f7SAndroid Build Coastguard Worker {
2176*03ce13f7SAndroid Build Coastguard Worker const float initializer[4] = { (float)f[0 % s], (float)f[1 % s], (float)f[2 % s], (float)f[3 % s] };
2177*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2178*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2179*03ce13f7SAndroid Build Coastguard Worker }
2180*03ce13f7SAndroid Build Coastguard Worker break;
2181*03ce13f7SAndroid Build Coastguard Worker case Type_v2f32:
2182*03ce13f7SAndroid Build Coastguard Worker {
2183*03ce13f7SAndroid Build Coastguard Worker const float initializer[4] = { (float)f[0 % s], (float)f[1 % s], (float)f[0 % s], (float)f[1 % s] };
2184*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(initializer) == vectorSize);
2185*03ce13f7SAndroid Build Coastguard Worker ptr = IceConstantData(initializer, vectorSize, alignment);
2186*03ce13f7SAndroid Build Coastguard Worker }
2187*03ce13f7SAndroid Build Coastguard Worker break;
2188*03ce13f7SAndroid Build Coastguard Worker default:
2189*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("Unknown constant vector type: %d", (int)reinterpret_cast<intptr_t>(type));
2190*03ce13f7SAndroid Build Coastguard Worker }
2191*03ce13f7SAndroid Build Coastguard Worker
2192*03ce13f7SAndroid Build Coastguard Worker ASSERT(ptr);
2193*03ce13f7SAndroid Build Coastguard Worker
2194*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = sz::createLoad(::function, ::basicBlock, ptr, T(type), alignment);
2195*03ce13f7SAndroid Build Coastguard Worker return V(result);
2196*03ce13f7SAndroid Build Coastguard Worker }
2197*03ce13f7SAndroid Build Coastguard Worker
createConstantString(const char * v)2198*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantString(const char *v)
2199*03ce13f7SAndroid Build Coastguard Worker {
2200*03ce13f7SAndroid Build Coastguard Worker // NOTE: Do not call RR_DEBUG_INFO_UPDATE_LOC() here to avoid recursion when called from rr::Printv
2201*03ce13f7SAndroid Build Coastguard Worker return V(IceConstantData(v, strlen(v) + 1));
2202*03ce13f7SAndroid Build Coastguard Worker }
2203*03ce13f7SAndroid Build Coastguard Worker
setOptimizerCallback(OptimizerCallback * callback)2204*03ce13f7SAndroid Build Coastguard Worker void Nucleus::setOptimizerCallback(OptimizerCallback *callback)
2205*03ce13f7SAndroid Build Coastguard Worker {
2206*03ce13f7SAndroid Build Coastguard Worker ::optimizerCallback = callback;
2207*03ce13f7SAndroid Build Coastguard Worker }
2208*03ce13f7SAndroid Build Coastguard Worker
type()2209*03ce13f7SAndroid Build Coastguard Worker Type *Void::type()
2210*03ce13f7SAndroid Build Coastguard Worker {
2211*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_void);
2212*03ce13f7SAndroid Build Coastguard Worker }
2213*03ce13f7SAndroid Build Coastguard Worker
type()2214*03ce13f7SAndroid Build Coastguard Worker Type *Bool::type()
2215*03ce13f7SAndroid Build Coastguard Worker {
2216*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i1);
2217*03ce13f7SAndroid Build Coastguard Worker }
2218*03ce13f7SAndroid Build Coastguard Worker
type()2219*03ce13f7SAndroid Build Coastguard Worker Type *Byte::type()
2220*03ce13f7SAndroid Build Coastguard Worker {
2221*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i8);
2222*03ce13f7SAndroid Build Coastguard Worker }
2223*03ce13f7SAndroid Build Coastguard Worker
type()2224*03ce13f7SAndroid Build Coastguard Worker Type *SByte::type()
2225*03ce13f7SAndroid Build Coastguard Worker {
2226*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i8);
2227*03ce13f7SAndroid Build Coastguard Worker }
2228*03ce13f7SAndroid Build Coastguard Worker
type()2229*03ce13f7SAndroid Build Coastguard Worker Type *Short::type()
2230*03ce13f7SAndroid Build Coastguard Worker {
2231*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i16);
2232*03ce13f7SAndroid Build Coastguard Worker }
2233*03ce13f7SAndroid Build Coastguard Worker
type()2234*03ce13f7SAndroid Build Coastguard Worker Type *UShort::type()
2235*03ce13f7SAndroid Build Coastguard Worker {
2236*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i16);
2237*03ce13f7SAndroid Build Coastguard Worker }
2238*03ce13f7SAndroid Build Coastguard Worker
type()2239*03ce13f7SAndroid Build Coastguard Worker Type *Byte4::type()
2240*03ce13f7SAndroid Build Coastguard Worker {
2241*03ce13f7SAndroid Build Coastguard Worker return T(Type_v4i8);
2242*03ce13f7SAndroid Build Coastguard Worker }
2243*03ce13f7SAndroid Build Coastguard Worker
type()2244*03ce13f7SAndroid Build Coastguard Worker Type *SByte4::type()
2245*03ce13f7SAndroid Build Coastguard Worker {
2246*03ce13f7SAndroid Build Coastguard Worker return T(Type_v4i8);
2247*03ce13f7SAndroid Build Coastguard Worker }
2248*03ce13f7SAndroid Build Coastguard Worker
SaturateUnsigned(RValue<Short> x)2249*03ce13f7SAndroid Build Coastguard Worker static RValue<Byte> SaturateUnsigned(RValue<Short> x)
2250*03ce13f7SAndroid Build Coastguard Worker {
2251*03ce13f7SAndroid Build Coastguard Worker return Byte(IfThenElse(Int(x) > 0xFF, Int(0xFF), IfThenElse(Int(x) < 0, Int(0), Int(x))));
2252*03ce13f7SAndroid Build Coastguard Worker }
2253*03ce13f7SAndroid Build Coastguard Worker
Extract(RValue<Byte8> val,int i)2254*03ce13f7SAndroid Build Coastguard Worker static RValue<Byte> Extract(RValue<Byte8> val, int i)
2255*03ce13f7SAndroid Build Coastguard Worker {
2256*03ce13f7SAndroid Build Coastguard Worker return RValue<Byte>(Nucleus::createExtractElement(val.value(), Byte::type(), i));
2257*03ce13f7SAndroid Build Coastguard Worker }
2258*03ce13f7SAndroid Build Coastguard Worker
Insert(RValue<Byte8> val,RValue<Byte> element,int i)2259*03ce13f7SAndroid Build Coastguard Worker static RValue<Byte8> Insert(RValue<Byte8> val, RValue<Byte> element, int i)
2260*03ce13f7SAndroid Build Coastguard Worker {
2261*03ce13f7SAndroid Build Coastguard Worker return RValue<Byte8>(Nucleus::createInsertElement(val.value(), element.value(), i));
2262*03ce13f7SAndroid Build Coastguard Worker }
2263*03ce13f7SAndroid Build Coastguard Worker
AddSat(RValue<Byte8> x,RValue<Byte8> y)2264*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> AddSat(RValue<Byte8> x, RValue<Byte8> y)
2265*03ce13f7SAndroid Build Coastguard Worker {
2266*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2267*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2268*03ce13f7SAndroid Build Coastguard Worker {
2269*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return SaturateUnsigned(Short(Int(a) + Int(b))); }, x, y);
2270*03ce13f7SAndroid Build Coastguard Worker }
2271*03ce13f7SAndroid Build Coastguard Worker else
2272*03ce13f7SAndroid Build Coastguard Worker {
2273*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8);
2274*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::AddSaturateUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2275*03ce13f7SAndroid Build Coastguard Worker auto paddusb = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2276*03ce13f7SAndroid Build Coastguard Worker paddusb->addArg(x.value());
2277*03ce13f7SAndroid Build Coastguard Worker paddusb->addArg(y.value());
2278*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(paddusb);
2279*03ce13f7SAndroid Build Coastguard Worker
2280*03ce13f7SAndroid Build Coastguard Worker return RValue<Byte8>(V(result));
2281*03ce13f7SAndroid Build Coastguard Worker }
2282*03ce13f7SAndroid Build Coastguard Worker }
2283*03ce13f7SAndroid Build Coastguard Worker
SubSat(RValue<Byte8> x,RValue<Byte8> y)2284*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> SubSat(RValue<Byte8> x, RValue<Byte8> y)
2285*03ce13f7SAndroid Build Coastguard Worker {
2286*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2287*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2288*03ce13f7SAndroid Build Coastguard Worker {
2289*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return SaturateUnsigned(Short(Int(a) - Int(b))); }, x, y);
2290*03ce13f7SAndroid Build Coastguard Worker }
2291*03ce13f7SAndroid Build Coastguard Worker else
2292*03ce13f7SAndroid Build Coastguard Worker {
2293*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8);
2294*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::SubtractSaturateUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2295*03ce13f7SAndroid Build Coastguard Worker auto psubusw = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2296*03ce13f7SAndroid Build Coastguard Worker psubusw->addArg(x.value());
2297*03ce13f7SAndroid Build Coastguard Worker psubusw->addArg(y.value());
2298*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(psubusw);
2299*03ce13f7SAndroid Build Coastguard Worker
2300*03ce13f7SAndroid Build Coastguard Worker return RValue<Byte8>(V(result));
2301*03ce13f7SAndroid Build Coastguard Worker }
2302*03ce13f7SAndroid Build Coastguard Worker }
2303*03ce13f7SAndroid Build Coastguard Worker
Extract(RValue<SByte8> val,int i)2304*03ce13f7SAndroid Build Coastguard Worker RValue<SByte> Extract(RValue<SByte8> val, int i)
2305*03ce13f7SAndroid Build Coastguard Worker {
2306*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2307*03ce13f7SAndroid Build Coastguard Worker return RValue<SByte>(Nucleus::createExtractElement(val.value(), SByte::type(), i));
2308*03ce13f7SAndroid Build Coastguard Worker }
2309*03ce13f7SAndroid Build Coastguard Worker
Insert(RValue<SByte8> val,RValue<SByte> element,int i)2310*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> Insert(RValue<SByte8> val, RValue<SByte> element, int i)
2311*03ce13f7SAndroid Build Coastguard Worker {
2312*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2313*03ce13f7SAndroid Build Coastguard Worker return RValue<SByte8>(Nucleus::createInsertElement(val.value(), element.value(), i));
2314*03ce13f7SAndroid Build Coastguard Worker }
2315*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<SByte8> lhs,unsigned char rhs)2316*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> operator>>(RValue<SByte8> lhs, unsigned char rhs)
2317*03ce13f7SAndroid Build Coastguard Worker {
2318*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2319*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2320*03ce13f7SAndroid Build Coastguard Worker {
2321*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto a) { return a >> SByte(rhs); }, lhs);
2322*03ce13f7SAndroid Build Coastguard Worker }
2323*03ce13f7SAndroid Build Coastguard Worker else
2324*03ce13f7SAndroid Build Coastguard Worker {
2325*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2326*03ce13f7SAndroid Build Coastguard Worker // SSE2 doesn't support byte vector shifts, so shift as shorts and recombine.
2327*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> hi = (As<Short4>(lhs) >> rhs) & Short4(0xFF00u);
2328*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> lo = As<Short4>(As<UShort4>((As<Short4>(lhs) << 8) >> rhs) >> 8);
2329*03ce13f7SAndroid Build Coastguard Worker
2330*03ce13f7SAndroid Build Coastguard Worker return As<SByte8>(hi | lo);
2331*03ce13f7SAndroid Build Coastguard Worker #else
2332*03ce13f7SAndroid Build Coastguard Worker return RValue<SByte8>(Nucleus::createAShr(lhs.value(), V(::context->getConstantInt32(rhs))));
2333*03ce13f7SAndroid Build Coastguard Worker #endif
2334*03ce13f7SAndroid Build Coastguard Worker }
2335*03ce13f7SAndroid Build Coastguard Worker }
2336*03ce13f7SAndroid Build Coastguard Worker
SignMask(RValue<Byte8> x)2337*03ce13f7SAndroid Build Coastguard Worker RValue<Int> SignMask(RValue<Byte8> x)
2338*03ce13f7SAndroid Build Coastguard Worker {
2339*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2340*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
2341*03ce13f7SAndroid Build Coastguard Worker {
2342*03ce13f7SAndroid Build Coastguard Worker Byte8 xx = As<Byte8>(As<SByte8>(x) >> 7) & Byte8(0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80);
2343*03ce13f7SAndroid Build Coastguard Worker return Int(Extract(xx, 0)) | Int(Extract(xx, 1)) | Int(Extract(xx, 2)) | Int(Extract(xx, 3)) | Int(Extract(xx, 4)) | Int(Extract(xx, 5)) | Int(Extract(xx, 6)) | Int(Extract(xx, 7));
2344*03ce13f7SAndroid Build Coastguard Worker }
2345*03ce13f7SAndroid Build Coastguard Worker else
2346*03ce13f7SAndroid Build Coastguard Worker {
2347*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32);
2348*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::SignMask, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2349*03ce13f7SAndroid Build Coastguard Worker auto movmsk = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
2350*03ce13f7SAndroid Build Coastguard Worker movmsk->addArg(x.value());
2351*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(movmsk);
2352*03ce13f7SAndroid Build Coastguard Worker
2353*03ce13f7SAndroid Build Coastguard Worker return RValue<Int>(V(result)) & 0xFF;
2354*03ce13f7SAndroid Build Coastguard Worker }
2355*03ce13f7SAndroid Build Coastguard Worker }
2356*03ce13f7SAndroid Build Coastguard Worker
2357*03ce13f7SAndroid Build Coastguard Worker // RValue<Byte8> CmpGT(RValue<Byte8> x, RValue<Byte8> y)
2358*03ce13f7SAndroid Build Coastguard Worker // {
2359*03ce13f7SAndroid Build Coastguard Worker // return RValue<Byte8>(createIntCompare(Ice::InstIcmp::Ugt, x.value(), y.value()));
2360*03ce13f7SAndroid Build Coastguard Worker // }
2361*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<Byte8> x,RValue<Byte8> y)2362*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> CmpEQ(RValue<Byte8> x, RValue<Byte8> y)
2363*03ce13f7SAndroid Build Coastguard Worker {
2364*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2365*03ce13f7SAndroid Build Coastguard Worker return RValue<Byte8>(Nucleus::createICmpEQ(x.value(), y.value()));
2366*03ce13f7SAndroid Build Coastguard Worker }
2367*03ce13f7SAndroid Build Coastguard Worker
type()2368*03ce13f7SAndroid Build Coastguard Worker Type *Byte8::type()
2369*03ce13f7SAndroid Build Coastguard Worker {
2370*03ce13f7SAndroid Build Coastguard Worker return T(Type_v8i8);
2371*03ce13f7SAndroid Build Coastguard Worker }
2372*03ce13f7SAndroid Build Coastguard Worker
2373*03ce13f7SAndroid Build Coastguard Worker // RValue<SByte8> operator<<(RValue<SByte8> lhs, unsigned char rhs)
2374*03ce13f7SAndroid Build Coastguard Worker // {
2375*03ce13f7SAndroid Build Coastguard Worker // return RValue<SByte8>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
2376*03ce13f7SAndroid Build Coastguard Worker // }
2377*03ce13f7SAndroid Build Coastguard Worker
2378*03ce13f7SAndroid Build Coastguard Worker // RValue<SByte8> operator>>(RValue<SByte8> lhs, unsigned char rhs)
2379*03ce13f7SAndroid Build Coastguard Worker // {
2380*03ce13f7SAndroid Build Coastguard Worker // return RValue<SByte8>(Nucleus::createAShr(lhs.value(), V(::context->getConstantInt32(rhs))));
2381*03ce13f7SAndroid Build Coastguard Worker // }
2382*03ce13f7SAndroid Build Coastguard Worker
SaturateSigned(RValue<Short> x)2383*03ce13f7SAndroid Build Coastguard Worker RValue<SByte> SaturateSigned(RValue<Short> x)
2384*03ce13f7SAndroid Build Coastguard Worker {
2385*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2386*03ce13f7SAndroid Build Coastguard Worker return SByte(IfThenElse(Int(x) > 0x7F, Int(0x7F), IfThenElse(Int(x) < -0x80, Int(0x80), Int(x))));
2387*03ce13f7SAndroid Build Coastguard Worker }
2388*03ce13f7SAndroid Build Coastguard Worker
AddSat(RValue<SByte8> x,RValue<SByte8> y)2389*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> AddSat(RValue<SByte8> x, RValue<SByte8> y)
2390*03ce13f7SAndroid Build Coastguard Worker {
2391*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2392*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2393*03ce13f7SAndroid Build Coastguard Worker {
2394*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return SaturateSigned(Short(Int(a) + Int(b))); }, x, y);
2395*03ce13f7SAndroid Build Coastguard Worker }
2396*03ce13f7SAndroid Build Coastguard Worker else
2397*03ce13f7SAndroid Build Coastguard Worker {
2398*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8);
2399*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::AddSaturateSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2400*03ce13f7SAndroid Build Coastguard Worker auto paddsb = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2401*03ce13f7SAndroid Build Coastguard Worker paddsb->addArg(x.value());
2402*03ce13f7SAndroid Build Coastguard Worker paddsb->addArg(y.value());
2403*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(paddsb);
2404*03ce13f7SAndroid Build Coastguard Worker
2405*03ce13f7SAndroid Build Coastguard Worker return RValue<SByte8>(V(result));
2406*03ce13f7SAndroid Build Coastguard Worker }
2407*03ce13f7SAndroid Build Coastguard Worker }
2408*03ce13f7SAndroid Build Coastguard Worker
SubSat(RValue<SByte8> x,RValue<SByte8> y)2409*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> SubSat(RValue<SByte8> x, RValue<SByte8> y)
2410*03ce13f7SAndroid Build Coastguard Worker {
2411*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2412*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2413*03ce13f7SAndroid Build Coastguard Worker {
2414*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return SaturateSigned(Short(Int(a) - Int(b))); }, x, y);
2415*03ce13f7SAndroid Build Coastguard Worker }
2416*03ce13f7SAndroid Build Coastguard Worker else
2417*03ce13f7SAndroid Build Coastguard Worker {
2418*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8);
2419*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::SubtractSaturateSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2420*03ce13f7SAndroid Build Coastguard Worker auto psubsb = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2421*03ce13f7SAndroid Build Coastguard Worker psubsb->addArg(x.value());
2422*03ce13f7SAndroid Build Coastguard Worker psubsb->addArg(y.value());
2423*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(psubsb);
2424*03ce13f7SAndroid Build Coastguard Worker
2425*03ce13f7SAndroid Build Coastguard Worker return RValue<SByte8>(V(result));
2426*03ce13f7SAndroid Build Coastguard Worker }
2427*03ce13f7SAndroid Build Coastguard Worker }
2428*03ce13f7SAndroid Build Coastguard Worker
SignMask(RValue<SByte8> x)2429*03ce13f7SAndroid Build Coastguard Worker RValue<Int> SignMask(RValue<SByte8> x)
2430*03ce13f7SAndroid Build Coastguard Worker {
2431*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2432*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
2433*03ce13f7SAndroid Build Coastguard Worker {
2434*03ce13f7SAndroid Build Coastguard Worker SByte8 xx = (x >> 7) & SByte8(0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80);
2435*03ce13f7SAndroid Build Coastguard Worker return Int(Extract(xx, 0)) | Int(Extract(xx, 1)) | Int(Extract(xx, 2)) | Int(Extract(xx, 3)) | Int(Extract(xx, 4)) | Int(Extract(xx, 5)) | Int(Extract(xx, 6)) | Int(Extract(xx, 7));
2436*03ce13f7SAndroid Build Coastguard Worker }
2437*03ce13f7SAndroid Build Coastguard Worker else
2438*03ce13f7SAndroid Build Coastguard Worker {
2439*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32);
2440*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::SignMask, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2441*03ce13f7SAndroid Build Coastguard Worker auto movmsk = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
2442*03ce13f7SAndroid Build Coastguard Worker movmsk->addArg(x.value());
2443*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(movmsk);
2444*03ce13f7SAndroid Build Coastguard Worker
2445*03ce13f7SAndroid Build Coastguard Worker return RValue<Int>(V(result)) & 0xFF;
2446*03ce13f7SAndroid Build Coastguard Worker }
2447*03ce13f7SAndroid Build Coastguard Worker }
2448*03ce13f7SAndroid Build Coastguard Worker
CmpGT(RValue<SByte8> x,RValue<SByte8> y)2449*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> CmpGT(RValue<SByte8> x, RValue<SByte8> y)
2450*03ce13f7SAndroid Build Coastguard Worker {
2451*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2452*03ce13f7SAndroid Build Coastguard Worker return RValue<Byte8>(createIntCompare(Ice::InstIcmp::Sgt, x.value(), y.value()));
2453*03ce13f7SAndroid Build Coastguard Worker }
2454*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<SByte8> x,RValue<SByte8> y)2455*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> CmpEQ(RValue<SByte8> x, RValue<SByte8> y)
2456*03ce13f7SAndroid Build Coastguard Worker {
2457*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2458*03ce13f7SAndroid Build Coastguard Worker return RValue<Byte8>(Nucleus::createICmpEQ(x.value(), y.value()));
2459*03ce13f7SAndroid Build Coastguard Worker }
2460*03ce13f7SAndroid Build Coastguard Worker
type()2461*03ce13f7SAndroid Build Coastguard Worker Type *SByte8::type()
2462*03ce13f7SAndroid Build Coastguard Worker {
2463*03ce13f7SAndroid Build Coastguard Worker return T(Type_v8i8);
2464*03ce13f7SAndroid Build Coastguard Worker }
2465*03ce13f7SAndroid Build Coastguard Worker
type()2466*03ce13f7SAndroid Build Coastguard Worker Type *Byte16::type()
2467*03ce13f7SAndroid Build Coastguard Worker {
2468*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v16i8);
2469*03ce13f7SAndroid Build Coastguard Worker }
2470*03ce13f7SAndroid Build Coastguard Worker
type()2471*03ce13f7SAndroid Build Coastguard Worker Type *SByte16::type()
2472*03ce13f7SAndroid Build Coastguard Worker {
2473*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v16i8);
2474*03ce13f7SAndroid Build Coastguard Worker }
2475*03ce13f7SAndroid Build Coastguard Worker
type()2476*03ce13f7SAndroid Build Coastguard Worker Type *Short2::type()
2477*03ce13f7SAndroid Build Coastguard Worker {
2478*03ce13f7SAndroid Build Coastguard Worker return T(Type_v2i16);
2479*03ce13f7SAndroid Build Coastguard Worker }
2480*03ce13f7SAndroid Build Coastguard Worker
type()2481*03ce13f7SAndroid Build Coastguard Worker Type *UShort2::type()
2482*03ce13f7SAndroid Build Coastguard Worker {
2483*03ce13f7SAndroid Build Coastguard Worker return T(Type_v2i16);
2484*03ce13f7SAndroid Build Coastguard Worker }
2485*03ce13f7SAndroid Build Coastguard Worker
Short4(RValue<Int4> cast)2486*03ce13f7SAndroid Build Coastguard Worker Short4::Short4(RValue<Int4> cast)
2487*03ce13f7SAndroid Build Coastguard Worker {
2488*03ce13f7SAndroid Build Coastguard Worker std::vector<int> select = { 0, 2, 4, 6, 0, 2, 4, 6 };
2489*03ce13f7SAndroid Build Coastguard Worker Value *short8 = Nucleus::createBitCast(cast.value(), Short8::type());
2490*03ce13f7SAndroid Build Coastguard Worker Value *packed = Nucleus::createShuffleVector(short8, short8, select);
2491*03ce13f7SAndroid Build Coastguard Worker
2492*03ce13f7SAndroid Build Coastguard Worker Value *int2 = RValue<Int2>(Int2(As<Int4>(packed))).value();
2493*03ce13f7SAndroid Build Coastguard Worker Value *short4 = Nucleus::createBitCast(int2, Short4::type());
2494*03ce13f7SAndroid Build Coastguard Worker
2495*03ce13f7SAndroid Build Coastguard Worker storeValue(short4);
2496*03ce13f7SAndroid Build Coastguard Worker }
2497*03ce13f7SAndroid Build Coastguard Worker
2498*03ce13f7SAndroid Build Coastguard Worker // Short4::Short4(RValue<Float> cast)
2499*03ce13f7SAndroid Build Coastguard Worker // {
2500*03ce13f7SAndroid Build Coastguard Worker // }
2501*03ce13f7SAndroid Build Coastguard Worker
Short4(RValue<Float4> cast)2502*03ce13f7SAndroid Build Coastguard Worker Short4::Short4(RValue<Float4> cast)
2503*03ce13f7SAndroid Build Coastguard Worker {
2504*03ce13f7SAndroid Build Coastguard Worker // TODO(b/150791192): Generalize and optimize
2505*03ce13f7SAndroid Build Coastguard Worker auto smin = std::numeric_limits<short>::min();
2506*03ce13f7SAndroid Build Coastguard Worker auto smax = std::numeric_limits<short>::max();
2507*03ce13f7SAndroid Build Coastguard Worker *this = Short4(Int4(Max(Min(cast, Float4(smax)), Float4(smin))));
2508*03ce13f7SAndroid Build Coastguard Worker }
2509*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<Short4> lhs,unsigned char rhs)2510*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> operator<<(RValue<Short4> lhs, unsigned char rhs)
2511*03ce13f7SAndroid Build Coastguard Worker {
2512*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2513*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2514*03ce13f7SAndroid Build Coastguard Worker {
2515*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << Short(rhs); }, lhs);
2516*03ce13f7SAndroid Build Coastguard Worker }
2517*03ce13f7SAndroid Build Coastguard Worker else
2518*03ce13f7SAndroid Build Coastguard Worker {
2519*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
2520*03ce13f7SAndroid Build Coastguard Worker }
2521*03ce13f7SAndroid Build Coastguard Worker }
2522*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<Short4> lhs,unsigned char rhs)2523*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> operator>>(RValue<Short4> lhs, unsigned char rhs)
2524*03ce13f7SAndroid Build Coastguard Worker {
2525*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2526*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2527*03ce13f7SAndroid Build Coastguard Worker {
2528*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> Short(rhs); }, lhs);
2529*03ce13f7SAndroid Build Coastguard Worker }
2530*03ce13f7SAndroid Build Coastguard Worker else
2531*03ce13f7SAndroid Build Coastguard Worker {
2532*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(Nucleus::createAShr(lhs.value(), V(::context->getConstantInt32(rhs))));
2533*03ce13f7SAndroid Build Coastguard Worker }
2534*03ce13f7SAndroid Build Coastguard Worker }
2535*03ce13f7SAndroid Build Coastguard Worker
Max(RValue<Short4> x,RValue<Short4> y)2536*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> Max(RValue<Short4> x, RValue<Short4> y)
2537*03ce13f7SAndroid Build Coastguard Worker {
2538*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2539*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1);
2540*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sle, condition, x.value(), y.value());
2541*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
2542*03ce13f7SAndroid Build Coastguard Worker
2543*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2544*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
2545*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
2546*03ce13f7SAndroid Build Coastguard Worker
2547*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(V(result));
2548*03ce13f7SAndroid Build Coastguard Worker }
2549*03ce13f7SAndroid Build Coastguard Worker
Min(RValue<Short4> x,RValue<Short4> y)2550*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> Min(RValue<Short4> x, RValue<Short4> y)
2551*03ce13f7SAndroid Build Coastguard Worker {
2552*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2553*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1);
2554*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sgt, condition, x.value(), y.value());
2555*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
2556*03ce13f7SAndroid Build Coastguard Worker
2557*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2558*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
2559*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
2560*03ce13f7SAndroid Build Coastguard Worker
2561*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(V(result));
2562*03ce13f7SAndroid Build Coastguard Worker }
2563*03ce13f7SAndroid Build Coastguard Worker
SaturateSigned(RValue<Int> x)2564*03ce13f7SAndroid Build Coastguard Worker RValue<Short> SaturateSigned(RValue<Int> x)
2565*03ce13f7SAndroid Build Coastguard Worker {
2566*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2567*03ce13f7SAndroid Build Coastguard Worker return Short(IfThenElse(x > 0x7FFF, Int(0x7FFF), IfThenElse(x < -0x8000, Int(0x8000), x)));
2568*03ce13f7SAndroid Build Coastguard Worker }
2569*03ce13f7SAndroid Build Coastguard Worker
AddSat(RValue<Short4> x,RValue<Short4> y)2570*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> AddSat(RValue<Short4> x, RValue<Short4> y)
2571*03ce13f7SAndroid Build Coastguard Worker {
2572*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2573*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2574*03ce13f7SAndroid Build Coastguard Worker {
2575*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return SaturateSigned(Int(a) + Int(b)); }, x, y);
2576*03ce13f7SAndroid Build Coastguard Worker }
2577*03ce13f7SAndroid Build Coastguard Worker else
2578*03ce13f7SAndroid Build Coastguard Worker {
2579*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2580*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::AddSaturateSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2581*03ce13f7SAndroid Build Coastguard Worker auto paddsw = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2582*03ce13f7SAndroid Build Coastguard Worker paddsw->addArg(x.value());
2583*03ce13f7SAndroid Build Coastguard Worker paddsw->addArg(y.value());
2584*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(paddsw);
2585*03ce13f7SAndroid Build Coastguard Worker
2586*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(V(result));
2587*03ce13f7SAndroid Build Coastguard Worker }
2588*03ce13f7SAndroid Build Coastguard Worker }
2589*03ce13f7SAndroid Build Coastguard Worker
SubSat(RValue<Short4> x,RValue<Short4> y)2590*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> SubSat(RValue<Short4> x, RValue<Short4> y)
2591*03ce13f7SAndroid Build Coastguard Worker {
2592*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2593*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2594*03ce13f7SAndroid Build Coastguard Worker {
2595*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return SaturateSigned(Int(a) - Int(b)); }, x, y);
2596*03ce13f7SAndroid Build Coastguard Worker }
2597*03ce13f7SAndroid Build Coastguard Worker else
2598*03ce13f7SAndroid Build Coastguard Worker {
2599*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2600*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::SubtractSaturateSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2601*03ce13f7SAndroid Build Coastguard Worker auto psubsw = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2602*03ce13f7SAndroid Build Coastguard Worker psubsw->addArg(x.value());
2603*03ce13f7SAndroid Build Coastguard Worker psubsw->addArg(y.value());
2604*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(psubsw);
2605*03ce13f7SAndroid Build Coastguard Worker
2606*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(V(result));
2607*03ce13f7SAndroid Build Coastguard Worker }
2608*03ce13f7SAndroid Build Coastguard Worker }
2609*03ce13f7SAndroid Build Coastguard Worker
MulHigh(RValue<Short4> x,RValue<Short4> y)2610*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> MulHigh(RValue<Short4> x, RValue<Short4> y)
2611*03ce13f7SAndroid Build Coastguard Worker {
2612*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2613*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2614*03ce13f7SAndroid Build Coastguard Worker {
2615*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return Short((Int(a) * Int(b)) >> 16); }, x, y);
2616*03ce13f7SAndroid Build Coastguard Worker }
2617*03ce13f7SAndroid Build Coastguard Worker else
2618*03ce13f7SAndroid Build Coastguard Worker {
2619*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2620*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::MultiplyHighSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2621*03ce13f7SAndroid Build Coastguard Worker auto pmulhw = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2622*03ce13f7SAndroid Build Coastguard Worker pmulhw->addArg(x.value());
2623*03ce13f7SAndroid Build Coastguard Worker pmulhw->addArg(y.value());
2624*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(pmulhw);
2625*03ce13f7SAndroid Build Coastguard Worker
2626*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(V(result));
2627*03ce13f7SAndroid Build Coastguard Worker }
2628*03ce13f7SAndroid Build Coastguard Worker }
2629*03ce13f7SAndroid Build Coastguard Worker
MulAdd(RValue<Short4> x,RValue<Short4> y)2630*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> MulAdd(RValue<Short4> x, RValue<Short4> y)
2631*03ce13f7SAndroid Build Coastguard Worker {
2632*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2633*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2634*03ce13f7SAndroid Build Coastguard Worker {
2635*03ce13f7SAndroid Build Coastguard Worker Int2 result;
2636*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, Int(Extract(x, 0)) * Int(Extract(y, 0)) + Int(Extract(x, 1)) * Int(Extract(y, 1)), 0);
2637*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, Int(Extract(x, 2)) * Int(Extract(y, 2)) + Int(Extract(x, 3)) * Int(Extract(y, 3)), 1);
2638*03ce13f7SAndroid Build Coastguard Worker
2639*03ce13f7SAndroid Build Coastguard Worker return result;
2640*03ce13f7SAndroid Build Coastguard Worker }
2641*03ce13f7SAndroid Build Coastguard Worker else
2642*03ce13f7SAndroid Build Coastguard Worker {
2643*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2644*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::MultiplyAddPairs, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2645*03ce13f7SAndroid Build Coastguard Worker auto pmaddwd = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2646*03ce13f7SAndroid Build Coastguard Worker pmaddwd->addArg(x.value());
2647*03ce13f7SAndroid Build Coastguard Worker pmaddwd->addArg(y.value());
2648*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(pmaddwd);
2649*03ce13f7SAndroid Build Coastguard Worker
2650*03ce13f7SAndroid Build Coastguard Worker return As<Int2>(V(result));
2651*03ce13f7SAndroid Build Coastguard Worker }
2652*03ce13f7SAndroid Build Coastguard Worker }
2653*03ce13f7SAndroid Build Coastguard Worker
PackSigned(RValue<Short4> x,RValue<Short4> y)2654*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> PackSigned(RValue<Short4> x, RValue<Short4> y)
2655*03ce13f7SAndroid Build Coastguard Worker {
2656*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2657*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2658*03ce13f7SAndroid Build Coastguard Worker {
2659*03ce13f7SAndroid Build Coastguard Worker SByte8 result;
2660*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(x, 0)), 0);
2661*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(x, 1)), 1);
2662*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(x, 2)), 2);
2663*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(x, 3)), 3);
2664*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(y, 0)), 4);
2665*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(y, 1)), 5);
2666*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(y, 2)), 6);
2667*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(y, 3)), 7);
2668*03ce13f7SAndroid Build Coastguard Worker
2669*03ce13f7SAndroid Build Coastguard Worker return result;
2670*03ce13f7SAndroid Build Coastguard Worker }
2671*03ce13f7SAndroid Build Coastguard Worker else
2672*03ce13f7SAndroid Build Coastguard Worker {
2673*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8);
2674*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::VectorPackSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2675*03ce13f7SAndroid Build Coastguard Worker auto pack = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2676*03ce13f7SAndroid Build Coastguard Worker pack->addArg(x.value());
2677*03ce13f7SAndroid Build Coastguard Worker pack->addArg(y.value());
2678*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(pack);
2679*03ce13f7SAndroid Build Coastguard Worker
2680*03ce13f7SAndroid Build Coastguard Worker return As<SByte8>(Swizzle(As<Int4>(V(result)), 0x0202));
2681*03ce13f7SAndroid Build Coastguard Worker }
2682*03ce13f7SAndroid Build Coastguard Worker }
2683*03ce13f7SAndroid Build Coastguard Worker
PackUnsigned(RValue<Short4> x,RValue<Short4> y)2684*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> PackUnsigned(RValue<Short4> x, RValue<Short4> y)
2685*03ce13f7SAndroid Build Coastguard Worker {
2686*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2687*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2688*03ce13f7SAndroid Build Coastguard Worker {
2689*03ce13f7SAndroid Build Coastguard Worker Byte8 result;
2690*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateUnsigned(Extract(x, 0)), 0);
2691*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateUnsigned(Extract(x, 1)), 1);
2692*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateUnsigned(Extract(x, 2)), 2);
2693*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateUnsigned(Extract(x, 3)), 3);
2694*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateUnsigned(Extract(y, 0)), 4);
2695*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateUnsigned(Extract(y, 1)), 5);
2696*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateUnsigned(Extract(y, 2)), 6);
2697*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateUnsigned(Extract(y, 3)), 7);
2698*03ce13f7SAndroid Build Coastguard Worker
2699*03ce13f7SAndroid Build Coastguard Worker return result;
2700*03ce13f7SAndroid Build Coastguard Worker }
2701*03ce13f7SAndroid Build Coastguard Worker else
2702*03ce13f7SAndroid Build Coastguard Worker {
2703*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8);
2704*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::VectorPackUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2705*03ce13f7SAndroid Build Coastguard Worker auto pack = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2706*03ce13f7SAndroid Build Coastguard Worker pack->addArg(x.value());
2707*03ce13f7SAndroid Build Coastguard Worker pack->addArg(y.value());
2708*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(pack);
2709*03ce13f7SAndroid Build Coastguard Worker
2710*03ce13f7SAndroid Build Coastguard Worker return As<Byte8>(Swizzle(As<Int4>(V(result)), 0x0202));
2711*03ce13f7SAndroid Build Coastguard Worker }
2712*03ce13f7SAndroid Build Coastguard Worker }
2713*03ce13f7SAndroid Build Coastguard Worker
CmpGT(RValue<Short4> x,RValue<Short4> y)2714*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> CmpGT(RValue<Short4> x, RValue<Short4> y)
2715*03ce13f7SAndroid Build Coastguard Worker {
2716*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2717*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(createIntCompare(Ice::InstIcmp::Sgt, x.value(), y.value()));
2718*03ce13f7SAndroid Build Coastguard Worker }
2719*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<Short4> x,RValue<Short4> y)2720*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> CmpEQ(RValue<Short4> x, RValue<Short4> y)
2721*03ce13f7SAndroid Build Coastguard Worker {
2722*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2723*03ce13f7SAndroid Build Coastguard Worker return RValue<Short4>(Nucleus::createICmpEQ(x.value(), y.value()));
2724*03ce13f7SAndroid Build Coastguard Worker }
2725*03ce13f7SAndroid Build Coastguard Worker
type()2726*03ce13f7SAndroid Build Coastguard Worker Type *Short4::type()
2727*03ce13f7SAndroid Build Coastguard Worker {
2728*03ce13f7SAndroid Build Coastguard Worker return T(Type_v4i16);
2729*03ce13f7SAndroid Build Coastguard Worker }
2730*03ce13f7SAndroid Build Coastguard Worker
UShort4(RValue<Float4> cast,bool saturate)2731*03ce13f7SAndroid Build Coastguard Worker UShort4::UShort4(RValue<Float4> cast, bool saturate)
2732*03ce13f7SAndroid Build Coastguard Worker {
2733*03ce13f7SAndroid Build Coastguard Worker if(saturate)
2734*03ce13f7SAndroid Build Coastguard Worker {
2735*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
2736*03ce13f7SAndroid Build Coastguard Worker {
2737*03ce13f7SAndroid Build Coastguard Worker // x86 produces 0x80000000 on 32-bit integer overflow/underflow.
2738*03ce13f7SAndroid Build Coastguard Worker // PackUnsigned takes care of 0x0000 saturation.
2739*03ce13f7SAndroid Build Coastguard Worker Int4 int4(Min(cast, Float4(0xFFFF)));
2740*03ce13f7SAndroid Build Coastguard Worker *this = As<UShort4>(PackUnsigned(int4, int4));
2741*03ce13f7SAndroid Build Coastguard Worker }
2742*03ce13f7SAndroid Build Coastguard Worker else if(CPUID::ARM)
2743*03ce13f7SAndroid Build Coastguard Worker {
2744*03ce13f7SAndroid Build Coastguard Worker // ARM saturates the 32-bit integer result on overflow/undeflow.
2745*03ce13f7SAndroid Build Coastguard Worker Int4 int4(cast);
2746*03ce13f7SAndroid Build Coastguard Worker *this = As<UShort4>(PackUnsigned(int4, int4));
2747*03ce13f7SAndroid Build Coastguard Worker }
2748*03ce13f7SAndroid Build Coastguard Worker else
2749*03ce13f7SAndroid Build Coastguard Worker {
2750*03ce13f7SAndroid Build Coastguard Worker *this = Short4(Int4(Max(Min(cast, Float4(0xFFFF)), Float4(0x0000))));
2751*03ce13f7SAndroid Build Coastguard Worker }
2752*03ce13f7SAndroid Build Coastguard Worker }
2753*03ce13f7SAndroid Build Coastguard Worker else
2754*03ce13f7SAndroid Build Coastguard Worker {
2755*03ce13f7SAndroid Build Coastguard Worker *this = Short4(Int4(cast));
2756*03ce13f7SAndroid Build Coastguard Worker }
2757*03ce13f7SAndroid Build Coastguard Worker }
2758*03ce13f7SAndroid Build Coastguard Worker
Extract(RValue<UShort4> val,int i)2759*03ce13f7SAndroid Build Coastguard Worker RValue<UShort> Extract(RValue<UShort4> val, int i)
2760*03ce13f7SAndroid Build Coastguard Worker {
2761*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort>(Nucleus::createExtractElement(val.value(), UShort::type(), i));
2762*03ce13f7SAndroid Build Coastguard Worker }
2763*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<UShort4> lhs,unsigned char rhs)2764*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> operator<<(RValue<UShort4> lhs, unsigned char rhs)
2765*03ce13f7SAndroid Build Coastguard Worker {
2766*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2767*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2768*03ce13f7SAndroid Build Coastguard Worker {
2769*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << UShort(rhs); }, lhs);
2770*03ce13f7SAndroid Build Coastguard Worker }
2771*03ce13f7SAndroid Build Coastguard Worker else
2772*03ce13f7SAndroid Build Coastguard Worker {
2773*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort4>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
2774*03ce13f7SAndroid Build Coastguard Worker }
2775*03ce13f7SAndroid Build Coastguard Worker }
2776*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<UShort4> lhs,unsigned char rhs)2777*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> operator>>(RValue<UShort4> lhs, unsigned char rhs)
2778*03ce13f7SAndroid Build Coastguard Worker {
2779*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2780*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2781*03ce13f7SAndroid Build Coastguard Worker {
2782*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> UShort(rhs); }, lhs);
2783*03ce13f7SAndroid Build Coastguard Worker }
2784*03ce13f7SAndroid Build Coastguard Worker else
2785*03ce13f7SAndroid Build Coastguard Worker {
2786*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort4>(Nucleus::createLShr(lhs.value(), V(::context->getConstantInt32(rhs))));
2787*03ce13f7SAndroid Build Coastguard Worker }
2788*03ce13f7SAndroid Build Coastguard Worker }
2789*03ce13f7SAndroid Build Coastguard Worker
Max(RValue<UShort4> x,RValue<UShort4> y)2790*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> Max(RValue<UShort4> x, RValue<UShort4> y)
2791*03ce13f7SAndroid Build Coastguard Worker {
2792*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2793*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1);
2794*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ule, condition, x.value(), y.value());
2795*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
2796*03ce13f7SAndroid Build Coastguard Worker
2797*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2798*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
2799*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
2800*03ce13f7SAndroid Build Coastguard Worker
2801*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort4>(V(result));
2802*03ce13f7SAndroid Build Coastguard Worker }
2803*03ce13f7SAndroid Build Coastguard Worker
Min(RValue<UShort4> x,RValue<UShort4> y)2804*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> Min(RValue<UShort4> x, RValue<UShort4> y)
2805*03ce13f7SAndroid Build Coastguard Worker {
2806*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1);
2807*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ugt, condition, x.value(), y.value());
2808*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
2809*03ce13f7SAndroid Build Coastguard Worker
2810*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2811*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
2812*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
2813*03ce13f7SAndroid Build Coastguard Worker
2814*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort4>(V(result));
2815*03ce13f7SAndroid Build Coastguard Worker }
2816*03ce13f7SAndroid Build Coastguard Worker
SaturateUnsigned(RValue<Int> x)2817*03ce13f7SAndroid Build Coastguard Worker RValue<UShort> SaturateUnsigned(RValue<Int> x)
2818*03ce13f7SAndroid Build Coastguard Worker {
2819*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2820*03ce13f7SAndroid Build Coastguard Worker return UShort(IfThenElse(x > 0xFFFF, Int(0xFFFF), IfThenElse(x < 0, Int(0), x)));
2821*03ce13f7SAndroid Build Coastguard Worker }
2822*03ce13f7SAndroid Build Coastguard Worker
AddSat(RValue<UShort4> x,RValue<UShort4> y)2823*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> AddSat(RValue<UShort4> x, RValue<UShort4> y)
2824*03ce13f7SAndroid Build Coastguard Worker {
2825*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2826*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2827*03ce13f7SAndroid Build Coastguard Worker {
2828*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return SaturateUnsigned(Int(a) + Int(b)); }, x, y);
2829*03ce13f7SAndroid Build Coastguard Worker }
2830*03ce13f7SAndroid Build Coastguard Worker else
2831*03ce13f7SAndroid Build Coastguard Worker {
2832*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2833*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::AddSaturateUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2834*03ce13f7SAndroid Build Coastguard Worker auto paddusw = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2835*03ce13f7SAndroid Build Coastguard Worker paddusw->addArg(x.value());
2836*03ce13f7SAndroid Build Coastguard Worker paddusw->addArg(y.value());
2837*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(paddusw);
2838*03ce13f7SAndroid Build Coastguard Worker
2839*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort4>(V(result));
2840*03ce13f7SAndroid Build Coastguard Worker }
2841*03ce13f7SAndroid Build Coastguard Worker }
2842*03ce13f7SAndroid Build Coastguard Worker
SubSat(RValue<UShort4> x,RValue<UShort4> y)2843*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> SubSat(RValue<UShort4> x, RValue<UShort4> y)
2844*03ce13f7SAndroid Build Coastguard Worker {
2845*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2846*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2847*03ce13f7SAndroid Build Coastguard Worker {
2848*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return SaturateUnsigned(Int(a) - Int(b)); }, x, y);
2849*03ce13f7SAndroid Build Coastguard Worker }
2850*03ce13f7SAndroid Build Coastguard Worker else
2851*03ce13f7SAndroid Build Coastguard Worker {
2852*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2853*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::SubtractSaturateUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2854*03ce13f7SAndroid Build Coastguard Worker auto psubusw = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2855*03ce13f7SAndroid Build Coastguard Worker psubusw->addArg(x.value());
2856*03ce13f7SAndroid Build Coastguard Worker psubusw->addArg(y.value());
2857*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(psubusw);
2858*03ce13f7SAndroid Build Coastguard Worker
2859*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort4>(V(result));
2860*03ce13f7SAndroid Build Coastguard Worker }
2861*03ce13f7SAndroid Build Coastguard Worker }
2862*03ce13f7SAndroid Build Coastguard Worker
MulHigh(RValue<UShort4> x,RValue<UShort4> y)2863*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> MulHigh(RValue<UShort4> x, RValue<UShort4> y)
2864*03ce13f7SAndroid Build Coastguard Worker {
2865*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2866*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2867*03ce13f7SAndroid Build Coastguard Worker {
2868*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return UShort((UInt(a) * UInt(b)) >> 16); }, x, y);
2869*03ce13f7SAndroid Build Coastguard Worker }
2870*03ce13f7SAndroid Build Coastguard Worker else
2871*03ce13f7SAndroid Build Coastguard Worker {
2872*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
2873*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::MultiplyHighUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
2874*03ce13f7SAndroid Build Coastguard Worker auto pmulhuw = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
2875*03ce13f7SAndroid Build Coastguard Worker pmulhuw->addArg(x.value());
2876*03ce13f7SAndroid Build Coastguard Worker pmulhuw->addArg(y.value());
2877*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(pmulhuw);
2878*03ce13f7SAndroid Build Coastguard Worker
2879*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort4>(V(result));
2880*03ce13f7SAndroid Build Coastguard Worker }
2881*03ce13f7SAndroid Build Coastguard Worker }
2882*03ce13f7SAndroid Build Coastguard Worker
MulHigh(RValue<Int4> x,RValue<Int4> y)2883*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> MulHigh(RValue<Int4> x, RValue<Int4> y)
2884*03ce13f7SAndroid Build Coastguard Worker {
2885*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2886*03ce13f7SAndroid Build Coastguard Worker // TODO: For x86, build an intrinsics version of this which uses shuffles + pmuludq.
2887*03ce13f7SAndroid Build Coastguard Worker
2888*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return Int((Long(a) * Long(b)) >> Long(Int(32))); }, x, y);
2889*03ce13f7SAndroid Build Coastguard Worker }
2890*03ce13f7SAndroid Build Coastguard Worker
MulHigh(RValue<UInt4> x,RValue<UInt4> y)2891*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> MulHigh(RValue<UInt4> x, RValue<UInt4> y)
2892*03ce13f7SAndroid Build Coastguard Worker {
2893*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2894*03ce13f7SAndroid Build Coastguard Worker // TODO: For x86, build an intrinsics version of this which uses shuffles + pmuludq.
2895*03ce13f7SAndroid Build Coastguard Worker
2896*03ce13f7SAndroid Build Coastguard Worker if(false) // Partial product based implementation.
2897*03ce13f7SAndroid Build Coastguard Worker {
2898*03ce13f7SAndroid Build Coastguard Worker auto xh = x >> 16;
2899*03ce13f7SAndroid Build Coastguard Worker auto yh = y >> 16;
2900*03ce13f7SAndroid Build Coastguard Worker auto xl = x & UInt4(0x0000FFFF);
2901*03ce13f7SAndroid Build Coastguard Worker auto yl = y & UInt4(0x0000FFFF);
2902*03ce13f7SAndroid Build Coastguard Worker auto xlyh = xl * yh;
2903*03ce13f7SAndroid Build Coastguard Worker auto xhyl = xh * yl;
2904*03ce13f7SAndroid Build Coastguard Worker auto xlyhh = xlyh >> 16;
2905*03ce13f7SAndroid Build Coastguard Worker auto xhylh = xhyl >> 16;
2906*03ce13f7SAndroid Build Coastguard Worker auto xlyhl = xlyh & UInt4(0x0000FFFF);
2907*03ce13f7SAndroid Build Coastguard Worker auto xhyll = xhyl & UInt4(0x0000FFFF);
2908*03ce13f7SAndroid Build Coastguard Worker auto xlylh = (xl * yl) >> 16;
2909*03ce13f7SAndroid Build Coastguard Worker auto oflow = (xlyhl + xhyll + xlylh) >> 16;
2910*03ce13f7SAndroid Build Coastguard Worker
2911*03ce13f7SAndroid Build Coastguard Worker return (xh * yh) + (xlyhh + xhylh) + oflow;
2912*03ce13f7SAndroid Build Coastguard Worker }
2913*03ce13f7SAndroid Build Coastguard Worker
2914*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a, auto b) { return UInt((Long(a) * Long(b)) >> Long(Int(32))); }, x, y);
2915*03ce13f7SAndroid Build Coastguard Worker }
2916*03ce13f7SAndroid Build Coastguard Worker
Average(RValue<UShort4> x,RValue<UShort4> y)2917*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> Average(RValue<UShort4> x, RValue<UShort4> y)
2918*03ce13f7SAndroid Build Coastguard Worker {
2919*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2920*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("RValue<UShort4> Average(RValue<UShort4> x, RValue<UShort4> y)");
2921*03ce13f7SAndroid Build Coastguard Worker return UShort4(0);
2922*03ce13f7SAndroid Build Coastguard Worker }
2923*03ce13f7SAndroid Build Coastguard Worker
type()2924*03ce13f7SAndroid Build Coastguard Worker Type *UShort4::type()
2925*03ce13f7SAndroid Build Coastguard Worker {
2926*03ce13f7SAndroid Build Coastguard Worker return T(Type_v4i16);
2927*03ce13f7SAndroid Build Coastguard Worker }
2928*03ce13f7SAndroid Build Coastguard Worker
Extract(RValue<Short8> val,int i)2929*03ce13f7SAndroid Build Coastguard Worker RValue<Short> Extract(RValue<Short8> val, int i)
2930*03ce13f7SAndroid Build Coastguard Worker {
2931*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2932*03ce13f7SAndroid Build Coastguard Worker return RValue<Short>(Nucleus::createExtractElement(val.value(), Short::type(), i));
2933*03ce13f7SAndroid Build Coastguard Worker }
2934*03ce13f7SAndroid Build Coastguard Worker
Insert(RValue<Short8> val,RValue<Short> element,int i)2935*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> Insert(RValue<Short8> val, RValue<Short> element, int i)
2936*03ce13f7SAndroid Build Coastguard Worker {
2937*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2938*03ce13f7SAndroid Build Coastguard Worker return RValue<Short8>(Nucleus::createInsertElement(val.value(), element.value(), i));
2939*03ce13f7SAndroid Build Coastguard Worker }
2940*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<Short8> lhs,unsigned char rhs)2941*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> operator<<(RValue<Short8> lhs, unsigned char rhs)
2942*03ce13f7SAndroid Build Coastguard Worker {
2943*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2944*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2945*03ce13f7SAndroid Build Coastguard Worker {
2946*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << Short(rhs); }, lhs);
2947*03ce13f7SAndroid Build Coastguard Worker }
2948*03ce13f7SAndroid Build Coastguard Worker else
2949*03ce13f7SAndroid Build Coastguard Worker {
2950*03ce13f7SAndroid Build Coastguard Worker return RValue<Short8>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
2951*03ce13f7SAndroid Build Coastguard Worker }
2952*03ce13f7SAndroid Build Coastguard Worker }
2953*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<Short8> lhs,unsigned char rhs)2954*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> operator>>(RValue<Short8> lhs, unsigned char rhs)
2955*03ce13f7SAndroid Build Coastguard Worker {
2956*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2957*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
2958*03ce13f7SAndroid Build Coastguard Worker {
2959*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> Short(rhs); }, lhs);
2960*03ce13f7SAndroid Build Coastguard Worker }
2961*03ce13f7SAndroid Build Coastguard Worker else
2962*03ce13f7SAndroid Build Coastguard Worker {
2963*03ce13f7SAndroid Build Coastguard Worker return RValue<Short8>(Nucleus::createAShr(lhs.value(), V(::context->getConstantInt32(rhs))));
2964*03ce13f7SAndroid Build Coastguard Worker }
2965*03ce13f7SAndroid Build Coastguard Worker }
2966*03ce13f7SAndroid Build Coastguard Worker
MulAdd(RValue<Short8> x,RValue<Short8> y)2967*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> MulAdd(RValue<Short8> x, RValue<Short8> y)
2968*03ce13f7SAndroid Build Coastguard Worker {
2969*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2970*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("RValue<Int4> MulAdd(RValue<Short8> x, RValue<Short8> y)");
2971*03ce13f7SAndroid Build Coastguard Worker return Int4(0);
2972*03ce13f7SAndroid Build Coastguard Worker }
2973*03ce13f7SAndroid Build Coastguard Worker
MulHigh(RValue<Short8> x,RValue<Short8> y)2974*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> MulHigh(RValue<Short8> x, RValue<Short8> y)
2975*03ce13f7SAndroid Build Coastguard Worker {
2976*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2977*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("RValue<Short8> MulHigh(RValue<Short8> x, RValue<Short8> y)");
2978*03ce13f7SAndroid Build Coastguard Worker return Short8(0);
2979*03ce13f7SAndroid Build Coastguard Worker }
2980*03ce13f7SAndroid Build Coastguard Worker
type()2981*03ce13f7SAndroid Build Coastguard Worker Type *Short8::type()
2982*03ce13f7SAndroid Build Coastguard Worker {
2983*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v8i16);
2984*03ce13f7SAndroid Build Coastguard Worker }
2985*03ce13f7SAndroid Build Coastguard Worker
Extract(RValue<UShort8> val,int i)2986*03ce13f7SAndroid Build Coastguard Worker RValue<UShort> Extract(RValue<UShort8> val, int i)
2987*03ce13f7SAndroid Build Coastguard Worker {
2988*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2989*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort>(Nucleus::createExtractElement(val.value(), UShort::type(), i));
2990*03ce13f7SAndroid Build Coastguard Worker }
2991*03ce13f7SAndroid Build Coastguard Worker
Insert(RValue<UShort8> val,RValue<UShort> element,int i)2992*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> Insert(RValue<UShort8> val, RValue<UShort> element, int i)
2993*03ce13f7SAndroid Build Coastguard Worker {
2994*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
2995*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort8>(Nucleus::createInsertElement(val.value(), element.value(), i));
2996*03ce13f7SAndroid Build Coastguard Worker }
2997*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<UShort8> lhs,unsigned char rhs)2998*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> operator<<(RValue<UShort8> lhs, unsigned char rhs)
2999*03ce13f7SAndroid Build Coastguard Worker {
3000*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3001*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3002*03ce13f7SAndroid Build Coastguard Worker {
3003*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << UShort(rhs); }, lhs);
3004*03ce13f7SAndroid Build Coastguard Worker }
3005*03ce13f7SAndroid Build Coastguard Worker else
3006*03ce13f7SAndroid Build Coastguard Worker {
3007*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort8>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
3008*03ce13f7SAndroid Build Coastguard Worker }
3009*03ce13f7SAndroid Build Coastguard Worker }
3010*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<UShort8> lhs,unsigned char rhs)3011*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> operator>>(RValue<UShort8> lhs, unsigned char rhs)
3012*03ce13f7SAndroid Build Coastguard Worker {
3013*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3014*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3015*03ce13f7SAndroid Build Coastguard Worker {
3016*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> UShort(rhs); }, lhs);
3017*03ce13f7SAndroid Build Coastguard Worker }
3018*03ce13f7SAndroid Build Coastguard Worker else
3019*03ce13f7SAndroid Build Coastguard Worker {
3020*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort8>(Nucleus::createLShr(lhs.value(), V(::context->getConstantInt32(rhs))));
3021*03ce13f7SAndroid Build Coastguard Worker }
3022*03ce13f7SAndroid Build Coastguard Worker }
3023*03ce13f7SAndroid Build Coastguard Worker
MulHigh(RValue<UShort8> x,RValue<UShort8> y)3024*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> MulHigh(RValue<UShort8> x, RValue<UShort8> y)
3025*03ce13f7SAndroid Build Coastguard Worker {
3026*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3027*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("RValue<UShort8> MulHigh(RValue<UShort8> x, RValue<UShort8> y)");
3028*03ce13f7SAndroid Build Coastguard Worker return UShort8(0);
3029*03ce13f7SAndroid Build Coastguard Worker }
3030*03ce13f7SAndroid Build Coastguard Worker
type()3031*03ce13f7SAndroid Build Coastguard Worker Type *UShort8::type()
3032*03ce13f7SAndroid Build Coastguard Worker {
3033*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v8i16);
3034*03ce13f7SAndroid Build Coastguard Worker }
3035*03ce13f7SAndroid Build Coastguard Worker
operator ++(Int & val,int)3036*03ce13f7SAndroid Build Coastguard Worker RValue<Int> operator++(Int &val, int) // Post-increment
3037*03ce13f7SAndroid Build Coastguard Worker {
3038*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3039*03ce13f7SAndroid Build Coastguard Worker RValue<Int> res = val;
3040*03ce13f7SAndroid Build Coastguard Worker val += 1;
3041*03ce13f7SAndroid Build Coastguard Worker return res;
3042*03ce13f7SAndroid Build Coastguard Worker }
3043*03ce13f7SAndroid Build Coastguard Worker
operator ++(Int & val)3044*03ce13f7SAndroid Build Coastguard Worker const Int &operator++(Int &val) // Pre-increment
3045*03ce13f7SAndroid Build Coastguard Worker {
3046*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3047*03ce13f7SAndroid Build Coastguard Worker val += 1;
3048*03ce13f7SAndroid Build Coastguard Worker return val;
3049*03ce13f7SAndroid Build Coastguard Worker }
3050*03ce13f7SAndroid Build Coastguard Worker
operator --(Int & val,int)3051*03ce13f7SAndroid Build Coastguard Worker RValue<Int> operator--(Int &val, int) // Post-decrement
3052*03ce13f7SAndroid Build Coastguard Worker {
3053*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3054*03ce13f7SAndroid Build Coastguard Worker RValue<Int> res = val;
3055*03ce13f7SAndroid Build Coastguard Worker val -= 1;
3056*03ce13f7SAndroid Build Coastguard Worker return res;
3057*03ce13f7SAndroid Build Coastguard Worker }
3058*03ce13f7SAndroid Build Coastguard Worker
operator --(Int & val)3059*03ce13f7SAndroid Build Coastguard Worker const Int &operator--(Int &val) // Pre-decrement
3060*03ce13f7SAndroid Build Coastguard Worker {
3061*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3062*03ce13f7SAndroid Build Coastguard Worker val -= 1;
3063*03ce13f7SAndroid Build Coastguard Worker return val;
3064*03ce13f7SAndroid Build Coastguard Worker }
3065*03ce13f7SAndroid Build Coastguard Worker
RoundInt(RValue<Float> cast)3066*03ce13f7SAndroid Build Coastguard Worker RValue<Int> RoundInt(RValue<Float> cast)
3067*03ce13f7SAndroid Build Coastguard Worker {
3068*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3069*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
3070*03ce13f7SAndroid Build Coastguard Worker {
3071*03ce13f7SAndroid Build Coastguard Worker // Push the fractional part off the mantissa. Accurate up to +/-2^22.
3072*03ce13f7SAndroid Build Coastguard Worker return Int((cast + Float(0x00C00000)) - Float(0x00C00000));
3073*03ce13f7SAndroid Build Coastguard Worker }
3074*03ce13f7SAndroid Build Coastguard Worker else
3075*03ce13f7SAndroid Build Coastguard Worker {
3076*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32);
3077*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3078*03ce13f7SAndroid Build Coastguard Worker auto nearbyint = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
3079*03ce13f7SAndroid Build Coastguard Worker nearbyint->addArg(cast.value());
3080*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(nearbyint);
3081*03ce13f7SAndroid Build Coastguard Worker
3082*03ce13f7SAndroid Build Coastguard Worker return RValue<Int>(V(result));
3083*03ce13f7SAndroid Build Coastguard Worker }
3084*03ce13f7SAndroid Build Coastguard Worker }
3085*03ce13f7SAndroid Build Coastguard Worker
type()3086*03ce13f7SAndroid Build Coastguard Worker Type *Int::type()
3087*03ce13f7SAndroid Build Coastguard Worker {
3088*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i32);
3089*03ce13f7SAndroid Build Coastguard Worker }
3090*03ce13f7SAndroid Build Coastguard Worker
type()3091*03ce13f7SAndroid Build Coastguard Worker Type *Long::type()
3092*03ce13f7SAndroid Build Coastguard Worker {
3093*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i64);
3094*03ce13f7SAndroid Build Coastguard Worker }
3095*03ce13f7SAndroid Build Coastguard Worker
UInt(RValue<Float> cast)3096*03ce13f7SAndroid Build Coastguard Worker UInt::UInt(RValue<Float> cast)
3097*03ce13f7SAndroid Build Coastguard Worker {
3098*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3099*03ce13f7SAndroid Build Coastguard Worker // Smallest positive value representable in UInt, but not in Int
3100*03ce13f7SAndroid Build Coastguard Worker const unsigned int ustart = 0x80000000u;
3101*03ce13f7SAndroid Build Coastguard Worker const float ustartf = float(ustart);
3102*03ce13f7SAndroid Build Coastguard Worker
3103*03ce13f7SAndroid Build Coastguard Worker // If the value is negative, store 0, otherwise store the result of the conversion
3104*03ce13f7SAndroid Build Coastguard Worker storeValue((~(As<Int>(cast) >> 31) &
3105*03ce13f7SAndroid Build Coastguard Worker // Check if the value can be represented as an Int
3106*03ce13f7SAndroid Build Coastguard Worker IfThenElse(cast >= ustartf,
3107*03ce13f7SAndroid Build Coastguard Worker // If the value is too large, subtract ustart and re-add it after conversion.
3108*03ce13f7SAndroid Build Coastguard Worker As<Int>(As<UInt>(Int(cast - Float(ustartf))) + UInt(ustart)),
3109*03ce13f7SAndroid Build Coastguard Worker // Otherwise, just convert normally
3110*03ce13f7SAndroid Build Coastguard Worker Int(cast)))
3111*03ce13f7SAndroid Build Coastguard Worker .value());
3112*03ce13f7SAndroid Build Coastguard Worker }
3113*03ce13f7SAndroid Build Coastguard Worker
operator ++(UInt & val,int)3114*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> operator++(UInt &val, int) // Post-increment
3115*03ce13f7SAndroid Build Coastguard Worker {
3116*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3117*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> res = val;
3118*03ce13f7SAndroid Build Coastguard Worker val += 1;
3119*03ce13f7SAndroid Build Coastguard Worker return res;
3120*03ce13f7SAndroid Build Coastguard Worker }
3121*03ce13f7SAndroid Build Coastguard Worker
operator ++(UInt & val)3122*03ce13f7SAndroid Build Coastguard Worker const UInt &operator++(UInt &val) // Pre-increment
3123*03ce13f7SAndroid Build Coastguard Worker {
3124*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3125*03ce13f7SAndroid Build Coastguard Worker val += 1;
3126*03ce13f7SAndroid Build Coastguard Worker return val;
3127*03ce13f7SAndroid Build Coastguard Worker }
3128*03ce13f7SAndroid Build Coastguard Worker
operator --(UInt & val,int)3129*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> operator--(UInt &val, int) // Post-decrement
3130*03ce13f7SAndroid Build Coastguard Worker {
3131*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3132*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> res = val;
3133*03ce13f7SAndroid Build Coastguard Worker val -= 1;
3134*03ce13f7SAndroid Build Coastguard Worker return res;
3135*03ce13f7SAndroid Build Coastguard Worker }
3136*03ce13f7SAndroid Build Coastguard Worker
operator --(UInt & val)3137*03ce13f7SAndroid Build Coastguard Worker const UInt &operator--(UInt &val) // Pre-decrement
3138*03ce13f7SAndroid Build Coastguard Worker {
3139*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3140*03ce13f7SAndroid Build Coastguard Worker val -= 1;
3141*03ce13f7SAndroid Build Coastguard Worker return val;
3142*03ce13f7SAndroid Build Coastguard Worker }
3143*03ce13f7SAndroid Build Coastguard Worker
3144*03ce13f7SAndroid Build Coastguard Worker // RValue<UInt> RoundUInt(RValue<Float> cast)
3145*03ce13f7SAndroid Build Coastguard Worker // {
3146*03ce13f7SAndroid Build Coastguard Worker // ASSERT(false && "UNIMPLEMENTED"); return RValue<UInt>(V(nullptr));
3147*03ce13f7SAndroid Build Coastguard Worker // }
3148*03ce13f7SAndroid Build Coastguard Worker
type()3149*03ce13f7SAndroid Build Coastguard Worker Type *UInt::type()
3150*03ce13f7SAndroid Build Coastguard Worker {
3151*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i32);
3152*03ce13f7SAndroid Build Coastguard Worker }
3153*03ce13f7SAndroid Build Coastguard Worker
3154*03ce13f7SAndroid Build Coastguard Worker // Int2::Int2(RValue<Int> cast)
3155*03ce13f7SAndroid Build Coastguard Worker // {
3156*03ce13f7SAndroid Build Coastguard Worker // Value *extend = Nucleus::createZExt(cast.value(), Long::type());
3157*03ce13f7SAndroid Build Coastguard Worker // Value *vector = Nucleus::createBitCast(extend, Int2::type());
3158*03ce13f7SAndroid Build Coastguard Worker //
3159*03ce13f7SAndroid Build Coastguard Worker // Constant *shuffle[2];
3160*03ce13f7SAndroid Build Coastguard Worker // shuffle[0] = Nucleus::createConstantInt(0);
3161*03ce13f7SAndroid Build Coastguard Worker // shuffle[1] = Nucleus::createConstantInt(0);
3162*03ce13f7SAndroid Build Coastguard Worker //
3163*03ce13f7SAndroid Build Coastguard Worker // Value *replicate = Nucleus::createShuffleVector(vector, UndefValue::get(Int2::type()), Nucleus::createConstantVector(shuffle, 2));
3164*03ce13f7SAndroid Build Coastguard Worker //
3165*03ce13f7SAndroid Build Coastguard Worker // storeValue(replicate);
3166*03ce13f7SAndroid Build Coastguard Worker // }
3167*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<Int2> lhs,unsigned char rhs)3168*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> operator<<(RValue<Int2> lhs, unsigned char rhs)
3169*03ce13f7SAndroid Build Coastguard Worker {
3170*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3171*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3172*03ce13f7SAndroid Build Coastguard Worker {
3173*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << rhs; }, lhs);
3174*03ce13f7SAndroid Build Coastguard Worker }
3175*03ce13f7SAndroid Build Coastguard Worker else
3176*03ce13f7SAndroid Build Coastguard Worker {
3177*03ce13f7SAndroid Build Coastguard Worker return RValue<Int2>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
3178*03ce13f7SAndroid Build Coastguard Worker }
3179*03ce13f7SAndroid Build Coastguard Worker }
3180*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<Int2> lhs,unsigned char rhs)3181*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> operator>>(RValue<Int2> lhs, unsigned char rhs)
3182*03ce13f7SAndroid Build Coastguard Worker {
3183*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3184*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3185*03ce13f7SAndroid Build Coastguard Worker {
3186*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> rhs; }, lhs);
3187*03ce13f7SAndroid Build Coastguard Worker }
3188*03ce13f7SAndroid Build Coastguard Worker else
3189*03ce13f7SAndroid Build Coastguard Worker {
3190*03ce13f7SAndroid Build Coastguard Worker return RValue<Int2>(Nucleus::createAShr(lhs.value(), V(::context->getConstantInt32(rhs))));
3191*03ce13f7SAndroid Build Coastguard Worker }
3192*03ce13f7SAndroid Build Coastguard Worker }
3193*03ce13f7SAndroid Build Coastguard Worker
type()3194*03ce13f7SAndroid Build Coastguard Worker Type *Int2::type()
3195*03ce13f7SAndroid Build Coastguard Worker {
3196*03ce13f7SAndroid Build Coastguard Worker return T(Type_v2i32);
3197*03ce13f7SAndroid Build Coastguard Worker }
3198*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<UInt2> lhs,unsigned char rhs)3199*03ce13f7SAndroid Build Coastguard Worker RValue<UInt2> operator<<(RValue<UInt2> lhs, unsigned char rhs)
3200*03ce13f7SAndroid Build Coastguard Worker {
3201*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3202*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3203*03ce13f7SAndroid Build Coastguard Worker {
3204*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << rhs; }, lhs);
3205*03ce13f7SAndroid Build Coastguard Worker }
3206*03ce13f7SAndroid Build Coastguard Worker else
3207*03ce13f7SAndroid Build Coastguard Worker {
3208*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt2>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
3209*03ce13f7SAndroid Build Coastguard Worker }
3210*03ce13f7SAndroid Build Coastguard Worker }
3211*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<UInt2> lhs,unsigned char rhs)3212*03ce13f7SAndroid Build Coastguard Worker RValue<UInt2> operator>>(RValue<UInt2> lhs, unsigned char rhs)
3213*03ce13f7SAndroid Build Coastguard Worker {
3214*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3215*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3216*03ce13f7SAndroid Build Coastguard Worker {
3217*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> rhs; }, lhs);
3218*03ce13f7SAndroid Build Coastguard Worker }
3219*03ce13f7SAndroid Build Coastguard Worker else
3220*03ce13f7SAndroid Build Coastguard Worker {
3221*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt2>(Nucleus::createLShr(lhs.value(), V(::context->getConstantInt32(rhs))));
3222*03ce13f7SAndroid Build Coastguard Worker }
3223*03ce13f7SAndroid Build Coastguard Worker }
3224*03ce13f7SAndroid Build Coastguard Worker
type()3225*03ce13f7SAndroid Build Coastguard Worker Type *UInt2::type()
3226*03ce13f7SAndroid Build Coastguard Worker {
3227*03ce13f7SAndroid Build Coastguard Worker return T(Type_v2i32);
3228*03ce13f7SAndroid Build Coastguard Worker }
3229*03ce13f7SAndroid Build Coastguard Worker
Int4(RValue<Byte4> cast)3230*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<Byte4> cast)
3231*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
3232*03ce13f7SAndroid Build Coastguard Worker {
3233*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3234*03ce13f7SAndroid Build Coastguard Worker Value *x = Nucleus::createBitCast(cast.value(), Int::type());
3235*03ce13f7SAndroid Build Coastguard Worker Value *a = Nucleus::createInsertElement(loadValue(), x, 0);
3236*03ce13f7SAndroid Build Coastguard Worker
3237*03ce13f7SAndroid Build Coastguard Worker Value *e;
3238*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23 };
3239*03ce13f7SAndroid Build Coastguard Worker Value *b = Nucleus::createBitCast(a, Byte16::type());
3240*03ce13f7SAndroid Build Coastguard Worker Value *c = Nucleus::createShuffleVector(b, Nucleus::createNullValue(Byte16::type()), swizzle);
3241*03ce13f7SAndroid Build Coastguard Worker
3242*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle2 = { 0, 8, 1, 9, 2, 10, 3, 11 };
3243*03ce13f7SAndroid Build Coastguard Worker Value *d = Nucleus::createBitCast(c, Short8::type());
3244*03ce13f7SAndroid Build Coastguard Worker e = Nucleus::createShuffleVector(d, Nucleus::createNullValue(Short8::type()), swizzle2);
3245*03ce13f7SAndroid Build Coastguard Worker
3246*03ce13f7SAndroid Build Coastguard Worker Value *f = Nucleus::createBitCast(e, Int4::type());
3247*03ce13f7SAndroid Build Coastguard Worker storeValue(f);
3248*03ce13f7SAndroid Build Coastguard Worker }
3249*03ce13f7SAndroid Build Coastguard Worker
Int4(RValue<SByte4> cast)3250*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<SByte4> cast)
3251*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
3252*03ce13f7SAndroid Build Coastguard Worker {
3253*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3254*03ce13f7SAndroid Build Coastguard Worker Value *x = Nucleus::createBitCast(cast.value(), Int::type());
3255*03ce13f7SAndroid Build Coastguard Worker Value *a = Nucleus::createInsertElement(loadValue(), x, 0);
3256*03ce13f7SAndroid Build Coastguard Worker
3257*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
3258*03ce13f7SAndroid Build Coastguard Worker Value *b = Nucleus::createBitCast(a, Byte16::type());
3259*03ce13f7SAndroid Build Coastguard Worker Value *c = Nucleus::createShuffleVector(b, b, swizzle);
3260*03ce13f7SAndroid Build Coastguard Worker
3261*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle2 = { 0, 0, 1, 1, 2, 2, 3, 3 };
3262*03ce13f7SAndroid Build Coastguard Worker Value *d = Nucleus::createBitCast(c, Short8::type());
3263*03ce13f7SAndroid Build Coastguard Worker Value *e = Nucleus::createShuffleVector(d, d, swizzle2);
3264*03ce13f7SAndroid Build Coastguard Worker
3265*03ce13f7SAndroid Build Coastguard Worker *this = As<Int4>(e) >> 24;
3266*03ce13f7SAndroid Build Coastguard Worker }
3267*03ce13f7SAndroid Build Coastguard Worker
Int4(RValue<Short4> cast)3268*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<Short4> cast)
3269*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
3270*03ce13f7SAndroid Build Coastguard Worker {
3271*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3272*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0, 0, 1, 1, 2, 2, 3, 3 };
3273*03ce13f7SAndroid Build Coastguard Worker Value *c = Nucleus::createShuffleVector(cast.value(), cast.value(), swizzle);
3274*03ce13f7SAndroid Build Coastguard Worker
3275*03ce13f7SAndroid Build Coastguard Worker *this = As<Int4>(c) >> 16;
3276*03ce13f7SAndroid Build Coastguard Worker }
3277*03ce13f7SAndroid Build Coastguard Worker
Int4(RValue<UShort4> cast)3278*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<UShort4> cast)
3279*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
3280*03ce13f7SAndroid Build Coastguard Worker {
3281*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3282*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0, 8, 1, 9, 2, 10, 3, 11 };
3283*03ce13f7SAndroid Build Coastguard Worker Value *c = Nucleus::createShuffleVector(cast.value(), Short8(0, 0, 0, 0, 0, 0, 0, 0).loadValue(), swizzle);
3284*03ce13f7SAndroid Build Coastguard Worker Value *d = Nucleus::createBitCast(c, Int4::type());
3285*03ce13f7SAndroid Build Coastguard Worker storeValue(d);
3286*03ce13f7SAndroid Build Coastguard Worker }
3287*03ce13f7SAndroid Build Coastguard Worker
Int4(RValue<Int> rhs)3288*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<Int> rhs)
3289*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
3290*03ce13f7SAndroid Build Coastguard Worker {
3291*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3292*03ce13f7SAndroid Build Coastguard Worker Value *vector = Nucleus::createBitCast(rhs.value(), Int4::type());
3293*03ce13f7SAndroid Build Coastguard Worker
3294*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0 };
3295*03ce13f7SAndroid Build Coastguard Worker Value *replicate = Nucleus::createShuffleVector(vector, vector, swizzle);
3296*03ce13f7SAndroid Build Coastguard Worker
3297*03ce13f7SAndroid Build Coastguard Worker storeValue(replicate);
3298*03ce13f7SAndroid Build Coastguard Worker }
3299*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<Int4> lhs,unsigned char rhs)3300*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> operator<<(RValue<Int4> lhs, unsigned char rhs)
3301*03ce13f7SAndroid Build Coastguard Worker {
3302*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3303*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3304*03ce13f7SAndroid Build Coastguard Worker {
3305*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << rhs; }, lhs);
3306*03ce13f7SAndroid Build Coastguard Worker }
3307*03ce13f7SAndroid Build Coastguard Worker else
3308*03ce13f7SAndroid Build Coastguard Worker {
3309*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
3310*03ce13f7SAndroid Build Coastguard Worker }
3311*03ce13f7SAndroid Build Coastguard Worker }
3312*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<Int4> lhs,unsigned char rhs)3313*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> operator>>(RValue<Int4> lhs, unsigned char rhs)
3314*03ce13f7SAndroid Build Coastguard Worker {
3315*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3316*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3317*03ce13f7SAndroid Build Coastguard Worker {
3318*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> rhs; }, lhs);
3319*03ce13f7SAndroid Build Coastguard Worker }
3320*03ce13f7SAndroid Build Coastguard Worker else
3321*03ce13f7SAndroid Build Coastguard Worker {
3322*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createAShr(lhs.value(), V(::context->getConstantInt32(rhs))));
3323*03ce13f7SAndroid Build Coastguard Worker }
3324*03ce13f7SAndroid Build Coastguard Worker }
3325*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<Int4> x,RValue<Int4> y)3326*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpEQ(RValue<Int4> x, RValue<Int4> y)
3327*03ce13f7SAndroid Build Coastguard Worker {
3328*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3329*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createICmpEQ(x.value(), y.value()));
3330*03ce13f7SAndroid Build Coastguard Worker }
3331*03ce13f7SAndroid Build Coastguard Worker
CmpLT(RValue<Int4> x,RValue<Int4> y)3332*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpLT(RValue<Int4> x, RValue<Int4> y)
3333*03ce13f7SAndroid Build Coastguard Worker {
3334*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3335*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createICmpSLT(x.value(), y.value()));
3336*03ce13f7SAndroid Build Coastguard Worker }
3337*03ce13f7SAndroid Build Coastguard Worker
CmpLE(RValue<Int4> x,RValue<Int4> y)3338*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpLE(RValue<Int4> x, RValue<Int4> y)
3339*03ce13f7SAndroid Build Coastguard Worker {
3340*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3341*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createICmpSLE(x.value(), y.value()));
3342*03ce13f7SAndroid Build Coastguard Worker }
3343*03ce13f7SAndroid Build Coastguard Worker
CmpNEQ(RValue<Int4> x,RValue<Int4> y)3344*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNEQ(RValue<Int4> x, RValue<Int4> y)
3345*03ce13f7SAndroid Build Coastguard Worker {
3346*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3347*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createICmpNE(x.value(), y.value()));
3348*03ce13f7SAndroid Build Coastguard Worker }
3349*03ce13f7SAndroid Build Coastguard Worker
CmpNLT(RValue<Int4> x,RValue<Int4> y)3350*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNLT(RValue<Int4> x, RValue<Int4> y)
3351*03ce13f7SAndroid Build Coastguard Worker {
3352*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3353*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createICmpSGE(x.value(), y.value()));
3354*03ce13f7SAndroid Build Coastguard Worker }
3355*03ce13f7SAndroid Build Coastguard Worker
CmpNLE(RValue<Int4> x,RValue<Int4> y)3356*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNLE(RValue<Int4> x, RValue<Int4> y)
3357*03ce13f7SAndroid Build Coastguard Worker {
3358*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3359*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createICmpSGT(x.value(), y.value()));
3360*03ce13f7SAndroid Build Coastguard Worker }
3361*03ce13f7SAndroid Build Coastguard Worker
Abs(RValue<Int4> x)3362*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> Abs(RValue<Int4> x)
3363*03ce13f7SAndroid Build Coastguard Worker {
3364*03ce13f7SAndroid Build Coastguard Worker // TODO: Optimize.
3365*03ce13f7SAndroid Build Coastguard Worker auto negative = x >> 31;
3366*03ce13f7SAndroid Build Coastguard Worker return (x ^ negative) - negative;
3367*03ce13f7SAndroid Build Coastguard Worker }
3368*03ce13f7SAndroid Build Coastguard Worker
Max(RValue<Int4> x,RValue<Int4> y)3369*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> Max(RValue<Int4> x, RValue<Int4> y)
3370*03ce13f7SAndroid Build Coastguard Worker {
3371*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3372*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
3373*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sle, condition, x.value(), y.value());
3374*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
3375*03ce13f7SAndroid Build Coastguard Worker
3376*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
3377*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
3378*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
3379*03ce13f7SAndroid Build Coastguard Worker
3380*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(V(result));
3381*03ce13f7SAndroid Build Coastguard Worker }
3382*03ce13f7SAndroid Build Coastguard Worker
Min(RValue<Int4> x,RValue<Int4> y)3383*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> Min(RValue<Int4> x, RValue<Int4> y)
3384*03ce13f7SAndroid Build Coastguard Worker {
3385*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3386*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
3387*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sgt, condition, x.value(), y.value());
3388*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
3389*03ce13f7SAndroid Build Coastguard Worker
3390*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
3391*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
3392*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
3393*03ce13f7SAndroid Build Coastguard Worker
3394*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(V(result));
3395*03ce13f7SAndroid Build Coastguard Worker }
3396*03ce13f7SAndroid Build Coastguard Worker
RoundInt(RValue<Float4> cast)3397*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> RoundInt(RValue<Float4> cast)
3398*03ce13f7SAndroid Build Coastguard Worker {
3399*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3400*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
3401*03ce13f7SAndroid Build Coastguard Worker {
3402*03ce13f7SAndroid Build Coastguard Worker // Push the fractional part off the mantissa. Accurate up to +/-2^22.
3403*03ce13f7SAndroid Build Coastguard Worker return Int4((cast + Float4(0x00C00000)) - Float4(0x00C00000));
3404*03ce13f7SAndroid Build Coastguard Worker }
3405*03ce13f7SAndroid Build Coastguard Worker else
3406*03ce13f7SAndroid Build Coastguard Worker {
3407*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
3408*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3409*03ce13f7SAndroid Build Coastguard Worker auto nearbyint = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
3410*03ce13f7SAndroid Build Coastguard Worker nearbyint->addArg(cast.value());
3411*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(nearbyint);
3412*03ce13f7SAndroid Build Coastguard Worker
3413*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(V(result));
3414*03ce13f7SAndroid Build Coastguard Worker }
3415*03ce13f7SAndroid Build Coastguard Worker }
3416*03ce13f7SAndroid Build Coastguard Worker
RoundIntClamped(RValue<Float4> cast)3417*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> RoundIntClamped(RValue<Float4> cast)
3418*03ce13f7SAndroid Build Coastguard Worker {
3419*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3420*03ce13f7SAndroid Build Coastguard Worker
3421*03ce13f7SAndroid Build Coastguard Worker // cvtps2dq produces 0x80000000, a negative value, for input larger than
3422*03ce13f7SAndroid Build Coastguard Worker // 2147483520.0, so clamp to 2147483520. Values less than -2147483520.0
3423*03ce13f7SAndroid Build Coastguard Worker // saturate to 0x80000000.
3424*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> clamped = Min(cast, Float4(0x7FFFFF80));
3425*03ce13f7SAndroid Build Coastguard Worker
3426*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
3427*03ce13f7SAndroid Build Coastguard Worker {
3428*03ce13f7SAndroid Build Coastguard Worker // Push the fractional part off the mantissa. Accurate up to +/-2^22.
3429*03ce13f7SAndroid Build Coastguard Worker return Int4((clamped + Float4(0x00C00000)) - Float4(0x00C00000));
3430*03ce13f7SAndroid Build Coastguard Worker }
3431*03ce13f7SAndroid Build Coastguard Worker else
3432*03ce13f7SAndroid Build Coastguard Worker {
3433*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
3434*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3435*03ce13f7SAndroid Build Coastguard Worker auto nearbyint = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
3436*03ce13f7SAndroid Build Coastguard Worker nearbyint->addArg(clamped.value());
3437*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(nearbyint);
3438*03ce13f7SAndroid Build Coastguard Worker
3439*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(V(result));
3440*03ce13f7SAndroid Build Coastguard Worker }
3441*03ce13f7SAndroid Build Coastguard Worker }
3442*03ce13f7SAndroid Build Coastguard Worker
PackSigned(RValue<Int4> x,RValue<Int4> y)3443*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> PackSigned(RValue<Int4> x, RValue<Int4> y)
3444*03ce13f7SAndroid Build Coastguard Worker {
3445*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3446*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3447*03ce13f7SAndroid Build Coastguard Worker {
3448*03ce13f7SAndroid Build Coastguard Worker Short8 result;
3449*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(x, 0)), 0);
3450*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(x, 1)), 1);
3451*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(x, 2)), 2);
3452*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(x, 3)), 3);
3453*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(y, 0)), 4);
3454*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(y, 1)), 5);
3455*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(y, 2)), 6);
3456*03ce13f7SAndroid Build Coastguard Worker result = Insert(result, SaturateSigned(Extract(y, 3)), 7);
3457*03ce13f7SAndroid Build Coastguard Worker
3458*03ce13f7SAndroid Build Coastguard Worker return result;
3459*03ce13f7SAndroid Build Coastguard Worker }
3460*03ce13f7SAndroid Build Coastguard Worker else
3461*03ce13f7SAndroid Build Coastguard Worker {
3462*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
3463*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::VectorPackSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3464*03ce13f7SAndroid Build Coastguard Worker auto pack = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
3465*03ce13f7SAndroid Build Coastguard Worker pack->addArg(x.value());
3466*03ce13f7SAndroid Build Coastguard Worker pack->addArg(y.value());
3467*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(pack);
3468*03ce13f7SAndroid Build Coastguard Worker
3469*03ce13f7SAndroid Build Coastguard Worker return RValue<Short8>(V(result));
3470*03ce13f7SAndroid Build Coastguard Worker }
3471*03ce13f7SAndroid Build Coastguard Worker }
3472*03ce13f7SAndroid Build Coastguard Worker
PackUnsigned(RValue<Int4> x,RValue<Int4> y)3473*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> PackUnsigned(RValue<Int4> x, RValue<Int4> y)
3474*03ce13f7SAndroid Build Coastguard Worker {
3475*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3476*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || !(CPUID::SSE4_1 || CPUID::ARM))
3477*03ce13f7SAndroid Build Coastguard Worker {
3478*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> sx = As<Int4>(x);
3479*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> bx = (sx & ~(sx >> 31)) - Int4(0x8000);
3480*03ce13f7SAndroid Build Coastguard Worker
3481*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> sy = As<Int4>(y);
3482*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> by = (sy & ~(sy >> 31)) - Int4(0x8000);
3483*03ce13f7SAndroid Build Coastguard Worker
3484*03ce13f7SAndroid Build Coastguard Worker return As<UShort8>(PackSigned(bx, by) + Short8(0x8000u));
3485*03ce13f7SAndroid Build Coastguard Worker }
3486*03ce13f7SAndroid Build Coastguard Worker else
3487*03ce13f7SAndroid Build Coastguard Worker {
3488*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
3489*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::VectorPackUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3490*03ce13f7SAndroid Build Coastguard Worker auto pack = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
3491*03ce13f7SAndroid Build Coastguard Worker pack->addArg(x.value());
3492*03ce13f7SAndroid Build Coastguard Worker pack->addArg(y.value());
3493*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(pack);
3494*03ce13f7SAndroid Build Coastguard Worker
3495*03ce13f7SAndroid Build Coastguard Worker return RValue<UShort8>(V(result));
3496*03ce13f7SAndroid Build Coastguard Worker }
3497*03ce13f7SAndroid Build Coastguard Worker }
3498*03ce13f7SAndroid Build Coastguard Worker
SignMask(RValue<Int4> x)3499*03ce13f7SAndroid Build Coastguard Worker RValue<Int> SignMask(RValue<Int4> x)
3500*03ce13f7SAndroid Build Coastguard Worker {
3501*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3502*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
3503*03ce13f7SAndroid Build Coastguard Worker {
3504*03ce13f7SAndroid Build Coastguard Worker Int4 xx = (x >> 31) & Int4(0x00000001, 0x00000002, 0x00000004, 0x00000008);
3505*03ce13f7SAndroid Build Coastguard Worker return Extract(xx, 0) | Extract(xx, 1) | Extract(xx, 2) | Extract(xx, 3);
3506*03ce13f7SAndroid Build Coastguard Worker }
3507*03ce13f7SAndroid Build Coastguard Worker else
3508*03ce13f7SAndroid Build Coastguard Worker {
3509*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32);
3510*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::SignMask, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3511*03ce13f7SAndroid Build Coastguard Worker auto movmsk = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
3512*03ce13f7SAndroid Build Coastguard Worker movmsk->addArg(x.value());
3513*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(movmsk);
3514*03ce13f7SAndroid Build Coastguard Worker
3515*03ce13f7SAndroid Build Coastguard Worker return RValue<Int>(V(result));
3516*03ce13f7SAndroid Build Coastguard Worker }
3517*03ce13f7SAndroid Build Coastguard Worker }
3518*03ce13f7SAndroid Build Coastguard Worker
type()3519*03ce13f7SAndroid Build Coastguard Worker Type *Int4::type()
3520*03ce13f7SAndroid Build Coastguard Worker {
3521*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v4i32);
3522*03ce13f7SAndroid Build Coastguard Worker }
3523*03ce13f7SAndroid Build Coastguard Worker
UInt4(RValue<Float4> cast)3524*03ce13f7SAndroid Build Coastguard Worker UInt4::UInt4(RValue<Float4> cast)
3525*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
3526*03ce13f7SAndroid Build Coastguard Worker {
3527*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3528*03ce13f7SAndroid Build Coastguard Worker // Smallest positive value representable in UInt, but not in Int
3529*03ce13f7SAndroid Build Coastguard Worker const unsigned int ustart = 0x80000000u;
3530*03ce13f7SAndroid Build Coastguard Worker const float ustartf = float(ustart);
3531*03ce13f7SAndroid Build Coastguard Worker
3532*03ce13f7SAndroid Build Coastguard Worker // Check if the value can be represented as an Int
3533*03ce13f7SAndroid Build Coastguard Worker Int4 uiValue = CmpNLT(cast, Float4(ustartf));
3534*03ce13f7SAndroid Build Coastguard Worker // If the value is too large, subtract ustart and re-add it after conversion.
3535*03ce13f7SAndroid Build Coastguard Worker uiValue = (uiValue & As<Int4>(As<UInt4>(Int4(cast - Float4(ustartf))) + UInt4(ustart))) |
3536*03ce13f7SAndroid Build Coastguard Worker // Otherwise, just convert normally
3537*03ce13f7SAndroid Build Coastguard Worker (~uiValue & Int4(cast));
3538*03ce13f7SAndroid Build Coastguard Worker // If the value is negative, store 0, otherwise store the result of the conversion
3539*03ce13f7SAndroid Build Coastguard Worker storeValue((~(As<Int4>(cast) >> 31) & uiValue).value());
3540*03ce13f7SAndroid Build Coastguard Worker }
3541*03ce13f7SAndroid Build Coastguard Worker
UInt4(RValue<UInt> rhs)3542*03ce13f7SAndroid Build Coastguard Worker UInt4::UInt4(RValue<UInt> rhs)
3543*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
3544*03ce13f7SAndroid Build Coastguard Worker {
3545*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3546*03ce13f7SAndroid Build Coastguard Worker Value *vector = Nucleus::createBitCast(rhs.value(), UInt4::type());
3547*03ce13f7SAndroid Build Coastguard Worker
3548*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0 };
3549*03ce13f7SAndroid Build Coastguard Worker Value *replicate = Nucleus::createShuffleVector(vector, vector, swizzle);
3550*03ce13f7SAndroid Build Coastguard Worker
3551*03ce13f7SAndroid Build Coastguard Worker storeValue(replicate);
3552*03ce13f7SAndroid Build Coastguard Worker }
3553*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<UInt4> lhs,unsigned char rhs)3554*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> operator<<(RValue<UInt4> lhs, unsigned char rhs)
3555*03ce13f7SAndroid Build Coastguard Worker {
3556*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3557*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3558*03ce13f7SAndroid Build Coastguard Worker {
3559*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << rhs; }, lhs);
3560*03ce13f7SAndroid Build Coastguard Worker }
3561*03ce13f7SAndroid Build Coastguard Worker else
3562*03ce13f7SAndroid Build Coastguard Worker {
3563*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
3564*03ce13f7SAndroid Build Coastguard Worker }
3565*03ce13f7SAndroid Build Coastguard Worker }
3566*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<UInt4> lhs,unsigned char rhs)3567*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> operator>>(RValue<UInt4> lhs, unsigned char rhs)
3568*03ce13f7SAndroid Build Coastguard Worker {
3569*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3570*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
3571*03ce13f7SAndroid Build Coastguard Worker {
3572*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> rhs; }, lhs);
3573*03ce13f7SAndroid Build Coastguard Worker }
3574*03ce13f7SAndroid Build Coastguard Worker else
3575*03ce13f7SAndroid Build Coastguard Worker {
3576*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(Nucleus::createLShr(lhs.value(), V(::context->getConstantInt32(rhs))));
3577*03ce13f7SAndroid Build Coastguard Worker }
3578*03ce13f7SAndroid Build Coastguard Worker }
3579*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<UInt4> x,RValue<UInt4> y)3580*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpEQ(RValue<UInt4> x, RValue<UInt4> y)
3581*03ce13f7SAndroid Build Coastguard Worker {
3582*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3583*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(Nucleus::createICmpEQ(x.value(), y.value()));
3584*03ce13f7SAndroid Build Coastguard Worker }
3585*03ce13f7SAndroid Build Coastguard Worker
CmpLT(RValue<UInt4> x,RValue<UInt4> y)3586*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpLT(RValue<UInt4> x, RValue<UInt4> y)
3587*03ce13f7SAndroid Build Coastguard Worker {
3588*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3589*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(Nucleus::createICmpULT(x.value(), y.value()));
3590*03ce13f7SAndroid Build Coastguard Worker }
3591*03ce13f7SAndroid Build Coastguard Worker
CmpLE(RValue<UInt4> x,RValue<UInt4> y)3592*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpLE(RValue<UInt4> x, RValue<UInt4> y)
3593*03ce13f7SAndroid Build Coastguard Worker {
3594*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3595*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(Nucleus::createICmpULE(x.value(), y.value()));
3596*03ce13f7SAndroid Build Coastguard Worker }
3597*03ce13f7SAndroid Build Coastguard Worker
CmpNEQ(RValue<UInt4> x,RValue<UInt4> y)3598*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpNEQ(RValue<UInt4> x, RValue<UInt4> y)
3599*03ce13f7SAndroid Build Coastguard Worker {
3600*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3601*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(Nucleus::createICmpNE(x.value(), y.value()));
3602*03ce13f7SAndroid Build Coastguard Worker }
3603*03ce13f7SAndroid Build Coastguard Worker
CmpNLT(RValue<UInt4> x,RValue<UInt4> y)3604*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpNLT(RValue<UInt4> x, RValue<UInt4> y)
3605*03ce13f7SAndroid Build Coastguard Worker {
3606*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3607*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(Nucleus::createICmpUGE(x.value(), y.value()));
3608*03ce13f7SAndroid Build Coastguard Worker }
3609*03ce13f7SAndroid Build Coastguard Worker
CmpNLE(RValue<UInt4> x,RValue<UInt4> y)3610*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpNLE(RValue<UInt4> x, RValue<UInt4> y)
3611*03ce13f7SAndroid Build Coastguard Worker {
3612*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3613*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(Nucleus::createICmpUGT(x.value(), y.value()));
3614*03ce13f7SAndroid Build Coastguard Worker }
3615*03ce13f7SAndroid Build Coastguard Worker
Max(RValue<UInt4> x,RValue<UInt4> y)3616*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Max(RValue<UInt4> x, RValue<UInt4> y)
3617*03ce13f7SAndroid Build Coastguard Worker {
3618*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3619*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
3620*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ule, condition, x.value(), y.value());
3621*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
3622*03ce13f7SAndroid Build Coastguard Worker
3623*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
3624*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
3625*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
3626*03ce13f7SAndroid Build Coastguard Worker
3627*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(V(result));
3628*03ce13f7SAndroid Build Coastguard Worker }
3629*03ce13f7SAndroid Build Coastguard Worker
Min(RValue<UInt4> x,RValue<UInt4> y)3630*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Min(RValue<UInt4> x, RValue<UInt4> y)
3631*03ce13f7SAndroid Build Coastguard Worker {
3632*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3633*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
3634*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ugt, condition, x.value(), y.value());
3635*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
3636*03ce13f7SAndroid Build Coastguard Worker
3637*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
3638*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
3639*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
3640*03ce13f7SAndroid Build Coastguard Worker
3641*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt4>(V(result));
3642*03ce13f7SAndroid Build Coastguard Worker }
3643*03ce13f7SAndroid Build Coastguard Worker
type()3644*03ce13f7SAndroid Build Coastguard Worker Type *UInt4::type()
3645*03ce13f7SAndroid Build Coastguard Worker {
3646*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v4i32);
3647*03ce13f7SAndroid Build Coastguard Worker }
3648*03ce13f7SAndroid Build Coastguard Worker
type()3649*03ce13f7SAndroid Build Coastguard Worker Type *Half::type()
3650*03ce13f7SAndroid Build Coastguard Worker {
3651*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_i16);
3652*03ce13f7SAndroid Build Coastguard Worker }
3653*03ce13f7SAndroid Build Coastguard Worker
Sqrt(RValue<Float> x)3654*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Sqrt(RValue<Float> x)
3655*03ce13f7SAndroid Build Coastguard Worker {
3656*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3657*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_f32);
3658*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Sqrt, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3659*03ce13f7SAndroid Build Coastguard Worker auto sqrt = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
3660*03ce13f7SAndroid Build Coastguard Worker sqrt->addArg(x.value());
3661*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(sqrt);
3662*03ce13f7SAndroid Build Coastguard Worker
3663*03ce13f7SAndroid Build Coastguard Worker return RValue<Float>(V(result));
3664*03ce13f7SAndroid Build Coastguard Worker }
3665*03ce13f7SAndroid Build Coastguard Worker
Round(RValue<Float> x)3666*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Round(RValue<Float> x)
3667*03ce13f7SAndroid Build Coastguard Worker {
3668*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3669*03ce13f7SAndroid Build Coastguard Worker return Float4(Round(Float4(x))).x;
3670*03ce13f7SAndroid Build Coastguard Worker }
3671*03ce13f7SAndroid Build Coastguard Worker
Trunc(RValue<Float> x)3672*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Trunc(RValue<Float> x)
3673*03ce13f7SAndroid Build Coastguard Worker {
3674*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3675*03ce13f7SAndroid Build Coastguard Worker return Float4(Trunc(Float4(x))).x;
3676*03ce13f7SAndroid Build Coastguard Worker }
3677*03ce13f7SAndroid Build Coastguard Worker
Frac(RValue<Float> x)3678*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Frac(RValue<Float> x)
3679*03ce13f7SAndroid Build Coastguard Worker {
3680*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3681*03ce13f7SAndroid Build Coastguard Worker return Float4(Frac(Float4(x))).x;
3682*03ce13f7SAndroid Build Coastguard Worker }
3683*03ce13f7SAndroid Build Coastguard Worker
Floor(RValue<Float> x)3684*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Floor(RValue<Float> x)
3685*03ce13f7SAndroid Build Coastguard Worker {
3686*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3687*03ce13f7SAndroid Build Coastguard Worker return Float4(Floor(Float4(x))).x;
3688*03ce13f7SAndroid Build Coastguard Worker }
3689*03ce13f7SAndroid Build Coastguard Worker
Ceil(RValue<Float> x)3690*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Ceil(RValue<Float> x)
3691*03ce13f7SAndroid Build Coastguard Worker {
3692*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3693*03ce13f7SAndroid Build Coastguard Worker return Float4(Ceil(Float4(x))).x;
3694*03ce13f7SAndroid Build Coastguard Worker }
3695*03ce13f7SAndroid Build Coastguard Worker
type()3696*03ce13f7SAndroid Build Coastguard Worker Type *Float::type()
3697*03ce13f7SAndroid Build Coastguard Worker {
3698*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_f32);
3699*03ce13f7SAndroid Build Coastguard Worker }
3700*03ce13f7SAndroid Build Coastguard Worker
type()3701*03ce13f7SAndroid Build Coastguard Worker Type *Float2::type()
3702*03ce13f7SAndroid Build Coastguard Worker {
3703*03ce13f7SAndroid Build Coastguard Worker return T(Type_v2f32);
3704*03ce13f7SAndroid Build Coastguard Worker }
3705*03ce13f7SAndroid Build Coastguard Worker
Float4(RValue<Float> rhs)3706*03ce13f7SAndroid Build Coastguard Worker Float4::Float4(RValue<Float> rhs)
3707*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
3708*03ce13f7SAndroid Build Coastguard Worker {
3709*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3710*03ce13f7SAndroid Build Coastguard Worker Value *vector = Nucleus::createBitCast(rhs.value(), Float4::type());
3711*03ce13f7SAndroid Build Coastguard Worker
3712*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0 };
3713*03ce13f7SAndroid Build Coastguard Worker Value *replicate = Nucleus::createShuffleVector(vector, vector, swizzle);
3714*03ce13f7SAndroid Build Coastguard Worker
3715*03ce13f7SAndroid Build Coastguard Worker storeValue(replicate);
3716*03ce13f7SAndroid Build Coastguard Worker }
3717*03ce13f7SAndroid Build Coastguard Worker
operator %(RValue<Float4> lhs,RValue<Float4> rhs)3718*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> operator%(RValue<Float4> lhs, RValue<Float4> rhs)
3719*03ce13f7SAndroid Build Coastguard Worker {
3720*03ce13f7SAndroid Build Coastguard Worker return ScalarizeCall(fmodf, lhs, rhs);
3721*03ce13f7SAndroid Build Coastguard Worker }
3722*03ce13f7SAndroid Build Coastguard Worker
MulAdd(RValue<Float4> x,RValue<Float4> y,RValue<Float4> z)3723*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> MulAdd(RValue<Float4> x, RValue<Float4> y, RValue<Float4> z)
3724*03ce13f7SAndroid Build Coastguard Worker {
3725*03ce13f7SAndroid Build Coastguard Worker // TODO(b/214591655): Use FMA when available.
3726*03ce13f7SAndroid Build Coastguard Worker return x * y + z;
3727*03ce13f7SAndroid Build Coastguard Worker }
3728*03ce13f7SAndroid Build Coastguard Worker
FMA(RValue<Float4> x,RValue<Float4> y,RValue<Float4> z)3729*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> FMA(RValue<Float4> x, RValue<Float4> y, RValue<Float4> z)
3730*03ce13f7SAndroid Build Coastguard Worker {
3731*03ce13f7SAndroid Build Coastguard Worker // TODO(b/214591655): Use FMA instructions when available.
3732*03ce13f7SAndroid Build Coastguard Worker return ScalarizeCall(fmaf, x, y, z);
3733*03ce13f7SAndroid Build Coastguard Worker }
3734*03ce13f7SAndroid Build Coastguard Worker
Abs(RValue<Float4> x)3735*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Abs(RValue<Float4> x)
3736*03ce13f7SAndroid Build Coastguard Worker {
3737*03ce13f7SAndroid Build Coastguard Worker // TODO: Optimize.
3738*03ce13f7SAndroid Build Coastguard Worker Value *vector = Nucleus::createBitCast(x.value(), Int4::type());
3739*03ce13f7SAndroid Build Coastguard Worker std::vector<int64_t> constantVector = { 0x7FFFFFFF };
3740*03ce13f7SAndroid Build Coastguard Worker Value *result = Nucleus::createAnd(vector, Nucleus::createConstantVector(constantVector, Int4::type()));
3741*03ce13f7SAndroid Build Coastguard Worker
3742*03ce13f7SAndroid Build Coastguard Worker return As<Float4>(result);
3743*03ce13f7SAndroid Build Coastguard Worker }
3744*03ce13f7SAndroid Build Coastguard Worker
Max(RValue<Float4> x,RValue<Float4> y)3745*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Max(RValue<Float4> x, RValue<Float4> y)
3746*03ce13f7SAndroid Build Coastguard Worker {
3747*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3748*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
3749*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstFcmp::create(::function, Ice::InstFcmp::Ogt, condition, x.value(), y.value());
3750*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
3751*03ce13f7SAndroid Build Coastguard Worker
3752*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
3753*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, x.value(), y.value());
3754*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
3755*03ce13f7SAndroid Build Coastguard Worker
3756*03ce13f7SAndroid Build Coastguard Worker return RValue<Float4>(V(result));
3757*03ce13f7SAndroid Build Coastguard Worker }
3758*03ce13f7SAndroid Build Coastguard Worker
Min(RValue<Float4> x,RValue<Float4> y)3759*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Min(RValue<Float4> x, RValue<Float4> y)
3760*03ce13f7SAndroid Build Coastguard Worker {
3761*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3762*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
3763*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstFcmp::create(::function, Ice::InstFcmp::Olt, condition, x.value(), y.value());
3764*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
3765*03ce13f7SAndroid Build Coastguard Worker
3766*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
3767*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, x.value(), y.value());
3768*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
3769*03ce13f7SAndroid Build Coastguard Worker
3770*03ce13f7SAndroid Build Coastguard Worker return RValue<Float4>(V(result));
3771*03ce13f7SAndroid Build Coastguard Worker }
3772*03ce13f7SAndroid Build Coastguard Worker
HasRcpApprox()3773*03ce13f7SAndroid Build Coastguard Worker bool HasRcpApprox()
3774*03ce13f7SAndroid Build Coastguard Worker {
3775*03ce13f7SAndroid Build Coastguard Worker // TODO(b/175612820): Update once we implement x86 SSE rcp_ss and rsqrt_ss intrinsics in Subzero
3776*03ce13f7SAndroid Build Coastguard Worker return false;
3777*03ce13f7SAndroid Build Coastguard Worker }
3778*03ce13f7SAndroid Build Coastguard Worker
RcpApprox(RValue<Float4> x,bool exactAtPow2)3779*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> RcpApprox(RValue<Float4> x, bool exactAtPow2)
3780*03ce13f7SAndroid Build Coastguard Worker {
3781*03ce13f7SAndroid Build Coastguard Worker // TODO(b/175612820): Update once we implement x86 SSE rcp_ss and rsqrt_ss intrinsics in Subzero
3782*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("RValue<Float4> RcpApprox()");
3783*03ce13f7SAndroid Build Coastguard Worker return { 0.0f };
3784*03ce13f7SAndroid Build Coastguard Worker }
3785*03ce13f7SAndroid Build Coastguard Worker
RcpApprox(RValue<Float> x,bool exactAtPow2)3786*03ce13f7SAndroid Build Coastguard Worker RValue<Float> RcpApprox(RValue<Float> x, bool exactAtPow2)
3787*03ce13f7SAndroid Build Coastguard Worker {
3788*03ce13f7SAndroid Build Coastguard Worker // TODO(b/175612820): Update once we implement x86 SSE rcp_ss and rsqrt_ss intrinsics in Subzero
3789*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("RValue<Float> RcpApprox()");
3790*03ce13f7SAndroid Build Coastguard Worker return { 0.0f };
3791*03ce13f7SAndroid Build Coastguard Worker }
3792*03ce13f7SAndroid Build Coastguard Worker
HasRcpSqrtApprox()3793*03ce13f7SAndroid Build Coastguard Worker bool HasRcpSqrtApprox()
3794*03ce13f7SAndroid Build Coastguard Worker {
3795*03ce13f7SAndroid Build Coastguard Worker return false;
3796*03ce13f7SAndroid Build Coastguard Worker }
3797*03ce13f7SAndroid Build Coastguard Worker
RcpSqrtApprox(RValue<Float4> x)3798*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> RcpSqrtApprox(RValue<Float4> x)
3799*03ce13f7SAndroid Build Coastguard Worker {
3800*03ce13f7SAndroid Build Coastguard Worker // TODO(b/175612820): Update once we implement x86 SSE rcp_ss and rsqrt_ss intrinsics in Subzero
3801*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("RValue<Float4> RcpSqrtApprox()");
3802*03ce13f7SAndroid Build Coastguard Worker return { 0.0f };
3803*03ce13f7SAndroid Build Coastguard Worker }
3804*03ce13f7SAndroid Build Coastguard Worker
RcpSqrtApprox(RValue<Float> x)3805*03ce13f7SAndroid Build Coastguard Worker RValue<Float> RcpSqrtApprox(RValue<Float> x)
3806*03ce13f7SAndroid Build Coastguard Worker {
3807*03ce13f7SAndroid Build Coastguard Worker // TODO(b/175612820): Update once we implement x86 SSE rcp_ss and rsqrt_ss intrinsics in Subzero
3808*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("RValue<Float> RcpSqrtApprox()");
3809*03ce13f7SAndroid Build Coastguard Worker return { 0.0f };
3810*03ce13f7SAndroid Build Coastguard Worker }
3811*03ce13f7SAndroid Build Coastguard Worker
Sqrt(RValue<Float4> x)3812*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Sqrt(RValue<Float4> x)
3813*03ce13f7SAndroid Build Coastguard Worker {
3814*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3815*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
3816*03ce13f7SAndroid Build Coastguard Worker {
3817*03ce13f7SAndroid Build Coastguard Worker Float4 result;
3818*03ce13f7SAndroid Build Coastguard Worker result.x = Sqrt(Float(Float4(x).x));
3819*03ce13f7SAndroid Build Coastguard Worker result.y = Sqrt(Float(Float4(x).y));
3820*03ce13f7SAndroid Build Coastguard Worker result.z = Sqrt(Float(Float4(x).z));
3821*03ce13f7SAndroid Build Coastguard Worker result.w = Sqrt(Float(Float4(x).w));
3822*03ce13f7SAndroid Build Coastguard Worker
3823*03ce13f7SAndroid Build Coastguard Worker return result;
3824*03ce13f7SAndroid Build Coastguard Worker }
3825*03ce13f7SAndroid Build Coastguard Worker else
3826*03ce13f7SAndroid Build Coastguard Worker {
3827*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
3828*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Sqrt, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3829*03ce13f7SAndroid Build Coastguard Worker auto sqrt = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
3830*03ce13f7SAndroid Build Coastguard Worker sqrt->addArg(x.value());
3831*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(sqrt);
3832*03ce13f7SAndroid Build Coastguard Worker
3833*03ce13f7SAndroid Build Coastguard Worker return RValue<Float4>(V(result));
3834*03ce13f7SAndroid Build Coastguard Worker }
3835*03ce13f7SAndroid Build Coastguard Worker }
3836*03ce13f7SAndroid Build Coastguard Worker
SignMask(RValue<Float4> x)3837*03ce13f7SAndroid Build Coastguard Worker RValue<Int> SignMask(RValue<Float4> x)
3838*03ce13f7SAndroid Build Coastguard Worker {
3839*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3840*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
3841*03ce13f7SAndroid Build Coastguard Worker {
3842*03ce13f7SAndroid Build Coastguard Worker Int4 xx = (As<Int4>(x) >> 31) & Int4(0x00000001, 0x00000002, 0x00000004, 0x00000008);
3843*03ce13f7SAndroid Build Coastguard Worker return Extract(xx, 0) | Extract(xx, 1) | Extract(xx, 2) | Extract(xx, 3);
3844*03ce13f7SAndroid Build Coastguard Worker }
3845*03ce13f7SAndroid Build Coastguard Worker else
3846*03ce13f7SAndroid Build Coastguard Worker {
3847*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32);
3848*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::SignMask, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3849*03ce13f7SAndroid Build Coastguard Worker auto movmsk = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
3850*03ce13f7SAndroid Build Coastguard Worker movmsk->addArg(x.value());
3851*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(movmsk);
3852*03ce13f7SAndroid Build Coastguard Worker
3853*03ce13f7SAndroid Build Coastguard Worker return RValue<Int>(V(result));
3854*03ce13f7SAndroid Build Coastguard Worker }
3855*03ce13f7SAndroid Build Coastguard Worker }
3856*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<Float4> x,RValue<Float4> y)3857*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpEQ(RValue<Float4> x, RValue<Float4> y)
3858*03ce13f7SAndroid Build Coastguard Worker {
3859*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3860*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpOEQ(x.value(), y.value()));
3861*03ce13f7SAndroid Build Coastguard Worker }
3862*03ce13f7SAndroid Build Coastguard Worker
CmpLT(RValue<Float4> x,RValue<Float4> y)3863*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpLT(RValue<Float4> x, RValue<Float4> y)
3864*03ce13f7SAndroid Build Coastguard Worker {
3865*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3866*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpOLT(x.value(), y.value()));
3867*03ce13f7SAndroid Build Coastguard Worker }
3868*03ce13f7SAndroid Build Coastguard Worker
CmpLE(RValue<Float4> x,RValue<Float4> y)3869*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpLE(RValue<Float4> x, RValue<Float4> y)
3870*03ce13f7SAndroid Build Coastguard Worker {
3871*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3872*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpOLE(x.value(), y.value()));
3873*03ce13f7SAndroid Build Coastguard Worker }
3874*03ce13f7SAndroid Build Coastguard Worker
CmpNEQ(RValue<Float4> x,RValue<Float4> y)3875*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNEQ(RValue<Float4> x, RValue<Float4> y)
3876*03ce13f7SAndroid Build Coastguard Worker {
3877*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3878*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpONE(x.value(), y.value()));
3879*03ce13f7SAndroid Build Coastguard Worker }
3880*03ce13f7SAndroid Build Coastguard Worker
CmpNLT(RValue<Float4> x,RValue<Float4> y)3881*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNLT(RValue<Float4> x, RValue<Float4> y)
3882*03ce13f7SAndroid Build Coastguard Worker {
3883*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3884*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpOGE(x.value(), y.value()));
3885*03ce13f7SAndroid Build Coastguard Worker }
3886*03ce13f7SAndroid Build Coastguard Worker
CmpNLE(RValue<Float4> x,RValue<Float4> y)3887*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNLE(RValue<Float4> x, RValue<Float4> y)
3888*03ce13f7SAndroid Build Coastguard Worker {
3889*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3890*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpOGT(x.value(), y.value()));
3891*03ce13f7SAndroid Build Coastguard Worker }
3892*03ce13f7SAndroid Build Coastguard Worker
CmpUEQ(RValue<Float4> x,RValue<Float4> y)3893*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y)
3894*03ce13f7SAndroid Build Coastguard Worker {
3895*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3896*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpUEQ(x.value(), y.value()));
3897*03ce13f7SAndroid Build Coastguard Worker }
3898*03ce13f7SAndroid Build Coastguard Worker
CmpULT(RValue<Float4> x,RValue<Float4> y)3899*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y)
3900*03ce13f7SAndroid Build Coastguard Worker {
3901*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3902*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpULT(x.value(), y.value()));
3903*03ce13f7SAndroid Build Coastguard Worker }
3904*03ce13f7SAndroid Build Coastguard Worker
CmpULE(RValue<Float4> x,RValue<Float4> y)3905*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y)
3906*03ce13f7SAndroid Build Coastguard Worker {
3907*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3908*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpULE(x.value(), y.value()));
3909*03ce13f7SAndroid Build Coastguard Worker }
3910*03ce13f7SAndroid Build Coastguard Worker
CmpUNEQ(RValue<Float4> x,RValue<Float4> y)3911*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y)
3912*03ce13f7SAndroid Build Coastguard Worker {
3913*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3914*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpUNE(x.value(), y.value()));
3915*03ce13f7SAndroid Build Coastguard Worker }
3916*03ce13f7SAndroid Build Coastguard Worker
CmpUNLT(RValue<Float4> x,RValue<Float4> y)3917*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y)
3918*03ce13f7SAndroid Build Coastguard Worker {
3919*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3920*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpUGE(x.value(), y.value()));
3921*03ce13f7SAndroid Build Coastguard Worker }
3922*03ce13f7SAndroid Build Coastguard Worker
CmpUNLE(RValue<Float4> x,RValue<Float4> y)3923*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y)
3924*03ce13f7SAndroid Build Coastguard Worker {
3925*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3926*03ce13f7SAndroid Build Coastguard Worker return RValue<Int4>(Nucleus::createFCmpUGT(x.value(), y.value()));
3927*03ce13f7SAndroid Build Coastguard Worker }
3928*03ce13f7SAndroid Build Coastguard Worker
Round(RValue<Float4> x)3929*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Round(RValue<Float4> x)
3930*03ce13f7SAndroid Build Coastguard Worker {
3931*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3932*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
3933*03ce13f7SAndroid Build Coastguard Worker {
3934*03ce13f7SAndroid Build Coastguard Worker // Push the fractional part off the mantissa. Accurate up to +/-2^22.
3935*03ce13f7SAndroid Build Coastguard Worker return (x + Float4(0x00C00000)) - Float4(0x00C00000);
3936*03ce13f7SAndroid Build Coastguard Worker }
3937*03ce13f7SAndroid Build Coastguard Worker else if(CPUID::SSE4_1)
3938*03ce13f7SAndroid Build Coastguard Worker {
3939*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
3940*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3941*03ce13f7SAndroid Build Coastguard Worker auto round = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
3942*03ce13f7SAndroid Build Coastguard Worker round->addArg(x.value());
3943*03ce13f7SAndroid Build Coastguard Worker round->addArg(::context->getConstantInt32(0));
3944*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(round);
3945*03ce13f7SAndroid Build Coastguard Worker
3946*03ce13f7SAndroid Build Coastguard Worker return RValue<Float4>(V(result));
3947*03ce13f7SAndroid Build Coastguard Worker }
3948*03ce13f7SAndroid Build Coastguard Worker else
3949*03ce13f7SAndroid Build Coastguard Worker {
3950*03ce13f7SAndroid Build Coastguard Worker return Float4(RoundInt(x));
3951*03ce13f7SAndroid Build Coastguard Worker }
3952*03ce13f7SAndroid Build Coastguard Worker }
3953*03ce13f7SAndroid Build Coastguard Worker
Trunc(RValue<Float4> x)3954*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Trunc(RValue<Float4> x)
3955*03ce13f7SAndroid Build Coastguard Worker {
3956*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3957*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
3958*03ce13f7SAndroid Build Coastguard Worker {
3959*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
3960*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
3961*03ce13f7SAndroid Build Coastguard Worker auto round = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
3962*03ce13f7SAndroid Build Coastguard Worker round->addArg(x.value());
3963*03ce13f7SAndroid Build Coastguard Worker round->addArg(::context->getConstantInt32(3));
3964*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(round);
3965*03ce13f7SAndroid Build Coastguard Worker
3966*03ce13f7SAndroid Build Coastguard Worker return RValue<Float4>(V(result));
3967*03ce13f7SAndroid Build Coastguard Worker }
3968*03ce13f7SAndroid Build Coastguard Worker else
3969*03ce13f7SAndroid Build Coastguard Worker {
3970*03ce13f7SAndroid Build Coastguard Worker return Float4(Int4(x));
3971*03ce13f7SAndroid Build Coastguard Worker }
3972*03ce13f7SAndroid Build Coastguard Worker }
3973*03ce13f7SAndroid Build Coastguard Worker
Frac(RValue<Float4> x)3974*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Frac(RValue<Float4> x)
3975*03ce13f7SAndroid Build Coastguard Worker {
3976*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3977*03ce13f7SAndroid Build Coastguard Worker Float4 frc;
3978*03ce13f7SAndroid Build Coastguard Worker
3979*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
3980*03ce13f7SAndroid Build Coastguard Worker {
3981*03ce13f7SAndroid Build Coastguard Worker frc = x - Floor(x);
3982*03ce13f7SAndroid Build Coastguard Worker }
3983*03ce13f7SAndroid Build Coastguard Worker else
3984*03ce13f7SAndroid Build Coastguard Worker {
3985*03ce13f7SAndroid Build Coastguard Worker frc = x - Float4(Int4(x)); // Signed fractional part.
3986*03ce13f7SAndroid Build Coastguard Worker
3987*03ce13f7SAndroid Build Coastguard Worker frc += As<Float4>(As<Int4>(CmpNLE(Float4(0.0f), frc)) & As<Int4>(Float4(1.0f))); // Add 1.0 if negative.
3988*03ce13f7SAndroid Build Coastguard Worker }
3989*03ce13f7SAndroid Build Coastguard Worker
3990*03ce13f7SAndroid Build Coastguard Worker // x - floor(x) can be 1.0 for very small negative x.
3991*03ce13f7SAndroid Build Coastguard Worker // Clamp against the value just below 1.0.
3992*03ce13f7SAndroid Build Coastguard Worker return Min(frc, As<Float4>(Int4(0x3F7FFFFF)));
3993*03ce13f7SAndroid Build Coastguard Worker }
3994*03ce13f7SAndroid Build Coastguard Worker
Floor(RValue<Float4> x)3995*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Floor(RValue<Float4> x)
3996*03ce13f7SAndroid Build Coastguard Worker {
3997*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
3998*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
3999*03ce13f7SAndroid Build Coastguard Worker {
4000*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
4001*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
4002*03ce13f7SAndroid Build Coastguard Worker auto round = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
4003*03ce13f7SAndroid Build Coastguard Worker round->addArg(x.value());
4004*03ce13f7SAndroid Build Coastguard Worker round->addArg(::context->getConstantInt32(1));
4005*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(round);
4006*03ce13f7SAndroid Build Coastguard Worker
4007*03ce13f7SAndroid Build Coastguard Worker return RValue<Float4>(V(result));
4008*03ce13f7SAndroid Build Coastguard Worker }
4009*03ce13f7SAndroid Build Coastguard Worker else
4010*03ce13f7SAndroid Build Coastguard Worker {
4011*03ce13f7SAndroid Build Coastguard Worker return x - Frac(x);
4012*03ce13f7SAndroid Build Coastguard Worker }
4013*03ce13f7SAndroid Build Coastguard Worker }
4014*03ce13f7SAndroid Build Coastguard Worker
Ceil(RValue<Float4> x)4015*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Ceil(RValue<Float4> x)
4016*03ce13f7SAndroid Build Coastguard Worker {
4017*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4018*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
4019*03ce13f7SAndroid Build Coastguard Worker {
4020*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
4021*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
4022*03ce13f7SAndroid Build Coastguard Worker auto round = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
4023*03ce13f7SAndroid Build Coastguard Worker round->addArg(x.value());
4024*03ce13f7SAndroid Build Coastguard Worker round->addArg(::context->getConstantInt32(2));
4025*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(round);
4026*03ce13f7SAndroid Build Coastguard Worker
4027*03ce13f7SAndroid Build Coastguard Worker return RValue<Float4>(V(result));
4028*03ce13f7SAndroid Build Coastguard Worker }
4029*03ce13f7SAndroid Build Coastguard Worker else
4030*03ce13f7SAndroid Build Coastguard Worker {
4031*03ce13f7SAndroid Build Coastguard Worker return -Floor(-x);
4032*03ce13f7SAndroid Build Coastguard Worker }
4033*03ce13f7SAndroid Build Coastguard Worker }
4034*03ce13f7SAndroid Build Coastguard Worker
type()4035*03ce13f7SAndroid Build Coastguard Worker Type *Float4::type()
4036*03ce13f7SAndroid Build Coastguard Worker {
4037*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v4f32);
4038*03ce13f7SAndroid Build Coastguard Worker }
4039*03ce13f7SAndroid Build Coastguard Worker
Ticks()4040*03ce13f7SAndroid Build Coastguard Worker RValue<Long> Ticks()
4041*03ce13f7SAndroid Build Coastguard Worker {
4042*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4043*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("RValue<Long> Ticks()");
4044*03ce13f7SAndroid Build Coastguard Worker return Long(Int(0));
4045*03ce13f7SAndroid Build Coastguard Worker }
4046*03ce13f7SAndroid Build Coastguard Worker
ConstantPointer(const void * ptr)4047*03ce13f7SAndroid Build Coastguard Worker RValue<Pointer<Byte>> ConstantPointer(const void *ptr)
4048*03ce13f7SAndroid Build Coastguard Worker {
4049*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4050*03ce13f7SAndroid Build Coastguard Worker return RValue<Pointer<Byte>>{ V(sz::getConstantPointer(::context, ptr)) };
4051*03ce13f7SAndroid Build Coastguard Worker }
4052*03ce13f7SAndroid Build Coastguard Worker
ConstantData(const void * data,size_t size)4053*03ce13f7SAndroid Build Coastguard Worker RValue<Pointer<Byte>> ConstantData(const void *data, size_t size)
4054*03ce13f7SAndroid Build Coastguard Worker {
4055*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4056*03ce13f7SAndroid Build Coastguard Worker return RValue<Pointer<Byte>>{ V(IceConstantData(data, size)) };
4057*03ce13f7SAndroid Build Coastguard Worker }
4058*03ce13f7SAndroid Build Coastguard Worker
Call(RValue<Pointer<Byte>> fptr,Type * retTy,std::initializer_list<Value * > args,std::initializer_list<Type * > argTys)4059*03ce13f7SAndroid Build Coastguard Worker Value *Call(RValue<Pointer<Byte>> fptr, Type *retTy, std::initializer_list<Value *> args, std::initializer_list<Type *> argTys)
4060*03ce13f7SAndroid Build Coastguard Worker {
4061*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4062*03ce13f7SAndroid Build Coastguard Worker return V(sz::Call(::function, ::basicBlock, T(retTy), V(fptr.value()), V(args), false));
4063*03ce13f7SAndroid Build Coastguard Worker }
4064*03ce13f7SAndroid Build Coastguard Worker
Breakpoint()4065*03ce13f7SAndroid Build Coastguard Worker void Breakpoint()
4066*03ce13f7SAndroid Build Coastguard Worker {
4067*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4068*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Trap, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
4069*03ce13f7SAndroid Build Coastguard Worker auto trap = Ice::InstIntrinsic::create(::function, 0, nullptr, intrinsic);
4070*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(trap);
4071*03ce13f7SAndroid Build Coastguard Worker }
4072*03ce13f7SAndroid Build Coastguard Worker
createFence(std::memory_order memoryOrder)4073*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createFence(std::memory_order memoryOrder)
4074*03ce13f7SAndroid Build Coastguard Worker {
4075*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4076*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::AtomicFence, Ice::Intrinsics::SideEffects_T, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
4077*03ce13f7SAndroid Build Coastguard Worker auto inst = Ice::InstIntrinsic::create(::function, 0, nullptr, intrinsic);
4078*03ce13f7SAndroid Build Coastguard Worker auto order = ::context->getConstantInt32(stdToIceMemoryOrder(memoryOrder));
4079*03ce13f7SAndroid Build Coastguard Worker inst->addArg(order);
4080*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(inst);
4081*03ce13f7SAndroid Build Coastguard Worker }
4082*03ce13f7SAndroid Build Coastguard Worker
createMaskedLoad(Value * ptr,Type * elTy,Value * mask,unsigned int alignment,bool zeroMaskedLanes)4083*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createMaskedLoad(Value *ptr, Type *elTy, Value *mask, unsigned int alignment, bool zeroMaskedLanes)
4084*03ce13f7SAndroid Build Coastguard Worker {
4085*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4086*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED("b/155867273 Subzero createMaskedLoad()");
4087*03ce13f7SAndroid Build Coastguard Worker return nullptr;
4088*03ce13f7SAndroid Build Coastguard Worker }
4089*03ce13f7SAndroid Build Coastguard Worker
createMaskedStore(Value * ptr,Value * val,Value * mask,unsigned int alignment)4090*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createMaskedStore(Value *ptr, Value *val, Value *mask, unsigned int alignment)
4091*03ce13f7SAndroid Build Coastguard Worker {
4092*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4093*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED("b/155867273 Subzero createMaskedStore()");
4094*03ce13f7SAndroid Build Coastguard Worker }
4095*03ce13f7SAndroid Build Coastguard Worker
4096*03ce13f7SAndroid Build Coastguard Worker template<typename T>
4097*03ce13f7SAndroid Build Coastguard Worker struct UnderlyingType
4098*03ce13f7SAndroid Build Coastguard Worker {
4099*03ce13f7SAndroid Build Coastguard Worker using Type = typename decltype(rr::Extract(std::declval<RValue<T>>(), 0))::rvalue_underlying_type;
4100*03ce13f7SAndroid Build Coastguard Worker };
4101*03ce13f7SAndroid Build Coastguard Worker
4102*03ce13f7SAndroid Build Coastguard Worker template<typename T>
4103*03ce13f7SAndroid Build Coastguard Worker using UnderlyingTypeT = typename UnderlyingType<T>::Type;
4104*03ce13f7SAndroid Build Coastguard Worker
4105*03ce13f7SAndroid Build Coastguard Worker template<typename T, typename EL = UnderlyingTypeT<T>>
gather(T & out,RValue<Pointer<EL>> base,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment,bool zeroMaskedLanes)4106*03ce13f7SAndroid Build Coastguard Worker static void gather(T &out, RValue<Pointer<EL>> base, RValue<SIMD::Int> offsets, RValue<SIMD::Int> mask, unsigned int alignment, bool zeroMaskedLanes)
4107*03ce13f7SAndroid Build Coastguard Worker {
4108*03ce13f7SAndroid Build Coastguard Worker constexpr bool atomic = false;
4109*03ce13f7SAndroid Build Coastguard Worker constexpr std::memory_order order = std::memory_order_relaxed;
4110*03ce13f7SAndroid Build Coastguard Worker
4111*03ce13f7SAndroid Build Coastguard Worker Pointer<Byte> baseBytePtr = base;
4112*03ce13f7SAndroid Build Coastguard Worker
4113*03ce13f7SAndroid Build Coastguard Worker out = T(0);
4114*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
4115*03ce13f7SAndroid Build Coastguard Worker {
4116*03ce13f7SAndroid Build Coastguard Worker If(Extract(mask, i) != 0)
4117*03ce13f7SAndroid Build Coastguard Worker {
4118*03ce13f7SAndroid Build Coastguard Worker auto offset = Extract(offsets, i);
4119*03ce13f7SAndroid Build Coastguard Worker auto el = Load(Pointer<EL>(&baseBytePtr[offset]), alignment, atomic, order);
4120*03ce13f7SAndroid Build Coastguard Worker out = Insert(out, el, i);
4121*03ce13f7SAndroid Build Coastguard Worker }
4122*03ce13f7SAndroid Build Coastguard Worker Else If(zeroMaskedLanes)
4123*03ce13f7SAndroid Build Coastguard Worker {
4124*03ce13f7SAndroid Build Coastguard Worker out = Insert(out, EL(0), i);
4125*03ce13f7SAndroid Build Coastguard Worker }
4126*03ce13f7SAndroid Build Coastguard Worker }
4127*03ce13f7SAndroid Build Coastguard Worker }
4128*03ce13f7SAndroid Build Coastguard Worker
4129*03ce13f7SAndroid Build Coastguard Worker template<typename T, typename EL = UnderlyingTypeT<T>>
scatter(RValue<Pointer<EL>> base,RValue<T> val,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment)4130*03ce13f7SAndroid Build Coastguard Worker static void scatter(RValue<Pointer<EL>> base, RValue<T> val, RValue<SIMD::Int> offsets, RValue<SIMD::Int> mask, unsigned int alignment)
4131*03ce13f7SAndroid Build Coastguard Worker {
4132*03ce13f7SAndroid Build Coastguard Worker constexpr bool atomic = false;
4133*03ce13f7SAndroid Build Coastguard Worker constexpr std::memory_order order = std::memory_order_relaxed;
4134*03ce13f7SAndroid Build Coastguard Worker
4135*03ce13f7SAndroid Build Coastguard Worker Pointer<Byte> baseBytePtr = base;
4136*03ce13f7SAndroid Build Coastguard Worker
4137*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
4138*03ce13f7SAndroid Build Coastguard Worker {
4139*03ce13f7SAndroid Build Coastguard Worker If(Extract(mask, i) != 0)
4140*03ce13f7SAndroid Build Coastguard Worker {
4141*03ce13f7SAndroid Build Coastguard Worker auto offset = Extract(offsets, i);
4142*03ce13f7SAndroid Build Coastguard Worker Store(Extract(val, i), Pointer<EL>(&baseBytePtr[offset]), alignment, atomic, order);
4143*03ce13f7SAndroid Build Coastguard Worker }
4144*03ce13f7SAndroid Build Coastguard Worker }
4145*03ce13f7SAndroid Build Coastguard Worker }
4146*03ce13f7SAndroid Build Coastguard Worker
Gather(RValue<Pointer<Float>> base,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment,bool zeroMaskedLanes)4147*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Gather(RValue<Pointer<Float>> base, RValue<SIMD::Int> offsets, RValue<SIMD::Int> mask, unsigned int alignment, bool zeroMaskedLanes /* = false */)
4148*03ce13f7SAndroid Build Coastguard Worker {
4149*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4150*03ce13f7SAndroid Build Coastguard Worker SIMD::Float result{};
4151*03ce13f7SAndroid Build Coastguard Worker gather(result, base, offsets, mask, alignment, zeroMaskedLanes);
4152*03ce13f7SAndroid Build Coastguard Worker return result;
4153*03ce13f7SAndroid Build Coastguard Worker }
4154*03ce13f7SAndroid Build Coastguard Worker
Gather(RValue<Pointer<Int>> base,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment,bool zeroMaskedLanes)4155*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Gather(RValue<Pointer<Int>> base, RValue<SIMD::Int> offsets, RValue<SIMD::Int> mask, unsigned int alignment, bool zeroMaskedLanes /* = false */)
4156*03ce13f7SAndroid Build Coastguard Worker {
4157*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4158*03ce13f7SAndroid Build Coastguard Worker SIMD::Int result{};
4159*03ce13f7SAndroid Build Coastguard Worker gather(result, base, offsets, mask, alignment, zeroMaskedLanes);
4160*03ce13f7SAndroid Build Coastguard Worker return result;
4161*03ce13f7SAndroid Build Coastguard Worker }
4162*03ce13f7SAndroid Build Coastguard Worker
Scatter(RValue<Pointer<Float>> base,RValue<SIMD::Float> val,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment)4163*03ce13f7SAndroid Build Coastguard Worker void Scatter(RValue<Pointer<Float>> base, RValue<SIMD::Float> val, RValue<SIMD::Int> offsets, RValue<SIMD::Int> mask, unsigned int alignment)
4164*03ce13f7SAndroid Build Coastguard Worker {
4165*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4166*03ce13f7SAndroid Build Coastguard Worker scatter(base, val, offsets, mask, alignment);
4167*03ce13f7SAndroid Build Coastguard Worker }
4168*03ce13f7SAndroid Build Coastguard Worker
Scatter(RValue<Pointer<Int>> base,RValue<SIMD::Int> val,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment)4169*03ce13f7SAndroid Build Coastguard Worker void Scatter(RValue<Pointer<Int>> base, RValue<SIMD::Int> val, RValue<SIMD::Int> offsets, RValue<SIMD::Int> mask, unsigned int alignment)
4170*03ce13f7SAndroid Build Coastguard Worker {
4171*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4172*03ce13f7SAndroid Build Coastguard Worker scatter<SIMD::Int>(base, val, offsets, mask, alignment);
4173*03ce13f7SAndroid Build Coastguard Worker }
4174*03ce13f7SAndroid Build Coastguard Worker
Ctlz(RValue<UInt> x,bool isZeroUndef)4175*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> Ctlz(RValue<UInt> x, bool isZeroUndef)
4176*03ce13f7SAndroid Build Coastguard Worker {
4177*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4178*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
4179*03ce13f7SAndroid Build Coastguard Worker {
4180*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("Subzero Ctlz()");
4181*03ce13f7SAndroid Build Coastguard Worker return UInt(0);
4182*03ce13f7SAndroid Build Coastguard Worker }
4183*03ce13f7SAndroid Build Coastguard Worker else
4184*03ce13f7SAndroid Build Coastguard Worker {
4185*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32);
4186*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Ctlz, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
4187*03ce13f7SAndroid Build Coastguard Worker auto ctlz = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
4188*03ce13f7SAndroid Build Coastguard Worker ctlz->addArg(x.value());
4189*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(ctlz);
4190*03ce13f7SAndroid Build Coastguard Worker
4191*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt>(V(result));
4192*03ce13f7SAndroid Build Coastguard Worker }
4193*03ce13f7SAndroid Build Coastguard Worker }
4194*03ce13f7SAndroid Build Coastguard Worker
Ctlz(RValue<UInt4> x,bool isZeroUndef)4195*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Ctlz(RValue<UInt4> x, bool isZeroUndef)
4196*03ce13f7SAndroid Build Coastguard Worker {
4197*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4198*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
4199*03ce13f7SAndroid Build Coastguard Worker {
4200*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("Subzero Ctlz()");
4201*03ce13f7SAndroid Build Coastguard Worker return UInt4(0);
4202*03ce13f7SAndroid Build Coastguard Worker }
4203*03ce13f7SAndroid Build Coastguard Worker else
4204*03ce13f7SAndroid Build Coastguard Worker {
4205*03ce13f7SAndroid Build Coastguard Worker return Scalarize([isZeroUndef](auto a) { return Ctlz(a, isZeroUndef); }, x);
4206*03ce13f7SAndroid Build Coastguard Worker }
4207*03ce13f7SAndroid Build Coastguard Worker }
4208*03ce13f7SAndroid Build Coastguard Worker
Cttz(RValue<UInt> x,bool isZeroUndef)4209*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> Cttz(RValue<UInt> x, bool isZeroUndef)
4210*03ce13f7SAndroid Build Coastguard Worker {
4211*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4212*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
4213*03ce13f7SAndroid Build Coastguard Worker {
4214*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("Subzero Cttz()");
4215*03ce13f7SAndroid Build Coastguard Worker return UInt(0);
4216*03ce13f7SAndroid Build Coastguard Worker }
4217*03ce13f7SAndroid Build Coastguard Worker else
4218*03ce13f7SAndroid Build Coastguard Worker {
4219*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32);
4220*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Cttz, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
4221*03ce13f7SAndroid Build Coastguard Worker auto cttz = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
4222*03ce13f7SAndroid Build Coastguard Worker cttz->addArg(x.value());
4223*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cttz);
4224*03ce13f7SAndroid Build Coastguard Worker
4225*03ce13f7SAndroid Build Coastguard Worker return RValue<UInt>(V(result));
4226*03ce13f7SAndroid Build Coastguard Worker }
4227*03ce13f7SAndroid Build Coastguard Worker }
4228*03ce13f7SAndroid Build Coastguard Worker
Cttz(RValue<UInt4> x,bool isZeroUndef)4229*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Cttz(RValue<UInt4> x, bool isZeroUndef)
4230*03ce13f7SAndroid Build Coastguard Worker {
4231*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4232*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
4233*03ce13f7SAndroid Build Coastguard Worker {
4234*03ce13f7SAndroid Build Coastguard Worker UNIMPLEMENTED_NO_BUG("Subzero Cttz()");
4235*03ce13f7SAndroid Build Coastguard Worker return UInt4(0);
4236*03ce13f7SAndroid Build Coastguard Worker }
4237*03ce13f7SAndroid Build Coastguard Worker else
4238*03ce13f7SAndroid Build Coastguard Worker {
4239*03ce13f7SAndroid Build Coastguard Worker return Scalarize([isZeroUndef](auto a) { return Cttz(a, isZeroUndef); }, x);
4240*03ce13f7SAndroid Build Coastguard Worker }
4241*03ce13f7SAndroid Build Coastguard Worker }
4242*03ce13f7SAndroid Build Coastguard Worker
4243*03ce13f7SAndroid Build Coastguard Worker // TODO(b/148276653): Both atomicMin and atomicMax use a static (global) mutex that makes all min
4244*03ce13f7SAndroid Build Coastguard Worker // operations for a given T mutually exclusive, rather than only the ones on the value pointed to
4245*03ce13f7SAndroid Build Coastguard Worker // by ptr. Use a CAS loop, as is done for LLVMReactor's min/max atomic for Android.
4246*03ce13f7SAndroid Build Coastguard Worker // TODO(b/148207274): Or, move this down into Subzero as a CAS-based operation.
4247*03ce13f7SAndroid Build Coastguard Worker template<typename T>
atomicMin(T * ptr,T value)4248*03ce13f7SAndroid Build Coastguard Worker static T atomicMin(T *ptr, T value)
4249*03ce13f7SAndroid Build Coastguard Worker {
4250*03ce13f7SAndroid Build Coastguard Worker static std::mutex m;
4251*03ce13f7SAndroid Build Coastguard Worker
4252*03ce13f7SAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(m);
4253*03ce13f7SAndroid Build Coastguard Worker T origValue = *ptr;
4254*03ce13f7SAndroid Build Coastguard Worker *ptr = std::min(origValue, value);
4255*03ce13f7SAndroid Build Coastguard Worker return origValue;
4256*03ce13f7SAndroid Build Coastguard Worker }
4257*03ce13f7SAndroid Build Coastguard Worker
4258*03ce13f7SAndroid Build Coastguard Worker template<typename T>
atomicMax(T * ptr,T value)4259*03ce13f7SAndroid Build Coastguard Worker static T atomicMax(T *ptr, T value)
4260*03ce13f7SAndroid Build Coastguard Worker {
4261*03ce13f7SAndroid Build Coastguard Worker static std::mutex m;
4262*03ce13f7SAndroid Build Coastguard Worker
4263*03ce13f7SAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(m);
4264*03ce13f7SAndroid Build Coastguard Worker T origValue = *ptr;
4265*03ce13f7SAndroid Build Coastguard Worker *ptr = std::max(origValue, value);
4266*03ce13f7SAndroid Build Coastguard Worker return origValue;
4267*03ce13f7SAndroid Build Coastguard Worker }
4268*03ce13f7SAndroid Build Coastguard Worker
MinAtomic(RValue<Pointer<Int>> x,RValue<Int> y,std::memory_order memoryOrder)4269*03ce13f7SAndroid Build Coastguard Worker RValue<Int> MinAtomic(RValue<Pointer<Int>> x, RValue<Int> y, std::memory_order memoryOrder)
4270*03ce13f7SAndroid Build Coastguard Worker {
4271*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4272*03ce13f7SAndroid Build Coastguard Worker return Call(atomicMin<int32_t>, x, y);
4273*03ce13f7SAndroid Build Coastguard Worker }
4274*03ce13f7SAndroid Build Coastguard Worker
MinAtomic(RValue<Pointer<UInt>> x,RValue<UInt> y,std::memory_order memoryOrder)4275*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> MinAtomic(RValue<Pointer<UInt>> x, RValue<UInt> y, std::memory_order memoryOrder)
4276*03ce13f7SAndroid Build Coastguard Worker {
4277*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4278*03ce13f7SAndroid Build Coastguard Worker return Call(atomicMin<uint32_t>, x, y);
4279*03ce13f7SAndroid Build Coastguard Worker }
4280*03ce13f7SAndroid Build Coastguard Worker
MaxAtomic(RValue<Pointer<Int>> x,RValue<Int> y,std::memory_order memoryOrder)4281*03ce13f7SAndroid Build Coastguard Worker RValue<Int> MaxAtomic(RValue<Pointer<Int>> x, RValue<Int> y, std::memory_order memoryOrder)
4282*03ce13f7SAndroid Build Coastguard Worker {
4283*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4284*03ce13f7SAndroid Build Coastguard Worker return Call(atomicMax<int32_t>, x, y);
4285*03ce13f7SAndroid Build Coastguard Worker }
4286*03ce13f7SAndroid Build Coastguard Worker
MaxAtomic(RValue<Pointer<UInt>> x,RValue<UInt> y,std::memory_order memoryOrder)4287*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> MaxAtomic(RValue<Pointer<UInt>> x, RValue<UInt> y, std::memory_order memoryOrder)
4288*03ce13f7SAndroid Build Coastguard Worker {
4289*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4290*03ce13f7SAndroid Build Coastguard Worker return Call(atomicMax<uint32_t>, x, y);
4291*03ce13f7SAndroid Build Coastguard Worker }
4292*03ce13f7SAndroid Build Coastguard Worker
EmitDebugLocation()4293*03ce13f7SAndroid Build Coastguard Worker void EmitDebugLocation()
4294*03ce13f7SAndroid Build Coastguard Worker {
4295*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
4296*03ce13f7SAndroid Build Coastguard Worker emitPrintLocation(getCallerBacktrace());
4297*03ce13f7SAndroid Build Coastguard Worker #endif // ENABLE_RR_DEBUG_INFO
4298*03ce13f7SAndroid Build Coastguard Worker }
EmitDebugVariable(Value * value)4299*03ce13f7SAndroid Build Coastguard Worker void EmitDebugVariable(Value *value) {}
FlushDebug()4300*03ce13f7SAndroid Build Coastguard Worker void FlushDebug() {}
4301*03ce13f7SAndroid Build Coastguard Worker
4302*03ce13f7SAndroid Build Coastguard Worker namespace {
4303*03ce13f7SAndroid Build Coastguard Worker namespace coro {
4304*03ce13f7SAndroid Build Coastguard Worker
4305*03ce13f7SAndroid Build Coastguard Worker // Instance data per generated coroutine
4306*03ce13f7SAndroid Build Coastguard Worker // This is the "handle" type used for Coroutine functions
4307*03ce13f7SAndroid Build Coastguard Worker // Lifetime: from yield to when CoroutineEntryDestroy generated function is called.
4308*03ce13f7SAndroid Build Coastguard Worker struct CoroutineData
4309*03ce13f7SAndroid Build Coastguard Worker {
4310*03ce13f7SAndroid Build Coastguard Worker bool useInternalScheduler = false;
4311*03ce13f7SAndroid Build Coastguard Worker bool done = false; // the coroutine should stop at the next yield()
4312*03ce13f7SAndroid Build Coastguard Worker bool terminated = false; // the coroutine has finished.
4313*03ce13f7SAndroid Build Coastguard Worker bool inRoutine = false; // is the coroutine currently executing?
4314*03ce13f7SAndroid Build Coastguard Worker marl::Scheduler::Fiber *mainFiber = nullptr;
4315*03ce13f7SAndroid Build Coastguard Worker marl::Scheduler::Fiber *routineFiber = nullptr;
4316*03ce13f7SAndroid Build Coastguard Worker void *promisePtr = nullptr;
4317*03ce13f7SAndroid Build Coastguard Worker };
4318*03ce13f7SAndroid Build Coastguard Worker
createCoroutineData()4319*03ce13f7SAndroid Build Coastguard Worker CoroutineData *createCoroutineData()
4320*03ce13f7SAndroid Build Coastguard Worker {
4321*03ce13f7SAndroid Build Coastguard Worker return new CoroutineData{};
4322*03ce13f7SAndroid Build Coastguard Worker }
4323*03ce13f7SAndroid Build Coastguard Worker
destroyCoroutineData(CoroutineData * coroData)4324*03ce13f7SAndroid Build Coastguard Worker void destroyCoroutineData(CoroutineData *coroData)
4325*03ce13f7SAndroid Build Coastguard Worker {
4326*03ce13f7SAndroid Build Coastguard Worker delete coroData;
4327*03ce13f7SAndroid Build Coastguard Worker }
4328*03ce13f7SAndroid Build Coastguard Worker
4329*03ce13f7SAndroid Build Coastguard Worker // suspend() pauses execution of the coroutine, and resumes execution from the
4330*03ce13f7SAndroid Build Coastguard Worker // caller's call to await().
4331*03ce13f7SAndroid Build Coastguard Worker // Returns true if await() is called again, or false if coroutine_destroy()
4332*03ce13f7SAndroid Build Coastguard Worker // is called.
suspend(Nucleus::CoroutineHandle handle)4333*03ce13f7SAndroid Build Coastguard Worker bool suspend(Nucleus::CoroutineHandle handle)
4334*03ce13f7SAndroid Build Coastguard Worker {
4335*03ce13f7SAndroid Build Coastguard Worker auto *coroData = reinterpret_cast<CoroutineData *>(handle);
4336*03ce13f7SAndroid Build Coastguard Worker ASSERT(marl::Scheduler::Fiber::current() == coroData->routineFiber);
4337*03ce13f7SAndroid Build Coastguard Worker ASSERT(coroData->inRoutine);
4338*03ce13f7SAndroid Build Coastguard Worker coroData->inRoutine = false;
4339*03ce13f7SAndroid Build Coastguard Worker coroData->mainFiber->notify();
4340*03ce13f7SAndroid Build Coastguard Worker while(!coroData->inRoutine)
4341*03ce13f7SAndroid Build Coastguard Worker {
4342*03ce13f7SAndroid Build Coastguard Worker coroData->routineFiber->wait();
4343*03ce13f7SAndroid Build Coastguard Worker }
4344*03ce13f7SAndroid Build Coastguard Worker return !coroData->done;
4345*03ce13f7SAndroid Build Coastguard Worker }
4346*03ce13f7SAndroid Build Coastguard Worker
4347*03ce13f7SAndroid Build Coastguard Worker // resume() is called by await(), blocking until the coroutine calls yield()
4348*03ce13f7SAndroid Build Coastguard Worker // or the coroutine terminates.
resume(Nucleus::CoroutineHandle handle)4349*03ce13f7SAndroid Build Coastguard Worker void resume(Nucleus::CoroutineHandle handle)
4350*03ce13f7SAndroid Build Coastguard Worker {
4351*03ce13f7SAndroid Build Coastguard Worker auto *coroData = reinterpret_cast<CoroutineData *>(handle);
4352*03ce13f7SAndroid Build Coastguard Worker ASSERT(marl::Scheduler::Fiber::current() == coroData->mainFiber);
4353*03ce13f7SAndroid Build Coastguard Worker ASSERT(!coroData->inRoutine);
4354*03ce13f7SAndroid Build Coastguard Worker coroData->inRoutine = true;
4355*03ce13f7SAndroid Build Coastguard Worker coroData->routineFiber->notify();
4356*03ce13f7SAndroid Build Coastguard Worker while(coroData->inRoutine)
4357*03ce13f7SAndroid Build Coastguard Worker {
4358*03ce13f7SAndroid Build Coastguard Worker coroData->mainFiber->wait();
4359*03ce13f7SAndroid Build Coastguard Worker }
4360*03ce13f7SAndroid Build Coastguard Worker }
4361*03ce13f7SAndroid Build Coastguard Worker
4362*03ce13f7SAndroid Build Coastguard Worker // stop() is called by coroutine_destroy(), signalling that it's done, then blocks
4363*03ce13f7SAndroid Build Coastguard Worker // until the coroutine ends, and deletes the coroutine data.
stop(Nucleus::CoroutineHandle handle)4364*03ce13f7SAndroid Build Coastguard Worker void stop(Nucleus::CoroutineHandle handle)
4365*03ce13f7SAndroid Build Coastguard Worker {
4366*03ce13f7SAndroid Build Coastguard Worker auto *coroData = reinterpret_cast<CoroutineData *>(handle);
4367*03ce13f7SAndroid Build Coastguard Worker ASSERT(marl::Scheduler::Fiber::current() == coroData->mainFiber);
4368*03ce13f7SAndroid Build Coastguard Worker ASSERT(!coroData->inRoutine);
4369*03ce13f7SAndroid Build Coastguard Worker if(!coroData->terminated)
4370*03ce13f7SAndroid Build Coastguard Worker {
4371*03ce13f7SAndroid Build Coastguard Worker coroData->done = true;
4372*03ce13f7SAndroid Build Coastguard Worker coroData->inRoutine = true;
4373*03ce13f7SAndroid Build Coastguard Worker coroData->routineFiber->notify();
4374*03ce13f7SAndroid Build Coastguard Worker while(!coroData->terminated)
4375*03ce13f7SAndroid Build Coastguard Worker {
4376*03ce13f7SAndroid Build Coastguard Worker coroData->mainFiber->wait();
4377*03ce13f7SAndroid Build Coastguard Worker }
4378*03ce13f7SAndroid Build Coastguard Worker }
4379*03ce13f7SAndroid Build Coastguard Worker if(coroData->useInternalScheduler)
4380*03ce13f7SAndroid Build Coastguard Worker {
4381*03ce13f7SAndroid Build Coastguard Worker ::getOrCreateScheduler().unbind();
4382*03ce13f7SAndroid Build Coastguard Worker }
4383*03ce13f7SAndroid Build Coastguard Worker coro::destroyCoroutineData(coroData); // free the coroutine data.
4384*03ce13f7SAndroid Build Coastguard Worker }
4385*03ce13f7SAndroid Build Coastguard Worker
4386*03ce13f7SAndroid Build Coastguard Worker namespace detail {
4387*03ce13f7SAndroid Build Coastguard Worker thread_local rr::Nucleus::CoroutineHandle coroHandle{};
4388*03ce13f7SAndroid Build Coastguard Worker } // namespace detail
4389*03ce13f7SAndroid Build Coastguard Worker
setHandleParam(Nucleus::CoroutineHandle handle)4390*03ce13f7SAndroid Build Coastguard Worker void setHandleParam(Nucleus::CoroutineHandle handle)
4391*03ce13f7SAndroid Build Coastguard Worker {
4392*03ce13f7SAndroid Build Coastguard Worker ASSERT(!detail::coroHandle);
4393*03ce13f7SAndroid Build Coastguard Worker detail::coroHandle = handle;
4394*03ce13f7SAndroid Build Coastguard Worker }
4395*03ce13f7SAndroid Build Coastguard Worker
getHandleParam()4396*03ce13f7SAndroid Build Coastguard Worker Nucleus::CoroutineHandle getHandleParam()
4397*03ce13f7SAndroid Build Coastguard Worker {
4398*03ce13f7SAndroid Build Coastguard Worker ASSERT(detail::coroHandle);
4399*03ce13f7SAndroid Build Coastguard Worker auto handle = detail::coroHandle;
4400*03ce13f7SAndroid Build Coastguard Worker detail::coroHandle = {};
4401*03ce13f7SAndroid Build Coastguard Worker return handle;
4402*03ce13f7SAndroid Build Coastguard Worker }
4403*03ce13f7SAndroid Build Coastguard Worker
isDone(Nucleus::CoroutineHandle handle)4404*03ce13f7SAndroid Build Coastguard Worker bool isDone(Nucleus::CoroutineHandle handle)
4405*03ce13f7SAndroid Build Coastguard Worker {
4406*03ce13f7SAndroid Build Coastguard Worker auto *coroData = reinterpret_cast<CoroutineData *>(handle);
4407*03ce13f7SAndroid Build Coastguard Worker return coroData->done;
4408*03ce13f7SAndroid Build Coastguard Worker }
4409*03ce13f7SAndroid Build Coastguard Worker
setPromisePtr(Nucleus::CoroutineHandle handle,void * promisePtr)4410*03ce13f7SAndroid Build Coastguard Worker void setPromisePtr(Nucleus::CoroutineHandle handle, void *promisePtr)
4411*03ce13f7SAndroid Build Coastguard Worker {
4412*03ce13f7SAndroid Build Coastguard Worker auto *coroData = reinterpret_cast<CoroutineData *>(handle);
4413*03ce13f7SAndroid Build Coastguard Worker coroData->promisePtr = promisePtr;
4414*03ce13f7SAndroid Build Coastguard Worker }
4415*03ce13f7SAndroid Build Coastguard Worker
getPromisePtr(Nucleus::CoroutineHandle handle)4416*03ce13f7SAndroid Build Coastguard Worker void *getPromisePtr(Nucleus::CoroutineHandle handle)
4417*03ce13f7SAndroid Build Coastguard Worker {
4418*03ce13f7SAndroid Build Coastguard Worker auto *coroData = reinterpret_cast<CoroutineData *>(handle);
4419*03ce13f7SAndroid Build Coastguard Worker return coroData->promisePtr;
4420*03ce13f7SAndroid Build Coastguard Worker }
4421*03ce13f7SAndroid Build Coastguard Worker
4422*03ce13f7SAndroid Build Coastguard Worker } // namespace coro
4423*03ce13f7SAndroid Build Coastguard Worker } // namespace
4424*03ce13f7SAndroid Build Coastguard Worker
4425*03ce13f7SAndroid Build Coastguard Worker // Used to generate coroutines.
4426*03ce13f7SAndroid Build Coastguard Worker // Lifetime: from yield to acquireCoroutine
4427*03ce13f7SAndroid Build Coastguard Worker class CoroutineGenerator
4428*03ce13f7SAndroid Build Coastguard Worker {
4429*03ce13f7SAndroid Build Coastguard Worker public:
CoroutineGenerator()4430*03ce13f7SAndroid Build Coastguard Worker CoroutineGenerator()
4431*03ce13f7SAndroid Build Coastguard Worker {
4432*03ce13f7SAndroid Build Coastguard Worker }
4433*03ce13f7SAndroid Build Coastguard Worker
4434*03ce13f7SAndroid Build Coastguard Worker // Inserts instructions at the top of the current function to make it a coroutine.
generateCoroutineBegin()4435*03ce13f7SAndroid Build Coastguard Worker void generateCoroutineBegin()
4436*03ce13f7SAndroid Build Coastguard Worker {
4437*03ce13f7SAndroid Build Coastguard Worker // Begin building the main coroutine_begin() function.
4438*03ce13f7SAndroid Build Coastguard Worker // We insert these instructions at the top of the entry node,
4439*03ce13f7SAndroid Build Coastguard Worker // before existing reactor-generated instructions.
4440*03ce13f7SAndroid Build Coastguard Worker
4441*03ce13f7SAndroid Build Coastguard Worker // CoroutineHandle coroutine_begin(<Arguments>)
4442*03ce13f7SAndroid Build Coastguard Worker // {
4443*03ce13f7SAndroid Build Coastguard Worker // this->handle = coro::getHandleParam();
4444*03ce13f7SAndroid Build Coastguard Worker //
4445*03ce13f7SAndroid Build Coastguard Worker // YieldType promise;
4446*03ce13f7SAndroid Build Coastguard Worker // coro::setPromisePtr(handle, &promise); // For await
4447*03ce13f7SAndroid Build Coastguard Worker //
4448*03ce13f7SAndroid Build Coastguard Worker // ... <REACTOR CODE> ...
4449*03ce13f7SAndroid Build Coastguard Worker //
4450*03ce13f7SAndroid Build Coastguard Worker
4451*03ce13f7SAndroid Build Coastguard Worker // this->handle = coro::getHandleParam();
4452*03ce13f7SAndroid Build Coastguard Worker this->handle = sz::Call(::function, ::entryBlock, coro::getHandleParam);
4453*03ce13f7SAndroid Build Coastguard Worker
4454*03ce13f7SAndroid Build Coastguard Worker // YieldType promise;
4455*03ce13f7SAndroid Build Coastguard Worker // coro::setPromisePtr(handle, &promise); // For await
4456*03ce13f7SAndroid Build Coastguard Worker this->promise = sz::allocateStackVariable(::function, T(::coroYieldType));
4457*03ce13f7SAndroid Build Coastguard Worker sz::Call(::function, ::entryBlock, coro::setPromisePtr, this->handle, this->promise);
4458*03ce13f7SAndroid Build Coastguard Worker }
4459*03ce13f7SAndroid Build Coastguard Worker
4460*03ce13f7SAndroid Build Coastguard Worker // Adds instructions for Yield() calls at the current location of the main coroutine function.
generateYield(Value * val)4461*03ce13f7SAndroid Build Coastguard Worker void generateYield(Value *val)
4462*03ce13f7SAndroid Build Coastguard Worker {
4463*03ce13f7SAndroid Build Coastguard Worker // ... <REACTOR CODE> ...
4464*03ce13f7SAndroid Build Coastguard Worker //
4465*03ce13f7SAndroid Build Coastguard Worker // promise = val;
4466*03ce13f7SAndroid Build Coastguard Worker // if (!coro::suspend(handle)) {
4467*03ce13f7SAndroid Build Coastguard Worker // return false; // coroutine has been stopped by the caller.
4468*03ce13f7SAndroid Build Coastguard Worker // }
4469*03ce13f7SAndroid Build Coastguard Worker //
4470*03ce13f7SAndroid Build Coastguard Worker // ... <REACTOR CODE> ...
4471*03ce13f7SAndroid Build Coastguard Worker
4472*03ce13f7SAndroid Build Coastguard Worker // promise = val;
4473*03ce13f7SAndroid Build Coastguard Worker Nucleus::createStore(val, V(this->promise), ::coroYieldType);
4474*03ce13f7SAndroid Build Coastguard Worker
4475*03ce13f7SAndroid Build Coastguard Worker // if (!coro::suspend(handle)) {
4476*03ce13f7SAndroid Build Coastguard Worker auto result = sz::Call(::function, ::basicBlock, coro::suspend, this->handle);
4477*03ce13f7SAndroid Build Coastguard Worker auto doneBlock = Nucleus::createBasicBlock();
4478*03ce13f7SAndroid Build Coastguard Worker auto resumeBlock = Nucleus::createBasicBlock();
4479*03ce13f7SAndroid Build Coastguard Worker Nucleus::createCondBr(V(result), resumeBlock, doneBlock);
4480*03ce13f7SAndroid Build Coastguard Worker
4481*03ce13f7SAndroid Build Coastguard Worker // return false; // coroutine has been stopped by the caller.
4482*03ce13f7SAndroid Build Coastguard Worker ::basicBlock = doneBlock;
4483*03ce13f7SAndroid Build Coastguard Worker Nucleus::createRetVoid(); // coroutine return value is ignored.
4484*03ce13f7SAndroid Build Coastguard Worker
4485*03ce13f7SAndroid Build Coastguard Worker // ... <REACTOR CODE> ...
4486*03ce13f7SAndroid Build Coastguard Worker ::basicBlock = resumeBlock;
4487*03ce13f7SAndroid Build Coastguard Worker }
4488*03ce13f7SAndroid Build Coastguard Worker
4489*03ce13f7SAndroid Build Coastguard Worker using FunctionUniquePtr = std::unique_ptr<Ice::Cfg>;
4490*03ce13f7SAndroid Build Coastguard Worker
4491*03ce13f7SAndroid Build Coastguard Worker // Generates the await function for the current coroutine.
4492*03ce13f7SAndroid Build Coastguard Worker // Cannot use Nucleus functions that modify ::function and ::basicBlock.
generateAwaitFunction()4493*03ce13f7SAndroid Build Coastguard Worker static FunctionUniquePtr generateAwaitFunction()
4494*03ce13f7SAndroid Build Coastguard Worker {
4495*03ce13f7SAndroid Build Coastguard Worker // bool coroutine_await(CoroutineHandle handle, YieldType* out)
4496*03ce13f7SAndroid Build Coastguard Worker // {
4497*03ce13f7SAndroid Build Coastguard Worker // if (coro::isDone())
4498*03ce13f7SAndroid Build Coastguard Worker // {
4499*03ce13f7SAndroid Build Coastguard Worker // return false;
4500*03ce13f7SAndroid Build Coastguard Worker // }
4501*03ce13f7SAndroid Build Coastguard Worker // else // resume
4502*03ce13f7SAndroid Build Coastguard Worker // {
4503*03ce13f7SAndroid Build Coastguard Worker // YieldType* promise = coro::getPromisePtr(handle);
4504*03ce13f7SAndroid Build Coastguard Worker // *out = *promise;
4505*03ce13f7SAndroid Build Coastguard Worker // coro::resume(handle);
4506*03ce13f7SAndroid Build Coastguard Worker // return true;
4507*03ce13f7SAndroid Build Coastguard Worker // }
4508*03ce13f7SAndroid Build Coastguard Worker // }
4509*03ce13f7SAndroid Build Coastguard Worker
4510*03ce13f7SAndroid Build Coastguard Worker // Subzero doesn't support bool types (IceType_i1) as return type
4511*03ce13f7SAndroid Build Coastguard Worker const Ice::Type ReturnType = Ice::IceType_i32;
4512*03ce13f7SAndroid Build Coastguard Worker const Ice::Type YieldPtrType = sz::getPointerType(T(::coroYieldType));
4513*03ce13f7SAndroid Build Coastguard Worker const Ice::Type HandleType = sz::getPointerType(Ice::IceType_void);
4514*03ce13f7SAndroid Build Coastguard Worker
4515*03ce13f7SAndroid Build Coastguard Worker Ice::Cfg *awaitFunc = sz::createFunction(::context, ReturnType, std::vector<Ice::Type>{ HandleType, YieldPtrType });
4516*03ce13f7SAndroid Build Coastguard Worker Ice::CfgLocalAllocatorScope scopedAlloc{ awaitFunc };
4517*03ce13f7SAndroid Build Coastguard Worker
4518*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *handle = awaitFunc->getArgs()[0];
4519*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *outPtr = awaitFunc->getArgs()[1];
4520*03ce13f7SAndroid Build Coastguard Worker
4521*03ce13f7SAndroid Build Coastguard Worker auto doneBlock = awaitFunc->makeNode();
4522*03ce13f7SAndroid Build Coastguard Worker {
4523*03ce13f7SAndroid Build Coastguard Worker // return false;
4524*03ce13f7SAndroid Build Coastguard Worker Ice::InstRet *ret = Ice::InstRet::create(awaitFunc, ::context->getConstantInt32(0));
4525*03ce13f7SAndroid Build Coastguard Worker doneBlock->appendInst(ret);
4526*03ce13f7SAndroid Build Coastguard Worker }
4527*03ce13f7SAndroid Build Coastguard Worker
4528*03ce13f7SAndroid Build Coastguard Worker auto resumeBlock = awaitFunc->makeNode();
4529*03ce13f7SAndroid Build Coastguard Worker {
4530*03ce13f7SAndroid Build Coastguard Worker // YieldType* promise = coro::getPromisePtr(handle);
4531*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *promise = sz::Call(awaitFunc, resumeBlock, coro::getPromisePtr, handle);
4532*03ce13f7SAndroid Build Coastguard Worker
4533*03ce13f7SAndroid Build Coastguard Worker // *out = *promise;
4534*03ce13f7SAndroid Build Coastguard Worker // Load promise value
4535*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *promiseVal = awaitFunc->makeVariable(T(::coroYieldType));
4536*03ce13f7SAndroid Build Coastguard Worker auto load = Ice::InstLoad::create(awaitFunc, promiseVal, promise);
4537*03ce13f7SAndroid Build Coastguard Worker resumeBlock->appendInst(load);
4538*03ce13f7SAndroid Build Coastguard Worker // Then store it in output param
4539*03ce13f7SAndroid Build Coastguard Worker auto store = Ice::InstStore::create(awaitFunc, promiseVal, outPtr);
4540*03ce13f7SAndroid Build Coastguard Worker resumeBlock->appendInst(store);
4541*03ce13f7SAndroid Build Coastguard Worker
4542*03ce13f7SAndroid Build Coastguard Worker // coro::resume(handle);
4543*03ce13f7SAndroid Build Coastguard Worker sz::Call(awaitFunc, resumeBlock, coro::resume, handle);
4544*03ce13f7SAndroid Build Coastguard Worker
4545*03ce13f7SAndroid Build Coastguard Worker // return true;
4546*03ce13f7SAndroid Build Coastguard Worker Ice::InstRet *ret = Ice::InstRet::create(awaitFunc, ::context->getConstantInt32(1));
4547*03ce13f7SAndroid Build Coastguard Worker resumeBlock->appendInst(ret);
4548*03ce13f7SAndroid Build Coastguard Worker }
4549*03ce13f7SAndroid Build Coastguard Worker
4550*03ce13f7SAndroid Build Coastguard Worker // if (coro::isDone())
4551*03ce13f7SAndroid Build Coastguard Worker // {
4552*03ce13f7SAndroid Build Coastguard Worker // <doneBlock>
4553*03ce13f7SAndroid Build Coastguard Worker // }
4554*03ce13f7SAndroid Build Coastguard Worker // else // resume
4555*03ce13f7SAndroid Build Coastguard Worker // {
4556*03ce13f7SAndroid Build Coastguard Worker // <resumeBlock>
4557*03ce13f7SAndroid Build Coastguard Worker // }
4558*03ce13f7SAndroid Build Coastguard Worker Ice::CfgNode *bb = awaitFunc->getEntryNode();
4559*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *done = sz::Call(awaitFunc, bb, coro::isDone, handle);
4560*03ce13f7SAndroid Build Coastguard Worker auto br = Ice::InstBr::create(awaitFunc, done, doneBlock, resumeBlock);
4561*03ce13f7SAndroid Build Coastguard Worker bb->appendInst(br);
4562*03ce13f7SAndroid Build Coastguard Worker
4563*03ce13f7SAndroid Build Coastguard Worker return FunctionUniquePtr{ awaitFunc };
4564*03ce13f7SAndroid Build Coastguard Worker }
4565*03ce13f7SAndroid Build Coastguard Worker
4566*03ce13f7SAndroid Build Coastguard Worker // Generates the destroy function for the current coroutine.
4567*03ce13f7SAndroid Build Coastguard Worker // Cannot use Nucleus functions that modify ::function and ::basicBlock.
generateDestroyFunction()4568*03ce13f7SAndroid Build Coastguard Worker static FunctionUniquePtr generateDestroyFunction()
4569*03ce13f7SAndroid Build Coastguard Worker {
4570*03ce13f7SAndroid Build Coastguard Worker // void coroutine_destroy(Nucleus::CoroutineHandle handle)
4571*03ce13f7SAndroid Build Coastguard Worker // {
4572*03ce13f7SAndroid Build Coastguard Worker // coro::stop(handle); // signal and wait for coroutine to stop, and delete coroutine data
4573*03ce13f7SAndroid Build Coastguard Worker // return;
4574*03ce13f7SAndroid Build Coastguard Worker // }
4575*03ce13f7SAndroid Build Coastguard Worker
4576*03ce13f7SAndroid Build Coastguard Worker const Ice::Type ReturnType = Ice::IceType_void;
4577*03ce13f7SAndroid Build Coastguard Worker const Ice::Type HandleType = sz::getPointerType(Ice::IceType_void);
4578*03ce13f7SAndroid Build Coastguard Worker
4579*03ce13f7SAndroid Build Coastguard Worker Ice::Cfg *destroyFunc = sz::createFunction(::context, ReturnType, std::vector<Ice::Type>{ HandleType });
4580*03ce13f7SAndroid Build Coastguard Worker Ice::CfgLocalAllocatorScope scopedAlloc{ destroyFunc };
4581*03ce13f7SAndroid Build Coastguard Worker
4582*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *handle = destroyFunc->getArgs()[0];
4583*03ce13f7SAndroid Build Coastguard Worker
4584*03ce13f7SAndroid Build Coastguard Worker auto *bb = destroyFunc->getEntryNode();
4585*03ce13f7SAndroid Build Coastguard Worker
4586*03ce13f7SAndroid Build Coastguard Worker // coro::stop(handle); // signal and wait for coroutine to stop, and delete coroutine data
4587*03ce13f7SAndroid Build Coastguard Worker sz::Call(destroyFunc, bb, coro::stop, handle);
4588*03ce13f7SAndroid Build Coastguard Worker
4589*03ce13f7SAndroid Build Coastguard Worker // return;
4590*03ce13f7SAndroid Build Coastguard Worker Ice::InstRet *ret = Ice::InstRet::create(destroyFunc);
4591*03ce13f7SAndroid Build Coastguard Worker bb->appendInst(ret);
4592*03ce13f7SAndroid Build Coastguard Worker
4593*03ce13f7SAndroid Build Coastguard Worker return FunctionUniquePtr{ destroyFunc };
4594*03ce13f7SAndroid Build Coastguard Worker }
4595*03ce13f7SAndroid Build Coastguard Worker
4596*03ce13f7SAndroid Build Coastguard Worker private:
4597*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *handle{};
4598*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *promise{};
4599*03ce13f7SAndroid Build Coastguard Worker };
4600*03ce13f7SAndroid Build Coastguard Worker
invokeCoroutineBegin(std::function<Nucleus::CoroutineHandle ()> beginFunc)4601*03ce13f7SAndroid Build Coastguard Worker static Nucleus::CoroutineHandle invokeCoroutineBegin(std::function<Nucleus::CoroutineHandle()> beginFunc)
4602*03ce13f7SAndroid Build Coastguard Worker {
4603*03ce13f7SAndroid Build Coastguard Worker // This doubles up as our coroutine handle
4604*03ce13f7SAndroid Build Coastguard Worker auto coroData = coro::createCoroutineData();
4605*03ce13f7SAndroid Build Coastguard Worker
4606*03ce13f7SAndroid Build Coastguard Worker coroData->useInternalScheduler = (marl::Scheduler::get() == nullptr);
4607*03ce13f7SAndroid Build Coastguard Worker if(coroData->useInternalScheduler)
4608*03ce13f7SAndroid Build Coastguard Worker {
4609*03ce13f7SAndroid Build Coastguard Worker ::getOrCreateScheduler().bind();
4610*03ce13f7SAndroid Build Coastguard Worker }
4611*03ce13f7SAndroid Build Coastguard Worker
4612*03ce13f7SAndroid Build Coastguard Worker auto run = [=] {
4613*03ce13f7SAndroid Build Coastguard Worker // Store handle in TLS so that the coroutine can grab it right away, before
4614*03ce13f7SAndroid Build Coastguard Worker // any fiber switch occurs.
4615*03ce13f7SAndroid Build Coastguard Worker coro::setHandleParam(coroData);
4616*03ce13f7SAndroid Build Coastguard Worker
4617*03ce13f7SAndroid Build Coastguard Worker ASSERT(!coroData->routineFiber);
4618*03ce13f7SAndroid Build Coastguard Worker coroData->routineFiber = marl::Scheduler::Fiber::current();
4619*03ce13f7SAndroid Build Coastguard Worker
4620*03ce13f7SAndroid Build Coastguard Worker beginFunc();
4621*03ce13f7SAndroid Build Coastguard Worker
4622*03ce13f7SAndroid Build Coastguard Worker ASSERT(coroData->inRoutine);
4623*03ce13f7SAndroid Build Coastguard Worker coroData->done = true; // coroutine is done.
4624*03ce13f7SAndroid Build Coastguard Worker coroData->terminated = true; // signal that the coroutine data is ready for freeing.
4625*03ce13f7SAndroid Build Coastguard Worker coroData->inRoutine = false;
4626*03ce13f7SAndroid Build Coastguard Worker coroData->mainFiber->notify();
4627*03ce13f7SAndroid Build Coastguard Worker };
4628*03ce13f7SAndroid Build Coastguard Worker
4629*03ce13f7SAndroid Build Coastguard Worker ASSERT(!coroData->mainFiber);
4630*03ce13f7SAndroid Build Coastguard Worker coroData->mainFiber = marl::Scheduler::Fiber::current();
4631*03ce13f7SAndroid Build Coastguard Worker
4632*03ce13f7SAndroid Build Coastguard Worker // block until the first yield or coroutine end
4633*03ce13f7SAndroid Build Coastguard Worker ASSERT(!coroData->inRoutine);
4634*03ce13f7SAndroid Build Coastguard Worker coroData->inRoutine = true;
4635*03ce13f7SAndroid Build Coastguard Worker marl::schedule(marl::Task(run, marl::Task::Flags::SameThread));
4636*03ce13f7SAndroid Build Coastguard Worker while(coroData->inRoutine)
4637*03ce13f7SAndroid Build Coastguard Worker {
4638*03ce13f7SAndroid Build Coastguard Worker coroData->mainFiber->wait();
4639*03ce13f7SAndroid Build Coastguard Worker }
4640*03ce13f7SAndroid Build Coastguard Worker
4641*03ce13f7SAndroid Build Coastguard Worker return coroData;
4642*03ce13f7SAndroid Build Coastguard Worker }
4643*03ce13f7SAndroid Build Coastguard Worker
createCoroutine(Type * yieldType,const std::vector<Type * > & params)4644*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createCoroutine(Type *yieldType, const std::vector<Type *> ¶ms)
4645*03ce13f7SAndroid Build Coastguard Worker {
4646*03ce13f7SAndroid Build Coastguard Worker // Start by creating a regular function
4647*03ce13f7SAndroid Build Coastguard Worker createFunction(yieldType, params);
4648*03ce13f7SAndroid Build Coastguard Worker
4649*03ce13f7SAndroid Build Coastguard Worker // Save in case yield() is called
4650*03ce13f7SAndroid Build Coastguard Worker ASSERT(::coroYieldType == nullptr); // Only one coroutine can be generated at once
4651*03ce13f7SAndroid Build Coastguard Worker ::coroYieldType = yieldType;
4652*03ce13f7SAndroid Build Coastguard Worker }
4653*03ce13f7SAndroid Build Coastguard Worker
yield(Value * val)4654*03ce13f7SAndroid Build Coastguard Worker void Nucleus::yield(Value *val)
4655*03ce13f7SAndroid Build Coastguard Worker {
4656*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4657*03ce13f7SAndroid Build Coastguard Worker Variable::materializeAll();
4658*03ce13f7SAndroid Build Coastguard Worker
4659*03ce13f7SAndroid Build Coastguard Worker // On first yield, we start generating coroutine functions
4660*03ce13f7SAndroid Build Coastguard Worker if(!::coroGen)
4661*03ce13f7SAndroid Build Coastguard Worker {
4662*03ce13f7SAndroid Build Coastguard Worker ::coroGen = std::make_shared<CoroutineGenerator>();
4663*03ce13f7SAndroid Build Coastguard Worker ::coroGen->generateCoroutineBegin();
4664*03ce13f7SAndroid Build Coastguard Worker }
4665*03ce13f7SAndroid Build Coastguard Worker
4666*03ce13f7SAndroid Build Coastguard Worker ASSERT(::coroGen);
4667*03ce13f7SAndroid Build Coastguard Worker ::coroGen->generateYield(val);
4668*03ce13f7SAndroid Build Coastguard Worker }
4669*03ce13f7SAndroid Build Coastguard Worker
coroutineEntryAwaitStub(Nucleus::CoroutineHandle,void * yieldValue)4670*03ce13f7SAndroid Build Coastguard Worker static bool coroutineEntryAwaitStub(Nucleus::CoroutineHandle, void *yieldValue)
4671*03ce13f7SAndroid Build Coastguard Worker {
4672*03ce13f7SAndroid Build Coastguard Worker return false;
4673*03ce13f7SAndroid Build Coastguard Worker }
4674*03ce13f7SAndroid Build Coastguard Worker
coroutineEntryDestroyStub(Nucleus::CoroutineHandle handle)4675*03ce13f7SAndroid Build Coastguard Worker static void coroutineEntryDestroyStub(Nucleus::CoroutineHandle handle)
4676*03ce13f7SAndroid Build Coastguard Worker {
4677*03ce13f7SAndroid Build Coastguard Worker }
4678*03ce13f7SAndroid Build Coastguard Worker
acquireCoroutine(const char * name)4679*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Routine> Nucleus::acquireCoroutine(const char *name)
4680*03ce13f7SAndroid Build Coastguard Worker {
4681*03ce13f7SAndroid Build Coastguard Worker if(::coroGen)
4682*03ce13f7SAndroid Build Coastguard Worker {
4683*03ce13f7SAndroid Build Coastguard Worker // Finish generating coroutine functions
4684*03ce13f7SAndroid Build Coastguard Worker {
4685*03ce13f7SAndroid Build Coastguard Worker Ice::CfgLocalAllocatorScope scopedAlloc{ ::function };
4686*03ce13f7SAndroid Build Coastguard Worker finalizeFunction();
4687*03ce13f7SAndroid Build Coastguard Worker }
4688*03ce13f7SAndroid Build Coastguard Worker
4689*03ce13f7SAndroid Build Coastguard Worker auto awaitFunc = ::coroGen->generateAwaitFunction();
4690*03ce13f7SAndroid Build Coastguard Worker auto destroyFunc = ::coroGen->generateDestroyFunction();
4691*03ce13f7SAndroid Build Coastguard Worker
4692*03ce13f7SAndroid Build Coastguard Worker // At this point, we no longer need the CoroutineGenerator.
4693*03ce13f7SAndroid Build Coastguard Worker ::coroGen.reset();
4694*03ce13f7SAndroid Build Coastguard Worker ::coroYieldType = nullptr;
4695*03ce13f7SAndroid Build Coastguard Worker
4696*03ce13f7SAndroid Build Coastguard Worker auto routine = rr::acquireRoutine({ ::function, awaitFunc.get(), destroyFunc.get() },
4697*03ce13f7SAndroid Build Coastguard Worker { name, "await", "destroy" });
4698*03ce13f7SAndroid Build Coastguard Worker
4699*03ce13f7SAndroid Build Coastguard Worker return routine;
4700*03ce13f7SAndroid Build Coastguard Worker }
4701*03ce13f7SAndroid Build Coastguard Worker else
4702*03ce13f7SAndroid Build Coastguard Worker {
4703*03ce13f7SAndroid Build Coastguard Worker {
4704*03ce13f7SAndroid Build Coastguard Worker Ice::CfgLocalAllocatorScope scopedAlloc{ ::function };
4705*03ce13f7SAndroid Build Coastguard Worker finalizeFunction();
4706*03ce13f7SAndroid Build Coastguard Worker }
4707*03ce13f7SAndroid Build Coastguard Worker
4708*03ce13f7SAndroid Build Coastguard Worker ::coroYieldType = nullptr;
4709*03ce13f7SAndroid Build Coastguard Worker
4710*03ce13f7SAndroid Build Coastguard Worker // Not an actual coroutine (no yields), so return stubs for await and destroy
4711*03ce13f7SAndroid Build Coastguard Worker auto routine = rr::acquireRoutine({ ::function }, { name });
4712*03ce13f7SAndroid Build Coastguard Worker
4713*03ce13f7SAndroid Build Coastguard Worker auto routineImpl = std::static_pointer_cast<ELFMemoryStreamer>(routine);
4714*03ce13f7SAndroid Build Coastguard Worker routineImpl->setEntry(Nucleus::CoroutineEntryAwait, reinterpret_cast<const void *>(&coroutineEntryAwaitStub));
4715*03ce13f7SAndroid Build Coastguard Worker routineImpl->setEntry(Nucleus::CoroutineEntryDestroy, reinterpret_cast<const void *>(&coroutineEntryDestroyStub));
4716*03ce13f7SAndroid Build Coastguard Worker return routine;
4717*03ce13f7SAndroid Build Coastguard Worker }
4718*03ce13f7SAndroid Build Coastguard Worker }
4719*03ce13f7SAndroid Build Coastguard Worker
invokeCoroutineBegin(Routine & routine,std::function<Nucleus::CoroutineHandle ()> func)4720*03ce13f7SAndroid Build Coastguard Worker Nucleus::CoroutineHandle Nucleus::invokeCoroutineBegin(Routine &routine, std::function<Nucleus::CoroutineHandle()> func)
4721*03ce13f7SAndroid Build Coastguard Worker {
4722*03ce13f7SAndroid Build Coastguard Worker const bool isCoroutine = routine.getEntry(Nucleus::CoroutineEntryAwait) != reinterpret_cast<const void *>(&coroutineEntryAwaitStub);
4723*03ce13f7SAndroid Build Coastguard Worker
4724*03ce13f7SAndroid Build Coastguard Worker if(isCoroutine)
4725*03ce13f7SAndroid Build Coastguard Worker {
4726*03ce13f7SAndroid Build Coastguard Worker return rr::invokeCoroutineBegin(func);
4727*03ce13f7SAndroid Build Coastguard Worker }
4728*03ce13f7SAndroid Build Coastguard Worker else
4729*03ce13f7SAndroid Build Coastguard Worker {
4730*03ce13f7SAndroid Build Coastguard Worker // For regular routines, just invoke the begin func directly
4731*03ce13f7SAndroid Build Coastguard Worker return func();
4732*03ce13f7SAndroid Build Coastguard Worker }
4733*03ce13f7SAndroid Build Coastguard Worker }
4734*03ce13f7SAndroid Build Coastguard Worker
Int(RValue<scalar::Int> rhs)4735*03ce13f7SAndroid Build Coastguard Worker SIMD::Int::Int(RValue<scalar::Int> rhs)
4736*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
4737*03ce13f7SAndroid Build Coastguard Worker {
4738*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4739*03ce13f7SAndroid Build Coastguard Worker Value *vector = Nucleus::createBitCast(rhs.value(), SIMD::Int::type());
4740*03ce13f7SAndroid Build Coastguard Worker
4741*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0 };
4742*03ce13f7SAndroid Build Coastguard Worker Value *replicate = Nucleus::createShuffleVector(vector, vector, swizzle);
4743*03ce13f7SAndroid Build Coastguard Worker
4744*03ce13f7SAndroid Build Coastguard Worker storeValue(replicate);
4745*03ce13f7SAndroid Build Coastguard Worker }
4746*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<SIMD::Int> lhs,unsigned char rhs)4747*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> operator<<(RValue<SIMD::Int> lhs, unsigned char rhs)
4748*03ce13f7SAndroid Build Coastguard Worker {
4749*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4750*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
4751*03ce13f7SAndroid Build Coastguard Worker {
4752*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << rhs; }, lhs);
4753*03ce13f7SAndroid Build Coastguard Worker }
4754*03ce13f7SAndroid Build Coastguard Worker else
4755*03ce13f7SAndroid Build Coastguard Worker {
4756*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
4757*03ce13f7SAndroid Build Coastguard Worker }
4758*03ce13f7SAndroid Build Coastguard Worker }
4759*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<SIMD::Int> lhs,unsigned char rhs)4760*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> operator>>(RValue<SIMD::Int> lhs, unsigned char rhs)
4761*03ce13f7SAndroid Build Coastguard Worker {
4762*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4763*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
4764*03ce13f7SAndroid Build Coastguard Worker {
4765*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> rhs; }, lhs);
4766*03ce13f7SAndroid Build Coastguard Worker }
4767*03ce13f7SAndroid Build Coastguard Worker else
4768*03ce13f7SAndroid Build Coastguard Worker {
4769*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createAShr(lhs.value(), V(::context->getConstantInt32(rhs))));
4770*03ce13f7SAndroid Build Coastguard Worker }
4771*03ce13f7SAndroid Build Coastguard Worker }
4772*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4773*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpEQ(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4774*03ce13f7SAndroid Build Coastguard Worker {
4775*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4776*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createICmpEQ(x.value(), y.value()));
4777*03ce13f7SAndroid Build Coastguard Worker }
4778*03ce13f7SAndroid Build Coastguard Worker
CmpLT(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4779*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpLT(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4780*03ce13f7SAndroid Build Coastguard Worker {
4781*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4782*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createICmpSLT(x.value(), y.value()));
4783*03ce13f7SAndroid Build Coastguard Worker }
4784*03ce13f7SAndroid Build Coastguard Worker
CmpLE(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4785*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpLE(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4786*03ce13f7SAndroid Build Coastguard Worker {
4787*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4788*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createICmpSLE(x.value(), y.value()));
4789*03ce13f7SAndroid Build Coastguard Worker }
4790*03ce13f7SAndroid Build Coastguard Worker
CmpNEQ(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4791*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNEQ(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4792*03ce13f7SAndroid Build Coastguard Worker {
4793*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4794*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createICmpNE(x.value(), y.value()));
4795*03ce13f7SAndroid Build Coastguard Worker }
4796*03ce13f7SAndroid Build Coastguard Worker
CmpNLT(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4797*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNLT(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4798*03ce13f7SAndroid Build Coastguard Worker {
4799*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4800*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createICmpSGE(x.value(), y.value()));
4801*03ce13f7SAndroid Build Coastguard Worker }
4802*03ce13f7SAndroid Build Coastguard Worker
CmpNLE(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4803*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNLE(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4804*03ce13f7SAndroid Build Coastguard Worker {
4805*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4806*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createICmpSGT(x.value(), y.value()));
4807*03ce13f7SAndroid Build Coastguard Worker }
4808*03ce13f7SAndroid Build Coastguard Worker
Abs(RValue<SIMD::Int> x)4809*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Abs(RValue<SIMD::Int> x)
4810*03ce13f7SAndroid Build Coastguard Worker {
4811*03ce13f7SAndroid Build Coastguard Worker // TODO: Optimize.
4812*03ce13f7SAndroid Build Coastguard Worker auto negative = x >> 31;
4813*03ce13f7SAndroid Build Coastguard Worker return (x ^ negative) - negative;
4814*03ce13f7SAndroid Build Coastguard Worker }
4815*03ce13f7SAndroid Build Coastguard Worker
Max(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4816*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Max(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4817*03ce13f7SAndroid Build Coastguard Worker {
4818*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4819*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
4820*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sle, condition, x.value(), y.value());
4821*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
4822*03ce13f7SAndroid Build Coastguard Worker
4823*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
4824*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
4825*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
4826*03ce13f7SAndroid Build Coastguard Worker
4827*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(V(result));
4828*03ce13f7SAndroid Build Coastguard Worker }
4829*03ce13f7SAndroid Build Coastguard Worker
Min(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4830*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Min(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4831*03ce13f7SAndroid Build Coastguard Worker {
4832*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4833*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
4834*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sgt, condition, x.value(), y.value());
4835*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
4836*03ce13f7SAndroid Build Coastguard Worker
4837*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
4838*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
4839*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
4840*03ce13f7SAndroid Build Coastguard Worker
4841*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(V(result));
4842*03ce13f7SAndroid Build Coastguard Worker }
4843*03ce13f7SAndroid Build Coastguard Worker
RoundInt(RValue<SIMD::Float> cast)4844*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> RoundInt(RValue<SIMD::Float> cast)
4845*03ce13f7SAndroid Build Coastguard Worker {
4846*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4847*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
4848*03ce13f7SAndroid Build Coastguard Worker {
4849*03ce13f7SAndroid Build Coastguard Worker // Push the fractional part off the mantissa. Accurate up to +/-2^22.
4850*03ce13f7SAndroid Build Coastguard Worker return SIMD::Int((cast + SIMD::Float(0x00C00000)) - SIMD::Float(0x00C00000));
4851*03ce13f7SAndroid Build Coastguard Worker }
4852*03ce13f7SAndroid Build Coastguard Worker else
4853*03ce13f7SAndroid Build Coastguard Worker {
4854*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
4855*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
4856*03ce13f7SAndroid Build Coastguard Worker auto nearbyint = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
4857*03ce13f7SAndroid Build Coastguard Worker nearbyint->addArg(cast.value());
4858*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(nearbyint);
4859*03ce13f7SAndroid Build Coastguard Worker
4860*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(V(result));
4861*03ce13f7SAndroid Build Coastguard Worker }
4862*03ce13f7SAndroid Build Coastguard Worker }
4863*03ce13f7SAndroid Build Coastguard Worker
RoundIntClamped(RValue<SIMD::Float> cast)4864*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> RoundIntClamped(RValue<SIMD::Float> cast)
4865*03ce13f7SAndroid Build Coastguard Worker {
4866*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4867*03ce13f7SAndroid Build Coastguard Worker
4868*03ce13f7SAndroid Build Coastguard Worker // cvtps2dq produces 0x80000000, a negative value, for input larger than
4869*03ce13f7SAndroid Build Coastguard Worker // 2147483520.0, so clamp to 2147483520. Values less than -2147483520.0
4870*03ce13f7SAndroid Build Coastguard Worker // saturate to 0x80000000.
4871*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> clamped = Min(cast, SIMD::Float(0x7FFFFF80));
4872*03ce13f7SAndroid Build Coastguard Worker
4873*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
4874*03ce13f7SAndroid Build Coastguard Worker {
4875*03ce13f7SAndroid Build Coastguard Worker // Push the fractional part off the mantissa. Accurate up to +/-2^22.
4876*03ce13f7SAndroid Build Coastguard Worker return SIMD::Int((clamped + SIMD::Float(0x00C00000)) - SIMD::Float(0x00C00000));
4877*03ce13f7SAndroid Build Coastguard Worker }
4878*03ce13f7SAndroid Build Coastguard Worker else
4879*03ce13f7SAndroid Build Coastguard Worker {
4880*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
4881*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
4882*03ce13f7SAndroid Build Coastguard Worker auto nearbyint = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
4883*03ce13f7SAndroid Build Coastguard Worker nearbyint->addArg(clamped.value());
4884*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(nearbyint);
4885*03ce13f7SAndroid Build Coastguard Worker
4886*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(V(result));
4887*03ce13f7SAndroid Build Coastguard Worker }
4888*03ce13f7SAndroid Build Coastguard Worker }
4889*03ce13f7SAndroid Build Coastguard Worker
Extract128(RValue<SIMD::Int> val,int i)4890*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> Extract128(RValue<SIMD::Int> val, int i)
4891*03ce13f7SAndroid Build Coastguard Worker {
4892*03ce13f7SAndroid Build Coastguard Worker ASSERT(SIMD::Width == 4);
4893*03ce13f7SAndroid Build Coastguard Worker ASSERT(i == 0);
4894*03ce13f7SAndroid Build Coastguard Worker
4895*03ce13f7SAndroid Build Coastguard Worker return As<Int4>(val);
4896*03ce13f7SAndroid Build Coastguard Worker }
4897*03ce13f7SAndroid Build Coastguard Worker
Insert128(RValue<SIMD::Int> val,RValue<Int4> element,int i)4898*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Insert128(RValue<SIMD::Int> val, RValue<Int4> element, int i)
4899*03ce13f7SAndroid Build Coastguard Worker {
4900*03ce13f7SAndroid Build Coastguard Worker ASSERT(SIMD::Width == 4);
4901*03ce13f7SAndroid Build Coastguard Worker ASSERT(i == 0);
4902*03ce13f7SAndroid Build Coastguard Worker
4903*03ce13f7SAndroid Build Coastguard Worker return As<SIMD::Int>(element);
4904*03ce13f7SAndroid Build Coastguard Worker }
4905*03ce13f7SAndroid Build Coastguard Worker
type()4906*03ce13f7SAndroid Build Coastguard Worker Type *SIMD::Int::type()
4907*03ce13f7SAndroid Build Coastguard Worker {
4908*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v4i32);
4909*03ce13f7SAndroid Build Coastguard Worker }
4910*03ce13f7SAndroid Build Coastguard Worker
UInt(RValue<SIMD::Float> cast)4911*03ce13f7SAndroid Build Coastguard Worker SIMD::UInt::UInt(RValue<SIMD::Float> cast)
4912*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
4913*03ce13f7SAndroid Build Coastguard Worker {
4914*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4915*03ce13f7SAndroid Build Coastguard Worker // Smallest positive value representable in UInt, but not in Int
4916*03ce13f7SAndroid Build Coastguard Worker const unsigned int ustart = 0x80000000u;
4917*03ce13f7SAndroid Build Coastguard Worker const float ustartf = float(ustart);
4918*03ce13f7SAndroid Build Coastguard Worker
4919*03ce13f7SAndroid Build Coastguard Worker // Check if the value can be represented as an Int
4920*03ce13f7SAndroid Build Coastguard Worker SIMD::Int uiValue = CmpNLT(cast, SIMD::Float(ustartf));
4921*03ce13f7SAndroid Build Coastguard Worker // If the value is too large, subtract ustart and re-add it after conversion.
4922*03ce13f7SAndroid Build Coastguard Worker uiValue = (uiValue & As<SIMD::Int>(As<SIMD::UInt>(SIMD::Int(cast - SIMD::Float(ustartf))) + SIMD::UInt(ustart))) |
4923*03ce13f7SAndroid Build Coastguard Worker // Otherwise, just convert normally
4924*03ce13f7SAndroid Build Coastguard Worker (~uiValue & SIMD::Int(cast));
4925*03ce13f7SAndroid Build Coastguard Worker // If the value is negative, store 0, otherwise store the result of the conversion
4926*03ce13f7SAndroid Build Coastguard Worker storeValue((~(As<SIMD::Int>(cast) >> 31) & uiValue).value());
4927*03ce13f7SAndroid Build Coastguard Worker }
4928*03ce13f7SAndroid Build Coastguard Worker
UInt(RValue<scalar::UInt> rhs)4929*03ce13f7SAndroid Build Coastguard Worker SIMD::UInt::UInt(RValue<scalar::UInt> rhs)
4930*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
4931*03ce13f7SAndroid Build Coastguard Worker {
4932*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4933*03ce13f7SAndroid Build Coastguard Worker Value *vector = Nucleus::createBitCast(rhs.value(), SIMD::UInt::type());
4934*03ce13f7SAndroid Build Coastguard Worker
4935*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0 };
4936*03ce13f7SAndroid Build Coastguard Worker Value *replicate = Nucleus::createShuffleVector(vector, vector, swizzle);
4937*03ce13f7SAndroid Build Coastguard Worker
4938*03ce13f7SAndroid Build Coastguard Worker storeValue(replicate);
4939*03ce13f7SAndroid Build Coastguard Worker }
4940*03ce13f7SAndroid Build Coastguard Worker
operator <<(RValue<SIMD::UInt> lhs,unsigned char rhs)4941*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> operator<<(RValue<SIMD::UInt> lhs, unsigned char rhs)
4942*03ce13f7SAndroid Build Coastguard Worker {
4943*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4944*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
4945*03ce13f7SAndroid Build Coastguard Worker {
4946*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x << rhs; }, lhs);
4947*03ce13f7SAndroid Build Coastguard Worker }
4948*03ce13f7SAndroid Build Coastguard Worker else
4949*03ce13f7SAndroid Build Coastguard Worker {
4950*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(Nucleus::createShl(lhs.value(), V(::context->getConstantInt32(rhs))));
4951*03ce13f7SAndroid Build Coastguard Worker }
4952*03ce13f7SAndroid Build Coastguard Worker }
4953*03ce13f7SAndroid Build Coastguard Worker
operator >>(RValue<SIMD::UInt> lhs,unsigned char rhs)4954*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> operator>>(RValue<SIMD::UInt> lhs, unsigned char rhs)
4955*03ce13f7SAndroid Build Coastguard Worker {
4956*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4957*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics)
4958*03ce13f7SAndroid Build Coastguard Worker {
4959*03ce13f7SAndroid Build Coastguard Worker return Scalarize([rhs](auto x) { return x >> rhs; }, lhs);
4960*03ce13f7SAndroid Build Coastguard Worker }
4961*03ce13f7SAndroid Build Coastguard Worker else
4962*03ce13f7SAndroid Build Coastguard Worker {
4963*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(Nucleus::createLShr(lhs.value(), V(::context->getConstantInt32(rhs))));
4964*03ce13f7SAndroid Build Coastguard Worker }
4965*03ce13f7SAndroid Build Coastguard Worker }
4966*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4967*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpEQ(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4968*03ce13f7SAndroid Build Coastguard Worker {
4969*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4970*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(Nucleus::createICmpEQ(x.value(), y.value()));
4971*03ce13f7SAndroid Build Coastguard Worker }
4972*03ce13f7SAndroid Build Coastguard Worker
CmpLT(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4973*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpLT(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4974*03ce13f7SAndroid Build Coastguard Worker {
4975*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4976*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(Nucleus::createICmpULT(x.value(), y.value()));
4977*03ce13f7SAndroid Build Coastguard Worker }
4978*03ce13f7SAndroid Build Coastguard Worker
CmpLE(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4979*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpLE(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4980*03ce13f7SAndroid Build Coastguard Worker {
4981*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4982*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(Nucleus::createICmpULE(x.value(), y.value()));
4983*03ce13f7SAndroid Build Coastguard Worker }
4984*03ce13f7SAndroid Build Coastguard Worker
CmpNEQ(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4985*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpNEQ(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4986*03ce13f7SAndroid Build Coastguard Worker {
4987*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4988*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(Nucleus::createICmpNE(x.value(), y.value()));
4989*03ce13f7SAndroid Build Coastguard Worker }
4990*03ce13f7SAndroid Build Coastguard Worker
CmpNLT(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4991*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpNLT(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4992*03ce13f7SAndroid Build Coastguard Worker {
4993*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
4994*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(Nucleus::createICmpUGE(x.value(), y.value()));
4995*03ce13f7SAndroid Build Coastguard Worker }
4996*03ce13f7SAndroid Build Coastguard Worker
CmpNLE(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4997*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpNLE(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4998*03ce13f7SAndroid Build Coastguard Worker {
4999*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5000*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(Nucleus::createICmpUGT(x.value(), y.value()));
5001*03ce13f7SAndroid Build Coastguard Worker }
5002*03ce13f7SAndroid Build Coastguard Worker
Max(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)5003*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> Max(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
5004*03ce13f7SAndroid Build Coastguard Worker {
5005*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5006*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
5007*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ule, condition, x.value(), y.value());
5008*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
5009*03ce13f7SAndroid Build Coastguard Worker
5010*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
5011*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
5012*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
5013*03ce13f7SAndroid Build Coastguard Worker
5014*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(V(result));
5015*03ce13f7SAndroid Build Coastguard Worker }
5016*03ce13f7SAndroid Build Coastguard Worker
Min(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)5017*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> Min(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
5018*03ce13f7SAndroid Build Coastguard Worker {
5019*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5020*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
5021*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ugt, condition, x.value(), y.value());
5022*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
5023*03ce13f7SAndroid Build Coastguard Worker
5024*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
5025*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, y.value(), x.value());
5026*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
5027*03ce13f7SAndroid Build Coastguard Worker
5028*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::UInt>(V(result));
5029*03ce13f7SAndroid Build Coastguard Worker }
5030*03ce13f7SAndroid Build Coastguard Worker
Extract128(RValue<SIMD::UInt> val,int i)5031*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Extract128(RValue<SIMD::UInt> val, int i)
5032*03ce13f7SAndroid Build Coastguard Worker {
5033*03ce13f7SAndroid Build Coastguard Worker ASSERT(SIMD::Width == 4);
5034*03ce13f7SAndroid Build Coastguard Worker ASSERT(i == 0);
5035*03ce13f7SAndroid Build Coastguard Worker
5036*03ce13f7SAndroid Build Coastguard Worker return As<UInt4>(val);
5037*03ce13f7SAndroid Build Coastguard Worker }
5038*03ce13f7SAndroid Build Coastguard Worker
Insert128(RValue<SIMD::UInt> val,RValue<UInt4> element,int i)5039*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> Insert128(RValue<SIMD::UInt> val, RValue<UInt4> element, int i)
5040*03ce13f7SAndroid Build Coastguard Worker {
5041*03ce13f7SAndroid Build Coastguard Worker ASSERT(SIMD::Width == 4);
5042*03ce13f7SAndroid Build Coastguard Worker ASSERT(i == 0);
5043*03ce13f7SAndroid Build Coastguard Worker
5044*03ce13f7SAndroid Build Coastguard Worker return As<SIMD::UInt>(element);
5045*03ce13f7SAndroid Build Coastguard Worker }
5046*03ce13f7SAndroid Build Coastguard Worker
type()5047*03ce13f7SAndroid Build Coastguard Worker Type *SIMD::UInt::type()
5048*03ce13f7SAndroid Build Coastguard Worker {
5049*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v4i32);
5050*03ce13f7SAndroid Build Coastguard Worker }
5051*03ce13f7SAndroid Build Coastguard Worker
Float(RValue<scalar::Float> rhs)5052*03ce13f7SAndroid Build Coastguard Worker SIMD::Float::Float(RValue<scalar::Float> rhs)
5053*03ce13f7SAndroid Build Coastguard Worker : XYZW(this)
5054*03ce13f7SAndroid Build Coastguard Worker {
5055*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5056*03ce13f7SAndroid Build Coastguard Worker Value *vector = Nucleus::createBitCast(rhs.value(), SIMD::Float::type());
5057*03ce13f7SAndroid Build Coastguard Worker
5058*03ce13f7SAndroid Build Coastguard Worker std::vector<int> swizzle = { 0 };
5059*03ce13f7SAndroid Build Coastguard Worker Value *replicate = Nucleus::createShuffleVector(vector, vector, swizzle);
5060*03ce13f7SAndroid Build Coastguard Worker
5061*03ce13f7SAndroid Build Coastguard Worker storeValue(replicate);
5062*03ce13f7SAndroid Build Coastguard Worker }
5063*03ce13f7SAndroid Build Coastguard Worker
operator %(RValue<SIMD::Float> lhs,RValue<SIMD::Float> rhs)5064*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> operator%(RValue<SIMD::Float> lhs, RValue<SIMD::Float> rhs)
5065*03ce13f7SAndroid Build Coastguard Worker {
5066*03ce13f7SAndroid Build Coastguard Worker return ScalarizeCall(fmodf, lhs, rhs);
5067*03ce13f7SAndroid Build Coastguard Worker }
5068*03ce13f7SAndroid Build Coastguard Worker
MulAdd(RValue<SIMD::Float> x,RValue<SIMD::Float> y,RValue<SIMD::Float> z)5069*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> MulAdd(RValue<SIMD::Float> x, RValue<SIMD::Float> y, RValue<SIMD::Float> z)
5070*03ce13f7SAndroid Build Coastguard Worker {
5071*03ce13f7SAndroid Build Coastguard Worker // TODO(b/214591655): Use FMA when available.
5072*03ce13f7SAndroid Build Coastguard Worker return x * y + z;
5073*03ce13f7SAndroid Build Coastguard Worker }
5074*03ce13f7SAndroid Build Coastguard Worker
FMA(RValue<SIMD::Float> x,RValue<SIMD::Float> y,RValue<SIMD::Float> z)5075*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> FMA(RValue<SIMD::Float> x, RValue<SIMD::Float> y, RValue<SIMD::Float> z)
5076*03ce13f7SAndroid Build Coastguard Worker {
5077*03ce13f7SAndroid Build Coastguard Worker // TODO(b/214591655): Use FMA instructions when available.
5078*03ce13f7SAndroid Build Coastguard Worker return ScalarizeCall(fmaf, x, y, z);
5079*03ce13f7SAndroid Build Coastguard Worker }
5080*03ce13f7SAndroid Build Coastguard Worker
Abs(RValue<SIMD::Float> x)5081*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Abs(RValue<SIMD::Float> x)
5082*03ce13f7SAndroid Build Coastguard Worker {
5083*03ce13f7SAndroid Build Coastguard Worker // TODO: Optimize.
5084*03ce13f7SAndroid Build Coastguard Worker Value *vector = Nucleus::createBitCast(x.value(), SIMD::Int::type());
5085*03ce13f7SAndroid Build Coastguard Worker std::vector<int64_t> constantVector = { 0x7FFFFFFF };
5086*03ce13f7SAndroid Build Coastguard Worker Value *result = Nucleus::createAnd(vector, Nucleus::createConstantVector(constantVector, SIMD::Int::type()));
5087*03ce13f7SAndroid Build Coastguard Worker
5088*03ce13f7SAndroid Build Coastguard Worker return As<SIMD::Float>(result);
5089*03ce13f7SAndroid Build Coastguard Worker }
5090*03ce13f7SAndroid Build Coastguard Worker
Max(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5091*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Max(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5092*03ce13f7SAndroid Build Coastguard Worker {
5093*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5094*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
5095*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstFcmp::create(::function, Ice::InstFcmp::Ogt, condition, x.value(), y.value());
5096*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
5097*03ce13f7SAndroid Build Coastguard Worker
5098*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
5099*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, x.value(), y.value());
5100*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
5101*03ce13f7SAndroid Build Coastguard Worker
5102*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Float>(V(result));
5103*03ce13f7SAndroid Build Coastguard Worker }
5104*03ce13f7SAndroid Build Coastguard Worker
Min(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5105*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Min(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5106*03ce13f7SAndroid Build Coastguard Worker {
5107*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5108*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
5109*03ce13f7SAndroid Build Coastguard Worker auto cmp = Ice::InstFcmp::create(::function, Ice::InstFcmp::Olt, condition, x.value(), y.value());
5110*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(cmp);
5111*03ce13f7SAndroid Build Coastguard Worker
5112*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
5113*03ce13f7SAndroid Build Coastguard Worker auto select = Ice::InstSelect::create(::function, result, condition, x.value(), y.value());
5114*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(select);
5115*03ce13f7SAndroid Build Coastguard Worker
5116*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Float>(V(result));
5117*03ce13f7SAndroid Build Coastguard Worker }
5118*03ce13f7SAndroid Build Coastguard Worker
Sqrt(RValue<SIMD::Float> x)5119*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Sqrt(RValue<SIMD::Float> x)
5120*03ce13f7SAndroid Build Coastguard Worker {
5121*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5122*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
5123*03ce13f7SAndroid Build Coastguard Worker {
5124*03ce13f7SAndroid Build Coastguard Worker return Scalarize([](auto a) { return Sqrt(a); }, x);
5125*03ce13f7SAndroid Build Coastguard Worker }
5126*03ce13f7SAndroid Build Coastguard Worker else
5127*03ce13f7SAndroid Build Coastguard Worker {
5128*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
5129*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Sqrt, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
5130*03ce13f7SAndroid Build Coastguard Worker auto sqrt = Ice::InstIntrinsic::create(::function, 1, result, intrinsic);
5131*03ce13f7SAndroid Build Coastguard Worker sqrt->addArg(x.value());
5132*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(sqrt);
5133*03ce13f7SAndroid Build Coastguard Worker
5134*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Float>(V(result));
5135*03ce13f7SAndroid Build Coastguard Worker }
5136*03ce13f7SAndroid Build Coastguard Worker }
5137*03ce13f7SAndroid Build Coastguard Worker
CmpEQ(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5138*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpEQ(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5139*03ce13f7SAndroid Build Coastguard Worker {
5140*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5141*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpOEQ(x.value(), y.value()));
5142*03ce13f7SAndroid Build Coastguard Worker }
5143*03ce13f7SAndroid Build Coastguard Worker
CmpLT(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5144*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpLT(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5145*03ce13f7SAndroid Build Coastguard Worker {
5146*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5147*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpOLT(x.value(), y.value()));
5148*03ce13f7SAndroid Build Coastguard Worker }
5149*03ce13f7SAndroid Build Coastguard Worker
CmpLE(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5150*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpLE(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5151*03ce13f7SAndroid Build Coastguard Worker {
5152*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5153*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpOLE(x.value(), y.value()));
5154*03ce13f7SAndroid Build Coastguard Worker }
5155*03ce13f7SAndroid Build Coastguard Worker
CmpNEQ(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5156*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNEQ(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5157*03ce13f7SAndroid Build Coastguard Worker {
5158*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5159*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpONE(x.value(), y.value()));
5160*03ce13f7SAndroid Build Coastguard Worker }
5161*03ce13f7SAndroid Build Coastguard Worker
CmpNLT(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5162*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNLT(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5163*03ce13f7SAndroid Build Coastguard Worker {
5164*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5165*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpOGE(x.value(), y.value()));
5166*03ce13f7SAndroid Build Coastguard Worker }
5167*03ce13f7SAndroid Build Coastguard Worker
CmpNLE(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5168*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNLE(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5169*03ce13f7SAndroid Build Coastguard Worker {
5170*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5171*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpOGT(x.value(), y.value()));
5172*03ce13f7SAndroid Build Coastguard Worker }
5173*03ce13f7SAndroid Build Coastguard Worker
CmpUEQ(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5174*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpUEQ(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5175*03ce13f7SAndroid Build Coastguard Worker {
5176*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5177*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpUEQ(x.value(), y.value()));
5178*03ce13f7SAndroid Build Coastguard Worker }
5179*03ce13f7SAndroid Build Coastguard Worker
CmpULT(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5180*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpULT(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5181*03ce13f7SAndroid Build Coastguard Worker {
5182*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5183*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpULT(x.value(), y.value()));
5184*03ce13f7SAndroid Build Coastguard Worker }
5185*03ce13f7SAndroid Build Coastguard Worker
CmpULE(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5186*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpULE(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5187*03ce13f7SAndroid Build Coastguard Worker {
5188*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5189*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpULE(x.value(), y.value()));
5190*03ce13f7SAndroid Build Coastguard Worker }
5191*03ce13f7SAndroid Build Coastguard Worker
CmpUNEQ(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5192*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpUNEQ(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5193*03ce13f7SAndroid Build Coastguard Worker {
5194*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5195*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpUNE(x.value(), y.value()));
5196*03ce13f7SAndroid Build Coastguard Worker }
5197*03ce13f7SAndroid Build Coastguard Worker
CmpUNLT(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5198*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpUNLT(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5199*03ce13f7SAndroid Build Coastguard Worker {
5200*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5201*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpUGE(x.value(), y.value()));
5202*03ce13f7SAndroid Build Coastguard Worker }
5203*03ce13f7SAndroid Build Coastguard Worker
CmpUNLE(RValue<SIMD::Float> x,RValue<SIMD::Float> y)5204*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpUNLE(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
5205*03ce13f7SAndroid Build Coastguard Worker {
5206*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5207*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Int>(Nucleus::createFCmpUGT(x.value(), y.value()));
5208*03ce13f7SAndroid Build Coastguard Worker }
5209*03ce13f7SAndroid Build Coastguard Worker
Round(RValue<SIMD::Float> x)5210*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Round(RValue<SIMD::Float> x)
5211*03ce13f7SAndroid Build Coastguard Worker {
5212*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5213*03ce13f7SAndroid Build Coastguard Worker if(emulateIntrinsics || CPUID::ARM)
5214*03ce13f7SAndroid Build Coastguard Worker {
5215*03ce13f7SAndroid Build Coastguard Worker // Push the fractional part off the mantissa. Accurate up to +/-2^22.
5216*03ce13f7SAndroid Build Coastguard Worker return (x + SIMD::Float(0x00C00000)) - SIMD::Float(0x00C00000);
5217*03ce13f7SAndroid Build Coastguard Worker }
5218*03ce13f7SAndroid Build Coastguard Worker else if(CPUID::SSE4_1)
5219*03ce13f7SAndroid Build Coastguard Worker {
5220*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
5221*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
5222*03ce13f7SAndroid Build Coastguard Worker auto round = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
5223*03ce13f7SAndroid Build Coastguard Worker round->addArg(x.value());
5224*03ce13f7SAndroid Build Coastguard Worker round->addArg(::context->getConstantInt32(0));
5225*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(round);
5226*03ce13f7SAndroid Build Coastguard Worker
5227*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Float>(V(result));
5228*03ce13f7SAndroid Build Coastguard Worker }
5229*03ce13f7SAndroid Build Coastguard Worker else
5230*03ce13f7SAndroid Build Coastguard Worker {
5231*03ce13f7SAndroid Build Coastguard Worker return SIMD::Float(RoundInt(x));
5232*03ce13f7SAndroid Build Coastguard Worker }
5233*03ce13f7SAndroid Build Coastguard Worker }
5234*03ce13f7SAndroid Build Coastguard Worker
Trunc(RValue<SIMD::Float> x)5235*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Trunc(RValue<SIMD::Float> x)
5236*03ce13f7SAndroid Build Coastguard Worker {
5237*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5238*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
5239*03ce13f7SAndroid Build Coastguard Worker {
5240*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
5241*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
5242*03ce13f7SAndroid Build Coastguard Worker auto round = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
5243*03ce13f7SAndroid Build Coastguard Worker round->addArg(x.value());
5244*03ce13f7SAndroid Build Coastguard Worker round->addArg(::context->getConstantInt32(3));
5245*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(round);
5246*03ce13f7SAndroid Build Coastguard Worker
5247*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Float>(V(result));
5248*03ce13f7SAndroid Build Coastguard Worker }
5249*03ce13f7SAndroid Build Coastguard Worker else
5250*03ce13f7SAndroid Build Coastguard Worker {
5251*03ce13f7SAndroid Build Coastguard Worker return SIMD::Float(SIMD::Int(x));
5252*03ce13f7SAndroid Build Coastguard Worker }
5253*03ce13f7SAndroid Build Coastguard Worker }
5254*03ce13f7SAndroid Build Coastguard Worker
Frac(RValue<SIMD::Float> x)5255*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Frac(RValue<SIMD::Float> x)
5256*03ce13f7SAndroid Build Coastguard Worker {
5257*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5258*03ce13f7SAndroid Build Coastguard Worker SIMD::Float frc;
5259*03ce13f7SAndroid Build Coastguard Worker
5260*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
5261*03ce13f7SAndroid Build Coastguard Worker {
5262*03ce13f7SAndroid Build Coastguard Worker frc = x - Floor(x);
5263*03ce13f7SAndroid Build Coastguard Worker }
5264*03ce13f7SAndroid Build Coastguard Worker else
5265*03ce13f7SAndroid Build Coastguard Worker {
5266*03ce13f7SAndroid Build Coastguard Worker frc = x - SIMD::Float(SIMD::Int(x)); // Signed fractional part.
5267*03ce13f7SAndroid Build Coastguard Worker
5268*03ce13f7SAndroid Build Coastguard Worker frc += As<SIMD::Float>(As<SIMD::Int>(CmpNLE(SIMD::Float(0.0f), frc)) & As<SIMD::Int>(SIMD::Float(1.0f))); // Add 1.0 if negative.
5269*03ce13f7SAndroid Build Coastguard Worker }
5270*03ce13f7SAndroid Build Coastguard Worker
5271*03ce13f7SAndroid Build Coastguard Worker // x - floor(x) can be 1.0 for very small negative x.
5272*03ce13f7SAndroid Build Coastguard Worker // Clamp against the value just below 1.0.
5273*03ce13f7SAndroid Build Coastguard Worker return Min(frc, As<SIMD::Float>(SIMD::Int(0x3F7FFFFF)));
5274*03ce13f7SAndroid Build Coastguard Worker }
5275*03ce13f7SAndroid Build Coastguard Worker
Floor(RValue<SIMD::Float> x)5276*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Floor(RValue<SIMD::Float> x)
5277*03ce13f7SAndroid Build Coastguard Worker {
5278*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5279*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
5280*03ce13f7SAndroid Build Coastguard Worker {
5281*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
5282*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
5283*03ce13f7SAndroid Build Coastguard Worker auto round = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
5284*03ce13f7SAndroid Build Coastguard Worker round->addArg(x.value());
5285*03ce13f7SAndroid Build Coastguard Worker round->addArg(::context->getConstantInt32(1));
5286*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(round);
5287*03ce13f7SAndroid Build Coastguard Worker
5288*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Float>(V(result));
5289*03ce13f7SAndroid Build Coastguard Worker }
5290*03ce13f7SAndroid Build Coastguard Worker else
5291*03ce13f7SAndroid Build Coastguard Worker {
5292*03ce13f7SAndroid Build Coastguard Worker return x - Frac(x);
5293*03ce13f7SAndroid Build Coastguard Worker }
5294*03ce13f7SAndroid Build Coastguard Worker }
5295*03ce13f7SAndroid Build Coastguard Worker
Ceil(RValue<SIMD::Float> x)5296*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Ceil(RValue<SIMD::Float> x)
5297*03ce13f7SAndroid Build Coastguard Worker {
5298*03ce13f7SAndroid Build Coastguard Worker RR_DEBUG_INFO_UPDATE_LOC();
5299*03ce13f7SAndroid Build Coastguard Worker if(CPUID::SSE4_1)
5300*03ce13f7SAndroid Build Coastguard Worker {
5301*03ce13f7SAndroid Build Coastguard Worker Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
5302*03ce13f7SAndroid Build Coastguard Worker const Ice::Intrinsics::IntrinsicInfo intrinsic = { Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F };
5303*03ce13f7SAndroid Build Coastguard Worker auto round = Ice::InstIntrinsic::create(::function, 2, result, intrinsic);
5304*03ce13f7SAndroid Build Coastguard Worker round->addArg(x.value());
5305*03ce13f7SAndroid Build Coastguard Worker round->addArg(::context->getConstantInt32(2));
5306*03ce13f7SAndroid Build Coastguard Worker ::basicBlock->appendInst(round);
5307*03ce13f7SAndroid Build Coastguard Worker
5308*03ce13f7SAndroid Build Coastguard Worker return RValue<SIMD::Float>(V(result));
5309*03ce13f7SAndroid Build Coastguard Worker }
5310*03ce13f7SAndroid Build Coastguard Worker else
5311*03ce13f7SAndroid Build Coastguard Worker {
5312*03ce13f7SAndroid Build Coastguard Worker return -Floor(-x);
5313*03ce13f7SAndroid Build Coastguard Worker }
5314*03ce13f7SAndroid Build Coastguard Worker }
5315*03ce13f7SAndroid Build Coastguard Worker
Extract128(RValue<SIMD::Float> val,int i)5316*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Extract128(RValue<SIMD::Float> val, int i)
5317*03ce13f7SAndroid Build Coastguard Worker {
5318*03ce13f7SAndroid Build Coastguard Worker ASSERT(SIMD::Width == 4);
5319*03ce13f7SAndroid Build Coastguard Worker ASSERT(i == 0);
5320*03ce13f7SAndroid Build Coastguard Worker
5321*03ce13f7SAndroid Build Coastguard Worker return As<Float4>(val);
5322*03ce13f7SAndroid Build Coastguard Worker }
5323*03ce13f7SAndroid Build Coastguard Worker
Insert128(RValue<SIMD::Float> val,RValue<Float4> element,int i)5324*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Insert128(RValue<SIMD::Float> val, RValue<Float4> element, int i)
5325*03ce13f7SAndroid Build Coastguard Worker {
5326*03ce13f7SAndroid Build Coastguard Worker ASSERT(SIMD::Width == 4);
5327*03ce13f7SAndroid Build Coastguard Worker ASSERT(i == 0);
5328*03ce13f7SAndroid Build Coastguard Worker
5329*03ce13f7SAndroid Build Coastguard Worker return As<SIMD::Float>(element);
5330*03ce13f7SAndroid Build Coastguard Worker }
5331*03ce13f7SAndroid Build Coastguard Worker
type()5332*03ce13f7SAndroid Build Coastguard Worker Type *SIMD::Float::type()
5333*03ce13f7SAndroid Build Coastguard Worker {
5334*03ce13f7SAndroid Build Coastguard Worker return T(Ice::IceType_v4f32);
5335*03ce13f7SAndroid Build Coastguard Worker }
5336*03ce13f7SAndroid Build Coastguard Worker
5337*03ce13f7SAndroid Build Coastguard Worker } // namespace rr
5338