xref: /aosp_15_r20/external/swiftshader/src/Reactor/SubzeroReactor.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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> &paramTypes)
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 &sectionHeader(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 *> &paramTypes)
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 *> &params)
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