xref: /aosp_15_r20/external/swiftshader/src/Reactor/LLVMReactor.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 "LLVMReactor.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "CPUID.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "Debug.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "LLVMReactorDebugInfo.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "PragmaInternals.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "Print.hpp"
22*03ce13f7SAndroid Build Coastguard Worker #include "Reactor.hpp"
23*03ce13f7SAndroid Build Coastguard Worker #include "SIMD.hpp"
24*03ce13f7SAndroid Build Coastguard Worker #include "x86.hpp"
25*03ce13f7SAndroid Build Coastguard Worker 
26*03ce13f7SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicsX86.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Alignment.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Error.h"
30*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
31*03ce13f7SAndroid Build Coastguard Worker 
32*03ce13f7SAndroid Build Coastguard Worker #include <fstream>
33*03ce13f7SAndroid Build Coastguard Worker #include <iostream>
34*03ce13f7SAndroid Build Coastguard Worker #include <mutex>
35*03ce13f7SAndroid Build Coastguard Worker #include <numeric>
36*03ce13f7SAndroid Build Coastguard Worker #include <thread>
37*03ce13f7SAndroid Build Coastguard Worker #include <unordered_map>
38*03ce13f7SAndroid Build Coastguard Worker 
39*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
40*03ce13f7SAndroid Build Coastguard Worker #	include <xmmintrin.h>
41*03ce13f7SAndroid Build Coastguard Worker #endif
42*03ce13f7SAndroid Build Coastguard Worker 
43*03ce13f7SAndroid Build Coastguard Worker #include <math.h>
44*03ce13f7SAndroid Build Coastguard Worker 
45*03ce13f7SAndroid Build Coastguard Worker #if defined(__x86_64__) && defined(_WIN32)
X86CompilationCallback()46*03ce13f7SAndroid Build Coastguard Worker extern "C" void X86CompilationCallback()
47*03ce13f7SAndroid Build Coastguard Worker {
48*03ce13f7SAndroid Build Coastguard Worker 	UNIMPLEMENTED_NO_BUG("X86CompilationCallback");
49*03ce13f7SAndroid Build Coastguard Worker }
50*03ce13f7SAndroid Build Coastguard Worker #endif
51*03ce13f7SAndroid Build Coastguard Worker 
52*03ce13f7SAndroid Build Coastguard Worker #if !LLVM_ENABLE_THREADS
53*03ce13f7SAndroid Build Coastguard Worker #	error "LLVM_ENABLE_THREADS needs to be enabled"
54*03ce13f7SAndroid Build Coastguard Worker #endif
55*03ce13f7SAndroid Build Coastguard Worker 
56*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR < 11
57*03ce13f7SAndroid Build Coastguard Worker namespace llvm {
58*03ce13f7SAndroid Build Coastguard Worker using FixedVectorType = VectorType;
59*03ce13f7SAndroid Build Coastguard Worker }  // namespace llvm
60*03ce13f7SAndroid Build Coastguard Worker #endif
61*03ce13f7SAndroid Build Coastguard Worker 
62*03ce13f7SAndroid Build Coastguard Worker namespace {
63*03ce13f7SAndroid Build Coastguard Worker 
64*03ce13f7SAndroid Build Coastguard Worker // Used to automatically invoke llvm_shutdown() when driver is unloaded
65*03ce13f7SAndroid Build Coastguard Worker llvm::llvm_shutdown_obj llvmShutdownObj;
66*03ce13f7SAndroid Build Coastguard Worker 
67*03ce13f7SAndroid Build Coastguard Worker // This has to be a raw pointer because glibc 2.17 doesn't support __cxa_thread_atexit_impl
68*03ce13f7SAndroid Build Coastguard Worker // for destructing objects at exit. See crbug.com/1074222
69*03ce13f7SAndroid Build Coastguard Worker thread_local rr::JITBuilder *jit = nullptr;
70*03ce13f7SAndroid Build Coastguard Worker 
getNumElements(llvm::FixedVectorType * vec)71*03ce13f7SAndroid Build Coastguard Worker auto getNumElements(llvm::FixedVectorType *vec)
72*03ce13f7SAndroid Build Coastguard Worker {
73*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
74*03ce13f7SAndroid Build Coastguard Worker 	return vec->getElementCount();
75*03ce13f7SAndroid Build Coastguard Worker #else
76*03ce13f7SAndroid Build Coastguard Worker 	return vec->getNumElements();
77*03ce13f7SAndroid Build Coastguard Worker #endif
78*03ce13f7SAndroid Build Coastguard Worker }
79*03ce13f7SAndroid Build Coastguard Worker 
lowerPAVG(llvm::Value * x,llvm::Value * y)80*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerPAVG(llvm::Value *x, llvm::Value *y)
81*03ce13f7SAndroid Build Coastguard Worker {
82*03ce13f7SAndroid Build Coastguard Worker 	llvm::VectorType *ty = llvm::cast<llvm::VectorType>(x->getType());
83*03ce13f7SAndroid Build Coastguard Worker 
84*03ce13f7SAndroid Build Coastguard Worker 	llvm::VectorType *extTy =
85*03ce13f7SAndroid Build Coastguard Worker 	    llvm::VectorType::getExtendedElementVectorType(ty);
86*03ce13f7SAndroid Build Coastguard Worker 	x = jit->builder->CreateZExt(x, extTy);
87*03ce13f7SAndroid Build Coastguard Worker 	y = jit->builder->CreateZExt(y, extTy);
88*03ce13f7SAndroid Build Coastguard Worker 
89*03ce13f7SAndroid Build Coastguard Worker 	// (x + y + 1) >> 1
90*03ce13f7SAndroid Build Coastguard Worker 	llvm::Constant *one = llvm::ConstantInt::get(extTy, 1);
91*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *res = jit->builder->CreateAdd(x, y);
92*03ce13f7SAndroid Build Coastguard Worker 	res = jit->builder->CreateAdd(res, one);
93*03ce13f7SAndroid Build Coastguard Worker 	res = jit->builder->CreateLShr(res, one);
94*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateTrunc(res, ty);
95*03ce13f7SAndroid Build Coastguard Worker }
96*03ce13f7SAndroid Build Coastguard Worker 
lowerPMINMAX(llvm::Value * x,llvm::Value * y,llvm::ICmpInst::Predicate pred)97*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerPMINMAX(llvm::Value *x, llvm::Value *y,
98*03ce13f7SAndroid Build Coastguard Worker                           llvm::ICmpInst::Predicate pred)
99*03ce13f7SAndroid Build Coastguard Worker {
100*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateSelect(jit->builder->CreateICmp(pred, x, y), x, y);
101*03ce13f7SAndroid Build Coastguard Worker }
102*03ce13f7SAndroid Build Coastguard Worker 
lowerPCMP(llvm::ICmpInst::Predicate pred,llvm::Value * x,llvm::Value * y,llvm::Type * dstTy)103*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerPCMP(llvm::ICmpInst::Predicate pred, llvm::Value *x,
104*03ce13f7SAndroid Build Coastguard Worker                        llvm::Value *y, llvm::Type *dstTy)
105*03ce13f7SAndroid Build Coastguard Worker {
106*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateSExt(jit->builder->CreateICmp(pred, x, y), dstTy, "");
107*03ce13f7SAndroid Build Coastguard Worker }
108*03ce13f7SAndroid Build Coastguard Worker 
lowerPFMINMAX(llvm::Value * x,llvm::Value * y,llvm::FCmpInst::Predicate pred)109*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerPFMINMAX(llvm::Value *x, llvm::Value *y,
110*03ce13f7SAndroid Build Coastguard Worker                                             llvm::FCmpInst::Predicate pred)
111*03ce13f7SAndroid Build Coastguard Worker {
112*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateSelect(jit->builder->CreateFCmp(pred, x, y), x, y);
113*03ce13f7SAndroid Build Coastguard Worker }
114*03ce13f7SAndroid Build Coastguard Worker 
lowerRound(llvm::Value * x)115*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerRound(llvm::Value *x)
116*03ce13f7SAndroid Build Coastguard Worker {
117*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *nearbyint = llvm::Intrinsic::getDeclaration(
118*03ce13f7SAndroid Build Coastguard Worker 	    jit->module.get(), llvm::Intrinsic::nearbyint, { x->getType() });
119*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateCall(nearbyint, { x });
120*03ce13f7SAndroid Build Coastguard Worker }
121*03ce13f7SAndroid Build Coastguard Worker 
lowerRoundInt(llvm::Value * x,llvm::Type * ty)122*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerRoundInt(llvm::Value *x, llvm::Type *ty)
123*03ce13f7SAndroid Build Coastguard Worker {
124*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateFPToSI(lowerRound(x), ty);
125*03ce13f7SAndroid Build Coastguard Worker }
126*03ce13f7SAndroid Build Coastguard Worker 
lowerFloor(llvm::Value * x)127*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerFloor(llvm::Value *x)
128*03ce13f7SAndroid Build Coastguard Worker {
129*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *floor = llvm::Intrinsic::getDeclaration(
130*03ce13f7SAndroid Build Coastguard Worker 	    jit->module.get(), llvm::Intrinsic::floor, { x->getType() });
131*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateCall(floor, { x });
132*03ce13f7SAndroid Build Coastguard Worker }
133*03ce13f7SAndroid Build Coastguard Worker 
lowerTrunc(llvm::Value * x)134*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerTrunc(llvm::Value *x)
135*03ce13f7SAndroid Build Coastguard Worker {
136*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *trunc = llvm::Intrinsic::getDeclaration(
137*03ce13f7SAndroid Build Coastguard Worker 	    jit->module.get(), llvm::Intrinsic::trunc, { x->getType() });
138*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateCall(trunc, { x });
139*03ce13f7SAndroid Build Coastguard Worker }
140*03ce13f7SAndroid Build Coastguard Worker 
lowerSQRT(llvm::Value * x)141*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerSQRT(llvm::Value *x)
142*03ce13f7SAndroid Build Coastguard Worker {
143*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *sqrt = llvm::Intrinsic::getDeclaration(
144*03ce13f7SAndroid Build Coastguard Worker 	    jit->module.get(), llvm::Intrinsic::sqrt, { x->getType() });
145*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateCall(sqrt, { x });
146*03ce13f7SAndroid Build Coastguard Worker }
147*03ce13f7SAndroid Build Coastguard Worker 
lowerRCP(llvm::Value * x)148*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerRCP(llvm::Value *x)
149*03ce13f7SAndroid Build Coastguard Worker {
150*03ce13f7SAndroid Build Coastguard Worker 	llvm::Type *ty = x->getType();
151*03ce13f7SAndroid Build Coastguard Worker 	llvm::Constant *one;
152*03ce13f7SAndroid Build Coastguard Worker 	if(llvm::FixedVectorType *vectorTy = llvm::dyn_cast<llvm::FixedVectorType>(ty))
153*03ce13f7SAndroid Build Coastguard Worker 	{
154*03ce13f7SAndroid Build Coastguard Worker 		one = llvm::ConstantVector::getSplat(getNumElements(vectorTy),
155*03ce13f7SAndroid Build Coastguard Worker 		                                     llvm::ConstantFP::get(vectorTy->getElementType(), 1));
156*03ce13f7SAndroid Build Coastguard Worker 	}
157*03ce13f7SAndroid Build Coastguard Worker 	else
158*03ce13f7SAndroid Build Coastguard Worker 	{
159*03ce13f7SAndroid Build Coastguard Worker 		one = llvm::ConstantFP::get(ty, 1);
160*03ce13f7SAndroid Build Coastguard Worker 	}
161*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateFDiv(one, x);
162*03ce13f7SAndroid Build Coastguard Worker }
163*03ce13f7SAndroid Build Coastguard Worker 
lowerRSQRT(llvm::Value * x)164*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerRSQRT(llvm::Value *x)
165*03ce13f7SAndroid Build Coastguard Worker {
166*03ce13f7SAndroid Build Coastguard Worker 	return lowerRCP(lowerSQRT(x));
167*03ce13f7SAndroid Build Coastguard Worker }
168*03ce13f7SAndroid Build Coastguard Worker 
lowerVectorShl(llvm::Value * x,uint64_t scalarY)169*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerVectorShl(llvm::Value *x, uint64_t scalarY)
170*03ce13f7SAndroid Build Coastguard Worker {
171*03ce13f7SAndroid Build Coastguard Worker 	llvm::FixedVectorType *ty = llvm::cast<llvm::FixedVectorType>(x->getType());
172*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *y = llvm::ConstantVector::getSplat(getNumElements(ty),
173*03ce13f7SAndroid Build Coastguard Worker 	                                                llvm::ConstantInt::get(ty->getElementType(), scalarY));
174*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateShl(x, y);
175*03ce13f7SAndroid Build Coastguard Worker }
176*03ce13f7SAndroid Build Coastguard Worker 
lowerVectorAShr(llvm::Value * x,uint64_t scalarY)177*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerVectorAShr(llvm::Value *x, uint64_t scalarY)
178*03ce13f7SAndroid Build Coastguard Worker {
179*03ce13f7SAndroid Build Coastguard Worker 	llvm::FixedVectorType *ty = llvm::cast<llvm::FixedVectorType>(x->getType());
180*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *y = llvm::ConstantVector::getSplat(getNumElements(ty),
181*03ce13f7SAndroid Build Coastguard Worker 	                                                llvm::ConstantInt::get(ty->getElementType(), scalarY));
182*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateAShr(x, y);
183*03ce13f7SAndroid Build Coastguard Worker }
184*03ce13f7SAndroid Build Coastguard Worker 
lowerVectorLShr(llvm::Value * x,uint64_t scalarY)185*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerVectorLShr(llvm::Value *x, uint64_t scalarY)
186*03ce13f7SAndroid Build Coastguard Worker {
187*03ce13f7SAndroid Build Coastguard Worker 	llvm::FixedVectorType *ty = llvm::cast<llvm::FixedVectorType>(x->getType());
188*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *y = llvm::ConstantVector::getSplat(getNumElements(ty),
189*03ce13f7SAndroid Build Coastguard Worker 	                                                llvm::ConstantInt::get(ty->getElementType(), scalarY));
190*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateLShr(x, y);
191*03ce13f7SAndroid Build Coastguard Worker }
192*03ce13f7SAndroid Build Coastguard Worker 
lowerShuffleVector(llvm::Value * v1,llvm::Value * v2,llvm::ArrayRef<int> select)193*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerShuffleVector(llvm::Value *v1, llvm::Value *v2, llvm::ArrayRef<int> select)
194*03ce13f7SAndroid Build Coastguard Worker {
195*03ce13f7SAndroid Build Coastguard Worker 	int size = select.size();
196*03ce13f7SAndroid Build Coastguard Worker 	const int maxSize = 16;
197*03ce13f7SAndroid Build Coastguard Worker 	llvm::Constant *swizzle[maxSize];
198*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(size <= maxSize);
199*03ce13f7SAndroid Build Coastguard Worker 
200*03ce13f7SAndroid Build Coastguard Worker 	for(int i = 0; i < size; i++)
201*03ce13f7SAndroid Build Coastguard Worker 	{
202*03ce13f7SAndroid Build Coastguard Worker 		swizzle[i] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*jit->context), select[i]);
203*03ce13f7SAndroid Build Coastguard Worker 	}
204*03ce13f7SAndroid Build Coastguard Worker 
205*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *shuffle = llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant *>(swizzle, size));
206*03ce13f7SAndroid Build Coastguard Worker 
207*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateShuffleVector(v1, v2, shuffle);
208*03ce13f7SAndroid Build Coastguard Worker }
209*03ce13f7SAndroid Build Coastguard Worker 
lowerMulAdd(llvm::Value * x,llvm::Value * y)210*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerMulAdd(llvm::Value *x, llvm::Value *y)
211*03ce13f7SAndroid Build Coastguard Worker {
212*03ce13f7SAndroid Build Coastguard Worker 	llvm::FixedVectorType *ty = llvm::cast<llvm::FixedVectorType>(x->getType());
213*03ce13f7SAndroid Build Coastguard Worker 	llvm::VectorType *extTy = llvm::VectorType::getExtendedElementVectorType(ty);
214*03ce13f7SAndroid Build Coastguard Worker 
215*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *extX = jit->builder->CreateSExt(x, extTy);
216*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *extY = jit->builder->CreateSExt(y, extTy);
217*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *mult = jit->builder->CreateMul(extX, extY);
218*03ce13f7SAndroid Build Coastguard Worker 
219*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *undef = llvm::UndefValue::get(extTy);
220*03ce13f7SAndroid Build Coastguard Worker 
221*03ce13f7SAndroid Build Coastguard Worker 	llvm::SmallVector<int, 16> evenIdx;
222*03ce13f7SAndroid Build Coastguard Worker 	llvm::SmallVector<int, 16> oddIdx;
223*03ce13f7SAndroid Build Coastguard Worker 	for(uint64_t i = 0, n = ty->getNumElements(); i < n; i += 2)
224*03ce13f7SAndroid Build Coastguard Worker 	{
225*03ce13f7SAndroid Build Coastguard Worker 		evenIdx.push_back(i);
226*03ce13f7SAndroid Build Coastguard Worker 		oddIdx.push_back(i + 1);
227*03ce13f7SAndroid Build Coastguard Worker 	}
228*03ce13f7SAndroid Build Coastguard Worker 
229*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *lhs = lowerShuffleVector(mult, undef, evenIdx);
230*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *rhs = lowerShuffleVector(mult, undef, oddIdx);
231*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateAdd(lhs, rhs);
232*03ce13f7SAndroid Build Coastguard Worker }
233*03ce13f7SAndroid Build Coastguard Worker 
lowerPack(llvm::Value * x,llvm::Value * y,bool isSigned)234*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerPack(llvm::Value *x, llvm::Value *y, bool isSigned)
235*03ce13f7SAndroid Build Coastguard Worker {
236*03ce13f7SAndroid Build Coastguard Worker 	llvm::FixedVectorType *srcTy = llvm::cast<llvm::FixedVectorType>(x->getType());
237*03ce13f7SAndroid Build Coastguard Worker 	llvm::VectorType *dstTy = llvm::VectorType::getTruncatedElementVectorType(srcTy);
238*03ce13f7SAndroid Build Coastguard Worker 
239*03ce13f7SAndroid Build Coastguard Worker 	llvm::IntegerType *dstElemTy =
240*03ce13f7SAndroid Build Coastguard Worker 	    llvm::cast<llvm::IntegerType>(dstTy->getElementType());
241*03ce13f7SAndroid Build Coastguard Worker 
242*03ce13f7SAndroid Build Coastguard Worker 	uint64_t truncNumBits = dstElemTy->getIntegerBitWidth();
243*03ce13f7SAndroid Build Coastguard Worker 	ASSERT_MSG(truncNumBits < 64, "shift 64 must be handled separately. truncNumBits: %d", int(truncNumBits));
244*03ce13f7SAndroid Build Coastguard Worker 	llvm::Constant *max, *min;
245*03ce13f7SAndroid Build Coastguard Worker 	if(isSigned)
246*03ce13f7SAndroid Build Coastguard Worker 	{
247*03ce13f7SAndroid Build Coastguard Worker 		max = llvm::ConstantInt::get(srcTy, (1LL << (truncNumBits - 1)) - 1, true);
248*03ce13f7SAndroid Build Coastguard Worker 		min = llvm::ConstantInt::get(srcTy, (-1LL << (truncNumBits - 1)), true);
249*03ce13f7SAndroid Build Coastguard Worker 	}
250*03ce13f7SAndroid Build Coastguard Worker 	else
251*03ce13f7SAndroid Build Coastguard Worker 	{
252*03ce13f7SAndroid Build Coastguard Worker 		max = llvm::ConstantInt::get(srcTy, (1ULL << truncNumBits) - 1, false);
253*03ce13f7SAndroid Build Coastguard Worker 		min = llvm::ConstantInt::get(srcTy, 0, false);
254*03ce13f7SAndroid Build Coastguard Worker 	}
255*03ce13f7SAndroid Build Coastguard Worker 
256*03ce13f7SAndroid Build Coastguard Worker 	x = lowerPMINMAX(x, min, llvm::ICmpInst::ICMP_SGT);
257*03ce13f7SAndroid Build Coastguard Worker 	x = lowerPMINMAX(x, max, llvm::ICmpInst::ICMP_SLT);
258*03ce13f7SAndroid Build Coastguard Worker 	y = lowerPMINMAX(y, min, llvm::ICmpInst::ICMP_SGT);
259*03ce13f7SAndroid Build Coastguard Worker 	y = lowerPMINMAX(y, max, llvm::ICmpInst::ICMP_SLT);
260*03ce13f7SAndroid Build Coastguard Worker 
261*03ce13f7SAndroid Build Coastguard Worker 	x = jit->builder->CreateTrunc(x, dstTy);
262*03ce13f7SAndroid Build Coastguard Worker 	y = jit->builder->CreateTrunc(y, dstTy);
263*03ce13f7SAndroid Build Coastguard Worker 
264*03ce13f7SAndroid Build Coastguard Worker 	llvm::SmallVector<int, 16> index(srcTy->getNumElements() * 2);
265*03ce13f7SAndroid Build Coastguard Worker 	std::iota(index.begin(), index.end(), 0);
266*03ce13f7SAndroid Build Coastguard Worker 
267*03ce13f7SAndroid Build Coastguard Worker 	return lowerShuffleVector(x, y, index);
268*03ce13f7SAndroid Build Coastguard Worker }
269*03ce13f7SAndroid Build Coastguard Worker 
lowerSignMask(llvm::Value * x,llvm::Type * retTy)270*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerSignMask(llvm::Value *x, llvm::Type *retTy)
271*03ce13f7SAndroid Build Coastguard Worker {
272*03ce13f7SAndroid Build Coastguard Worker 	llvm::FixedVectorType *ty = llvm::cast<llvm::FixedVectorType>(x->getType());
273*03ce13f7SAndroid Build Coastguard Worker 	llvm::Constant *zero = llvm::ConstantInt::get(ty, 0);
274*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *cmp = jit->builder->CreateICmpSLT(x, zero);
275*03ce13f7SAndroid Build Coastguard Worker 
276*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *ret = jit->builder->CreateZExt(
277*03ce13f7SAndroid Build Coastguard Worker 	    jit->builder->CreateExtractElement(cmp, static_cast<uint64_t>(0)), retTy);
278*03ce13f7SAndroid Build Coastguard Worker 	for(uint64_t i = 1, n = ty->getNumElements(); i < n; ++i)
279*03ce13f7SAndroid Build Coastguard Worker 	{
280*03ce13f7SAndroid Build Coastguard Worker 		llvm::Value *elem = jit->builder->CreateZExt(
281*03ce13f7SAndroid Build Coastguard Worker 		    jit->builder->CreateExtractElement(cmp, i), retTy);
282*03ce13f7SAndroid Build Coastguard Worker 		ret = jit->builder->CreateOr(ret, jit->builder->CreateShl(elem, i));
283*03ce13f7SAndroid Build Coastguard Worker 	}
284*03ce13f7SAndroid Build Coastguard Worker 	return ret;
285*03ce13f7SAndroid Build Coastguard Worker }
286*03ce13f7SAndroid Build Coastguard Worker 
lowerFPSignMask(llvm::Value * x,llvm::Type * retTy)287*03ce13f7SAndroid Build Coastguard Worker [[maybe_unused]] llvm::Value *lowerFPSignMask(llvm::Value *x, llvm::Type *retTy)
288*03ce13f7SAndroid Build Coastguard Worker {
289*03ce13f7SAndroid Build Coastguard Worker 	llvm::FixedVectorType *ty = llvm::cast<llvm::FixedVectorType>(x->getType());
290*03ce13f7SAndroid Build Coastguard Worker 	llvm::Constant *zero = llvm::ConstantFP::get(ty, 0);
291*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *cmp = jit->builder->CreateFCmpULT(x, zero);
292*03ce13f7SAndroid Build Coastguard Worker 
293*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *ret = jit->builder->CreateZExt(
294*03ce13f7SAndroid Build Coastguard Worker 	    jit->builder->CreateExtractElement(cmp, static_cast<uint64_t>(0)), retTy);
295*03ce13f7SAndroid Build Coastguard Worker 	for(uint64_t i = 1, n = ty->getNumElements(); i < n; ++i)
296*03ce13f7SAndroid Build Coastguard Worker 	{
297*03ce13f7SAndroid Build Coastguard Worker 		llvm::Value *elem = jit->builder->CreateZExt(
298*03ce13f7SAndroid Build Coastguard Worker 		    jit->builder->CreateExtractElement(cmp, i), retTy);
299*03ce13f7SAndroid Build Coastguard Worker 		ret = jit->builder->CreateOr(ret, jit->builder->CreateShl(elem, i));
300*03ce13f7SAndroid Build Coastguard Worker 	}
301*03ce13f7SAndroid Build Coastguard Worker 	return ret;
302*03ce13f7SAndroid Build Coastguard Worker }
303*03ce13f7SAndroid Build Coastguard Worker 
lowerPUADDSAT(llvm::Value * x,llvm::Value * y)304*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerPUADDSAT(llvm::Value *x, llvm::Value *y)
305*03ce13f7SAndroid Build Coastguard Worker {
306*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateBinaryIntrinsic(llvm::Intrinsic::uadd_sat, x, y);
307*03ce13f7SAndroid Build Coastguard Worker }
308*03ce13f7SAndroid Build Coastguard Worker 
lowerPSADDSAT(llvm::Value * x,llvm::Value * y)309*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerPSADDSAT(llvm::Value *x, llvm::Value *y)
310*03ce13f7SAndroid Build Coastguard Worker {
311*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateBinaryIntrinsic(llvm::Intrinsic::sadd_sat, x, y);
312*03ce13f7SAndroid Build Coastguard Worker }
313*03ce13f7SAndroid Build Coastguard Worker 
lowerPUSUBSAT(llvm::Value * x,llvm::Value * y)314*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerPUSUBSAT(llvm::Value *x, llvm::Value *y)
315*03ce13f7SAndroid Build Coastguard Worker {
316*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateBinaryIntrinsic(llvm::Intrinsic::usub_sat, x, y);
317*03ce13f7SAndroid Build Coastguard Worker }
318*03ce13f7SAndroid Build Coastguard Worker 
lowerPSSUBSAT(llvm::Value * x,llvm::Value * y)319*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerPSSUBSAT(llvm::Value *x, llvm::Value *y)
320*03ce13f7SAndroid Build Coastguard Worker {
321*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateBinaryIntrinsic(llvm::Intrinsic::ssub_sat, x, y);
322*03ce13f7SAndroid Build Coastguard Worker }
323*03ce13f7SAndroid Build Coastguard Worker 
lowerMulHigh(llvm::Value * x,llvm::Value * y,bool sext)324*03ce13f7SAndroid Build Coastguard Worker llvm::Value *lowerMulHigh(llvm::Value *x, llvm::Value *y, bool sext)
325*03ce13f7SAndroid Build Coastguard Worker {
326*03ce13f7SAndroid Build Coastguard Worker 	llvm::VectorType *ty = llvm::cast<llvm::VectorType>(x->getType());
327*03ce13f7SAndroid Build Coastguard Worker 	llvm::VectorType *extTy = llvm::VectorType::getExtendedElementVectorType(ty);
328*03ce13f7SAndroid Build Coastguard Worker 
329*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *extX, *extY;
330*03ce13f7SAndroid Build Coastguard Worker 	if(sext)
331*03ce13f7SAndroid Build Coastguard Worker 	{
332*03ce13f7SAndroid Build Coastguard Worker 		extX = jit->builder->CreateSExt(x, extTy);
333*03ce13f7SAndroid Build Coastguard Worker 		extY = jit->builder->CreateSExt(y, extTy);
334*03ce13f7SAndroid Build Coastguard Worker 	}
335*03ce13f7SAndroid Build Coastguard Worker 	else
336*03ce13f7SAndroid Build Coastguard Worker 	{
337*03ce13f7SAndroid Build Coastguard Worker 		extX = jit->builder->CreateZExt(x, extTy);
338*03ce13f7SAndroid Build Coastguard Worker 		extY = jit->builder->CreateZExt(y, extTy);
339*03ce13f7SAndroid Build Coastguard Worker 	}
340*03ce13f7SAndroid Build Coastguard Worker 
341*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *mult = jit->builder->CreateMul(extX, extY);
342*03ce13f7SAndroid Build Coastguard Worker 
343*03ce13f7SAndroid Build Coastguard Worker 	llvm::IntegerType *intTy = llvm::cast<llvm::IntegerType>(ty->getElementType());
344*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *mulh = jit->builder->CreateAShr(mult, intTy->getBitWidth());
345*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateTrunc(mulh, ty);
346*03ce13f7SAndroid Build Coastguard Worker }
347*03ce13f7SAndroid Build Coastguard Worker 
348*03ce13f7SAndroid Build Coastguard Worker // TODO(crbug.com/swiftshader/185): A temporary workaround for failing chromium tests.
clampForShift(llvm::Value * rhs)349*03ce13f7SAndroid Build Coastguard Worker llvm::Value *clampForShift(llvm::Value *rhs)
350*03ce13f7SAndroid Build Coastguard Worker {
351*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *max;
352*03ce13f7SAndroid Build Coastguard Worker 	if(auto *vec = llvm::dyn_cast<llvm::FixedVectorType>(rhs->getType()))
353*03ce13f7SAndroid Build Coastguard Worker 	{
354*03ce13f7SAndroid Build Coastguard Worker 		auto N = vec->getElementType()->getIntegerBitWidth() - 1;
355*03ce13f7SAndroid Build Coastguard Worker 		max = llvm::ConstantVector::getSplat(getNumElements(vec), llvm::ConstantInt::get(vec->getElementType(), N));
356*03ce13f7SAndroid Build Coastguard Worker 	}
357*03ce13f7SAndroid Build Coastguard Worker 	else
358*03ce13f7SAndroid Build Coastguard Worker 	{
359*03ce13f7SAndroid Build Coastguard Worker 		auto N = rhs->getType()->getIntegerBitWidth() - 1;
360*03ce13f7SAndroid Build Coastguard Worker 		max = llvm::ConstantInt::get(rhs->getType(), N);
361*03ce13f7SAndroid Build Coastguard Worker 	}
362*03ce13f7SAndroid Build Coastguard Worker 	return jit->builder->CreateSelect(jit->builder->CreateICmpULE(rhs, max), rhs, max);
363*03ce13f7SAndroid Build Coastguard Worker }
364*03ce13f7SAndroid Build Coastguard Worker 
365*03ce13f7SAndroid Build Coastguard Worker }  // namespace
366*03ce13f7SAndroid Build Coastguard Worker 
367*03ce13f7SAndroid Build Coastguard Worker namespace rr {
368*03ce13f7SAndroid Build Coastguard Worker 
369*03ce13f7SAndroid Build Coastguard Worker const int SIMD::Width = 4;
370*03ce13f7SAndroid Build Coastguard Worker 
backendName()371*03ce13f7SAndroid Build Coastguard Worker std::string Caps::backendName()
372*03ce13f7SAndroid Build Coastguard Worker {
373*03ce13f7SAndroid Build Coastguard Worker 	return std::string("LLVM ") + LLVM_VERSION_STRING;
374*03ce13f7SAndroid Build Coastguard Worker }
375*03ce13f7SAndroid Build Coastguard Worker 
coroutinesSupported()376*03ce13f7SAndroid Build Coastguard Worker bool Caps::coroutinesSupported()
377*03ce13f7SAndroid Build Coastguard Worker {
378*03ce13f7SAndroid Build Coastguard Worker 	return true;
379*03ce13f7SAndroid Build Coastguard Worker }
380*03ce13f7SAndroid Build Coastguard Worker 
fmaIsFast()381*03ce13f7SAndroid Build Coastguard Worker bool Caps::fmaIsFast()
382*03ce13f7SAndroid Build Coastguard Worker {
383*03ce13f7SAndroid Build Coastguard Worker 	static bool AVX2 = CPUID::supportsAVX2();  // Also checks for FMA support
384*03ce13f7SAndroid Build Coastguard Worker 
385*03ce13f7SAndroid Build Coastguard Worker 	// If x86 FMA instructions are supported, assume LLVM will emit them instead of making calls to std::fma().
386*03ce13f7SAndroid Build Coastguard Worker 	return AVX2;
387*03ce13f7SAndroid Build Coastguard Worker }
388*03ce13f7SAndroid Build Coastguard Worker 
389*03ce13f7SAndroid Build Coastguard Worker // The abstract Type* types are implemented as LLVM types, except that
390*03ce13f7SAndroid Build Coastguard Worker // 64-bit vectors are emulated using 128-bit ones to avoid use of MMX in x86
391*03ce13f7SAndroid Build Coastguard Worker // and VFP in ARM, and eliminate the overhead of converting them to explicit
392*03ce13f7SAndroid Build Coastguard Worker // 128-bit ones. LLVM types are pointers, so we can represent emulated types
393*03ce13f7SAndroid Build Coastguard Worker // as abstract pointers with small enum values.
394*03ce13f7SAndroid Build Coastguard Worker enum InternalType : uintptr_t
395*03ce13f7SAndroid Build Coastguard Worker {
396*03ce13f7SAndroid Build Coastguard Worker 	// Emulated types:
397*03ce13f7SAndroid Build Coastguard Worker 	Type_v2i32,
398*03ce13f7SAndroid Build Coastguard Worker 	Type_v4i16,
399*03ce13f7SAndroid Build Coastguard Worker 	Type_v2i16,
400*03ce13f7SAndroid Build Coastguard Worker 	Type_v8i8,
401*03ce13f7SAndroid Build Coastguard Worker 	Type_v4i8,
402*03ce13f7SAndroid Build Coastguard Worker 	Type_v2f32,
403*03ce13f7SAndroid Build Coastguard Worker 	EmulatedTypeCount,
404*03ce13f7SAndroid Build Coastguard Worker 	// Returned by asInternalType() to indicate that the abstract Type*
405*03ce13f7SAndroid Build Coastguard Worker 	// should be interpreted as LLVM type pointer:
406*03ce13f7SAndroid Build Coastguard Worker 	Type_LLVM
407*03ce13f7SAndroid Build Coastguard Worker };
408*03ce13f7SAndroid Build Coastguard Worker 
asInternalType(Type * type)409*03ce13f7SAndroid Build Coastguard Worker inline InternalType asInternalType(Type *type)
410*03ce13f7SAndroid Build Coastguard Worker {
411*03ce13f7SAndroid Build Coastguard Worker 	InternalType t = static_cast<InternalType>(reinterpret_cast<uintptr_t>(type));
412*03ce13f7SAndroid Build Coastguard Worker 	return (t < EmulatedTypeCount) ? t : Type_LLVM;
413*03ce13f7SAndroid Build Coastguard Worker }
414*03ce13f7SAndroid Build Coastguard Worker 
T(Type * t)415*03ce13f7SAndroid Build Coastguard Worker llvm::Type *T(Type *t)
416*03ce13f7SAndroid Build Coastguard Worker {
417*03ce13f7SAndroid Build Coastguard Worker 	// Use 128-bit vectors to implement logically shorter ones.
418*03ce13f7SAndroid Build Coastguard Worker 	switch(asInternalType(t))
419*03ce13f7SAndroid Build Coastguard Worker 	{
420*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2i32: return T(Int4::type());
421*03ce13f7SAndroid Build Coastguard Worker 	case Type_v4i16: return T(Short8::type());
422*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2i16: return T(Short8::type());
423*03ce13f7SAndroid Build Coastguard Worker 	case Type_v8i8: return T(Byte16::type());
424*03ce13f7SAndroid Build Coastguard Worker 	case Type_v4i8: return T(Byte16::type());
425*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2f32: return T(Float4::type());
426*03ce13f7SAndroid Build Coastguard Worker 	case Type_LLVM: return reinterpret_cast<llvm::Type *>(t);
427*03ce13f7SAndroid Build Coastguard Worker 	default:
428*03ce13f7SAndroid Build Coastguard Worker 		UNREACHABLE("asInternalType(t): %d", int(asInternalType(t)));
429*03ce13f7SAndroid Build Coastguard Worker 		return nullptr;
430*03ce13f7SAndroid Build Coastguard Worker 	}
431*03ce13f7SAndroid Build Coastguard Worker }
432*03ce13f7SAndroid Build Coastguard Worker 
T(InternalType t)433*03ce13f7SAndroid Build Coastguard Worker Type *T(InternalType t)
434*03ce13f7SAndroid Build Coastguard Worker {
435*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<Type *>(t);
436*03ce13f7SAndroid Build Coastguard Worker }
437*03ce13f7SAndroid Build Coastguard Worker 
T(const std::vector<Type * > & t)438*03ce13f7SAndroid Build Coastguard Worker inline const std::vector<llvm::Type *> &T(const std::vector<Type *> &t)
439*03ce13f7SAndroid Build Coastguard Worker {
440*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<const std::vector<llvm::Type *> &>(t);
441*03ce13f7SAndroid Build Coastguard Worker }
442*03ce13f7SAndroid Build Coastguard Worker 
B(BasicBlock * t)443*03ce13f7SAndroid Build Coastguard Worker inline llvm::BasicBlock *B(BasicBlock *t)
444*03ce13f7SAndroid Build Coastguard Worker {
445*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<llvm::BasicBlock *>(t);
446*03ce13f7SAndroid Build Coastguard Worker }
447*03ce13f7SAndroid Build Coastguard Worker 
B(llvm::BasicBlock * t)448*03ce13f7SAndroid Build Coastguard Worker inline BasicBlock *B(llvm::BasicBlock *t)
449*03ce13f7SAndroid Build Coastguard Worker {
450*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<BasicBlock *>(t);
451*03ce13f7SAndroid Build Coastguard Worker }
452*03ce13f7SAndroid Build Coastguard Worker 
typeSize(Type * type)453*03ce13f7SAndroid Build Coastguard Worker static size_t typeSize(Type *type)
454*03ce13f7SAndroid Build Coastguard Worker {
455*03ce13f7SAndroid Build Coastguard Worker 	switch(asInternalType(type))
456*03ce13f7SAndroid Build Coastguard Worker 	{
457*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2i32: return 8;
458*03ce13f7SAndroid Build Coastguard Worker 	case Type_v4i16: return 8;
459*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2i16: return 4;
460*03ce13f7SAndroid Build Coastguard Worker 	case Type_v8i8: return 8;
461*03ce13f7SAndroid Build Coastguard Worker 	case Type_v4i8: return 4;
462*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2f32: return 8;
463*03ce13f7SAndroid Build Coastguard Worker 	case Type_LLVM:
464*03ce13f7SAndroid Build Coastguard Worker 		{
465*03ce13f7SAndroid Build Coastguard Worker 			llvm::Type *t = T(type);
466*03ce13f7SAndroid Build Coastguard Worker 
467*03ce13f7SAndroid Build Coastguard Worker 			if(t->isPointerTy())
468*03ce13f7SAndroid Build Coastguard Worker 			{
469*03ce13f7SAndroid Build Coastguard Worker 				return sizeof(void *);
470*03ce13f7SAndroid Build Coastguard Worker 			}
471*03ce13f7SAndroid Build Coastguard Worker 
472*03ce13f7SAndroid Build Coastguard Worker 			// At this point we should only have LLVM 'primitive' types.
473*03ce13f7SAndroid Build Coastguard Worker 			unsigned int bits = t->getPrimitiveSizeInBits();
474*03ce13f7SAndroid Build Coastguard Worker 			ASSERT_MSG(bits != 0, "bits: %d", int(bits));
475*03ce13f7SAndroid Build Coastguard Worker 
476*03ce13f7SAndroid Build Coastguard Worker 			// TODO(capn): Booleans are 1 bit integers in LLVM's SSA type system,
477*03ce13f7SAndroid Build Coastguard Worker 			// but are typically stored as one byte. The DataLayout structure should
478*03ce13f7SAndroid Build Coastguard Worker 			// be used here and many other places if this assumption fails.
479*03ce13f7SAndroid Build Coastguard Worker 			return (bits + 7) / 8;
480*03ce13f7SAndroid Build Coastguard Worker 		}
481*03ce13f7SAndroid Build Coastguard Worker 		break;
482*03ce13f7SAndroid Build Coastguard Worker 	default:
483*03ce13f7SAndroid Build Coastguard Worker 		UNREACHABLE("asInternalType(type): %d", int(asInternalType(type)));
484*03ce13f7SAndroid Build Coastguard Worker 		return 0;
485*03ce13f7SAndroid Build Coastguard Worker 	}
486*03ce13f7SAndroid Build Coastguard Worker }
487*03ce13f7SAndroid Build Coastguard Worker 
createFunction(const char * name,llvm::Type * retTy,const std::vector<llvm::Type * > & params)488*03ce13f7SAndroid Build Coastguard Worker static llvm::Function *createFunction(const char *name, llvm::Type *retTy, const std::vector<llvm::Type *> &params)
489*03ce13f7SAndroid Build Coastguard Worker {
490*03ce13f7SAndroid Build Coastguard Worker 	llvm::FunctionType *functionType = llvm::FunctionType::get(retTy, params, false);
491*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Function::Create(functionType, llvm::GlobalValue::InternalLinkage, name, jit->module.get());
492*03ce13f7SAndroid Build Coastguard Worker 
493*03ce13f7SAndroid Build Coastguard Worker 	func->setLinkage(llvm::GlobalValue::ExternalLinkage);
494*03ce13f7SAndroid Build Coastguard Worker 	func->setDoesNotThrow();
495*03ce13f7SAndroid Build Coastguard Worker 	func->setCallingConv(llvm::CallingConv::C);
496*03ce13f7SAndroid Build Coastguard Worker 
497*03ce13f7SAndroid Build Coastguard Worker 	if(__has_feature(address_sanitizer))
498*03ce13f7SAndroid Build Coastguard Worker 	{
499*03ce13f7SAndroid Build Coastguard Worker 		func->addFnAttr(llvm::Attribute::SanitizeAddress);
500*03ce13f7SAndroid Build Coastguard Worker 	}
501*03ce13f7SAndroid Build Coastguard Worker 
502*03ce13f7SAndroid Build Coastguard Worker 	func->addFnAttr("warn-stack-size", "524288");  // Warn when a function uses more than 512 KiB of stack memory
503*03ce13f7SAndroid Build Coastguard Worker 
504*03ce13f7SAndroid Build Coastguard Worker 	return func;
505*03ce13f7SAndroid Build Coastguard Worker }
506*03ce13f7SAndroid Build Coastguard Worker 
Nucleus()507*03ce13f7SAndroid Build Coastguard Worker Nucleus::Nucleus()
508*03ce13f7SAndroid Build Coastguard Worker {
509*03ce13f7SAndroid Build Coastguard Worker #if !__has_feature(memory_sanitizer)
510*03ce13f7SAndroid Build Coastguard Worker 	// thread_local variables in shared libraries are initialized at load-time,
511*03ce13f7SAndroid Build Coastguard Worker 	// but this is not observed by MemorySanitizer if the loader itself was not
512*03ce13f7SAndroid Build Coastguard Worker 	// instrumented, leading to false-positive uninitialized variable errors.
513*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(jit == nullptr);
514*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(Variable::unmaterializedVariables == nullptr);
515*03ce13f7SAndroid Build Coastguard Worker #endif
516*03ce13f7SAndroid Build Coastguard Worker 
517*03ce13f7SAndroid Build Coastguard Worker 	jit = new JITBuilder();
518*03ce13f7SAndroid Build Coastguard Worker 	Variable::unmaterializedVariables = new Variable::UnmaterializedVariables();
519*03ce13f7SAndroid Build Coastguard Worker }
520*03ce13f7SAndroid Build Coastguard Worker 
~Nucleus()521*03ce13f7SAndroid Build Coastguard Worker Nucleus::~Nucleus()
522*03ce13f7SAndroid Build Coastguard Worker {
523*03ce13f7SAndroid Build Coastguard Worker 	delete Variable::unmaterializedVariables;
524*03ce13f7SAndroid Build Coastguard Worker 	Variable::unmaterializedVariables = nullptr;
525*03ce13f7SAndroid Build Coastguard Worker 
526*03ce13f7SAndroid Build Coastguard Worker 	delete jit;
527*03ce13f7SAndroid Build Coastguard Worker 	jit = nullptr;
528*03ce13f7SAndroid Build Coastguard Worker }
529*03ce13f7SAndroid Build Coastguard Worker 
acquireRoutine(const char * name)530*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Routine> Nucleus::acquireRoutine(const char *name)
531*03ce13f7SAndroid Build Coastguard Worker {
532*03ce13f7SAndroid Build Coastguard Worker 	if(jit->builder->GetInsertBlock()->empty() || !jit->builder->GetInsertBlock()->back().isTerminator())
533*03ce13f7SAndroid Build Coastguard Worker 	{
534*03ce13f7SAndroid Build Coastguard Worker 		llvm::Type *type = jit->function->getReturnType();
535*03ce13f7SAndroid Build Coastguard Worker 
536*03ce13f7SAndroid Build Coastguard Worker 		if(type->isVoidTy())
537*03ce13f7SAndroid Build Coastguard Worker 		{
538*03ce13f7SAndroid Build Coastguard Worker 			createRetVoid();
539*03ce13f7SAndroid Build Coastguard Worker 		}
540*03ce13f7SAndroid Build Coastguard Worker 		else
541*03ce13f7SAndroid Build Coastguard Worker 		{
542*03ce13f7SAndroid Build Coastguard Worker 			createRet(V(llvm::UndefValue::get(type)));
543*03ce13f7SAndroid Build Coastguard Worker 		}
544*03ce13f7SAndroid Build Coastguard Worker 	}
545*03ce13f7SAndroid Build Coastguard Worker 
546*03ce13f7SAndroid Build Coastguard Worker 	std::shared_ptr<Routine> routine;
547*03ce13f7SAndroid Build Coastguard Worker 
548*03ce13f7SAndroid Build Coastguard Worker 	auto acquire = [&](rr::JITBuilder *jit) {
549*03ce13f7SAndroid Build Coastguard Worker 	// ::jit is thread-local, so when this is executed on a separate thread (see JIT_IN_SEPARATE_THREAD)
550*03ce13f7SAndroid Build Coastguard Worker 	// it needs to only use the jit variable passed in as an argument.
551*03ce13f7SAndroid Build Coastguard Worker 
552*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
553*03ce13f7SAndroid Build Coastguard Worker 		if(jit->debugInfo != nullptr)
554*03ce13f7SAndroid Build Coastguard Worker 		{
555*03ce13f7SAndroid Build Coastguard Worker 			jit->debugInfo->Finalize();
556*03ce13f7SAndroid Build Coastguard Worker 		}
557*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_DEBUG_INFO
558*03ce13f7SAndroid Build Coastguard Worker 
559*03ce13f7SAndroid Build Coastguard Worker 		if(false)
560*03ce13f7SAndroid Build Coastguard Worker 		{
561*03ce13f7SAndroid Build Coastguard Worker 			std::error_code error;
562*03ce13f7SAndroid Build Coastguard Worker 			llvm::raw_fd_ostream file(std::string(name) + "-llvm-dump-unopt.txt", error);
563*03ce13f7SAndroid Build Coastguard Worker 			jit->module->print(file, 0);
564*03ce13f7SAndroid Build Coastguard Worker 		}
565*03ce13f7SAndroid Build Coastguard Worker 
566*03ce13f7SAndroid Build Coastguard Worker 		jit->runPasses();
567*03ce13f7SAndroid Build Coastguard Worker 
568*03ce13f7SAndroid Build Coastguard Worker 		if(false)
569*03ce13f7SAndroid Build Coastguard Worker 		{
570*03ce13f7SAndroid Build Coastguard Worker 			std::error_code error;
571*03ce13f7SAndroid Build Coastguard Worker 			llvm::raw_fd_ostream file(std::string(name) + "-llvm-dump-opt.txt", error);
572*03ce13f7SAndroid Build Coastguard Worker 			jit->module->print(file, 0);
573*03ce13f7SAndroid Build Coastguard Worker 		}
574*03ce13f7SAndroid Build Coastguard Worker 
575*03ce13f7SAndroid Build Coastguard Worker 		routine = jit->acquireRoutine(name, &jit->function, 1);
576*03ce13f7SAndroid Build Coastguard Worker 	};
577*03ce13f7SAndroid Build Coastguard Worker 
578*03ce13f7SAndroid Build Coastguard Worker #ifdef JIT_IN_SEPARATE_THREAD
579*03ce13f7SAndroid Build Coastguard Worker 	// Perform optimizations and codegen in a separate thread to avoid stack overflow.
580*03ce13f7SAndroid Build Coastguard Worker 	// FIXME(b/149829034): This is not a long-term solution. Reactor has no control
581*03ce13f7SAndroid Build Coastguard Worker 	// over the threading and stack sizes of its users, so this should be addressed
582*03ce13f7SAndroid Build Coastguard Worker 	// at a higher level instead.
583*03ce13f7SAndroid Build Coastguard Worker 	std::thread thread(acquire, jit);
584*03ce13f7SAndroid Build Coastguard Worker 	thread.join();
585*03ce13f7SAndroid Build Coastguard Worker #else
586*03ce13f7SAndroid Build Coastguard Worker 	acquire(jit);
587*03ce13f7SAndroid Build Coastguard Worker #endif
588*03ce13f7SAndroid Build Coastguard Worker 
589*03ce13f7SAndroid Build Coastguard Worker 	return routine;
590*03ce13f7SAndroid Build Coastguard Worker }
591*03ce13f7SAndroid Build Coastguard Worker 
allocateStackVariable(Type * type,int arraySize)592*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::allocateStackVariable(Type *type, int arraySize)
593*03ce13f7SAndroid Build Coastguard Worker {
594*03ce13f7SAndroid Build Coastguard Worker 	// Need to allocate it in the entry block for mem2reg to work
595*03ce13f7SAndroid Build Coastguard Worker 	llvm::BasicBlock &entryBlock = jit->function->getEntryBlock();
596*03ce13f7SAndroid Build Coastguard Worker 
597*03ce13f7SAndroid Build Coastguard Worker 	llvm::Instruction *declaration;
598*03ce13f7SAndroid Build Coastguard Worker 
599*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
600*03ce13f7SAndroid Build Coastguard Worker 	auto align = jit->module->getDataLayout().getPrefTypeAlign(T(type));
601*03ce13f7SAndroid Build Coastguard Worker #else
602*03ce13f7SAndroid Build Coastguard Worker 	auto align = llvm::MaybeAlign(jit->module->getDataLayout().getPrefTypeAlignment(T(type)));
603*03ce13f7SAndroid Build Coastguard Worker #endif
604*03ce13f7SAndroid Build Coastguard Worker 
605*03ce13f7SAndroid Build Coastguard Worker 	if(arraySize)
606*03ce13f7SAndroid Build Coastguard Worker 	{
607*03ce13f7SAndroid Build Coastguard Worker 		Value *size = (sizeof(size_t) == 8) ? Nucleus::createConstantLong(arraySize) : Nucleus::createConstantInt(arraySize);
608*03ce13f7SAndroid Build Coastguard Worker 		declaration = new llvm::AllocaInst(T(type), 0, V(size), align);
609*03ce13f7SAndroid Build Coastguard Worker 	}
610*03ce13f7SAndroid Build Coastguard Worker 	else
611*03ce13f7SAndroid Build Coastguard Worker 	{
612*03ce13f7SAndroid Build Coastguard Worker 		declaration = new llvm::AllocaInst(T(type), 0, (llvm::Value *)nullptr, align);
613*03ce13f7SAndroid Build Coastguard Worker 	}
614*03ce13f7SAndroid Build Coastguard Worker 
615*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 16
616*03ce13f7SAndroid Build Coastguard Worker 	declaration->insertInto(&entryBlock, entryBlock.begin());
617*03ce13f7SAndroid Build Coastguard Worker #else
618*03ce13f7SAndroid Build Coastguard Worker 	entryBlock.getInstList().push_front(declaration);
619*03ce13f7SAndroid Build Coastguard Worker #endif
620*03ce13f7SAndroid Build Coastguard Worker 
621*03ce13f7SAndroid Build Coastguard Worker 	if(getPragmaState(InitializeLocalVariables))
622*03ce13f7SAndroid Build Coastguard Worker 	{
623*03ce13f7SAndroid Build Coastguard Worker 		llvm::Type *i8PtrTy = llvm::Type::getInt8Ty(*jit->context)->getPointerTo();
624*03ce13f7SAndroid Build Coastguard Worker 		llvm::Type *i32Ty = llvm::Type::getInt32Ty(*jit->context);
625*03ce13f7SAndroid Build Coastguard Worker 		llvm::Function *memset = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::memset, { i8PtrTy, i32Ty });
626*03ce13f7SAndroid Build Coastguard Worker 
627*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateCall(memset, { jit->builder->CreatePointerCast(declaration, i8PtrTy),
628*03ce13f7SAndroid Build Coastguard Worker 		                                   V(Nucleus::createConstantByte((unsigned char)0)),
629*03ce13f7SAndroid Build Coastguard Worker 		                                   V(Nucleus::createConstantInt((int)typeSize(type) * (arraySize ? arraySize : 1))),
630*03ce13f7SAndroid Build Coastguard Worker 		                                   V(Nucleus::createConstantBool(false)) });
631*03ce13f7SAndroid Build Coastguard Worker 	}
632*03ce13f7SAndroid Build Coastguard Worker 
633*03ce13f7SAndroid Build Coastguard Worker 	return V(declaration);
634*03ce13f7SAndroid Build Coastguard Worker }
635*03ce13f7SAndroid Build Coastguard Worker 
createBasicBlock()636*03ce13f7SAndroid Build Coastguard Worker BasicBlock *Nucleus::createBasicBlock()
637*03ce13f7SAndroid Build Coastguard Worker {
638*03ce13f7SAndroid Build Coastguard Worker 	return B(llvm::BasicBlock::Create(*jit->context, "", jit->function));
639*03ce13f7SAndroid Build Coastguard Worker }
640*03ce13f7SAndroid Build Coastguard Worker 
getInsertBlock()641*03ce13f7SAndroid Build Coastguard Worker BasicBlock *Nucleus::getInsertBlock()
642*03ce13f7SAndroid Build Coastguard Worker {
643*03ce13f7SAndroid Build Coastguard Worker 	return B(jit->builder->GetInsertBlock());
644*03ce13f7SAndroid Build Coastguard Worker }
645*03ce13f7SAndroid Build Coastguard Worker 
setInsertBlock(BasicBlock * basicBlock)646*03ce13f7SAndroid Build Coastguard Worker void Nucleus::setInsertBlock(BasicBlock *basicBlock)
647*03ce13f7SAndroid Build Coastguard Worker {
648*03ce13f7SAndroid Build Coastguard Worker 	// assert(jit->builder->GetInsertBlock()->back().isTerminator());
649*03ce13f7SAndroid Build Coastguard Worker 
650*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->SetInsertPoint(B(basicBlock));
651*03ce13f7SAndroid Build Coastguard Worker }
652*03ce13f7SAndroid Build Coastguard Worker 
createFunction(Type * ReturnType,const std::vector<Type * > & Params)653*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createFunction(Type *ReturnType, const std::vector<Type *> &Params)
654*03ce13f7SAndroid Build Coastguard Worker {
655*03ce13f7SAndroid Build Coastguard Worker 	jit->function = rr::createFunction("", T(ReturnType), T(Params));
656*03ce13f7SAndroid Build Coastguard Worker 
657*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
658*03ce13f7SAndroid Build Coastguard Worker 	jit->debugInfo = std::make_unique<DebugInfo>(jit->builder.get(), jit->context.get(), jit->module.get(), jit->function);
659*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_DEBUG_INFO
660*03ce13f7SAndroid Build Coastguard Worker 
661*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->SetInsertPoint(llvm::BasicBlock::Create(*jit->context, "", jit->function));
662*03ce13f7SAndroid Build Coastguard Worker }
663*03ce13f7SAndroid Build Coastguard Worker 
getArgument(unsigned int index)664*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::getArgument(unsigned int index)
665*03ce13f7SAndroid Build Coastguard Worker {
666*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function::arg_iterator args = jit->function->arg_begin();
667*03ce13f7SAndroid Build Coastguard Worker 
668*03ce13f7SAndroid Build Coastguard Worker 	while(index)
669*03ce13f7SAndroid Build Coastguard Worker 	{
670*03ce13f7SAndroid Build Coastguard Worker 		args++;
671*03ce13f7SAndroid Build Coastguard Worker 		index--;
672*03ce13f7SAndroid Build Coastguard Worker 	}
673*03ce13f7SAndroid Build Coastguard Worker 
674*03ce13f7SAndroid Build Coastguard Worker 	return V(&*args);
675*03ce13f7SAndroid Build Coastguard Worker }
676*03ce13f7SAndroid Build Coastguard Worker 
createRetVoid()677*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createRetVoid()
678*03ce13f7SAndroid Build Coastguard Worker {
679*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
680*03ce13f7SAndroid Build Coastguard Worker 
681*03ce13f7SAndroid Build Coastguard Worker 	ASSERT_MSG(jit->function->getReturnType() == T(Void::type()), "Return type mismatch");
682*03ce13f7SAndroid Build Coastguard Worker 
683*03ce13f7SAndroid Build Coastguard Worker 	// Code generated after this point is unreachable, so any variables
684*03ce13f7SAndroid Build Coastguard Worker 	// being read can safely return an undefined value. We have to avoid
685*03ce13f7SAndroid Build Coastguard Worker 	// materializing variables after the terminator ret instruction.
686*03ce13f7SAndroid Build Coastguard Worker 	Variable::killUnmaterialized();
687*03ce13f7SAndroid Build Coastguard Worker 
688*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateRetVoid();
689*03ce13f7SAndroid Build Coastguard Worker }
690*03ce13f7SAndroid Build Coastguard Worker 
createRet(Value * v)691*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createRet(Value *v)
692*03ce13f7SAndroid Build Coastguard Worker {
693*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
694*03ce13f7SAndroid Build Coastguard Worker 
695*03ce13f7SAndroid Build Coastguard Worker 	ASSERT_MSG(jit->function->getReturnType() == V(v)->getType(), "Return type mismatch");
696*03ce13f7SAndroid Build Coastguard Worker 
697*03ce13f7SAndroid Build Coastguard Worker 	// Code generated after this point is unreachable, so any variables
698*03ce13f7SAndroid Build Coastguard Worker 	// being read can safely return an undefined value. We have to avoid
699*03ce13f7SAndroid Build Coastguard Worker 	// materializing variables after the terminator ret instruction.
700*03ce13f7SAndroid Build Coastguard Worker 	Variable::killUnmaterialized();
701*03ce13f7SAndroid Build Coastguard Worker 
702*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateRet(V(v));
703*03ce13f7SAndroid Build Coastguard Worker }
704*03ce13f7SAndroid Build Coastguard Worker 
createBr(BasicBlock * dest)705*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createBr(BasicBlock *dest)
706*03ce13f7SAndroid Build Coastguard Worker {
707*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
708*03ce13f7SAndroid Build Coastguard Worker 	Variable::materializeAll();
709*03ce13f7SAndroid Build Coastguard Worker 
710*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateBr(B(dest));
711*03ce13f7SAndroid Build Coastguard Worker }
712*03ce13f7SAndroid Build Coastguard Worker 
createCondBr(Value * cond,BasicBlock * ifTrue,BasicBlock * ifFalse)713*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createCondBr(Value *cond, BasicBlock *ifTrue, BasicBlock *ifFalse)
714*03ce13f7SAndroid Build Coastguard Worker {
715*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
716*03ce13f7SAndroid Build Coastguard Worker 	Variable::materializeAll();
717*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateCondBr(V(cond), B(ifTrue), B(ifFalse));
718*03ce13f7SAndroid Build Coastguard Worker }
719*03ce13f7SAndroid Build Coastguard Worker 
createAdd(Value * lhs,Value * rhs)720*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAdd(Value *lhs, Value *rhs)
721*03ce13f7SAndroid Build Coastguard Worker {
722*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
723*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAdd(V(lhs), V(rhs)));
724*03ce13f7SAndroid Build Coastguard Worker }
725*03ce13f7SAndroid Build Coastguard Worker 
createSub(Value * lhs,Value * rhs)726*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSub(Value *lhs, Value *rhs)
727*03ce13f7SAndroid Build Coastguard Worker {
728*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
729*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateSub(V(lhs), V(rhs)));
730*03ce13f7SAndroid Build Coastguard Worker }
731*03ce13f7SAndroid Build Coastguard Worker 
createMul(Value * lhs,Value * rhs)732*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createMul(Value *lhs, Value *rhs)
733*03ce13f7SAndroid Build Coastguard Worker {
734*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
735*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateMul(V(lhs), V(rhs)));
736*03ce13f7SAndroid Build Coastguard Worker }
737*03ce13f7SAndroid Build Coastguard Worker 
createUDiv(Value * lhs,Value * rhs)738*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createUDiv(Value *lhs, Value *rhs)
739*03ce13f7SAndroid Build Coastguard Worker {
740*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
741*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateUDiv(V(lhs), V(rhs)));
742*03ce13f7SAndroid Build Coastguard Worker }
743*03ce13f7SAndroid Build Coastguard Worker 
createSDiv(Value * lhs,Value * rhs)744*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSDiv(Value *lhs, Value *rhs)
745*03ce13f7SAndroid Build Coastguard Worker {
746*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
747*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateSDiv(V(lhs), V(rhs)));
748*03ce13f7SAndroid Build Coastguard Worker }
749*03ce13f7SAndroid Build Coastguard Worker 
createFAdd(Value * lhs,Value * rhs)750*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFAdd(Value *lhs, Value *rhs)
751*03ce13f7SAndroid Build Coastguard Worker {
752*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
753*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFAdd(V(lhs), V(rhs)));
754*03ce13f7SAndroid Build Coastguard Worker }
755*03ce13f7SAndroid Build Coastguard Worker 
createFSub(Value * lhs,Value * rhs)756*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFSub(Value *lhs, Value *rhs)
757*03ce13f7SAndroid Build Coastguard Worker {
758*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
759*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFSub(V(lhs), V(rhs)));
760*03ce13f7SAndroid Build Coastguard Worker }
761*03ce13f7SAndroid Build Coastguard Worker 
createFMul(Value * lhs,Value * rhs)762*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFMul(Value *lhs, Value *rhs)
763*03ce13f7SAndroid Build Coastguard Worker {
764*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
765*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFMul(V(lhs), V(rhs)));
766*03ce13f7SAndroid Build Coastguard Worker }
767*03ce13f7SAndroid Build Coastguard Worker 
createFDiv(Value * lhs,Value * rhs)768*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFDiv(Value *lhs, Value *rhs)
769*03ce13f7SAndroid Build Coastguard Worker {
770*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
771*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFDiv(V(lhs), V(rhs)));
772*03ce13f7SAndroid Build Coastguard Worker }
773*03ce13f7SAndroid Build Coastguard Worker 
createURem(Value * lhs,Value * rhs)774*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createURem(Value *lhs, Value *rhs)
775*03ce13f7SAndroid Build Coastguard Worker {
776*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
777*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateURem(V(lhs), V(rhs)));
778*03ce13f7SAndroid Build Coastguard Worker }
779*03ce13f7SAndroid Build Coastguard Worker 
createSRem(Value * lhs,Value * rhs)780*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSRem(Value *lhs, Value *rhs)
781*03ce13f7SAndroid Build Coastguard Worker {
782*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
783*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateSRem(V(lhs), V(rhs)));
784*03ce13f7SAndroid Build Coastguard Worker }
785*03ce13f7SAndroid Build Coastguard Worker 
createFRem(Value * lhs,Value * rhs)786*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFRem(Value *lhs, Value *rhs)
787*03ce13f7SAndroid Build Coastguard Worker {
788*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
789*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFRem(V(lhs), V(rhs)));
790*03ce13f7SAndroid Build Coastguard Worker }
791*03ce13f7SAndroid Build Coastguard Worker 
operator %(RValue<Float4> lhs,RValue<Float4> rhs)792*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> operator%(RValue<Float4> lhs, RValue<Float4> rhs)
793*03ce13f7SAndroid Build Coastguard Worker {
794*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(Nucleus::createFRem(lhs.value(), rhs.value()));
795*03ce13f7SAndroid Build Coastguard Worker }
796*03ce13f7SAndroid Build Coastguard Worker 
createShl(Value * lhs,Value * rhs)797*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createShl(Value *lhs, Value *rhs)
798*03ce13f7SAndroid Build Coastguard Worker {
799*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
800*03ce13f7SAndroid Build Coastguard Worker 	auto *clamped_rhs = clampForShift(V(rhs));
801*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateShl(V(lhs), clamped_rhs));
802*03ce13f7SAndroid Build Coastguard Worker }
803*03ce13f7SAndroid Build Coastguard Worker 
createLShr(Value * lhs,Value * rhs)804*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createLShr(Value *lhs, Value *rhs)
805*03ce13f7SAndroid Build Coastguard Worker {
806*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
807*03ce13f7SAndroid Build Coastguard Worker 	auto *clamped_rhs = clampForShift(V(rhs));
808*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateLShr(V(lhs), clamped_rhs));
809*03ce13f7SAndroid Build Coastguard Worker }
810*03ce13f7SAndroid Build Coastguard Worker 
createAShr(Value * lhs,Value * rhs)811*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAShr(Value *lhs, Value *rhs)
812*03ce13f7SAndroid Build Coastguard Worker {
813*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
814*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAShr(V(lhs), V(rhs)));
815*03ce13f7SAndroid Build Coastguard Worker }
816*03ce13f7SAndroid Build Coastguard Worker 
createAnd(Value * lhs,Value * rhs)817*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAnd(Value *lhs, Value *rhs)
818*03ce13f7SAndroid Build Coastguard Worker {
819*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
820*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAnd(V(lhs), V(rhs)));
821*03ce13f7SAndroid Build Coastguard Worker }
822*03ce13f7SAndroid Build Coastguard Worker 
createOr(Value * lhs,Value * rhs)823*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createOr(Value *lhs, Value *rhs)
824*03ce13f7SAndroid Build Coastguard Worker {
825*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
826*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateOr(V(lhs), V(rhs)));
827*03ce13f7SAndroid Build Coastguard Worker }
828*03ce13f7SAndroid Build Coastguard Worker 
createXor(Value * lhs,Value * rhs)829*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createXor(Value *lhs, Value *rhs)
830*03ce13f7SAndroid Build Coastguard Worker {
831*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
832*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateXor(V(lhs), V(rhs)));
833*03ce13f7SAndroid Build Coastguard Worker }
834*03ce13f7SAndroid Build Coastguard Worker 
createNeg(Value * v)835*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createNeg(Value *v)
836*03ce13f7SAndroid Build Coastguard Worker {
837*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
838*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateNeg(V(v)));
839*03ce13f7SAndroid Build Coastguard Worker }
840*03ce13f7SAndroid Build Coastguard Worker 
createFNeg(Value * v)841*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFNeg(Value *v)
842*03ce13f7SAndroid Build Coastguard Worker {
843*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
844*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFNeg(V(v)));
845*03ce13f7SAndroid Build Coastguard Worker }
846*03ce13f7SAndroid Build Coastguard Worker 
createNot(Value * v)847*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createNot(Value *v)
848*03ce13f7SAndroid Build Coastguard Worker {
849*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
850*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateNot(V(v)));
851*03ce13f7SAndroid Build Coastguard Worker }
852*03ce13f7SAndroid Build Coastguard Worker 
createLoad(Value * ptr,Type * type,bool isVolatile,unsigned int alignment,bool atomic,std::memory_order memoryOrder)853*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createLoad(Value *ptr, Type *type, bool isVolatile, unsigned int alignment, bool atomic, std::memory_order memoryOrder)
854*03ce13f7SAndroid Build Coastguard Worker {
855*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
856*03ce13f7SAndroid Build Coastguard Worker 	switch(asInternalType(type))
857*03ce13f7SAndroid Build Coastguard Worker 	{
858*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2i32:
859*03ce13f7SAndroid Build Coastguard Worker 	case Type_v4i16:
860*03ce13f7SAndroid Build Coastguard Worker 	case Type_v8i8:
861*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2f32:
862*03ce13f7SAndroid Build Coastguard Worker 		return createBitCast(
863*03ce13f7SAndroid Build Coastguard Worker 		    createInsertElement(
864*03ce13f7SAndroid Build Coastguard Worker 		        V(llvm::UndefValue::get(llvm::VectorType::get(T(Long::type()), 2, false))),
865*03ce13f7SAndroid Build Coastguard Worker 		        createLoad(createBitCast(ptr, Pointer<Long>::type()), Long::type(), isVolatile, alignment, atomic, memoryOrder),
866*03ce13f7SAndroid Build Coastguard Worker 		        0),
867*03ce13f7SAndroid Build Coastguard Worker 		    type);
868*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2i16:
869*03ce13f7SAndroid Build Coastguard Worker 	case Type_v4i8:
870*03ce13f7SAndroid Build Coastguard Worker 		if(alignment != 0)  // Not a local variable (all vectors are 128-bit).
871*03ce13f7SAndroid Build Coastguard Worker 		{
872*03ce13f7SAndroid Build Coastguard Worker 			Value *u = V(llvm::UndefValue::get(llvm::VectorType::get(T(Long::type()), 2, false)));
873*03ce13f7SAndroid Build Coastguard Worker 			Value *i = createLoad(createBitCast(ptr, Pointer<Int>::type()), Int::type(), isVolatile, alignment, atomic, memoryOrder);
874*03ce13f7SAndroid Build Coastguard Worker 			i = createZExt(i, Long::type());
875*03ce13f7SAndroid Build Coastguard Worker 			Value *v = createInsertElement(u, i, 0);
876*03ce13f7SAndroid Build Coastguard Worker 			return createBitCast(v, type);
877*03ce13f7SAndroid Build Coastguard Worker 		}
878*03ce13f7SAndroid Build Coastguard Worker 		// Fallthrough to non-emulated case.
879*03ce13f7SAndroid Build Coastguard Worker 	case Type_LLVM:
880*03ce13f7SAndroid Build Coastguard Worker 		{
881*03ce13f7SAndroid Build Coastguard Worker 			auto elTy = T(type);
882*03ce13f7SAndroid Build Coastguard Worker 
883*03ce13f7SAndroid Build Coastguard Worker 			if(!atomic)
884*03ce13f7SAndroid Build Coastguard Worker 			{
885*03ce13f7SAndroid Build Coastguard Worker 				return V(jit->builder->CreateAlignedLoad(elTy, V(ptr), llvm::MaybeAlign(alignment), isVolatile));
886*03ce13f7SAndroid Build Coastguard Worker 			}
887*03ce13f7SAndroid Build Coastguard Worker 			else if(elTy->isIntegerTy() || elTy->isPointerTy())
888*03ce13f7SAndroid Build Coastguard Worker 			{
889*03ce13f7SAndroid Build Coastguard Worker 				// Integers and pointers can be atomically loaded by setting
890*03ce13f7SAndroid Build Coastguard Worker 				// the ordering constraint on the load instruction.
891*03ce13f7SAndroid Build Coastguard Worker 				auto load = jit->builder->CreateAlignedLoad(elTy, V(ptr), llvm::MaybeAlign(alignment), isVolatile);
892*03ce13f7SAndroid Build Coastguard Worker 				load->setAtomic(atomicOrdering(atomic, memoryOrder));
893*03ce13f7SAndroid Build Coastguard Worker 				return V(load);
894*03ce13f7SAndroid Build Coastguard Worker 			}
895*03ce13f7SAndroid Build Coastguard Worker 			else if(elTy->isFloatTy() || elTy->isDoubleTy())
896*03ce13f7SAndroid Build Coastguard Worker 			{
897*03ce13f7SAndroid Build Coastguard Worker 				// LLVM claims to support atomic loads of float types as
898*03ce13f7SAndroid Build Coastguard Worker 				// above, but certain backends cannot deal with this.
899*03ce13f7SAndroid Build Coastguard Worker 				// Load as an integer and bitcast. See b/136037244.
900*03ce13f7SAndroid Build Coastguard Worker 				auto size = jit->module->getDataLayout().getTypeStoreSize(elTy);
901*03ce13f7SAndroid Build Coastguard Worker 				auto elAsIntTy = llvm::IntegerType::get(*jit->context, size * 8);
902*03ce13f7SAndroid Build Coastguard Worker 				auto ptrCast = jit->builder->CreatePointerCast(V(ptr), elAsIntTy->getPointerTo());
903*03ce13f7SAndroid Build Coastguard Worker 				auto load = jit->builder->CreateAlignedLoad(elAsIntTy, ptrCast, llvm::MaybeAlign(alignment), isVolatile);
904*03ce13f7SAndroid Build Coastguard Worker 				load->setAtomic(atomicOrdering(atomic, memoryOrder));
905*03ce13f7SAndroid Build Coastguard Worker 				auto loadCast = jit->builder->CreateBitCast(load, elTy);
906*03ce13f7SAndroid Build Coastguard Worker 				return V(loadCast);
907*03ce13f7SAndroid Build Coastguard Worker 			}
908*03ce13f7SAndroid Build Coastguard Worker 			else
909*03ce13f7SAndroid Build Coastguard Worker 			{
910*03ce13f7SAndroid Build Coastguard Worker 				// More exotic types require falling back to the extern:
911*03ce13f7SAndroid Build Coastguard Worker 				// void __atomic_load(size_t size, void *ptr, void *ret, int ordering)
912*03ce13f7SAndroid Build Coastguard Worker 				auto sizetTy = llvm::IntegerType::get(*jit->context, sizeof(size_t) * 8);
913*03ce13f7SAndroid Build Coastguard Worker 				auto intTy = llvm::IntegerType::get(*jit->context, sizeof(int) * 8);
914*03ce13f7SAndroid Build Coastguard Worker 				auto i8Ty = llvm::Type::getInt8Ty(*jit->context);
915*03ce13f7SAndroid Build Coastguard Worker 				auto i8PtrTy = i8Ty->getPointerTo();
916*03ce13f7SAndroid Build Coastguard Worker 				auto voidTy = llvm::Type::getVoidTy(*jit->context);
917*03ce13f7SAndroid Build Coastguard Worker 				auto funcTy = llvm::FunctionType::get(voidTy, { sizetTy, i8PtrTy, i8PtrTy, intTy }, false);
918*03ce13f7SAndroid Build Coastguard Worker 				auto func = jit->module->getOrInsertFunction("__atomic_load", funcTy);
919*03ce13f7SAndroid Build Coastguard Worker 				auto size = jit->module->getDataLayout().getTypeStoreSize(elTy);
920*03ce13f7SAndroid Build Coastguard Worker 				auto out = allocateStackVariable(type);
921*03ce13f7SAndroid Build Coastguard Worker 				jit->builder->CreateCall(func, {
922*03ce13f7SAndroid Build Coastguard Worker 				                                   llvm::ConstantInt::get(sizetTy, size),
923*03ce13f7SAndroid Build Coastguard Worker 				                                   jit->builder->CreatePointerCast(V(ptr), i8PtrTy),
924*03ce13f7SAndroid Build Coastguard Worker 				                                   jit->builder->CreatePointerCast(V(out), i8PtrTy),
925*03ce13f7SAndroid Build Coastguard Worker 				                                   llvm::ConstantInt::get(intTy, uint64_t(atomicOrdering(true, memoryOrder))),
926*03ce13f7SAndroid Build Coastguard Worker 				                               });
927*03ce13f7SAndroid Build Coastguard Worker 				return V(jit->builder->CreateLoad(T(type), V(out)));
928*03ce13f7SAndroid Build Coastguard Worker 			}
929*03ce13f7SAndroid Build Coastguard Worker 		}
930*03ce13f7SAndroid Build Coastguard Worker 	default:
931*03ce13f7SAndroid Build Coastguard Worker 		UNREACHABLE("asInternalType(type): %d", int(asInternalType(type)));
932*03ce13f7SAndroid Build Coastguard Worker 		return nullptr;
933*03ce13f7SAndroid Build Coastguard Worker 	}
934*03ce13f7SAndroid Build Coastguard Worker }
935*03ce13f7SAndroid Build Coastguard Worker 
createStore(Value * value,Value * ptr,Type * type,bool isVolatile,unsigned int alignment,bool atomic,std::memory_order memoryOrder)936*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatile, unsigned int alignment, bool atomic, std::memory_order memoryOrder)
937*03ce13f7SAndroid Build Coastguard Worker {
938*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
939*03ce13f7SAndroid Build Coastguard Worker 	switch(asInternalType(type))
940*03ce13f7SAndroid Build Coastguard Worker 	{
941*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2i32:
942*03ce13f7SAndroid Build Coastguard Worker 	case Type_v4i16:
943*03ce13f7SAndroid Build Coastguard Worker 	case Type_v8i8:
944*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2f32:
945*03ce13f7SAndroid Build Coastguard Worker 		createStore(
946*03ce13f7SAndroid Build Coastguard Worker 		    createExtractElement(
947*03ce13f7SAndroid Build Coastguard Worker 		        createBitCast(value, T(llvm::VectorType::get(T(Long::type()), 2, false))), Long::type(), 0),
948*03ce13f7SAndroid Build Coastguard Worker 		    createBitCast(ptr, Pointer<Long>::type()),
949*03ce13f7SAndroid Build Coastguard Worker 		    Long::type(), isVolatile, alignment, atomic, memoryOrder);
950*03ce13f7SAndroid Build Coastguard Worker 		return value;
951*03ce13f7SAndroid Build Coastguard Worker 	case Type_v2i16:
952*03ce13f7SAndroid Build Coastguard Worker 	case Type_v4i8:
953*03ce13f7SAndroid Build Coastguard Worker 		if(alignment != 0)  // Not a local variable (all vectors are 128-bit).
954*03ce13f7SAndroid Build Coastguard Worker 		{
955*03ce13f7SAndroid Build Coastguard Worker 			createStore(
956*03ce13f7SAndroid Build Coastguard Worker 			    createExtractElement(createBitCast(value, Int4::type()), Int::type(), 0),
957*03ce13f7SAndroid Build Coastguard Worker 			    createBitCast(ptr, Pointer<Int>::type()),
958*03ce13f7SAndroid Build Coastguard Worker 			    Int::type(), isVolatile, alignment, atomic, memoryOrder);
959*03ce13f7SAndroid Build Coastguard Worker 			return value;
960*03ce13f7SAndroid Build Coastguard Worker 		}
961*03ce13f7SAndroid Build Coastguard Worker 		// Fallthrough to non-emulated case.
962*03ce13f7SAndroid Build Coastguard Worker 	case Type_LLVM:
963*03ce13f7SAndroid Build Coastguard Worker 		{
964*03ce13f7SAndroid Build Coastguard Worker 			auto elTy = T(type);
965*03ce13f7SAndroid Build Coastguard Worker 
966*03ce13f7SAndroid Build Coastguard Worker 			if(__has_feature(memory_sanitizer) && !jit->msanInstrumentation)
967*03ce13f7SAndroid Build Coastguard Worker 			{
968*03ce13f7SAndroid Build Coastguard Worker 				// Mark all memory writes as initialized by calling __msan_unpoison
969*03ce13f7SAndroid Build Coastguard Worker 				// void __msan_unpoison(const volatile void *a, size_t size)
970*03ce13f7SAndroid Build Coastguard Worker 				auto voidTy = llvm::Type::getVoidTy(*jit->context);
971*03ce13f7SAndroid Build Coastguard Worker 				auto i8Ty = llvm::Type::getInt8Ty(*jit->context);
972*03ce13f7SAndroid Build Coastguard Worker 				auto voidPtrTy = i8Ty->getPointerTo();
973*03ce13f7SAndroid Build Coastguard Worker 				auto sizetTy = llvm::IntegerType::get(*jit->context, sizeof(size_t) * 8);
974*03ce13f7SAndroid Build Coastguard Worker 				auto funcTy = llvm::FunctionType::get(voidTy, { voidPtrTy, sizetTy }, false);
975*03ce13f7SAndroid Build Coastguard Worker 				auto func = jit->module->getOrInsertFunction("__msan_unpoison", funcTy);
976*03ce13f7SAndroid Build Coastguard Worker 				auto size = jit->module->getDataLayout().getTypeStoreSize(elTy);
977*03ce13f7SAndroid Build Coastguard Worker 
978*03ce13f7SAndroid Build Coastguard Worker 				jit->builder->CreateCall(func, { jit->builder->CreatePointerCast(V(ptr), voidPtrTy),
979*03ce13f7SAndroid Build Coastguard Worker 				                                 llvm::ConstantInt::get(sizetTy, size) });
980*03ce13f7SAndroid Build Coastguard Worker 			}
981*03ce13f7SAndroid Build Coastguard Worker 
982*03ce13f7SAndroid Build Coastguard Worker 			if(!atomic)
983*03ce13f7SAndroid Build Coastguard Worker 			{
984*03ce13f7SAndroid Build Coastguard Worker 				jit->builder->CreateAlignedStore(V(value), V(ptr), llvm::MaybeAlign(alignment), isVolatile);
985*03ce13f7SAndroid Build Coastguard Worker 			}
986*03ce13f7SAndroid Build Coastguard Worker 			else if(elTy->isIntegerTy() || elTy->isPointerTy())
987*03ce13f7SAndroid Build Coastguard Worker 			{
988*03ce13f7SAndroid Build Coastguard Worker 				// Integers and pointers can be atomically stored by setting
989*03ce13f7SAndroid Build Coastguard Worker 				// the ordering constraint on the store instruction.
990*03ce13f7SAndroid Build Coastguard Worker 				auto store = jit->builder->CreateAlignedStore(V(value), V(ptr), llvm::MaybeAlign(alignment), isVolatile);
991*03ce13f7SAndroid Build Coastguard Worker 				store->setAtomic(atomicOrdering(atomic, memoryOrder));
992*03ce13f7SAndroid Build Coastguard Worker 			}
993*03ce13f7SAndroid Build Coastguard Worker 			else if(elTy->isFloatTy() || elTy->isDoubleTy())
994*03ce13f7SAndroid Build Coastguard Worker 			{
995*03ce13f7SAndroid Build Coastguard Worker 				// LLVM claims to support atomic stores of float types as
996*03ce13f7SAndroid Build Coastguard Worker 				// above, but certain backends cannot deal with this.
997*03ce13f7SAndroid Build Coastguard Worker 				// Store as an bitcast integer. See b/136037244.
998*03ce13f7SAndroid Build Coastguard Worker 				auto size = jit->module->getDataLayout().getTypeStoreSize(elTy);
999*03ce13f7SAndroid Build Coastguard Worker 				auto elAsIntTy = llvm::IntegerType::get(*jit->context, size * 8);
1000*03ce13f7SAndroid Build Coastguard Worker 				auto valCast = jit->builder->CreateBitCast(V(value), elAsIntTy);
1001*03ce13f7SAndroid Build Coastguard Worker 				auto ptrCast = jit->builder->CreatePointerCast(V(ptr), elAsIntTy->getPointerTo());
1002*03ce13f7SAndroid Build Coastguard Worker 				auto store = jit->builder->CreateAlignedStore(valCast, ptrCast, llvm::MaybeAlign(alignment), isVolatile);
1003*03ce13f7SAndroid Build Coastguard Worker 				store->setAtomic(atomicOrdering(atomic, memoryOrder));
1004*03ce13f7SAndroid Build Coastguard Worker 			}
1005*03ce13f7SAndroid Build Coastguard Worker 			else
1006*03ce13f7SAndroid Build Coastguard Worker 			{
1007*03ce13f7SAndroid Build Coastguard Worker 				// More exotic types require falling back to the extern:
1008*03ce13f7SAndroid Build Coastguard Worker 				// void __atomic_store(size_t size, void *ptr, void *val, int ordering)
1009*03ce13f7SAndroid Build Coastguard Worker 				auto sizetTy = llvm::IntegerType::get(*jit->context, sizeof(size_t) * 8);
1010*03ce13f7SAndroid Build Coastguard Worker 				auto intTy = llvm::IntegerType::get(*jit->context, sizeof(int) * 8);
1011*03ce13f7SAndroid Build Coastguard Worker 				auto i8Ty = llvm::Type::getInt8Ty(*jit->context);
1012*03ce13f7SAndroid Build Coastguard Worker 				auto i8PtrTy = i8Ty->getPointerTo();
1013*03ce13f7SAndroid Build Coastguard Worker 				auto voidTy = llvm::Type::getVoidTy(*jit->context);
1014*03ce13f7SAndroid Build Coastguard Worker 				auto funcTy = llvm::FunctionType::get(voidTy, { sizetTy, i8PtrTy, i8PtrTy, intTy }, false);
1015*03ce13f7SAndroid Build Coastguard Worker 				auto func = jit->module->getOrInsertFunction("__atomic_store", funcTy);
1016*03ce13f7SAndroid Build Coastguard Worker 				auto size = jit->module->getDataLayout().getTypeStoreSize(elTy);
1017*03ce13f7SAndroid Build Coastguard Worker 				auto copy = allocateStackVariable(type);
1018*03ce13f7SAndroid Build Coastguard Worker 				jit->builder->CreateStore(V(value), V(copy));
1019*03ce13f7SAndroid Build Coastguard Worker 				jit->builder->CreateCall(func, {
1020*03ce13f7SAndroid Build Coastguard Worker 				                                   llvm::ConstantInt::get(sizetTy, size),
1021*03ce13f7SAndroid Build Coastguard Worker 				                                   jit->builder->CreatePointerCast(V(ptr), i8PtrTy),
1022*03ce13f7SAndroid Build Coastguard Worker 				                                   jit->builder->CreatePointerCast(V(copy), i8PtrTy),
1023*03ce13f7SAndroid Build Coastguard Worker 				                                   llvm::ConstantInt::get(intTy, uint64_t(atomicOrdering(true, memoryOrder))),
1024*03ce13f7SAndroid Build Coastguard Worker 				                               });
1025*03ce13f7SAndroid Build Coastguard Worker 			}
1026*03ce13f7SAndroid Build Coastguard Worker 
1027*03ce13f7SAndroid Build Coastguard Worker 			return value;
1028*03ce13f7SAndroid Build Coastguard Worker 		}
1029*03ce13f7SAndroid Build Coastguard Worker 	default:
1030*03ce13f7SAndroid Build Coastguard Worker 		UNREACHABLE("asInternalType(type): %d", int(asInternalType(type)));
1031*03ce13f7SAndroid Build Coastguard Worker 		return nullptr;
1032*03ce13f7SAndroid Build Coastguard Worker 	}
1033*03ce13f7SAndroid Build Coastguard Worker }
1034*03ce13f7SAndroid Build Coastguard Worker 
createMaskedLoad(Value * ptr,Type * elTy,Value * mask,unsigned int alignment,bool zeroMaskedLanes)1035*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createMaskedLoad(Value *ptr, Type *elTy, Value *mask, unsigned int alignment, bool zeroMaskedLanes)
1036*03ce13f7SAndroid Build Coastguard Worker {
1037*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1038*03ce13f7SAndroid Build Coastguard Worker 
1039*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(V(ptr)->getType()->isPointerTy());
1040*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(V(mask)->getType()->isVectorTy());
1041*03ce13f7SAndroid Build Coastguard Worker 
1042*03ce13f7SAndroid Build Coastguard Worker 	auto numEls = llvm::cast<llvm::FixedVectorType>(V(mask)->getType())->getNumElements();
1043*03ce13f7SAndroid Build Coastguard Worker 	auto i1Ty = llvm::Type::getInt1Ty(*jit->context);
1044*03ce13f7SAndroid Build Coastguard Worker 	auto i32Ty = llvm::Type::getInt32Ty(*jit->context);
1045*03ce13f7SAndroid Build Coastguard Worker 	auto elVecTy = llvm::VectorType::get(T(elTy), numEls, false);
1046*03ce13f7SAndroid Build Coastguard Worker 	auto elVecPtrTy = elVecTy->getPointerTo();
1047*03ce13f7SAndroid Build Coastguard Worker 	auto i8Mask = jit->builder->CreateIntCast(V(mask), llvm::VectorType::get(i1Ty, numEls, false), false);  // vec<int, int, ...> -> vec<bool, bool, ...>
1048*03ce13f7SAndroid Build Coastguard Worker 	auto passthrough = zeroMaskedLanes ? llvm::Constant::getNullValue(elVecTy) : llvm::UndefValue::get(elVecTy);
1049*03ce13f7SAndroid Build Coastguard Worker 	auto align = llvm::ConstantInt::get(i32Ty, alignment);
1050*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::masked_load, { elVecTy, elVecPtrTy });
1051*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateCall(func, { V(ptr), align, i8Mask, passthrough }));
1052*03ce13f7SAndroid Build Coastguard Worker }
1053*03ce13f7SAndroid Build Coastguard Worker 
createMaskedStore(Value * ptr,Value * val,Value * mask,unsigned int alignment)1054*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createMaskedStore(Value *ptr, Value *val, Value *mask, unsigned int alignment)
1055*03ce13f7SAndroid Build Coastguard Worker {
1056*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1057*03ce13f7SAndroid Build Coastguard Worker 
1058*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(V(ptr)->getType()->isPointerTy());
1059*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(V(val)->getType()->isVectorTy());
1060*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(V(mask)->getType()->isVectorTy());
1061*03ce13f7SAndroid Build Coastguard Worker 
1062*03ce13f7SAndroid Build Coastguard Worker 	auto numEls = llvm::cast<llvm::FixedVectorType>(V(mask)->getType())->getNumElements();
1063*03ce13f7SAndroid Build Coastguard Worker 	auto i1Ty = llvm::Type::getInt1Ty(*jit->context);
1064*03ce13f7SAndroid Build Coastguard Worker 	auto i32Ty = llvm::Type::getInt32Ty(*jit->context);
1065*03ce13f7SAndroid Build Coastguard Worker 	auto elVecTy = V(val)->getType();
1066*03ce13f7SAndroid Build Coastguard Worker 	auto elVecPtrTy = elVecTy->getPointerTo();
1067*03ce13f7SAndroid Build Coastguard Worker 	auto i1Mask = jit->builder->CreateIntCast(V(mask), llvm::VectorType::get(i1Ty, numEls, false), false);  // vec<int, int, ...> -> vec<bool, bool, ...>
1068*03ce13f7SAndroid Build Coastguard Worker 	auto align = llvm::ConstantInt::get(i32Ty, alignment);
1069*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::masked_store, { elVecTy, elVecPtrTy });
1070*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateCall(func, { V(val), V(ptr), align, i1Mask });
1071*03ce13f7SAndroid Build Coastguard Worker 
1072*03ce13f7SAndroid Build Coastguard Worker 	if(__has_feature(memory_sanitizer) && !jit->msanInstrumentation)
1073*03ce13f7SAndroid Build Coastguard Worker 	{
1074*03ce13f7SAndroid Build Coastguard Worker 		// Mark memory writes as initialized by calling __msan_unpoison
1075*03ce13f7SAndroid Build Coastguard Worker 		// void __msan_unpoison(const volatile void *a, size_t size)
1076*03ce13f7SAndroid Build Coastguard Worker 		auto voidTy = llvm::Type::getVoidTy(*jit->context);
1077*03ce13f7SAndroid Build Coastguard Worker 		auto voidPtrTy = voidTy->getPointerTo();
1078*03ce13f7SAndroid Build Coastguard Worker 		auto sizetTy = llvm::IntegerType::get(*jit->context, sizeof(size_t) * 8);
1079*03ce13f7SAndroid Build Coastguard Worker 		auto funcTy = llvm::FunctionType::get(voidTy, { voidPtrTy, sizetTy }, false);
1080*03ce13f7SAndroid Build Coastguard Worker 		auto func = jit->module->getOrInsertFunction("__msan_unpoison", funcTy);
1081*03ce13f7SAndroid Build Coastguard Worker 		auto size = jit->module->getDataLayout().getTypeStoreSize(llvm::cast<llvm::VectorType>(elVecTy)->getElementType());
1082*03ce13f7SAndroid Build Coastguard Worker 
1083*03ce13f7SAndroid Build Coastguard Worker 		for(unsigned i = 0; i < numEls; i++)
1084*03ce13f7SAndroid Build Coastguard Worker 		{
1085*03ce13f7SAndroid Build Coastguard Worker 			// Check mask for this element
1086*03ce13f7SAndroid Build Coastguard Worker 			auto idx = llvm::ConstantInt::get(i32Ty, i);
1087*03ce13f7SAndroid Build Coastguard Worker 			auto thenBlock = llvm::BasicBlock::Create(*jit->context, "", jit->function);
1088*03ce13f7SAndroid Build Coastguard Worker 			auto mergeBlock = llvm::BasicBlock::Create(*jit->context, "", jit->function);
1089*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->CreateCondBr(jit->builder->CreateExtractElement(i1Mask, idx), thenBlock, mergeBlock);
1090*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->SetInsertPoint(thenBlock);
1091*03ce13f7SAndroid Build Coastguard Worker 
1092*03ce13f7SAndroid Build Coastguard Worker 			// Insert __msan_unpoison call in conditional block
1093*03ce13f7SAndroid Build Coastguard Worker 			auto elPtr = jit->builder->CreateGEP(elVecTy, V(ptr), idx);
1094*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->CreateCall(func, { jit->builder->CreatePointerCast(elPtr, voidPtrTy),
1095*03ce13f7SAndroid Build Coastguard Worker 			                                 llvm::ConstantInt::get(sizetTy, size) });
1096*03ce13f7SAndroid Build Coastguard Worker 
1097*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->CreateBr(mergeBlock);
1098*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->SetInsertPoint(mergeBlock);
1099*03ce13f7SAndroid Build Coastguard Worker 		}
1100*03ce13f7SAndroid Build Coastguard Worker 	}
1101*03ce13f7SAndroid Build Coastguard Worker }
1102*03ce13f7SAndroid Build Coastguard Worker 
createGather(llvm::Value * base,llvm::Type * elTy,llvm::Value * offsets,llvm::Value * mask,unsigned int alignment,bool zeroMaskedLanes)1103*03ce13f7SAndroid Build Coastguard Worker static llvm::Value *createGather(llvm::Value *base, llvm::Type *elTy, llvm::Value *offsets, llvm::Value *mask, unsigned int alignment, bool zeroMaskedLanes)
1104*03ce13f7SAndroid Build Coastguard Worker {
1105*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(base->getType()->isPointerTy());
1106*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(offsets->getType()->isVectorTy());
1107*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(mask->getType()->isVectorTy());
1108*03ce13f7SAndroid Build Coastguard Worker 
1109*03ce13f7SAndroid Build Coastguard Worker 	auto numEls = llvm::cast<llvm::FixedVectorType>(mask->getType())->getNumElements();
1110*03ce13f7SAndroid Build Coastguard Worker 	auto i1Ty = llvm::Type::getInt1Ty(*jit->context);
1111*03ce13f7SAndroid Build Coastguard Worker 	auto i32Ty = llvm::Type::getInt32Ty(*jit->context);
1112*03ce13f7SAndroid Build Coastguard Worker 	auto i8Ty = llvm::Type::getInt8Ty(*jit->context);
1113*03ce13f7SAndroid Build Coastguard Worker 	auto i8PtrTy = i8Ty->getPointerTo();
1114*03ce13f7SAndroid Build Coastguard Worker 	auto elPtrTy = elTy->getPointerTo();
1115*03ce13f7SAndroid Build Coastguard Worker 	auto elVecTy = llvm::VectorType::get(elTy, numEls, false);
1116*03ce13f7SAndroid Build Coastguard Worker 	auto elPtrVecTy = llvm::VectorType::get(elPtrTy, numEls, false);
1117*03ce13f7SAndroid Build Coastguard Worker 	auto i8Base = jit->builder->CreatePointerCast(base, i8PtrTy);
1118*03ce13f7SAndroid Build Coastguard Worker 	auto i8Ptrs = jit->builder->CreateGEP(i8Ty, i8Base, offsets);
1119*03ce13f7SAndroid Build Coastguard Worker 	auto elPtrs = jit->builder->CreatePointerCast(i8Ptrs, elPtrVecTy);
1120*03ce13f7SAndroid Build Coastguard Worker 	auto i1Mask = jit->builder->CreateIntCast(mask, llvm::VectorType::get(i1Ty, numEls, false), false);  // vec<int, int, ...> -> vec<bool, bool, ...>
1121*03ce13f7SAndroid Build Coastguard Worker 	auto passthrough = zeroMaskedLanes ? llvm::Constant::getNullValue(elVecTy) : llvm::UndefValue::get(elVecTy);
1122*03ce13f7SAndroid Build Coastguard Worker 
1123*03ce13f7SAndroid Build Coastguard Worker 	if(!__has_feature(memory_sanitizer))
1124*03ce13f7SAndroid Build Coastguard Worker 	{
1125*03ce13f7SAndroid Build Coastguard Worker 		auto align = llvm::ConstantInt::get(i32Ty, alignment);
1126*03ce13f7SAndroid Build Coastguard Worker 		auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::masked_gather, { elVecTy, elPtrVecTy });
1127*03ce13f7SAndroid Build Coastguard Worker 		return jit->builder->CreateCall(func, { elPtrs, align, i1Mask, passthrough });
1128*03ce13f7SAndroid Build Coastguard Worker 	}
1129*03ce13f7SAndroid Build Coastguard Worker 	else  // __has_feature(memory_sanitizer)
1130*03ce13f7SAndroid Build Coastguard Worker 	{
1131*03ce13f7SAndroid Build Coastguard Worker 		// MemorySanitizer currently does not support instrumenting llvm::Intrinsic::masked_gather
1132*03ce13f7SAndroid Build Coastguard Worker 		// Work around it by emulating gather with element-wise loads.
1133*03ce13f7SAndroid Build Coastguard Worker 		// TODO(b/172238865): Remove when supported by MemorySanitizer.
1134*03ce13f7SAndroid Build Coastguard Worker 
1135*03ce13f7SAndroid Build Coastguard Worker 		Value *result = Nucleus::allocateStackVariable(T(elVecTy));
1136*03ce13f7SAndroid Build Coastguard Worker 		Nucleus::createStore(V(passthrough), result, T(elVecTy));
1137*03ce13f7SAndroid Build Coastguard Worker 
1138*03ce13f7SAndroid Build Coastguard Worker 		for(unsigned i = 0; i < numEls; i++)
1139*03ce13f7SAndroid Build Coastguard Worker 		{
1140*03ce13f7SAndroid Build Coastguard Worker 			// Check mask for this element
1141*03ce13f7SAndroid Build Coastguard Worker 			Value *elementMask = Nucleus::createExtractElement(V(i1Mask), T(i1Ty), i);
1142*03ce13f7SAndroid Build Coastguard Worker 
1143*03ce13f7SAndroid Build Coastguard Worker 			If(RValue<Bool>(elementMask))
1144*03ce13f7SAndroid Build Coastguard Worker 			{
1145*03ce13f7SAndroid Build Coastguard Worker 				Value *elPtr = Nucleus::createExtractElement(V(elPtrs), T(elPtrTy), i);
1146*03ce13f7SAndroid Build Coastguard Worker 				Value *el = Nucleus::createLoad(elPtr, T(elTy), /*isVolatile */ false, alignment, /* atomic */ false, std::memory_order_relaxed);
1147*03ce13f7SAndroid Build Coastguard Worker 
1148*03ce13f7SAndroid Build Coastguard Worker 				Value *v = Nucleus::createLoad(result, T(elVecTy));
1149*03ce13f7SAndroid Build Coastguard Worker 				v = Nucleus::createInsertElement(v, el, i);
1150*03ce13f7SAndroid Build Coastguard Worker 				Nucleus::createStore(v, result, T(elVecTy));
1151*03ce13f7SAndroid Build Coastguard Worker 			}
1152*03ce13f7SAndroid Build Coastguard Worker 		}
1153*03ce13f7SAndroid Build Coastguard Worker 
1154*03ce13f7SAndroid Build Coastguard Worker 		return V(Nucleus::createLoad(result, T(elVecTy)));
1155*03ce13f7SAndroid Build Coastguard Worker 	}
1156*03ce13f7SAndroid Build Coastguard Worker }
1157*03ce13f7SAndroid Build Coastguard Worker 
Gather(RValue<Pointer<Float>> base,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment,bool zeroMaskedLanes)1158*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 */)
1159*03ce13f7SAndroid Build Coastguard Worker {
1160*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Float>(V(createGather(V(base.value()), T(Float::type()), V(offsets.value()), V(mask.value()), alignment, zeroMaskedLanes)));
1161*03ce13f7SAndroid Build Coastguard Worker }
1162*03ce13f7SAndroid Build Coastguard Worker 
Gather(RValue<Pointer<Int>> base,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment,bool zeroMaskedLanes)1163*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 */)
1164*03ce13f7SAndroid Build Coastguard Worker {
1165*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Int>(V(createGather(V(base.value()), T(Int::type()), V(offsets.value()), V(mask.value()), alignment, zeroMaskedLanes)));
1166*03ce13f7SAndroid Build Coastguard Worker }
1167*03ce13f7SAndroid Build Coastguard Worker 
createScatter(llvm::Value * base,llvm::Value * val,llvm::Value * offsets,llvm::Value * mask,unsigned int alignment)1168*03ce13f7SAndroid Build Coastguard Worker static void createScatter(llvm::Value *base, llvm::Value *val, llvm::Value *offsets, llvm::Value *mask, unsigned int alignment)
1169*03ce13f7SAndroid Build Coastguard Worker {
1170*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(base->getType()->isPointerTy());
1171*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(val->getType()->isVectorTy());
1172*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(offsets->getType()->isVectorTy());
1173*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(mask->getType()->isVectorTy());
1174*03ce13f7SAndroid Build Coastguard Worker 
1175*03ce13f7SAndroid Build Coastguard Worker 	auto numEls = llvm::cast<llvm::FixedVectorType>(mask->getType())->getNumElements();
1176*03ce13f7SAndroid Build Coastguard Worker 	auto i1Ty = llvm::Type::getInt1Ty(*jit->context);
1177*03ce13f7SAndroid Build Coastguard Worker 	auto i32Ty = llvm::Type::getInt32Ty(*jit->context);
1178*03ce13f7SAndroid Build Coastguard Worker 	auto i8Ty = llvm::Type::getInt8Ty(*jit->context);
1179*03ce13f7SAndroid Build Coastguard Worker 	auto i8PtrTy = i8Ty->getPointerTo();
1180*03ce13f7SAndroid Build Coastguard Worker 	auto elVecTy = val->getType();
1181*03ce13f7SAndroid Build Coastguard Worker 	auto elTy = llvm::cast<llvm::VectorType>(elVecTy)->getElementType();
1182*03ce13f7SAndroid Build Coastguard Worker 	auto elPtrTy = elTy->getPointerTo();
1183*03ce13f7SAndroid Build Coastguard Worker 	auto elPtrVecTy = llvm::VectorType::get(elPtrTy, numEls, false);
1184*03ce13f7SAndroid Build Coastguard Worker 
1185*03ce13f7SAndroid Build Coastguard Worker 	auto i8Base = jit->builder->CreatePointerCast(base, i8PtrTy);
1186*03ce13f7SAndroid Build Coastguard Worker 	auto i8Ptrs = jit->builder->CreateGEP(i8Ty, i8Base, offsets);
1187*03ce13f7SAndroid Build Coastguard Worker 	auto elPtrs = jit->builder->CreatePointerCast(i8Ptrs, elPtrVecTy);
1188*03ce13f7SAndroid Build Coastguard Worker 	auto i1Mask = jit->builder->CreateIntCast(mask, llvm::VectorType::get(i1Ty, numEls, false), false);  // vec<int, int, ...> -> vec<bool, bool, ...>
1189*03ce13f7SAndroid Build Coastguard Worker 
1190*03ce13f7SAndroid Build Coastguard Worker 	if(!__has_feature(memory_sanitizer))
1191*03ce13f7SAndroid Build Coastguard Worker 	{
1192*03ce13f7SAndroid Build Coastguard Worker 		auto align = llvm::ConstantInt::get(i32Ty, alignment);
1193*03ce13f7SAndroid Build Coastguard Worker 		auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::masked_scatter, { elVecTy, elPtrVecTy });
1194*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateCall(func, { val, elPtrs, align, i1Mask });
1195*03ce13f7SAndroid Build Coastguard Worker 	}
1196*03ce13f7SAndroid Build Coastguard Worker 	else  // __has_feature(memory_sanitizer)
1197*03ce13f7SAndroid Build Coastguard Worker 	{
1198*03ce13f7SAndroid Build Coastguard Worker 		// MemorySanitizer currently does not support instrumenting llvm::Intrinsic::masked_scatter
1199*03ce13f7SAndroid Build Coastguard Worker 		// Work around it by emulating scatter with element-wise stores.
1200*03ce13f7SAndroid Build Coastguard Worker 		// TODO(b/172238865): Remove when supported by MemorySanitizer.
1201*03ce13f7SAndroid Build Coastguard Worker 
1202*03ce13f7SAndroid Build Coastguard Worker 		for(unsigned i = 0; i < numEls; i++)
1203*03ce13f7SAndroid Build Coastguard Worker 		{
1204*03ce13f7SAndroid Build Coastguard Worker 			// Check mask for this element
1205*03ce13f7SAndroid Build Coastguard Worker 			auto idx = llvm::ConstantInt::get(i32Ty, i);
1206*03ce13f7SAndroid Build Coastguard Worker 			auto thenBlock = llvm::BasicBlock::Create(*jit->context, "", jit->function);
1207*03ce13f7SAndroid Build Coastguard Worker 			auto mergeBlock = llvm::BasicBlock::Create(*jit->context, "", jit->function);
1208*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->CreateCondBr(jit->builder->CreateExtractElement(i1Mask, idx), thenBlock, mergeBlock);
1209*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->SetInsertPoint(thenBlock);
1210*03ce13f7SAndroid Build Coastguard Worker 
1211*03ce13f7SAndroid Build Coastguard Worker 			auto el = jit->builder->CreateExtractElement(val, idx);
1212*03ce13f7SAndroid Build Coastguard Worker 			auto elPtr = jit->builder->CreateExtractElement(elPtrs, idx);
1213*03ce13f7SAndroid Build Coastguard Worker 			Nucleus::createStore(V(el), V(elPtr), T(elTy), /*isVolatile */ false, alignment, /* atomic */ false, std::memory_order_relaxed);
1214*03ce13f7SAndroid Build Coastguard Worker 
1215*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->CreateBr(mergeBlock);
1216*03ce13f7SAndroid Build Coastguard Worker 			jit->builder->SetInsertPoint(mergeBlock);
1217*03ce13f7SAndroid Build Coastguard Worker 		}
1218*03ce13f7SAndroid Build Coastguard Worker 	}
1219*03ce13f7SAndroid Build Coastguard Worker }
1220*03ce13f7SAndroid Build Coastguard Worker 
Scatter(RValue<Pointer<Float>> base,RValue<SIMD::Float> val,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment)1221*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)
1222*03ce13f7SAndroid Build Coastguard Worker {
1223*03ce13f7SAndroid Build Coastguard Worker 	return createScatter(V(base.value()), V(val.value()), V(offsets.value()), V(mask.value()), alignment);
1224*03ce13f7SAndroid Build Coastguard Worker }
1225*03ce13f7SAndroid Build Coastguard Worker 
Scatter(RValue<Pointer<Int>> base,RValue<SIMD::Int> val,RValue<SIMD::Int> offsets,RValue<SIMD::Int> mask,unsigned int alignment)1226*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)
1227*03ce13f7SAndroid Build Coastguard Worker {
1228*03ce13f7SAndroid Build Coastguard Worker 	return createScatter(V(base.value()), V(val.value()), V(offsets.value()), V(mask.value()), alignment);
1229*03ce13f7SAndroid Build Coastguard Worker }
1230*03ce13f7SAndroid Build Coastguard Worker 
createFence(std::memory_order memoryOrder)1231*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createFence(std::memory_order memoryOrder)
1232*03ce13f7SAndroid Build Coastguard Worker {
1233*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1234*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateFence(atomicOrdering(true, memoryOrder));
1235*03ce13f7SAndroid Build Coastguard Worker }
1236*03ce13f7SAndroid Build Coastguard Worker 
createGEP(Value * ptr,Type * type,Value * index,bool unsignedIndex)1237*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex)
1238*03ce13f7SAndroid Build Coastguard Worker {
1239*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1240*03ce13f7SAndroid Build Coastguard Worker 
1241*03ce13f7SAndroid Build Coastguard Worker 	if(sizeof(void *) == 8)
1242*03ce13f7SAndroid Build Coastguard Worker 	{
1243*03ce13f7SAndroid Build Coastguard Worker 		// LLVM manual: "When indexing into an array, pointer or vector,
1244*03ce13f7SAndroid Build Coastguard Worker 		// integers of any width are allowed, and they are not required to
1245*03ce13f7SAndroid Build Coastguard Worker 		// be constant. These integers are treated as signed values where
1246*03ce13f7SAndroid Build Coastguard Worker 		// relevant."
1247*03ce13f7SAndroid Build Coastguard Worker 		//
1248*03ce13f7SAndroid Build Coastguard Worker 		// Thus if we want indexes to be treated as unsigned we have to
1249*03ce13f7SAndroid Build Coastguard Worker 		// zero-extend them ourselves.
1250*03ce13f7SAndroid Build Coastguard Worker 		//
1251*03ce13f7SAndroid Build Coastguard Worker 		// Note that this is not because we want to address anywhere near
1252*03ce13f7SAndroid Build Coastguard Worker 		// 4 GB of data. Instead this is important for performance because
1253*03ce13f7SAndroid Build Coastguard Worker 		// x86 supports automatic zero-extending of 32-bit registers to
1254*03ce13f7SAndroid Build Coastguard Worker 		// 64-bit. Thus when indexing into an array using a uint32 is
1255*03ce13f7SAndroid Build Coastguard Worker 		// actually faster than an int32.
1256*03ce13f7SAndroid Build Coastguard Worker 		index = unsignedIndex ? createZExt(index, Long::type()) : createSExt(index, Long::type());
1257*03ce13f7SAndroid Build Coastguard Worker 	}
1258*03ce13f7SAndroid Build Coastguard Worker 
1259*03ce13f7SAndroid Build Coastguard Worker 	// For non-emulated types we can rely on LLVM's GEP to calculate the
1260*03ce13f7SAndroid Build Coastguard Worker 	// effective address correctly.
1261*03ce13f7SAndroid Build Coastguard Worker 	if(asInternalType(type) == Type_LLVM)
1262*03ce13f7SAndroid Build Coastguard Worker 	{
1263*03ce13f7SAndroid Build Coastguard Worker 		return V(jit->builder->CreateGEP(T(type), V(ptr), V(index)));
1264*03ce13f7SAndroid Build Coastguard Worker 	}
1265*03ce13f7SAndroid Build Coastguard Worker 
1266*03ce13f7SAndroid Build Coastguard Worker 	// For emulated types we have to multiply the index by the intended
1267*03ce13f7SAndroid Build Coastguard Worker 	// type size ourselves to obain the byte offset.
1268*03ce13f7SAndroid Build Coastguard Worker 	index = (sizeof(void *) == 8) ? createMul(index, createConstantLong((int64_t)typeSize(type))) : createMul(index, createConstantInt((int)typeSize(type)));
1269*03ce13f7SAndroid Build Coastguard Worker 
1270*03ce13f7SAndroid Build Coastguard Worker 	// Cast to a byte pointer, apply the byte offset, and cast back to the
1271*03ce13f7SAndroid Build Coastguard Worker 	// original pointer type.
1272*03ce13f7SAndroid Build Coastguard Worker 	return createBitCast(
1273*03ce13f7SAndroid Build Coastguard Worker 	    V(jit->builder->CreateGEP(T(Byte::type()), V(createBitCast(ptr, T(llvm::PointerType::get(T(Byte::type()), 0)))), V(index))),
1274*03ce13f7SAndroid Build Coastguard Worker 	    T(llvm::PointerType::get(T(type), 0)));
1275*03ce13f7SAndroid Build Coastguard Worker }
1276*03ce13f7SAndroid Build Coastguard Worker 
createAtomicAdd(Value * ptr,Value * value,std::memory_order memoryOrder)1277*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicAdd(Value *ptr, Value *value, std::memory_order memoryOrder)
1278*03ce13f7SAndroid Build Coastguard Worker {
1279*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1280*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::Add, V(ptr), V(value),
1281*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1282*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1283*03ce13f7SAndroid Build Coastguard Worker #endif
1284*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1285*03ce13f7SAndroid Build Coastguard Worker }
1286*03ce13f7SAndroid Build Coastguard Worker 
createAtomicSub(Value * ptr,Value * value,std::memory_order memoryOrder)1287*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicSub(Value *ptr, Value *value, std::memory_order memoryOrder)
1288*03ce13f7SAndroid Build Coastguard Worker {
1289*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1290*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::Sub, V(ptr), V(value),
1291*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1292*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1293*03ce13f7SAndroid Build Coastguard Worker #endif
1294*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1295*03ce13f7SAndroid Build Coastguard Worker }
1296*03ce13f7SAndroid Build Coastguard Worker 
createAtomicAnd(Value * ptr,Value * value,std::memory_order memoryOrder)1297*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicAnd(Value *ptr, Value *value, std::memory_order memoryOrder)
1298*03ce13f7SAndroid Build Coastguard Worker {
1299*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1300*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::And, V(ptr), V(value),
1301*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1302*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1303*03ce13f7SAndroid Build Coastguard Worker #endif
1304*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1305*03ce13f7SAndroid Build Coastguard Worker }
1306*03ce13f7SAndroid Build Coastguard Worker 
createAtomicOr(Value * ptr,Value * value,std::memory_order memoryOrder)1307*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicOr(Value *ptr, Value *value, std::memory_order memoryOrder)
1308*03ce13f7SAndroid Build Coastguard Worker {
1309*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1310*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::Or, V(ptr), V(value),
1311*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1312*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1313*03ce13f7SAndroid Build Coastguard Worker #endif
1314*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1315*03ce13f7SAndroid Build Coastguard Worker }
1316*03ce13f7SAndroid Build Coastguard Worker 
createAtomicXor(Value * ptr,Value * value,std::memory_order memoryOrder)1317*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicXor(Value *ptr, Value *value, std::memory_order memoryOrder)
1318*03ce13f7SAndroid Build Coastguard Worker {
1319*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1320*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::Xor, V(ptr), V(value),
1321*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1322*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1323*03ce13f7SAndroid Build Coastguard Worker #endif
1324*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1325*03ce13f7SAndroid Build Coastguard Worker }
1326*03ce13f7SAndroid Build Coastguard Worker 
createAtomicMin(Value * ptr,Value * value,std::memory_order memoryOrder)1327*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicMin(Value *ptr, Value *value, std::memory_order memoryOrder)
1328*03ce13f7SAndroid Build Coastguard Worker {
1329*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1330*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::Min, V(ptr), V(value),
1331*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1332*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1333*03ce13f7SAndroid Build Coastguard Worker #endif
1334*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1335*03ce13f7SAndroid Build Coastguard Worker }
1336*03ce13f7SAndroid Build Coastguard Worker 
createAtomicMax(Value * ptr,Value * value,std::memory_order memoryOrder)1337*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicMax(Value *ptr, Value *value, std::memory_order memoryOrder)
1338*03ce13f7SAndroid Build Coastguard Worker {
1339*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1340*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::Max, V(ptr), V(value),
1341*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1342*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1343*03ce13f7SAndroid Build Coastguard Worker #endif
1344*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1345*03ce13f7SAndroid Build Coastguard Worker }
1346*03ce13f7SAndroid Build Coastguard Worker 
createAtomicUMin(Value * ptr,Value * value,std::memory_order memoryOrder)1347*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicUMin(Value *ptr, Value *value, std::memory_order memoryOrder)
1348*03ce13f7SAndroid Build Coastguard Worker {
1349*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1350*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::UMin, V(ptr), V(value),
1351*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1352*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1353*03ce13f7SAndroid Build Coastguard Worker #endif
1354*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1355*03ce13f7SAndroid Build Coastguard Worker }
1356*03ce13f7SAndroid Build Coastguard Worker 
createAtomicUMax(Value * ptr,Value * value,std::memory_order memoryOrder)1357*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicUMax(Value *ptr, Value *value, std::memory_order memoryOrder)
1358*03ce13f7SAndroid Build Coastguard Worker {
1359*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1360*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::UMax, V(ptr), V(value),
1361*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1362*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1363*03ce13f7SAndroid Build Coastguard Worker #endif
1364*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1365*03ce13f7SAndroid Build Coastguard Worker }
1366*03ce13f7SAndroid Build Coastguard Worker 
createAtomicExchange(Value * ptr,Value * value,std::memory_order memoryOrder)1367*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicExchange(Value *ptr, Value *value, std::memory_order memoryOrder)
1368*03ce13f7SAndroid Build Coastguard Worker {
1369*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1370*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, V(ptr), V(value),
1371*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1372*03ce13f7SAndroid Build Coastguard Worker 	                                       llvm::MaybeAlign(),
1373*03ce13f7SAndroid Build Coastguard Worker #endif
1374*03ce13f7SAndroid Build Coastguard Worker 	                                       atomicOrdering(true, memoryOrder)));
1375*03ce13f7SAndroid Build Coastguard Worker }
1376*03ce13f7SAndroid Build Coastguard Worker 
createAtomicCompareExchange(Value * ptr,Value * value,Value * compare,std::memory_order memoryOrderEqual,std::memory_order memoryOrderUnequal)1377*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createAtomicCompareExchange(Value *ptr, Value *value, Value *compare, std::memory_order memoryOrderEqual, std::memory_order memoryOrderUnequal)
1378*03ce13f7SAndroid Build Coastguard Worker {
1379*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1380*03ce13f7SAndroid Build Coastguard Worker 	// Note: AtomicCmpXchgInstruction returns a 2-member struct containing {result, success-flag}, not the result directly.
1381*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateExtractValue(
1382*03ce13f7SAndroid Build Coastguard Worker 	    jit->builder->CreateAtomicCmpXchg(V(ptr), V(compare), V(value),
1383*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
1384*03ce13f7SAndroid Build Coastguard Worker 	                                      llvm::MaybeAlign(),
1385*03ce13f7SAndroid Build Coastguard Worker #endif
1386*03ce13f7SAndroid Build Coastguard Worker 	                                      atomicOrdering(true, memoryOrderEqual),
1387*03ce13f7SAndroid Build Coastguard Worker 	                                      atomicOrdering(true, memoryOrderUnequal)),
1388*03ce13f7SAndroid Build Coastguard Worker 	    llvm::ArrayRef<unsigned>(0u)));
1389*03ce13f7SAndroid Build Coastguard Worker }
1390*03ce13f7SAndroid Build Coastguard Worker 
createTrunc(Value * v,Type * destType)1391*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createTrunc(Value *v, Type *destType)
1392*03ce13f7SAndroid Build Coastguard Worker {
1393*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1394*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateTrunc(V(v), T(destType)));
1395*03ce13f7SAndroid Build Coastguard Worker }
1396*03ce13f7SAndroid Build Coastguard Worker 
createZExt(Value * v,Type * destType)1397*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createZExt(Value *v, Type *destType)
1398*03ce13f7SAndroid Build Coastguard Worker {
1399*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1400*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateZExt(V(v), T(destType)));
1401*03ce13f7SAndroid Build Coastguard Worker }
1402*03ce13f7SAndroid Build Coastguard Worker 
createSExt(Value * v,Type * destType)1403*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSExt(Value *v, Type *destType)
1404*03ce13f7SAndroid Build Coastguard Worker {
1405*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1406*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateSExt(V(v), T(destType)));
1407*03ce13f7SAndroid Build Coastguard Worker }
1408*03ce13f7SAndroid Build Coastguard Worker 
createFPToUI(Value * v,Type * destType)1409*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFPToUI(Value *v, Type *destType)
1410*03ce13f7SAndroid Build Coastguard Worker {
1411*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1412*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFPToUI(V(v), T(destType)));
1413*03ce13f7SAndroid Build Coastguard Worker }
1414*03ce13f7SAndroid Build Coastguard Worker 
createFPToSI(Value * v,Type * destType)1415*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFPToSI(Value *v, Type *destType)
1416*03ce13f7SAndroid Build Coastguard Worker {
1417*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1418*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFPToSI(V(v), T(destType)));
1419*03ce13f7SAndroid Build Coastguard Worker }
1420*03ce13f7SAndroid Build Coastguard Worker 
createSIToFP(Value * v,Type * destType)1421*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSIToFP(Value *v, Type *destType)
1422*03ce13f7SAndroid Build Coastguard Worker {
1423*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1424*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateSIToFP(V(v), T(destType)));
1425*03ce13f7SAndroid Build Coastguard Worker }
1426*03ce13f7SAndroid Build Coastguard Worker 
createFPTrunc(Value * v,Type * destType)1427*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFPTrunc(Value *v, Type *destType)
1428*03ce13f7SAndroid Build Coastguard Worker {
1429*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1430*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFPTrunc(V(v), T(destType)));
1431*03ce13f7SAndroid Build Coastguard Worker }
1432*03ce13f7SAndroid Build Coastguard Worker 
createFPExt(Value * v,Type * destType)1433*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFPExt(Value *v, Type *destType)
1434*03ce13f7SAndroid Build Coastguard Worker {
1435*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1436*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFPExt(V(v), T(destType)));
1437*03ce13f7SAndroid Build Coastguard Worker }
1438*03ce13f7SAndroid Build Coastguard Worker 
createBitCast(Value * v,Type * destType)1439*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createBitCast(Value *v, Type *destType)
1440*03ce13f7SAndroid Build Coastguard Worker {
1441*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1442*03ce13f7SAndroid Build Coastguard Worker 	// Bitcasts must be between types of the same logical size. But with emulated narrow vectors we need
1443*03ce13f7SAndroid Build Coastguard Worker 	// support for casting between scalars and wide vectors. Emulate them by writing to the stack and
1444*03ce13f7SAndroid Build Coastguard Worker 	// reading back as the destination type.
1445*03ce13f7SAndroid Build Coastguard Worker 	if(!V(v)->getType()->isVectorTy() && T(destType)->isVectorTy())
1446*03ce13f7SAndroid Build Coastguard Worker 	{
1447*03ce13f7SAndroid Build Coastguard Worker 		Value *readAddress = allocateStackVariable(destType);
1448*03ce13f7SAndroid Build Coastguard Worker 		Value *writeAddress = createBitCast(readAddress, T(llvm::PointerType::get(V(v)->getType(), 0)));
1449*03ce13f7SAndroid Build Coastguard Worker 		createStore(v, writeAddress, T(V(v)->getType()));
1450*03ce13f7SAndroid Build Coastguard Worker 		return createLoad(readAddress, destType);
1451*03ce13f7SAndroid Build Coastguard Worker 	}
1452*03ce13f7SAndroid Build Coastguard Worker 	else if(V(v)->getType()->isVectorTy() && !T(destType)->isVectorTy())
1453*03ce13f7SAndroid Build Coastguard Worker 	{
1454*03ce13f7SAndroid Build Coastguard Worker 		Value *writeAddress = allocateStackVariable(T(V(v)->getType()));
1455*03ce13f7SAndroid Build Coastguard Worker 		createStore(v, writeAddress, T(V(v)->getType()));
1456*03ce13f7SAndroid Build Coastguard Worker 		Value *readAddress = createBitCast(writeAddress, T(llvm::PointerType::get(T(destType), 0)));
1457*03ce13f7SAndroid Build Coastguard Worker 		return createLoad(readAddress, destType);
1458*03ce13f7SAndroid Build Coastguard Worker 	}
1459*03ce13f7SAndroid Build Coastguard Worker 
1460*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateBitCast(V(v), T(destType)));
1461*03ce13f7SAndroid Build Coastguard Worker }
1462*03ce13f7SAndroid Build Coastguard Worker 
createICmpEQ(Value * lhs,Value * rhs)1463*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpEQ(Value *lhs, Value *rhs)
1464*03ce13f7SAndroid Build Coastguard Worker {
1465*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1466*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpEQ(V(lhs), V(rhs)));
1467*03ce13f7SAndroid Build Coastguard Worker }
1468*03ce13f7SAndroid Build Coastguard Worker 
createICmpNE(Value * lhs,Value * rhs)1469*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpNE(Value *lhs, Value *rhs)
1470*03ce13f7SAndroid Build Coastguard Worker {
1471*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1472*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpNE(V(lhs), V(rhs)));
1473*03ce13f7SAndroid Build Coastguard Worker }
1474*03ce13f7SAndroid Build Coastguard Worker 
createICmpUGT(Value * lhs,Value * rhs)1475*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpUGT(Value *lhs, Value *rhs)
1476*03ce13f7SAndroid Build Coastguard Worker {
1477*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1478*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpUGT(V(lhs), V(rhs)));
1479*03ce13f7SAndroid Build Coastguard Worker }
1480*03ce13f7SAndroid Build Coastguard Worker 
createICmpUGE(Value * lhs,Value * rhs)1481*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpUGE(Value *lhs, Value *rhs)
1482*03ce13f7SAndroid Build Coastguard Worker {
1483*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1484*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpUGE(V(lhs), V(rhs)));
1485*03ce13f7SAndroid Build Coastguard Worker }
1486*03ce13f7SAndroid Build Coastguard Worker 
createICmpULT(Value * lhs,Value * rhs)1487*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpULT(Value *lhs, Value *rhs)
1488*03ce13f7SAndroid Build Coastguard Worker {
1489*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1490*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpULT(V(lhs), V(rhs)));
1491*03ce13f7SAndroid Build Coastguard Worker }
1492*03ce13f7SAndroid Build Coastguard Worker 
createICmpULE(Value * lhs,Value * rhs)1493*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpULE(Value *lhs, Value *rhs)
1494*03ce13f7SAndroid Build Coastguard Worker {
1495*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1496*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpULE(V(lhs), V(rhs)));
1497*03ce13f7SAndroid Build Coastguard Worker }
1498*03ce13f7SAndroid Build Coastguard Worker 
createICmpSGT(Value * lhs,Value * rhs)1499*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpSGT(Value *lhs, Value *rhs)
1500*03ce13f7SAndroid Build Coastguard Worker {
1501*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1502*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpSGT(V(lhs), V(rhs)));
1503*03ce13f7SAndroid Build Coastguard Worker }
1504*03ce13f7SAndroid Build Coastguard Worker 
createICmpSGE(Value * lhs,Value * rhs)1505*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpSGE(Value *lhs, Value *rhs)
1506*03ce13f7SAndroid Build Coastguard Worker {
1507*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1508*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpSGE(V(lhs), V(rhs)));
1509*03ce13f7SAndroid Build Coastguard Worker }
1510*03ce13f7SAndroid Build Coastguard Worker 
createICmpSLT(Value * lhs,Value * rhs)1511*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpSLT(Value *lhs, Value *rhs)
1512*03ce13f7SAndroid Build Coastguard Worker {
1513*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1514*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpSLT(V(lhs), V(rhs)));
1515*03ce13f7SAndroid Build Coastguard Worker }
1516*03ce13f7SAndroid Build Coastguard Worker 
createICmpSLE(Value * lhs,Value * rhs)1517*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createICmpSLE(Value *lhs, Value *rhs)
1518*03ce13f7SAndroid Build Coastguard Worker {
1519*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1520*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateICmpSLE(V(lhs), V(rhs)));
1521*03ce13f7SAndroid Build Coastguard Worker }
1522*03ce13f7SAndroid Build Coastguard Worker 
createFCmpOEQ(Value * lhs,Value * rhs)1523*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOEQ(Value *lhs, Value *rhs)
1524*03ce13f7SAndroid Build Coastguard Worker {
1525*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1526*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpOEQ(V(lhs), V(rhs)));
1527*03ce13f7SAndroid Build Coastguard Worker }
1528*03ce13f7SAndroid Build Coastguard Worker 
createFCmpOGT(Value * lhs,Value * rhs)1529*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOGT(Value *lhs, Value *rhs)
1530*03ce13f7SAndroid Build Coastguard Worker {
1531*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1532*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpOGT(V(lhs), V(rhs)));
1533*03ce13f7SAndroid Build Coastguard Worker }
1534*03ce13f7SAndroid Build Coastguard Worker 
createFCmpOGE(Value * lhs,Value * rhs)1535*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOGE(Value *lhs, Value *rhs)
1536*03ce13f7SAndroid Build Coastguard Worker {
1537*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1538*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpOGE(V(lhs), V(rhs)));
1539*03ce13f7SAndroid Build Coastguard Worker }
1540*03ce13f7SAndroid Build Coastguard Worker 
createFCmpOLT(Value * lhs,Value * rhs)1541*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOLT(Value *lhs, Value *rhs)
1542*03ce13f7SAndroid Build Coastguard Worker {
1543*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1544*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpOLT(V(lhs), V(rhs)));
1545*03ce13f7SAndroid Build Coastguard Worker }
1546*03ce13f7SAndroid Build Coastguard Worker 
createFCmpOLE(Value * lhs,Value * rhs)1547*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpOLE(Value *lhs, Value *rhs)
1548*03ce13f7SAndroid Build Coastguard Worker {
1549*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1550*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpOLE(V(lhs), V(rhs)));
1551*03ce13f7SAndroid Build Coastguard Worker }
1552*03ce13f7SAndroid Build Coastguard Worker 
createFCmpONE(Value * lhs,Value * rhs)1553*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpONE(Value *lhs, Value *rhs)
1554*03ce13f7SAndroid Build Coastguard Worker {
1555*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1556*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpONE(V(lhs), V(rhs)));
1557*03ce13f7SAndroid Build Coastguard Worker }
1558*03ce13f7SAndroid Build Coastguard Worker 
createFCmpORD(Value * lhs,Value * rhs)1559*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpORD(Value *lhs, Value *rhs)
1560*03ce13f7SAndroid Build Coastguard Worker {
1561*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1562*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpORD(V(lhs), V(rhs)));
1563*03ce13f7SAndroid Build Coastguard Worker }
1564*03ce13f7SAndroid Build Coastguard Worker 
createFCmpUNO(Value * lhs,Value * rhs)1565*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUNO(Value *lhs, Value *rhs)
1566*03ce13f7SAndroid Build Coastguard Worker {
1567*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1568*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpUNO(V(lhs), V(rhs)));
1569*03ce13f7SAndroid Build Coastguard Worker }
1570*03ce13f7SAndroid Build Coastguard Worker 
createFCmpUEQ(Value * lhs,Value * rhs)1571*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUEQ(Value *lhs, Value *rhs)
1572*03ce13f7SAndroid Build Coastguard Worker {
1573*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1574*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpUEQ(V(lhs), V(rhs)));
1575*03ce13f7SAndroid Build Coastguard Worker }
1576*03ce13f7SAndroid Build Coastguard Worker 
createFCmpUGT(Value * lhs,Value * rhs)1577*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUGT(Value *lhs, Value *rhs)
1578*03ce13f7SAndroid Build Coastguard Worker {
1579*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1580*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpUGT(V(lhs), V(rhs)));
1581*03ce13f7SAndroid Build Coastguard Worker }
1582*03ce13f7SAndroid Build Coastguard Worker 
createFCmpUGE(Value * lhs,Value * rhs)1583*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUGE(Value *lhs, Value *rhs)
1584*03ce13f7SAndroid Build Coastguard Worker {
1585*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1586*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpUGE(V(lhs), V(rhs)));
1587*03ce13f7SAndroid Build Coastguard Worker }
1588*03ce13f7SAndroid Build Coastguard Worker 
createFCmpULT(Value * lhs,Value * rhs)1589*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpULT(Value *lhs, Value *rhs)
1590*03ce13f7SAndroid Build Coastguard Worker {
1591*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1592*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpULT(V(lhs), V(rhs)));
1593*03ce13f7SAndroid Build Coastguard Worker }
1594*03ce13f7SAndroid Build Coastguard Worker 
createFCmpULE(Value * lhs,Value * rhs)1595*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpULE(Value *lhs, Value *rhs)
1596*03ce13f7SAndroid Build Coastguard Worker {
1597*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1598*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpULE(V(lhs), V(rhs)));
1599*03ce13f7SAndroid Build Coastguard Worker }
1600*03ce13f7SAndroid Build Coastguard Worker 
createFCmpUNE(Value * lhs,Value * rhs)1601*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createFCmpUNE(Value *lhs, Value *rhs)
1602*03ce13f7SAndroid Build Coastguard Worker {
1603*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1604*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateFCmpUNE(V(lhs), V(rhs)));
1605*03ce13f7SAndroid Build Coastguard Worker }
1606*03ce13f7SAndroid Build Coastguard Worker 
createExtractElement(Value * vector,Type * type,int index)1607*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createExtractElement(Value *vector, Type *type, int index)
1608*03ce13f7SAndroid Build Coastguard Worker {
1609*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1610*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(V(vector)->getType()->getContainedType(0) == T(type));
1611*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateExtractElement(V(vector), V(createConstantInt(index))));
1612*03ce13f7SAndroid Build Coastguard Worker }
1613*03ce13f7SAndroid Build Coastguard Worker 
createInsertElement(Value * vector,Value * element,int index)1614*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createInsertElement(Value *vector, Value *element, int index)
1615*03ce13f7SAndroid Build Coastguard Worker {
1616*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1617*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateInsertElement(V(vector), V(element), V(createConstantInt(index))));
1618*03ce13f7SAndroid Build Coastguard Worker }
1619*03ce13f7SAndroid Build Coastguard Worker 
createShuffleVector(Value * v1,Value * v2,std::vector<int> select)1620*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createShuffleVector(Value *v1, Value *v2, std::vector<int> select)
1621*03ce13f7SAndroid Build Coastguard Worker {
1622*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1623*03ce13f7SAndroid Build Coastguard Worker 
1624*03ce13f7SAndroid Build Coastguard Worker 	size_t size = llvm::cast<llvm::FixedVectorType>(V(v1)->getType())->getNumElements();
1625*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(size == llvm::cast<llvm::FixedVectorType>(V(v2)->getType())->getNumElements());
1626*03ce13f7SAndroid Build Coastguard Worker 
1627*03ce13f7SAndroid Build Coastguard Worker 	llvm::SmallVector<int, 16> mask;
1628*03ce13f7SAndroid Build Coastguard Worker 	const size_t selectSize = select.size();
1629*03ce13f7SAndroid Build Coastguard Worker 	for(size_t i = 0; i < size; i++)
1630*03ce13f7SAndroid Build Coastguard Worker 	{
1631*03ce13f7SAndroid Build Coastguard Worker 		mask.push_back(select[i % selectSize]);
1632*03ce13f7SAndroid Build Coastguard Worker 	}
1633*03ce13f7SAndroid Build Coastguard Worker 
1634*03ce13f7SAndroid Build Coastguard Worker 	return V(lowerShuffleVector(V(v1), V(v2), mask));
1635*03ce13f7SAndroid Build Coastguard Worker }
1636*03ce13f7SAndroid Build Coastguard Worker 
createSelect(Value * c,Value * ifTrue,Value * ifFalse)1637*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createSelect(Value *c, Value *ifTrue, Value *ifFalse)
1638*03ce13f7SAndroid Build Coastguard Worker {
1639*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1640*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateSelect(V(c), V(ifTrue), V(ifFalse)));
1641*03ce13f7SAndroid Build Coastguard Worker }
1642*03ce13f7SAndroid Build Coastguard Worker 
createSwitch(Value * control,BasicBlock * defaultBranch,unsigned numCases)1643*03ce13f7SAndroid Build Coastguard Worker SwitchCases *Nucleus::createSwitch(Value *control, BasicBlock *defaultBranch, unsigned numCases)
1644*03ce13f7SAndroid Build Coastguard Worker {
1645*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1646*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<SwitchCases *>(jit->builder->CreateSwitch(V(control), B(defaultBranch), numCases));
1647*03ce13f7SAndroid Build Coastguard Worker }
1648*03ce13f7SAndroid Build Coastguard Worker 
addSwitchCase(SwitchCases * switchCases,int label,BasicBlock * branch)1649*03ce13f7SAndroid Build Coastguard Worker void Nucleus::addSwitchCase(SwitchCases *switchCases, int label, BasicBlock *branch)
1650*03ce13f7SAndroid Build Coastguard Worker {
1651*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1652*03ce13f7SAndroid Build Coastguard Worker 	llvm::SwitchInst *sw = reinterpret_cast<llvm::SwitchInst *>(switchCases);
1653*03ce13f7SAndroid Build Coastguard Worker 	sw->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*jit->context), label, true), B(branch));
1654*03ce13f7SAndroid Build Coastguard Worker }
1655*03ce13f7SAndroid Build Coastguard Worker 
createUnreachable()1656*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createUnreachable()
1657*03ce13f7SAndroid Build Coastguard Worker {
1658*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1659*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateUnreachable();
1660*03ce13f7SAndroid Build Coastguard Worker }
1661*03ce13f7SAndroid Build Coastguard Worker 
getType(Value * value)1662*03ce13f7SAndroid Build Coastguard Worker Type *Nucleus::getType(Value *value)
1663*03ce13f7SAndroid Build Coastguard Worker {
1664*03ce13f7SAndroid Build Coastguard Worker 	return T(V(value)->getType());
1665*03ce13f7SAndroid Build Coastguard Worker }
1666*03ce13f7SAndroid Build Coastguard Worker 
getContainedType(Type * vectorType)1667*03ce13f7SAndroid Build Coastguard Worker Type *Nucleus::getContainedType(Type *vectorType)
1668*03ce13f7SAndroid Build Coastguard Worker {
1669*03ce13f7SAndroid Build Coastguard Worker 	return T(T(vectorType)->getContainedType(0));
1670*03ce13f7SAndroid Build Coastguard Worker }
1671*03ce13f7SAndroid Build Coastguard Worker 
getPointerType(Type * ElementType)1672*03ce13f7SAndroid Build Coastguard Worker Type *Nucleus::getPointerType(Type *ElementType)
1673*03ce13f7SAndroid Build Coastguard Worker {
1674*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::PointerType::get(T(ElementType), 0));
1675*03ce13f7SAndroid Build Coastguard Worker }
1676*03ce13f7SAndroid Build Coastguard Worker 
getNaturalIntType()1677*03ce13f7SAndroid Build Coastguard Worker static llvm::Type *getNaturalIntType()
1678*03ce13f7SAndroid Build Coastguard Worker {
1679*03ce13f7SAndroid Build Coastguard Worker 	return llvm::Type::getIntNTy(*jit->context, sizeof(int) * 8);
1680*03ce13f7SAndroid Build Coastguard Worker }
1681*03ce13f7SAndroid Build Coastguard Worker 
getPrintfStorageType(Type * valueType)1682*03ce13f7SAndroid Build Coastguard Worker Type *Nucleus::getPrintfStorageType(Type *valueType)
1683*03ce13f7SAndroid Build Coastguard Worker {
1684*03ce13f7SAndroid Build Coastguard Worker 	llvm::Type *valueTy = T(valueType);
1685*03ce13f7SAndroid Build Coastguard Worker 	if(valueTy->isIntegerTy())
1686*03ce13f7SAndroid Build Coastguard Worker 	{
1687*03ce13f7SAndroid Build Coastguard Worker 		return T(getNaturalIntType());
1688*03ce13f7SAndroid Build Coastguard Worker 	}
1689*03ce13f7SAndroid Build Coastguard Worker 	if(valueTy->isFloatTy())
1690*03ce13f7SAndroid Build Coastguard Worker 	{
1691*03ce13f7SAndroid Build Coastguard Worker 		return T(llvm::Type::getDoubleTy(*jit->context));
1692*03ce13f7SAndroid Build Coastguard Worker 	}
1693*03ce13f7SAndroid Build Coastguard Worker 
1694*03ce13f7SAndroid Build Coastguard Worker 	UNIMPLEMENTED_NO_BUG("getPrintfStorageType: add more cases as needed");
1695*03ce13f7SAndroid Build Coastguard Worker 	return {};
1696*03ce13f7SAndroid Build Coastguard Worker }
1697*03ce13f7SAndroid Build Coastguard Worker 
createNullValue(Type * Ty)1698*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createNullValue(Type *Ty)
1699*03ce13f7SAndroid Build Coastguard Worker {
1700*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1701*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::Constant::getNullValue(T(Ty)));
1702*03ce13f7SAndroid Build Coastguard Worker }
1703*03ce13f7SAndroid Build Coastguard Worker 
createConstantLong(int64_t i)1704*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantLong(int64_t i)
1705*03ce13f7SAndroid Build Coastguard Worker {
1706*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1707*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantInt::get(llvm::Type::getInt64Ty(*jit->context), i, true));
1708*03ce13f7SAndroid Build Coastguard Worker }
1709*03ce13f7SAndroid Build Coastguard Worker 
createConstantInt(int i)1710*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantInt(int i)
1711*03ce13f7SAndroid Build Coastguard Worker {
1712*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1713*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*jit->context), i, true));
1714*03ce13f7SAndroid Build Coastguard Worker }
1715*03ce13f7SAndroid Build Coastguard Worker 
createConstantInt(unsigned int i)1716*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantInt(unsigned int i)
1717*03ce13f7SAndroid Build Coastguard Worker {
1718*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1719*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*jit->context), i, false));
1720*03ce13f7SAndroid Build Coastguard Worker }
1721*03ce13f7SAndroid Build Coastguard Worker 
createConstantBool(bool b)1722*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantBool(bool b)
1723*03ce13f7SAndroid Build Coastguard Worker {
1724*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1725*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantInt::get(llvm::Type::getInt1Ty(*jit->context), b));
1726*03ce13f7SAndroid Build Coastguard Worker }
1727*03ce13f7SAndroid Build Coastguard Worker 
createConstantByte(signed char i)1728*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantByte(signed char i)
1729*03ce13f7SAndroid Build Coastguard Worker {
1730*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1731*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantInt::get(llvm::Type::getInt8Ty(*jit->context), i, true));
1732*03ce13f7SAndroid Build Coastguard Worker }
1733*03ce13f7SAndroid Build Coastguard Worker 
createConstantByte(unsigned char i)1734*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantByte(unsigned char i)
1735*03ce13f7SAndroid Build Coastguard Worker {
1736*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1737*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantInt::get(llvm::Type::getInt8Ty(*jit->context), i, false));
1738*03ce13f7SAndroid Build Coastguard Worker }
1739*03ce13f7SAndroid Build Coastguard Worker 
createConstantShort(short i)1740*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantShort(short i)
1741*03ce13f7SAndroid Build Coastguard Worker {
1742*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1743*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantInt::get(llvm::Type::getInt16Ty(*jit->context), i, true));
1744*03ce13f7SAndroid Build Coastguard Worker }
1745*03ce13f7SAndroid Build Coastguard Worker 
createConstantShort(unsigned short i)1746*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantShort(unsigned short i)
1747*03ce13f7SAndroid Build Coastguard Worker {
1748*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1749*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantInt::get(llvm::Type::getInt16Ty(*jit->context), i, false));
1750*03ce13f7SAndroid Build Coastguard Worker }
1751*03ce13f7SAndroid Build Coastguard Worker 
createConstantFloat(float x)1752*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantFloat(float x)
1753*03ce13f7SAndroid Build Coastguard Worker {
1754*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1755*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantFP::get(T(Float::type()), x));
1756*03ce13f7SAndroid Build Coastguard Worker }
1757*03ce13f7SAndroid Build Coastguard Worker 
createNullPointer(Type * Ty)1758*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createNullPointer(Type *Ty)
1759*03ce13f7SAndroid Build Coastguard Worker {
1760*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1761*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantPointerNull::get(llvm::PointerType::get(T(Ty), 0)));
1762*03ce13f7SAndroid Build Coastguard Worker }
1763*03ce13f7SAndroid Build Coastguard Worker 
createConstantVector(std::vector<int64_t> constants,Type * type)1764*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantVector(std::vector<int64_t> constants, Type *type)
1765*03ce13f7SAndroid Build Coastguard Worker {
1766*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1767*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(llvm::isa<llvm::VectorType>(T(type)));
1768*03ce13f7SAndroid Build Coastguard Worker 	const size_t numConstants = constants.size();                                             // Number of provided constants for the (emulated) type.
1769*03ce13f7SAndroid Build Coastguard Worker 	const size_t numElements = llvm::cast<llvm::FixedVectorType>(T(type))->getNumElements();  // Number of elements of the underlying vector type.
1770*03ce13f7SAndroid Build Coastguard Worker 	llvm::SmallVector<llvm::Constant *, 16> constantVector;
1771*03ce13f7SAndroid Build Coastguard Worker 
1772*03ce13f7SAndroid Build Coastguard Worker 	for(size_t i = 0; i < numElements; i++)
1773*03ce13f7SAndroid Build Coastguard Worker 	{
1774*03ce13f7SAndroid Build Coastguard Worker 		constantVector.push_back(llvm::ConstantInt::get(T(type)->getContainedType(0), constants[i % numConstants]));
1775*03ce13f7SAndroid Build Coastguard Worker 	}
1776*03ce13f7SAndroid Build Coastguard Worker 
1777*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant *>(constantVector)));
1778*03ce13f7SAndroid Build Coastguard Worker }
1779*03ce13f7SAndroid Build Coastguard Worker 
createConstantVector(std::vector<double> constants,Type * type)1780*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantVector(std::vector<double> constants, Type *type)
1781*03ce13f7SAndroid Build Coastguard Worker {
1782*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1783*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(llvm::isa<llvm::VectorType>(T(type)));
1784*03ce13f7SAndroid Build Coastguard Worker 	const size_t numConstants = constants.size();                                             // Number of provided constants for the (emulated) type.
1785*03ce13f7SAndroid Build Coastguard Worker 	const size_t numElements = llvm::cast<llvm::FixedVectorType>(T(type))->getNumElements();  // Number of elements of the underlying vector type.
1786*03ce13f7SAndroid Build Coastguard Worker 	llvm::SmallVector<llvm::Constant *, 16> constantVector;
1787*03ce13f7SAndroid Build Coastguard Worker 
1788*03ce13f7SAndroid Build Coastguard Worker 	for(size_t i = 0; i < numElements; i++)
1789*03ce13f7SAndroid Build Coastguard Worker 	{
1790*03ce13f7SAndroid Build Coastguard Worker 		constantVector.push_back(llvm::ConstantFP::get(T(type)->getContainedType(0), constants[i % numConstants]));
1791*03ce13f7SAndroid Build Coastguard Worker 	}
1792*03ce13f7SAndroid Build Coastguard Worker 
1793*03ce13f7SAndroid Build Coastguard Worker 	return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant *>(constantVector)));
1794*03ce13f7SAndroid Build Coastguard Worker }
1795*03ce13f7SAndroid Build Coastguard Worker 
createConstantString(const char * v)1796*03ce13f7SAndroid Build Coastguard Worker Value *Nucleus::createConstantString(const char *v)
1797*03ce13f7SAndroid Build Coastguard Worker {
1798*03ce13f7SAndroid Build Coastguard Worker 	// NOTE: Do not call RR_DEBUG_INFO_UPDATE_LOC() here to avoid recursion when called from rr::Printv
1799*03ce13f7SAndroid Build Coastguard Worker 	auto ptr = jit->builder->CreateGlobalStringPtr(v);
1800*03ce13f7SAndroid Build Coastguard Worker 	return V(ptr);
1801*03ce13f7SAndroid Build Coastguard Worker }
1802*03ce13f7SAndroid Build Coastguard Worker 
setOptimizerCallback(OptimizerCallback * callback)1803*03ce13f7SAndroid Build Coastguard Worker void Nucleus::setOptimizerCallback(OptimizerCallback *callback)
1804*03ce13f7SAndroid Build Coastguard Worker {
1805*03ce13f7SAndroid Build Coastguard Worker 	// The LLVM backend does not produce optimizer reports.
1806*03ce13f7SAndroid Build Coastguard Worker 	(void)callback;
1807*03ce13f7SAndroid Build Coastguard Worker }
1808*03ce13f7SAndroid Build Coastguard Worker 
type()1809*03ce13f7SAndroid Build Coastguard Worker Type *Void::type()
1810*03ce13f7SAndroid Build Coastguard Worker {
1811*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getVoidTy(*jit->context));
1812*03ce13f7SAndroid Build Coastguard Worker }
1813*03ce13f7SAndroid Build Coastguard Worker 
type()1814*03ce13f7SAndroid Build Coastguard Worker Type *Bool::type()
1815*03ce13f7SAndroid Build Coastguard Worker {
1816*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt1Ty(*jit->context));
1817*03ce13f7SAndroid Build Coastguard Worker }
1818*03ce13f7SAndroid Build Coastguard Worker 
type()1819*03ce13f7SAndroid Build Coastguard Worker Type *Byte::type()
1820*03ce13f7SAndroid Build Coastguard Worker {
1821*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt8Ty(*jit->context));
1822*03ce13f7SAndroid Build Coastguard Worker }
1823*03ce13f7SAndroid Build Coastguard Worker 
type()1824*03ce13f7SAndroid Build Coastguard Worker Type *SByte::type()
1825*03ce13f7SAndroid Build Coastguard Worker {
1826*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt8Ty(*jit->context));
1827*03ce13f7SAndroid Build Coastguard Worker }
1828*03ce13f7SAndroid Build Coastguard Worker 
type()1829*03ce13f7SAndroid Build Coastguard Worker Type *Short::type()
1830*03ce13f7SAndroid Build Coastguard Worker {
1831*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt16Ty(*jit->context));
1832*03ce13f7SAndroid Build Coastguard Worker }
1833*03ce13f7SAndroid Build Coastguard Worker 
type()1834*03ce13f7SAndroid Build Coastguard Worker Type *UShort::type()
1835*03ce13f7SAndroid Build Coastguard Worker {
1836*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt16Ty(*jit->context));
1837*03ce13f7SAndroid Build Coastguard Worker }
1838*03ce13f7SAndroid Build Coastguard Worker 
type()1839*03ce13f7SAndroid Build Coastguard Worker Type *Byte4::type()
1840*03ce13f7SAndroid Build Coastguard Worker {
1841*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v4i8);
1842*03ce13f7SAndroid Build Coastguard Worker }
1843*03ce13f7SAndroid Build Coastguard Worker 
type()1844*03ce13f7SAndroid Build Coastguard Worker Type *SByte4::type()
1845*03ce13f7SAndroid Build Coastguard Worker {
1846*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v4i8);
1847*03ce13f7SAndroid Build Coastguard Worker }
1848*03ce13f7SAndroid Build Coastguard Worker 
AddSat(RValue<Byte8> x,RValue<Byte8> y)1849*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> AddSat(RValue<Byte8> x, RValue<Byte8> y)
1850*03ce13f7SAndroid Build Coastguard Worker {
1851*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1852*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1853*03ce13f7SAndroid Build Coastguard Worker 	return x86::paddusb(x, y);
1854*03ce13f7SAndroid Build Coastguard Worker #else
1855*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPUADDSAT(V(x.value()), V(y.value()))));
1856*03ce13f7SAndroid Build Coastguard Worker #endif
1857*03ce13f7SAndroid Build Coastguard Worker }
1858*03ce13f7SAndroid Build Coastguard Worker 
SubSat(RValue<Byte8> x,RValue<Byte8> y)1859*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> SubSat(RValue<Byte8> x, RValue<Byte8> y)
1860*03ce13f7SAndroid Build Coastguard Worker {
1861*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1862*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1863*03ce13f7SAndroid Build Coastguard Worker 	return x86::psubusb(x, y);
1864*03ce13f7SAndroid Build Coastguard Worker #else
1865*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPUSUBSAT(V(x.value()), V(y.value()))));
1866*03ce13f7SAndroid Build Coastguard Worker #endif
1867*03ce13f7SAndroid Build Coastguard Worker }
1868*03ce13f7SAndroid Build Coastguard Worker 
SignMask(RValue<Byte8> x)1869*03ce13f7SAndroid Build Coastguard Worker RValue<Int> SignMask(RValue<Byte8> x)
1870*03ce13f7SAndroid Build Coastguard Worker {
1871*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1872*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1873*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmovmskb(x);
1874*03ce13f7SAndroid Build Coastguard Worker #else
1875*03ce13f7SAndroid Build Coastguard Worker 	return As<Int>(V(lowerSignMask(V(x.value()), T(Int::type()))));
1876*03ce13f7SAndroid Build Coastguard Worker #endif
1877*03ce13f7SAndroid Build Coastguard Worker }
1878*03ce13f7SAndroid Build Coastguard Worker 
1879*03ce13f7SAndroid Build Coastguard Worker //	RValue<Byte8> CmpGT(RValue<Byte8> x, RValue<Byte8> y)
1880*03ce13f7SAndroid Build Coastguard Worker //	{
1881*03ce13f7SAndroid Build Coastguard Worker //#if defined(__i386__) || defined(__x86_64__)
1882*03ce13f7SAndroid Build Coastguard Worker //		return x86::pcmpgtb(x, y);   // FIXME: Signedness
1883*03ce13f7SAndroid Build Coastguard Worker //#else
1884*03ce13f7SAndroid Build Coastguard Worker //		return As<Byte8>(V(lowerPCMP(llvm::ICmpInst::ICMP_SGT, V(x.value()), V(y.value()), T(Byte8::type()))));
1885*03ce13f7SAndroid Build Coastguard Worker //#endif
1886*03ce13f7SAndroid Build Coastguard Worker //	}
1887*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<Byte8> x,RValue<Byte8> y)1888*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> CmpEQ(RValue<Byte8> x, RValue<Byte8> y)
1889*03ce13f7SAndroid Build Coastguard Worker {
1890*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1891*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1892*03ce13f7SAndroid Build Coastguard Worker 	return x86::pcmpeqb(x, y);
1893*03ce13f7SAndroid Build Coastguard Worker #else
1894*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPCMP(llvm::ICmpInst::ICMP_EQ, V(x.value()), V(y.value()), T(Byte8::type()))));
1895*03ce13f7SAndroid Build Coastguard Worker #endif
1896*03ce13f7SAndroid Build Coastguard Worker }
1897*03ce13f7SAndroid Build Coastguard Worker 
type()1898*03ce13f7SAndroid Build Coastguard Worker Type *Byte8::type()
1899*03ce13f7SAndroid Build Coastguard Worker {
1900*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v8i8);
1901*03ce13f7SAndroid Build Coastguard Worker }
1902*03ce13f7SAndroid Build Coastguard Worker 
AddSat(RValue<SByte8> x,RValue<SByte8> y)1903*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> AddSat(RValue<SByte8> x, RValue<SByte8> y)
1904*03ce13f7SAndroid Build Coastguard Worker {
1905*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1906*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1907*03ce13f7SAndroid Build Coastguard Worker 	return x86::paddsb(x, y);
1908*03ce13f7SAndroid Build Coastguard Worker #else
1909*03ce13f7SAndroid Build Coastguard Worker 	return As<SByte8>(V(lowerPSADDSAT(V(x.value()), V(y.value()))));
1910*03ce13f7SAndroid Build Coastguard Worker #endif
1911*03ce13f7SAndroid Build Coastguard Worker }
1912*03ce13f7SAndroid Build Coastguard Worker 
SubSat(RValue<SByte8> x,RValue<SByte8> y)1913*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> SubSat(RValue<SByte8> x, RValue<SByte8> y)
1914*03ce13f7SAndroid Build Coastguard Worker {
1915*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1916*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1917*03ce13f7SAndroid Build Coastguard Worker 	return x86::psubsb(x, y);
1918*03ce13f7SAndroid Build Coastguard Worker #else
1919*03ce13f7SAndroid Build Coastguard Worker 	return As<SByte8>(V(lowerPSSUBSAT(V(x.value()), V(y.value()))));
1920*03ce13f7SAndroid Build Coastguard Worker #endif
1921*03ce13f7SAndroid Build Coastguard Worker }
1922*03ce13f7SAndroid Build Coastguard Worker 
SignMask(RValue<SByte8> x)1923*03ce13f7SAndroid Build Coastguard Worker RValue<Int> SignMask(RValue<SByte8> x)
1924*03ce13f7SAndroid Build Coastguard Worker {
1925*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1926*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1927*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmovmskb(As<Byte8>(x));
1928*03ce13f7SAndroid Build Coastguard Worker #else
1929*03ce13f7SAndroid Build Coastguard Worker 	return As<Int>(V(lowerSignMask(V(x.value()), T(Int::type()))));
1930*03ce13f7SAndroid Build Coastguard Worker #endif
1931*03ce13f7SAndroid Build Coastguard Worker }
1932*03ce13f7SAndroid Build Coastguard Worker 
CmpGT(RValue<SByte8> x,RValue<SByte8> y)1933*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> CmpGT(RValue<SByte8> x, RValue<SByte8> y)
1934*03ce13f7SAndroid Build Coastguard Worker {
1935*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1936*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1937*03ce13f7SAndroid Build Coastguard Worker 	return x86::pcmpgtb(x, y);
1938*03ce13f7SAndroid Build Coastguard Worker #else
1939*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPCMP(llvm::ICmpInst::ICMP_SGT, V(x.value()), V(y.value()), T(Byte8::type()))));
1940*03ce13f7SAndroid Build Coastguard Worker #endif
1941*03ce13f7SAndroid Build Coastguard Worker }
1942*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<SByte8> x,RValue<SByte8> y)1943*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> CmpEQ(RValue<SByte8> x, RValue<SByte8> y)
1944*03ce13f7SAndroid Build Coastguard Worker {
1945*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1946*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1947*03ce13f7SAndroid Build Coastguard Worker 	return x86::pcmpeqb(As<Byte8>(x), As<Byte8>(y));
1948*03ce13f7SAndroid Build Coastguard Worker #else
1949*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPCMP(llvm::ICmpInst::ICMP_EQ, V(x.value()), V(y.value()), T(Byte8::type()))));
1950*03ce13f7SAndroid Build Coastguard Worker #endif
1951*03ce13f7SAndroid Build Coastguard Worker }
1952*03ce13f7SAndroid Build Coastguard Worker 
type()1953*03ce13f7SAndroid Build Coastguard Worker Type *SByte8::type()
1954*03ce13f7SAndroid Build Coastguard Worker {
1955*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v8i8);
1956*03ce13f7SAndroid Build Coastguard Worker }
1957*03ce13f7SAndroid Build Coastguard Worker 
type()1958*03ce13f7SAndroid Build Coastguard Worker Type *Byte16::type()
1959*03ce13f7SAndroid Build Coastguard Worker {
1960*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(Byte::type()), 16, false));
1961*03ce13f7SAndroid Build Coastguard Worker }
1962*03ce13f7SAndroid Build Coastguard Worker 
type()1963*03ce13f7SAndroid Build Coastguard Worker Type *SByte16::type()
1964*03ce13f7SAndroid Build Coastguard Worker {
1965*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(SByte::type()), 16, false));
1966*03ce13f7SAndroid Build Coastguard Worker }
1967*03ce13f7SAndroid Build Coastguard Worker 
type()1968*03ce13f7SAndroid Build Coastguard Worker Type *Short2::type()
1969*03ce13f7SAndroid Build Coastguard Worker {
1970*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v2i16);
1971*03ce13f7SAndroid Build Coastguard Worker }
1972*03ce13f7SAndroid Build Coastguard Worker 
type()1973*03ce13f7SAndroid Build Coastguard Worker Type *UShort2::type()
1974*03ce13f7SAndroid Build Coastguard Worker {
1975*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v2i16);
1976*03ce13f7SAndroid Build Coastguard Worker }
1977*03ce13f7SAndroid Build Coastguard Worker 
Short4(RValue<Int4> cast)1978*03ce13f7SAndroid Build Coastguard Worker Short4::Short4(RValue<Int4> cast)
1979*03ce13f7SAndroid Build Coastguard Worker {
1980*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1981*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> select = { 0, 2, 4, 6, 0, 2, 4, 6 };
1982*03ce13f7SAndroid Build Coastguard Worker 	Value *short8 = Nucleus::createBitCast(cast.value(), Short8::type());
1983*03ce13f7SAndroid Build Coastguard Worker 
1984*03ce13f7SAndroid Build Coastguard Worker 	Value *packed = Nucleus::createShuffleVector(short8, short8, select);
1985*03ce13f7SAndroid Build Coastguard Worker 	Value *short4 = As<Short4>(Int2(As<Int4>(packed))).value();
1986*03ce13f7SAndroid Build Coastguard Worker 
1987*03ce13f7SAndroid Build Coastguard Worker 	storeValue(short4);
1988*03ce13f7SAndroid Build Coastguard Worker }
1989*03ce13f7SAndroid Build Coastguard Worker 
1990*03ce13f7SAndroid Build Coastguard Worker //	Short4::Short4(RValue<Float> cast)
1991*03ce13f7SAndroid Build Coastguard Worker //	{
1992*03ce13f7SAndroid Build Coastguard Worker //	}
1993*03ce13f7SAndroid Build Coastguard Worker 
Short4(RValue<Float4> cast)1994*03ce13f7SAndroid Build Coastguard Worker Short4::Short4(RValue<Float4> cast)
1995*03ce13f7SAndroid Build Coastguard Worker {
1996*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
1997*03ce13f7SAndroid Build Coastguard Worker 	Int4 v4i32 = Int4(cast);
1998*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
1999*03ce13f7SAndroid Build Coastguard Worker 	v4i32 = As<Int4>(x86::packssdw(v4i32, v4i32));
2000*03ce13f7SAndroid Build Coastguard Worker #else
2001*03ce13f7SAndroid Build Coastguard Worker 	Value *v = v4i32.loadValue();
2002*03ce13f7SAndroid Build Coastguard Worker 	v4i32 = As<Int4>(V(lowerPack(V(v), V(v), true)));
2003*03ce13f7SAndroid Build Coastguard Worker #endif
2004*03ce13f7SAndroid Build Coastguard Worker 
2005*03ce13f7SAndroid Build Coastguard Worker 	storeValue(As<Short4>(Int2(v4i32)).value());
2006*03ce13f7SAndroid Build Coastguard Worker }
2007*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<Short4> lhs,unsigned char rhs)2008*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> operator<<(RValue<Short4> lhs, unsigned char rhs)
2009*03ce13f7SAndroid Build Coastguard Worker {
2010*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2011*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2012*03ce13f7SAndroid Build Coastguard Worker 	//	return RValue<Short4>(Nucleus::createShl(lhs.value(), rhs.value()));
2013*03ce13f7SAndroid Build Coastguard Worker 
2014*03ce13f7SAndroid Build Coastguard Worker 	return x86::psllw(lhs, rhs);
2015*03ce13f7SAndroid Build Coastguard Worker #else
2016*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerVectorShl(V(lhs.value()), rhs)));
2017*03ce13f7SAndroid Build Coastguard Worker #endif
2018*03ce13f7SAndroid Build Coastguard Worker }
2019*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<Short4> lhs,unsigned char rhs)2020*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> operator>>(RValue<Short4> lhs, unsigned char rhs)
2021*03ce13f7SAndroid Build Coastguard Worker {
2022*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2023*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2024*03ce13f7SAndroid Build Coastguard Worker 	return x86::psraw(lhs, rhs);
2025*03ce13f7SAndroid Build Coastguard Worker #else
2026*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerVectorAShr(V(lhs.value()), rhs)));
2027*03ce13f7SAndroid Build Coastguard Worker #endif
2028*03ce13f7SAndroid Build Coastguard Worker }
2029*03ce13f7SAndroid Build Coastguard Worker 
Max(RValue<Short4> x,RValue<Short4> y)2030*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> Max(RValue<Short4> x, RValue<Short4> y)
2031*03ce13f7SAndroid Build Coastguard Worker {
2032*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2033*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2034*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmaxsw(x, y);
2035*03ce13f7SAndroid Build Coastguard Worker #else
2036*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Short4>(V(lowerPMINMAX(V(x.value()), V(y.value()), llvm::ICmpInst::ICMP_SGT)));
2037*03ce13f7SAndroid Build Coastguard Worker #endif
2038*03ce13f7SAndroid Build Coastguard Worker }
2039*03ce13f7SAndroid Build Coastguard Worker 
Min(RValue<Short4> x,RValue<Short4> y)2040*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> Min(RValue<Short4> x, RValue<Short4> y)
2041*03ce13f7SAndroid Build Coastguard Worker {
2042*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2043*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2044*03ce13f7SAndroid Build Coastguard Worker 	return x86::pminsw(x, y);
2045*03ce13f7SAndroid Build Coastguard Worker #else
2046*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Short4>(V(lowerPMINMAX(V(x.value()), V(y.value()), llvm::ICmpInst::ICMP_SLT)));
2047*03ce13f7SAndroid Build Coastguard Worker #endif
2048*03ce13f7SAndroid Build Coastguard Worker }
2049*03ce13f7SAndroid Build Coastguard Worker 
AddSat(RValue<Short4> x,RValue<Short4> y)2050*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> AddSat(RValue<Short4> x, RValue<Short4> y)
2051*03ce13f7SAndroid Build Coastguard Worker {
2052*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2053*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2054*03ce13f7SAndroid Build Coastguard Worker 	return x86::paddsw(x, y);
2055*03ce13f7SAndroid Build Coastguard Worker #else
2056*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPSADDSAT(V(x.value()), V(y.value()))));
2057*03ce13f7SAndroid Build Coastguard Worker #endif
2058*03ce13f7SAndroid Build Coastguard Worker }
2059*03ce13f7SAndroid Build Coastguard Worker 
SubSat(RValue<Short4> x,RValue<Short4> y)2060*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> SubSat(RValue<Short4> x, RValue<Short4> y)
2061*03ce13f7SAndroid Build Coastguard Worker {
2062*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2063*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2064*03ce13f7SAndroid Build Coastguard Worker 	return x86::psubsw(x, y);
2065*03ce13f7SAndroid Build Coastguard Worker #else
2066*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPSSUBSAT(V(x.value()), V(y.value()))));
2067*03ce13f7SAndroid Build Coastguard Worker #endif
2068*03ce13f7SAndroid Build Coastguard Worker }
2069*03ce13f7SAndroid Build Coastguard Worker 
MulHigh(RValue<Short4> x,RValue<Short4> y)2070*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> MulHigh(RValue<Short4> x, RValue<Short4> y)
2071*03ce13f7SAndroid Build Coastguard Worker {
2072*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2073*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2074*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmulhw(x, y);
2075*03ce13f7SAndroid Build Coastguard Worker #else
2076*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerMulHigh(V(x.value()), V(y.value()), true)));
2077*03ce13f7SAndroid Build Coastguard Worker #endif
2078*03ce13f7SAndroid Build Coastguard Worker }
2079*03ce13f7SAndroid Build Coastguard Worker 
MulAdd(RValue<Short4> x,RValue<Short4> y)2080*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> MulAdd(RValue<Short4> x, RValue<Short4> y)
2081*03ce13f7SAndroid Build Coastguard Worker {
2082*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2083*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2084*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmaddwd(x, y);
2085*03ce13f7SAndroid Build Coastguard Worker #else
2086*03ce13f7SAndroid Build Coastguard Worker 	return As<Int2>(V(lowerMulAdd(V(x.value()), V(y.value()))));
2087*03ce13f7SAndroid Build Coastguard Worker #endif
2088*03ce13f7SAndroid Build Coastguard Worker }
2089*03ce13f7SAndroid Build Coastguard Worker 
PackSigned(RValue<Short4> x,RValue<Short4> y)2090*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> PackSigned(RValue<Short4> x, RValue<Short4> y)
2091*03ce13f7SAndroid Build Coastguard Worker {
2092*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2093*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2094*03ce13f7SAndroid Build Coastguard Worker 	auto result = x86::packsswb(x, y);
2095*03ce13f7SAndroid Build Coastguard Worker #else
2096*03ce13f7SAndroid Build Coastguard Worker 	auto result = V(lowerPack(V(x.value()), V(y.value()), true));
2097*03ce13f7SAndroid Build Coastguard Worker #endif
2098*03ce13f7SAndroid Build Coastguard Worker 	return As<SByte8>(Swizzle(As<Int4>(result), 0x0202));
2099*03ce13f7SAndroid Build Coastguard Worker }
2100*03ce13f7SAndroid Build Coastguard Worker 
PackUnsigned(RValue<Short4> x,RValue<Short4> y)2101*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> PackUnsigned(RValue<Short4> x, RValue<Short4> y)
2102*03ce13f7SAndroid Build Coastguard Worker {
2103*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2104*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2105*03ce13f7SAndroid Build Coastguard Worker 	auto result = x86::packuswb(x, y);
2106*03ce13f7SAndroid Build Coastguard Worker #else
2107*03ce13f7SAndroid Build Coastguard Worker 	auto result = V(lowerPack(V(x.value()), V(y.value()), false));
2108*03ce13f7SAndroid Build Coastguard Worker #endif
2109*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(Swizzle(As<Int4>(result), 0x0202));
2110*03ce13f7SAndroid Build Coastguard Worker }
2111*03ce13f7SAndroid Build Coastguard Worker 
CmpGT(RValue<Short4> x,RValue<Short4> y)2112*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> CmpGT(RValue<Short4> x, RValue<Short4> y)
2113*03ce13f7SAndroid Build Coastguard Worker {
2114*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2115*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2116*03ce13f7SAndroid Build Coastguard Worker 	return x86::pcmpgtw(x, y);
2117*03ce13f7SAndroid Build Coastguard Worker #else
2118*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPCMP(llvm::ICmpInst::ICMP_SGT, V(x.value()), V(y.value()), T(Short4::type()))));
2119*03ce13f7SAndroid Build Coastguard Worker #endif
2120*03ce13f7SAndroid Build Coastguard Worker }
2121*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<Short4> x,RValue<Short4> y)2122*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> CmpEQ(RValue<Short4> x, RValue<Short4> y)
2123*03ce13f7SAndroid Build Coastguard Worker {
2124*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2125*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2126*03ce13f7SAndroid Build Coastguard Worker 	return x86::pcmpeqw(x, y);
2127*03ce13f7SAndroid Build Coastguard Worker #else
2128*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPCMP(llvm::ICmpInst::ICMP_EQ, V(x.value()), V(y.value()), T(Short4::type()))));
2129*03ce13f7SAndroid Build Coastguard Worker #endif
2130*03ce13f7SAndroid Build Coastguard Worker }
2131*03ce13f7SAndroid Build Coastguard Worker 
type()2132*03ce13f7SAndroid Build Coastguard Worker Type *Short4::type()
2133*03ce13f7SAndroid Build Coastguard Worker {
2134*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v4i16);
2135*03ce13f7SAndroid Build Coastguard Worker }
2136*03ce13f7SAndroid Build Coastguard Worker 
UShort4(RValue<Float4> cast,bool saturate)2137*03ce13f7SAndroid Build Coastguard Worker UShort4::UShort4(RValue<Float4> cast, bool saturate)
2138*03ce13f7SAndroid Build Coastguard Worker {
2139*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2140*03ce13f7SAndroid Build Coastguard Worker 	if(saturate)
2141*03ce13f7SAndroid Build Coastguard Worker 	{
2142*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2143*03ce13f7SAndroid Build Coastguard Worker 		if(CPUID::supportsSSE4_1())
2144*03ce13f7SAndroid Build Coastguard Worker 		{
2145*03ce13f7SAndroid Build Coastguard Worker 			Int4 int4(Min(cast, Float4(0xFFFF)));  // packusdw takes care of 0x0000 saturation
2146*03ce13f7SAndroid Build Coastguard Worker 			*this = As<Short4>(PackUnsigned(int4, int4));
2147*03ce13f7SAndroid Build Coastguard Worker 		}
2148*03ce13f7SAndroid Build Coastguard Worker 		else
2149*03ce13f7SAndroid Build Coastguard Worker #endif
2150*03ce13f7SAndroid Build Coastguard Worker 		{
2151*03ce13f7SAndroid Build Coastguard Worker 			*this = Short4(Int4(Max(Min(cast, Float4(0xFFFF)), Float4(0x0000))));
2152*03ce13f7SAndroid Build Coastguard Worker 		}
2153*03ce13f7SAndroid Build Coastguard Worker 	}
2154*03ce13f7SAndroid Build Coastguard Worker 	else
2155*03ce13f7SAndroid Build Coastguard Worker 	{
2156*03ce13f7SAndroid Build Coastguard Worker 		*this = Short4(Int4(cast));
2157*03ce13f7SAndroid Build Coastguard Worker 	}
2158*03ce13f7SAndroid Build Coastguard Worker }
2159*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<UShort4> lhs,unsigned char rhs)2160*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> operator<<(RValue<UShort4> lhs, unsigned char rhs)
2161*03ce13f7SAndroid Build Coastguard Worker {
2162*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2163*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2164*03ce13f7SAndroid Build Coastguard Worker 	//	return RValue<Short4>(Nucleus::createShl(lhs.value(), rhs.value()));
2165*03ce13f7SAndroid Build Coastguard Worker 
2166*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(x86::psllw(As<Short4>(lhs), rhs));
2167*03ce13f7SAndroid Build Coastguard Worker #else
2168*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerVectorShl(V(lhs.value()), rhs)));
2169*03ce13f7SAndroid Build Coastguard Worker #endif
2170*03ce13f7SAndroid Build Coastguard Worker }
2171*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<UShort4> lhs,unsigned char rhs)2172*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> operator>>(RValue<UShort4> lhs, unsigned char rhs)
2173*03ce13f7SAndroid Build Coastguard Worker {
2174*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2175*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2176*03ce13f7SAndroid Build Coastguard Worker 	//	return RValue<Short4>(Nucleus::createLShr(lhs.value(), rhs.value()));
2177*03ce13f7SAndroid Build Coastguard Worker 
2178*03ce13f7SAndroid Build Coastguard Worker 	return x86::psrlw(lhs, rhs);
2179*03ce13f7SAndroid Build Coastguard Worker #else
2180*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerVectorLShr(V(lhs.value()), rhs)));
2181*03ce13f7SAndroid Build Coastguard Worker #endif
2182*03ce13f7SAndroid Build Coastguard Worker }
2183*03ce13f7SAndroid Build Coastguard Worker 
Max(RValue<UShort4> x,RValue<UShort4> y)2184*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> Max(RValue<UShort4> x, RValue<UShort4> y)
2185*03ce13f7SAndroid Build Coastguard Worker {
2186*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2187*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UShort4>(Max(As<Short4>(x) - Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u), As<Short4>(y) - Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u)) + Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u));
2188*03ce13f7SAndroid Build Coastguard Worker }
2189*03ce13f7SAndroid Build Coastguard Worker 
Min(RValue<UShort4> x,RValue<UShort4> y)2190*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> Min(RValue<UShort4> x, RValue<UShort4> y)
2191*03ce13f7SAndroid Build Coastguard Worker {
2192*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2193*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UShort4>(Min(As<Short4>(x) - Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u), As<Short4>(y) - Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u)) + Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u));
2194*03ce13f7SAndroid Build Coastguard Worker }
2195*03ce13f7SAndroid Build Coastguard Worker 
AddSat(RValue<UShort4> x,RValue<UShort4> y)2196*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> AddSat(RValue<UShort4> x, RValue<UShort4> y)
2197*03ce13f7SAndroid Build Coastguard Worker {
2198*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2199*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2200*03ce13f7SAndroid Build Coastguard Worker 	return x86::paddusw(x, y);
2201*03ce13f7SAndroid Build Coastguard Worker #else
2202*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerPUADDSAT(V(x.value()), V(y.value()))));
2203*03ce13f7SAndroid Build Coastguard Worker #endif
2204*03ce13f7SAndroid Build Coastguard Worker }
2205*03ce13f7SAndroid Build Coastguard Worker 
SubSat(RValue<UShort4> x,RValue<UShort4> y)2206*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> SubSat(RValue<UShort4> x, RValue<UShort4> y)
2207*03ce13f7SAndroid Build Coastguard Worker {
2208*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2209*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2210*03ce13f7SAndroid Build Coastguard Worker 	return x86::psubusw(x, y);
2211*03ce13f7SAndroid Build Coastguard Worker #else
2212*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerPUSUBSAT(V(x.value()), V(y.value()))));
2213*03ce13f7SAndroid Build Coastguard Worker #endif
2214*03ce13f7SAndroid Build Coastguard Worker }
2215*03ce13f7SAndroid Build Coastguard Worker 
MulHigh(RValue<UShort4> x,RValue<UShort4> y)2216*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> MulHigh(RValue<UShort4> x, RValue<UShort4> y)
2217*03ce13f7SAndroid Build Coastguard Worker {
2218*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2219*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2220*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmulhuw(x, y);
2221*03ce13f7SAndroid Build Coastguard Worker #else
2222*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerMulHigh(V(x.value()), V(y.value()), false)));
2223*03ce13f7SAndroid Build Coastguard Worker #endif
2224*03ce13f7SAndroid Build Coastguard Worker }
2225*03ce13f7SAndroid Build Coastguard Worker 
Average(RValue<UShort4> x,RValue<UShort4> y)2226*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> Average(RValue<UShort4> x, RValue<UShort4> y)
2227*03ce13f7SAndroid Build Coastguard Worker {
2228*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2229*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2230*03ce13f7SAndroid Build Coastguard Worker 	return x86::pavgw(x, y);
2231*03ce13f7SAndroid Build Coastguard Worker #else
2232*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerPAVG(V(x.value()), V(y.value()))));
2233*03ce13f7SAndroid Build Coastguard Worker #endif
2234*03ce13f7SAndroid Build Coastguard Worker }
2235*03ce13f7SAndroid Build Coastguard Worker 
type()2236*03ce13f7SAndroid Build Coastguard Worker Type *UShort4::type()
2237*03ce13f7SAndroid Build Coastguard Worker {
2238*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v4i16);
2239*03ce13f7SAndroid Build Coastguard Worker }
2240*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<Short8> lhs,unsigned char rhs)2241*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> operator<<(RValue<Short8> lhs, unsigned char rhs)
2242*03ce13f7SAndroid Build Coastguard Worker {
2243*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2244*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2245*03ce13f7SAndroid Build Coastguard Worker 	return x86::psllw(lhs, rhs);
2246*03ce13f7SAndroid Build Coastguard Worker #else
2247*03ce13f7SAndroid Build Coastguard Worker 	return As<Short8>(V(lowerVectorShl(V(lhs.value()), rhs)));
2248*03ce13f7SAndroid Build Coastguard Worker #endif
2249*03ce13f7SAndroid Build Coastguard Worker }
2250*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<Short8> lhs,unsigned char rhs)2251*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> operator>>(RValue<Short8> lhs, unsigned char rhs)
2252*03ce13f7SAndroid Build Coastguard Worker {
2253*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2254*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2255*03ce13f7SAndroid Build Coastguard Worker 	return x86::psraw(lhs, rhs);
2256*03ce13f7SAndroid Build Coastguard Worker #else
2257*03ce13f7SAndroid Build Coastguard Worker 	return As<Short8>(V(lowerVectorAShr(V(lhs.value()), rhs)));
2258*03ce13f7SAndroid Build Coastguard Worker #endif
2259*03ce13f7SAndroid Build Coastguard Worker }
2260*03ce13f7SAndroid Build Coastguard Worker 
MulAdd(RValue<Short8> x,RValue<Short8> y)2261*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> MulAdd(RValue<Short8> x, RValue<Short8> y)
2262*03ce13f7SAndroid Build Coastguard Worker {
2263*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2264*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2265*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmaddwd(x, y);
2266*03ce13f7SAndroid Build Coastguard Worker #else
2267*03ce13f7SAndroid Build Coastguard Worker 	return As<Int4>(V(lowerMulAdd(V(x.value()), V(y.value()))));
2268*03ce13f7SAndroid Build Coastguard Worker #endif
2269*03ce13f7SAndroid Build Coastguard Worker }
2270*03ce13f7SAndroid Build Coastguard Worker 
MulHigh(RValue<Short8> x,RValue<Short8> y)2271*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> MulHigh(RValue<Short8> x, RValue<Short8> y)
2272*03ce13f7SAndroid Build Coastguard Worker {
2273*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2274*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2275*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmulhw(x, y);
2276*03ce13f7SAndroid Build Coastguard Worker #else
2277*03ce13f7SAndroid Build Coastguard Worker 	return As<Short8>(V(lowerMulHigh(V(x.value()), V(y.value()), true)));
2278*03ce13f7SAndroid Build Coastguard Worker #endif
2279*03ce13f7SAndroid Build Coastguard Worker }
2280*03ce13f7SAndroid Build Coastguard Worker 
type()2281*03ce13f7SAndroid Build Coastguard Worker Type *Short8::type()
2282*03ce13f7SAndroid Build Coastguard Worker {
2283*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(Short::type()), 8, false));
2284*03ce13f7SAndroid Build Coastguard Worker }
2285*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<UShort8> lhs,unsigned char rhs)2286*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> operator<<(RValue<UShort8> lhs, unsigned char rhs)
2287*03ce13f7SAndroid Build Coastguard Worker {
2288*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2289*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2290*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort8>(x86::psllw(As<Short8>(lhs), rhs));
2291*03ce13f7SAndroid Build Coastguard Worker #else
2292*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort8>(V(lowerVectorShl(V(lhs.value()), rhs)));
2293*03ce13f7SAndroid Build Coastguard Worker #endif
2294*03ce13f7SAndroid Build Coastguard Worker }
2295*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<UShort8> lhs,unsigned char rhs)2296*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> operator>>(RValue<UShort8> lhs, unsigned char rhs)
2297*03ce13f7SAndroid Build Coastguard Worker {
2298*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2299*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2300*03ce13f7SAndroid Build Coastguard Worker 	return x86::psrlw(lhs, rhs);  // FIXME: Fallback required
2301*03ce13f7SAndroid Build Coastguard Worker #else
2302*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort8>(V(lowerVectorLShr(V(lhs.value()), rhs)));
2303*03ce13f7SAndroid Build Coastguard Worker #endif
2304*03ce13f7SAndroid Build Coastguard Worker }
2305*03ce13f7SAndroid Build Coastguard Worker 
MulHigh(RValue<UShort8> x,RValue<UShort8> y)2306*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> MulHigh(RValue<UShort8> x, RValue<UShort8> y)
2307*03ce13f7SAndroid Build Coastguard Worker {
2308*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2309*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2310*03ce13f7SAndroid Build Coastguard Worker 	return x86::pmulhuw(x, y);
2311*03ce13f7SAndroid Build Coastguard Worker #else
2312*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort8>(V(lowerMulHigh(V(x.value()), V(y.value()), false)));
2313*03ce13f7SAndroid Build Coastguard Worker #endif
2314*03ce13f7SAndroid Build Coastguard Worker }
2315*03ce13f7SAndroid Build Coastguard Worker 
type()2316*03ce13f7SAndroid Build Coastguard Worker Type *UShort8::type()
2317*03ce13f7SAndroid Build Coastguard Worker {
2318*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(UShort::type()), 8, false));
2319*03ce13f7SAndroid Build Coastguard Worker }
2320*03ce13f7SAndroid Build Coastguard Worker 
operator ++(Int & val,int)2321*03ce13f7SAndroid Build Coastguard Worker RValue<Int> operator++(Int &val, int)  // Post-increment
2322*03ce13f7SAndroid Build Coastguard Worker {
2323*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2324*03ce13f7SAndroid Build Coastguard Worker 	RValue<Int> res = val;
2325*03ce13f7SAndroid Build Coastguard Worker 
2326*03ce13f7SAndroid Build Coastguard Worker 	Value *inc = Nucleus::createAdd(res.value(), Nucleus::createConstantInt(1));
2327*03ce13f7SAndroid Build Coastguard Worker 	val.storeValue(inc);
2328*03ce13f7SAndroid Build Coastguard Worker 
2329*03ce13f7SAndroid Build Coastguard Worker 	return res;
2330*03ce13f7SAndroid Build Coastguard Worker }
2331*03ce13f7SAndroid Build Coastguard Worker 
operator ++(Int & val)2332*03ce13f7SAndroid Build Coastguard Worker const Int &operator++(Int &val)  // Pre-increment
2333*03ce13f7SAndroid Build Coastguard Worker {
2334*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2335*03ce13f7SAndroid Build Coastguard Worker 	Value *inc = Nucleus::createAdd(val.loadValue(), Nucleus::createConstantInt(1));
2336*03ce13f7SAndroid Build Coastguard Worker 	val.storeValue(inc);
2337*03ce13f7SAndroid Build Coastguard Worker 
2338*03ce13f7SAndroid Build Coastguard Worker 	return val;
2339*03ce13f7SAndroid Build Coastguard Worker }
2340*03ce13f7SAndroid Build Coastguard Worker 
operator --(Int & val,int)2341*03ce13f7SAndroid Build Coastguard Worker RValue<Int> operator--(Int &val, int)  // Post-decrement
2342*03ce13f7SAndroid Build Coastguard Worker {
2343*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2344*03ce13f7SAndroid Build Coastguard Worker 	RValue<Int> res = val;
2345*03ce13f7SAndroid Build Coastguard Worker 
2346*03ce13f7SAndroid Build Coastguard Worker 	Value *inc = Nucleus::createSub(res.value(), Nucleus::createConstantInt(1));
2347*03ce13f7SAndroid Build Coastguard Worker 	val.storeValue(inc);
2348*03ce13f7SAndroid Build Coastguard Worker 
2349*03ce13f7SAndroid Build Coastguard Worker 	return res;
2350*03ce13f7SAndroid Build Coastguard Worker }
2351*03ce13f7SAndroid Build Coastguard Worker 
operator --(Int & val)2352*03ce13f7SAndroid Build Coastguard Worker const Int &operator--(Int &val)  // Pre-decrement
2353*03ce13f7SAndroid Build Coastguard Worker {
2354*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2355*03ce13f7SAndroid Build Coastguard Worker 	Value *inc = Nucleus::createSub(val.loadValue(), Nucleus::createConstantInt(1));
2356*03ce13f7SAndroid Build Coastguard Worker 	val.storeValue(inc);
2357*03ce13f7SAndroid Build Coastguard Worker 
2358*03ce13f7SAndroid Build Coastguard Worker 	return val;
2359*03ce13f7SAndroid Build Coastguard Worker }
2360*03ce13f7SAndroid Build Coastguard Worker 
RoundInt(RValue<Float> cast)2361*03ce13f7SAndroid Build Coastguard Worker RValue<Int> RoundInt(RValue<Float> cast)
2362*03ce13f7SAndroid Build Coastguard Worker {
2363*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2364*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2365*03ce13f7SAndroid Build Coastguard Worker 	return x86::cvtss2si(cast);
2366*03ce13f7SAndroid Build Coastguard Worker #else
2367*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int>(V(lowerRoundInt(V(cast.value()), T(Int::type()))));
2368*03ce13f7SAndroid Build Coastguard Worker #endif
2369*03ce13f7SAndroid Build Coastguard Worker }
2370*03ce13f7SAndroid Build Coastguard Worker 
type()2371*03ce13f7SAndroid Build Coastguard Worker Type *Int::type()
2372*03ce13f7SAndroid Build Coastguard Worker {
2373*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt32Ty(*jit->context));
2374*03ce13f7SAndroid Build Coastguard Worker }
2375*03ce13f7SAndroid Build Coastguard Worker 
type()2376*03ce13f7SAndroid Build Coastguard Worker Type *Long::type()
2377*03ce13f7SAndroid Build Coastguard Worker {
2378*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt64Ty(*jit->context));
2379*03ce13f7SAndroid Build Coastguard Worker }
2380*03ce13f7SAndroid Build Coastguard Worker 
UInt(RValue<Float> cast)2381*03ce13f7SAndroid Build Coastguard Worker UInt::UInt(RValue<Float> cast)
2382*03ce13f7SAndroid Build Coastguard Worker {
2383*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2384*03ce13f7SAndroid Build Coastguard Worker 	Value *integer = Nucleus::createFPToUI(cast.value(), UInt::type());
2385*03ce13f7SAndroid Build Coastguard Worker 	storeValue(integer);
2386*03ce13f7SAndroid Build Coastguard Worker }
2387*03ce13f7SAndroid Build Coastguard Worker 
operator ++(UInt & val,int)2388*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> operator++(UInt &val, int)  // Post-increment
2389*03ce13f7SAndroid Build Coastguard Worker {
2390*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2391*03ce13f7SAndroid Build Coastguard Worker 	RValue<UInt> res = val;
2392*03ce13f7SAndroid Build Coastguard Worker 
2393*03ce13f7SAndroid Build Coastguard Worker 	Value *inc = Nucleus::createAdd(res.value(), Nucleus::createConstantInt(1));
2394*03ce13f7SAndroid Build Coastguard Worker 	val.storeValue(inc);
2395*03ce13f7SAndroid Build Coastguard Worker 
2396*03ce13f7SAndroid Build Coastguard Worker 	return res;
2397*03ce13f7SAndroid Build Coastguard Worker }
2398*03ce13f7SAndroid Build Coastguard Worker 
operator ++(UInt & val)2399*03ce13f7SAndroid Build Coastguard Worker const UInt &operator++(UInt &val)  // Pre-increment
2400*03ce13f7SAndroid Build Coastguard Worker {
2401*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2402*03ce13f7SAndroid Build Coastguard Worker 	Value *inc = Nucleus::createAdd(val.loadValue(), Nucleus::createConstantInt(1));
2403*03ce13f7SAndroid Build Coastguard Worker 	val.storeValue(inc);
2404*03ce13f7SAndroid Build Coastguard Worker 
2405*03ce13f7SAndroid Build Coastguard Worker 	return val;
2406*03ce13f7SAndroid Build Coastguard Worker }
2407*03ce13f7SAndroid Build Coastguard Worker 
operator --(UInt & val,int)2408*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> operator--(UInt &val, int)  // Post-decrement
2409*03ce13f7SAndroid Build Coastguard Worker {
2410*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2411*03ce13f7SAndroid Build Coastguard Worker 	RValue<UInt> res = val;
2412*03ce13f7SAndroid Build Coastguard Worker 
2413*03ce13f7SAndroid Build Coastguard Worker 	Value *inc = Nucleus::createSub(res.value(), Nucleus::createConstantInt(1));
2414*03ce13f7SAndroid Build Coastguard Worker 	val.storeValue(inc);
2415*03ce13f7SAndroid Build Coastguard Worker 
2416*03ce13f7SAndroid Build Coastguard Worker 	return res;
2417*03ce13f7SAndroid Build Coastguard Worker }
2418*03ce13f7SAndroid Build Coastguard Worker 
operator --(UInt & val)2419*03ce13f7SAndroid Build Coastguard Worker const UInt &operator--(UInt &val)  // Pre-decrement
2420*03ce13f7SAndroid Build Coastguard Worker {
2421*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2422*03ce13f7SAndroid Build Coastguard Worker 	Value *inc = Nucleus::createSub(val.loadValue(), Nucleus::createConstantInt(1));
2423*03ce13f7SAndroid Build Coastguard Worker 	val.storeValue(inc);
2424*03ce13f7SAndroid Build Coastguard Worker 
2425*03ce13f7SAndroid Build Coastguard Worker 	return val;
2426*03ce13f7SAndroid Build Coastguard Worker }
2427*03ce13f7SAndroid Build Coastguard Worker 
2428*03ce13f7SAndroid Build Coastguard Worker //	RValue<UInt> RoundUInt(RValue<Float> cast)
2429*03ce13f7SAndroid Build Coastguard Worker //	{
2430*03ce13f7SAndroid Build Coastguard Worker //#if defined(__i386__) || defined(__x86_64__)
2431*03ce13f7SAndroid Build Coastguard Worker //		return x86::cvtss2si(val);   // FIXME: Unsigned
2432*03ce13f7SAndroid Build Coastguard Worker //#else
2433*03ce13f7SAndroid Build Coastguard Worker //		return IfThenElse(cast > 0.0f, Int(cast + 0.5f), Int(cast - 0.5f));
2434*03ce13f7SAndroid Build Coastguard Worker //#endif
2435*03ce13f7SAndroid Build Coastguard Worker //	}
2436*03ce13f7SAndroid Build Coastguard Worker 
type()2437*03ce13f7SAndroid Build Coastguard Worker Type *UInt::type()
2438*03ce13f7SAndroid Build Coastguard Worker {
2439*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt32Ty(*jit->context));
2440*03ce13f7SAndroid Build Coastguard Worker }
2441*03ce13f7SAndroid Build Coastguard Worker 
2442*03ce13f7SAndroid Build Coastguard Worker //	Int2::Int2(RValue<Int> cast)
2443*03ce13f7SAndroid Build Coastguard Worker //	{
2444*03ce13f7SAndroid Build Coastguard Worker //		Value *extend = Nucleus::createZExt(cast.value(), Long::type());
2445*03ce13f7SAndroid Build Coastguard Worker //		Value *vector = Nucleus::createBitCast(extend, Int2::type());
2446*03ce13f7SAndroid Build Coastguard Worker //
2447*03ce13f7SAndroid Build Coastguard Worker //		int shuffle[2] = {0, 0};
2448*03ce13f7SAndroid Build Coastguard Worker //		Value *replicate = Nucleus::createShuffleVector(vector, vector, shuffle);
2449*03ce13f7SAndroid Build Coastguard Worker //
2450*03ce13f7SAndroid Build Coastguard Worker //		storeValue(replicate);
2451*03ce13f7SAndroid Build Coastguard Worker //	}
2452*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<Int2> lhs,unsigned char rhs)2453*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> operator<<(RValue<Int2> lhs, unsigned char rhs)
2454*03ce13f7SAndroid Build Coastguard Worker {
2455*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2456*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2457*03ce13f7SAndroid Build Coastguard Worker 	//	return RValue<Int2>(Nucleus::createShl(lhs.value(), rhs.value()));
2458*03ce13f7SAndroid Build Coastguard Worker 
2459*03ce13f7SAndroid Build Coastguard Worker 	return x86::pslld(lhs, rhs);
2460*03ce13f7SAndroid Build Coastguard Worker #else
2461*03ce13f7SAndroid Build Coastguard Worker 	return As<Int2>(V(lowerVectorShl(V(lhs.value()), rhs)));
2462*03ce13f7SAndroid Build Coastguard Worker #endif
2463*03ce13f7SAndroid Build Coastguard Worker }
2464*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<Int2> lhs,unsigned char rhs)2465*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> operator>>(RValue<Int2> lhs, unsigned char rhs)
2466*03ce13f7SAndroid Build Coastguard Worker {
2467*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2468*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2469*03ce13f7SAndroid Build Coastguard Worker 	//	return RValue<Int2>(Nucleus::createAShr(lhs.value(), rhs.value()));
2470*03ce13f7SAndroid Build Coastguard Worker 
2471*03ce13f7SAndroid Build Coastguard Worker 	return x86::psrad(lhs, rhs);
2472*03ce13f7SAndroid Build Coastguard Worker #else
2473*03ce13f7SAndroid Build Coastguard Worker 	return As<Int2>(V(lowerVectorAShr(V(lhs.value()), rhs)));
2474*03ce13f7SAndroid Build Coastguard Worker #endif
2475*03ce13f7SAndroid Build Coastguard Worker }
2476*03ce13f7SAndroid Build Coastguard Worker 
type()2477*03ce13f7SAndroid Build Coastguard Worker Type *Int2::type()
2478*03ce13f7SAndroid Build Coastguard Worker {
2479*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v2i32);
2480*03ce13f7SAndroid Build Coastguard Worker }
2481*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<UInt2> lhs,unsigned char rhs)2482*03ce13f7SAndroid Build Coastguard Worker RValue<UInt2> operator<<(RValue<UInt2> lhs, unsigned char rhs)
2483*03ce13f7SAndroid Build Coastguard Worker {
2484*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2485*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2486*03ce13f7SAndroid Build Coastguard Worker 	//	return RValue<UInt2>(Nucleus::createShl(lhs.value(), rhs.value()));
2487*03ce13f7SAndroid Build Coastguard Worker 
2488*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt2>(x86::pslld(As<Int2>(lhs), rhs));
2489*03ce13f7SAndroid Build Coastguard Worker #else
2490*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt2>(V(lowerVectorShl(V(lhs.value()), rhs)));
2491*03ce13f7SAndroid Build Coastguard Worker #endif
2492*03ce13f7SAndroid Build Coastguard Worker }
2493*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<UInt2> lhs,unsigned char rhs)2494*03ce13f7SAndroid Build Coastguard Worker RValue<UInt2> operator>>(RValue<UInt2> lhs, unsigned char rhs)
2495*03ce13f7SAndroid Build Coastguard Worker {
2496*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2497*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2498*03ce13f7SAndroid Build Coastguard Worker 	//	return RValue<UInt2>(Nucleus::createLShr(lhs.value(), rhs.value()));
2499*03ce13f7SAndroid Build Coastguard Worker 
2500*03ce13f7SAndroid Build Coastguard Worker 	return x86::psrld(lhs, rhs);
2501*03ce13f7SAndroid Build Coastguard Worker #else
2502*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt2>(V(lowerVectorLShr(V(lhs.value()), rhs)));
2503*03ce13f7SAndroid Build Coastguard Worker #endif
2504*03ce13f7SAndroid Build Coastguard Worker }
2505*03ce13f7SAndroid Build Coastguard Worker 
type()2506*03ce13f7SAndroid Build Coastguard Worker Type *UInt2::type()
2507*03ce13f7SAndroid Build Coastguard Worker {
2508*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v2i32);
2509*03ce13f7SAndroid Build Coastguard Worker }
2510*03ce13f7SAndroid Build Coastguard Worker 
Int4(RValue<Byte4> cast)2511*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<Byte4> cast)
2512*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
2513*03ce13f7SAndroid Build Coastguard Worker {
2514*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2515*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23 };
2516*03ce13f7SAndroid Build Coastguard Worker 	Value *a = Nucleus::createBitCast(cast.value(), Byte16::type());
2517*03ce13f7SAndroid Build Coastguard Worker 	Value *b = Nucleus::createShuffleVector(a, Nucleus::createNullValue(Byte16::type()), swizzle);
2518*03ce13f7SAndroid Build Coastguard Worker 
2519*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle2 = { 0, 8, 1, 9, 2, 10, 3, 11 };
2520*03ce13f7SAndroid Build Coastguard Worker 	Value *c = Nucleus::createBitCast(b, Short8::type());
2521*03ce13f7SAndroid Build Coastguard Worker 	Value *d = Nucleus::createShuffleVector(c, Nucleus::createNullValue(Short8::type()), swizzle2);
2522*03ce13f7SAndroid Build Coastguard Worker 
2523*03ce13f7SAndroid Build Coastguard Worker 	*this = As<Int4>(d);
2524*03ce13f7SAndroid Build Coastguard Worker }
2525*03ce13f7SAndroid Build Coastguard Worker 
Int4(RValue<SByte4> cast)2526*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<SByte4> cast)
2527*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
2528*03ce13f7SAndroid Build Coastguard Worker {
2529*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2530*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
2531*03ce13f7SAndroid Build Coastguard Worker 	Value *a = Nucleus::createBitCast(cast.value(), Byte16::type());
2532*03ce13f7SAndroid Build Coastguard Worker 	Value *b = Nucleus::createShuffleVector(a, a, swizzle);
2533*03ce13f7SAndroid Build Coastguard Worker 
2534*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle2 = { 0, 0, 1, 1, 2, 2, 3, 3 };
2535*03ce13f7SAndroid Build Coastguard Worker 	Value *c = Nucleus::createBitCast(b, Short8::type());
2536*03ce13f7SAndroid Build Coastguard Worker 	Value *d = Nucleus::createShuffleVector(c, c, swizzle2);
2537*03ce13f7SAndroid Build Coastguard Worker 
2538*03ce13f7SAndroid Build Coastguard Worker 	*this = As<Int4>(d) >> 24;
2539*03ce13f7SAndroid Build Coastguard Worker }
2540*03ce13f7SAndroid Build Coastguard Worker 
Int4(RValue<Short4> cast)2541*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<Short4> cast)
2542*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
2543*03ce13f7SAndroid Build Coastguard Worker {
2544*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2545*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0, 0, 1, 1, 2, 2, 3, 3 };
2546*03ce13f7SAndroid Build Coastguard Worker 	Value *c = Nucleus::createShuffleVector(cast.value(), cast.value(), swizzle);
2547*03ce13f7SAndroid Build Coastguard Worker 	*this = As<Int4>(c) >> 16;
2548*03ce13f7SAndroid Build Coastguard Worker }
2549*03ce13f7SAndroid Build Coastguard Worker 
Int4(RValue<UShort4> cast)2550*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<UShort4> cast)
2551*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
2552*03ce13f7SAndroid Build Coastguard Worker {
2553*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2554*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0, 8, 1, 9, 2, 10, 3, 11 };
2555*03ce13f7SAndroid Build Coastguard Worker 	Value *c = Nucleus::createShuffleVector(cast.value(), Short8(0, 0, 0, 0, 0, 0, 0, 0).loadValue(), swizzle);
2556*03ce13f7SAndroid Build Coastguard Worker 	*this = As<Int4>(c);
2557*03ce13f7SAndroid Build Coastguard Worker }
2558*03ce13f7SAndroid Build Coastguard Worker 
Int4(RValue<Int> rhs)2559*03ce13f7SAndroid Build Coastguard Worker Int4::Int4(RValue<Int> rhs)
2560*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
2561*03ce13f7SAndroid Build Coastguard Worker {
2562*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2563*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = loadValue();
2564*03ce13f7SAndroid Build Coastguard Worker 	Value *insert = Nucleus::createInsertElement(vector, rhs.value(), 0);
2565*03ce13f7SAndroid Build Coastguard Worker 
2566*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0, 0, 0, 0 };
2567*03ce13f7SAndroid Build Coastguard Worker 	Value *replicate = Nucleus::createShuffleVector(insert, insert, swizzle);
2568*03ce13f7SAndroid Build Coastguard Worker 
2569*03ce13f7SAndroid Build Coastguard Worker 	storeValue(replicate);
2570*03ce13f7SAndroid Build Coastguard Worker }
2571*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<Int4> lhs,unsigned char rhs)2572*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> operator<<(RValue<Int4> lhs, unsigned char rhs)
2573*03ce13f7SAndroid Build Coastguard Worker {
2574*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2575*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2576*03ce13f7SAndroid Build Coastguard Worker 	return x86::pslld(lhs, rhs);
2577*03ce13f7SAndroid Build Coastguard Worker #else
2578*03ce13f7SAndroid Build Coastguard Worker 	return As<Int4>(V(lowerVectorShl(V(lhs.value()), rhs)));
2579*03ce13f7SAndroid Build Coastguard Worker #endif
2580*03ce13f7SAndroid Build Coastguard Worker }
2581*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<Int4> lhs,unsigned char rhs)2582*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> operator>>(RValue<Int4> lhs, unsigned char rhs)
2583*03ce13f7SAndroid Build Coastguard Worker {
2584*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2585*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2586*03ce13f7SAndroid Build Coastguard Worker 	return x86::psrad(lhs, rhs);
2587*03ce13f7SAndroid Build Coastguard Worker #else
2588*03ce13f7SAndroid Build Coastguard Worker 	return As<Int4>(V(lowerVectorAShr(V(lhs.value()), rhs)));
2589*03ce13f7SAndroid Build Coastguard Worker #endif
2590*03ce13f7SAndroid Build Coastguard Worker }
2591*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<Int4> x,RValue<Int4> y)2592*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpEQ(RValue<Int4> x, RValue<Int4> y)
2593*03ce13f7SAndroid Build Coastguard Worker {
2594*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2595*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpEQ(x.value(), y.value()), Int4::type()));
2596*03ce13f7SAndroid Build Coastguard Worker }
2597*03ce13f7SAndroid Build Coastguard Worker 
CmpLT(RValue<Int4> x,RValue<Int4> y)2598*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpLT(RValue<Int4> x, RValue<Int4> y)
2599*03ce13f7SAndroid Build Coastguard Worker {
2600*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2601*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpSLT(x.value(), y.value()), Int4::type()));
2602*03ce13f7SAndroid Build Coastguard Worker }
2603*03ce13f7SAndroid Build Coastguard Worker 
CmpLE(RValue<Int4> x,RValue<Int4> y)2604*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpLE(RValue<Int4> x, RValue<Int4> y)
2605*03ce13f7SAndroid Build Coastguard Worker {
2606*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2607*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpSLE(x.value(), y.value()), Int4::type()));
2608*03ce13f7SAndroid Build Coastguard Worker }
2609*03ce13f7SAndroid Build Coastguard Worker 
CmpNEQ(RValue<Int4> x,RValue<Int4> y)2610*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNEQ(RValue<Int4> x, RValue<Int4> y)
2611*03ce13f7SAndroid Build Coastguard Worker {
2612*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2613*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpNE(x.value(), y.value()), Int4::type()));
2614*03ce13f7SAndroid Build Coastguard Worker }
2615*03ce13f7SAndroid Build Coastguard Worker 
CmpNLT(RValue<Int4> x,RValue<Int4> y)2616*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNLT(RValue<Int4> x, RValue<Int4> y)
2617*03ce13f7SAndroid Build Coastguard Worker {
2618*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2619*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpSGE(x.value(), y.value()), Int4::type()));
2620*03ce13f7SAndroid Build Coastguard Worker }
2621*03ce13f7SAndroid Build Coastguard Worker 
CmpNLE(RValue<Int4> x,RValue<Int4> y)2622*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNLE(RValue<Int4> x, RValue<Int4> y)
2623*03ce13f7SAndroid Build Coastguard Worker {
2624*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2625*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpSGT(x.value(), y.value()), Int4::type()));
2626*03ce13f7SAndroid Build Coastguard Worker }
2627*03ce13f7SAndroid Build Coastguard Worker 
Abs(RValue<Int4> x)2628*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> Abs(RValue<Int4> x)
2629*03ce13f7SAndroid Build Coastguard Worker {
2630*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 12
2631*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::abs, { V(x.value())->getType() });
2632*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(V(jit->builder->CreateCall(func, { V(x.value()), llvm::ConstantInt::getFalse(*jit->context) })));
2633*03ce13f7SAndroid Build Coastguard Worker #else
2634*03ce13f7SAndroid Build Coastguard Worker 	auto negative = x >> 31;
2635*03ce13f7SAndroid Build Coastguard Worker 	return (x ^ negative) - negative;
2636*03ce13f7SAndroid Build Coastguard Worker #endif
2637*03ce13f7SAndroid Build Coastguard Worker }
2638*03ce13f7SAndroid Build Coastguard Worker 
Max(RValue<Int4> x,RValue<Int4> y)2639*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> Max(RValue<Int4> x, RValue<Int4> y)
2640*03ce13f7SAndroid Build Coastguard Worker {
2641*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2642*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2643*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
2644*03ce13f7SAndroid Build Coastguard Worker 	{
2645*03ce13f7SAndroid Build Coastguard Worker 		return x86::pmaxsd(x, y);
2646*03ce13f7SAndroid Build Coastguard Worker 	}
2647*03ce13f7SAndroid Build Coastguard Worker 	else
2648*03ce13f7SAndroid Build Coastguard Worker #endif
2649*03ce13f7SAndroid Build Coastguard Worker 	{
2650*03ce13f7SAndroid Build Coastguard Worker 		RValue<Int4> greater = CmpNLE(x, y);
2651*03ce13f7SAndroid Build Coastguard Worker 		return (x & greater) | (y & ~greater);
2652*03ce13f7SAndroid Build Coastguard Worker 	}
2653*03ce13f7SAndroid Build Coastguard Worker }
2654*03ce13f7SAndroid Build Coastguard Worker 
Min(RValue<Int4> x,RValue<Int4> y)2655*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> Min(RValue<Int4> x, RValue<Int4> y)
2656*03ce13f7SAndroid Build Coastguard Worker {
2657*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2658*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2659*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
2660*03ce13f7SAndroid Build Coastguard Worker 	{
2661*03ce13f7SAndroid Build Coastguard Worker 		return x86::pminsd(x, y);
2662*03ce13f7SAndroid Build Coastguard Worker 	}
2663*03ce13f7SAndroid Build Coastguard Worker 	else
2664*03ce13f7SAndroid Build Coastguard Worker #endif
2665*03ce13f7SAndroid Build Coastguard Worker 	{
2666*03ce13f7SAndroid Build Coastguard Worker 		RValue<Int4> less = CmpLT(x, y);
2667*03ce13f7SAndroid Build Coastguard Worker 		return (x & less) | (y & ~less);
2668*03ce13f7SAndroid Build Coastguard Worker 	}
2669*03ce13f7SAndroid Build Coastguard Worker }
2670*03ce13f7SAndroid Build Coastguard Worker 
RoundInt(RValue<Float4> cast)2671*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> RoundInt(RValue<Float4> cast)
2672*03ce13f7SAndroid Build Coastguard Worker {
2673*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2674*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(__x86_64__)) && !__has_feature(memory_sanitizer)
2675*03ce13f7SAndroid Build Coastguard Worker 	return x86::cvtps2dq(cast);
2676*03ce13f7SAndroid Build Coastguard Worker #else
2677*03ce13f7SAndroid Build Coastguard Worker 	return As<Int4>(V(lowerRoundInt(V(cast.value()), T(Int4::type()))));
2678*03ce13f7SAndroid Build Coastguard Worker #endif
2679*03ce13f7SAndroid Build Coastguard Worker }
2680*03ce13f7SAndroid Build Coastguard Worker 
RoundIntClamped(RValue<Float4> cast)2681*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> RoundIntClamped(RValue<Float4> cast)
2682*03ce13f7SAndroid Build Coastguard Worker {
2683*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2684*03ce13f7SAndroid Build Coastguard Worker 
2685*03ce13f7SAndroid Build Coastguard Worker // TODO(b/165000222): Check if fptosi_sat produces optimal code for x86 and ARM.
2686*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(__x86_64__)) && !__has_feature(memory_sanitizer)
2687*03ce13f7SAndroid Build Coastguard Worker 	// cvtps2dq produces 0x80000000, a negative value, for input larger than
2688*03ce13f7SAndroid Build Coastguard Worker 	// 2147483520.0, so clamp to 2147483520. Values less than -2147483520.0
2689*03ce13f7SAndroid Build Coastguard Worker 	// saturate to 0x80000000.
2690*03ce13f7SAndroid Build Coastguard Worker 	return x86::cvtps2dq(Min(cast, Float4(0x7FFFFF80)));
2691*03ce13f7SAndroid Build Coastguard Worker #elif defined(__arm__) || defined(__aarch64__)
2692*03ce13f7SAndroid Build Coastguard Worker 	// ARM saturates to the largest positive or negative integer. Unit tests
2693*03ce13f7SAndroid Build Coastguard Worker 	// verify that lowerRoundInt() behaves as desired.
2694*03ce13f7SAndroid Build Coastguard Worker 	return As<Int4>(V(lowerRoundInt(V(cast.value()), T(Int4::type()))));
2695*03ce13f7SAndroid Build Coastguard Worker #elif LLVM_VERSION_MAJOR >= 14
2696*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *rounded = lowerRound(V(cast.value()));
2697*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *fptosi_sat = llvm::Intrinsic::getDeclaration(
2698*03ce13f7SAndroid Build Coastguard Worker 	    jit->module.get(), llvm::Intrinsic::fptosi_sat, { T(Int4::type()), T(Float4::type()) });
2699*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(V(jit->builder->CreateCall(fptosi_sat, { rounded })));
2700*03ce13f7SAndroid Build Coastguard Worker #else
2701*03ce13f7SAndroid Build Coastguard Worker 	RValue<Float4> clamped = Max(Min(cast, Float4(0x7FFFFF80)), Float4(static_cast<int>(0x80000000)));
2702*03ce13f7SAndroid Build Coastguard Worker 	return As<Int4>(V(lowerRoundInt(V(clamped.value()), T(Int4::type()))));
2703*03ce13f7SAndroid Build Coastguard Worker #endif
2704*03ce13f7SAndroid Build Coastguard Worker }
2705*03ce13f7SAndroid Build Coastguard Worker 
MulHigh(RValue<Int4> x,RValue<Int4> y)2706*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> MulHigh(RValue<Int4> x, RValue<Int4> y)
2707*03ce13f7SAndroid Build Coastguard Worker {
2708*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2709*03ce13f7SAndroid Build Coastguard Worker 	// TODO: For x86, build an intrinsics version of this which uses shuffles + pmuludq.
2710*03ce13f7SAndroid Build Coastguard Worker 	return As<Int4>(V(lowerMulHigh(V(x.value()), V(y.value()), true)));
2711*03ce13f7SAndroid Build Coastguard Worker }
2712*03ce13f7SAndroid Build Coastguard Worker 
MulHigh(RValue<UInt4> x,RValue<UInt4> y)2713*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> MulHigh(RValue<UInt4> x, RValue<UInt4> y)
2714*03ce13f7SAndroid Build Coastguard Worker {
2715*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2716*03ce13f7SAndroid Build Coastguard Worker 	// TODO: For x86, build an intrinsics version of this which uses shuffles + pmuludq.
2717*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt4>(V(lowerMulHigh(V(x.value()), V(y.value()), false)));
2718*03ce13f7SAndroid Build Coastguard Worker }
2719*03ce13f7SAndroid Build Coastguard Worker 
PackSigned(RValue<Int4> x,RValue<Int4> y)2720*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> PackSigned(RValue<Int4> x, RValue<Int4> y)
2721*03ce13f7SAndroid Build Coastguard Worker {
2722*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2723*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2724*03ce13f7SAndroid Build Coastguard Worker 	return x86::packssdw(x, y);
2725*03ce13f7SAndroid Build Coastguard Worker #else
2726*03ce13f7SAndroid Build Coastguard Worker 	return As<Short8>(V(lowerPack(V(x.value()), V(y.value()), true)));
2727*03ce13f7SAndroid Build Coastguard Worker #endif
2728*03ce13f7SAndroid Build Coastguard Worker }
2729*03ce13f7SAndroid Build Coastguard Worker 
PackUnsigned(RValue<Int4> x,RValue<Int4> y)2730*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> PackUnsigned(RValue<Int4> x, RValue<Int4> y)
2731*03ce13f7SAndroid Build Coastguard Worker {
2732*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2733*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2734*03ce13f7SAndroid Build Coastguard Worker 	return x86::packusdw(x, y);
2735*03ce13f7SAndroid Build Coastguard Worker #else
2736*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort8>(V(lowerPack(V(x.value()), V(y.value()), false)));
2737*03ce13f7SAndroid Build Coastguard Worker #endif
2738*03ce13f7SAndroid Build Coastguard Worker }
2739*03ce13f7SAndroid Build Coastguard Worker 
SignMask(RValue<Int4> x)2740*03ce13f7SAndroid Build Coastguard Worker RValue<Int> SignMask(RValue<Int4> x)
2741*03ce13f7SAndroid Build Coastguard Worker {
2742*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2743*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2744*03ce13f7SAndroid Build Coastguard Worker 	return x86::movmskps(As<Float4>(x));
2745*03ce13f7SAndroid Build Coastguard Worker #else
2746*03ce13f7SAndroid Build Coastguard Worker 	return As<Int>(V(lowerSignMask(V(x.value()), T(Int::type()))));
2747*03ce13f7SAndroid Build Coastguard Worker #endif
2748*03ce13f7SAndroid Build Coastguard Worker }
2749*03ce13f7SAndroid Build Coastguard Worker 
type()2750*03ce13f7SAndroid Build Coastguard Worker Type *Int4::type()
2751*03ce13f7SAndroid Build Coastguard Worker {
2752*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(Int::type()), 4, false));
2753*03ce13f7SAndroid Build Coastguard Worker }
2754*03ce13f7SAndroid Build Coastguard Worker 
UInt4(RValue<Float4> cast)2755*03ce13f7SAndroid Build Coastguard Worker UInt4::UInt4(RValue<Float4> cast)
2756*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
2757*03ce13f7SAndroid Build Coastguard Worker {
2758*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2759*03ce13f7SAndroid Build Coastguard Worker 	Value *xyzw = Nucleus::createFPToUI(cast.value(), UInt4::type());
2760*03ce13f7SAndroid Build Coastguard Worker 	storeValue(xyzw);
2761*03ce13f7SAndroid Build Coastguard Worker }
2762*03ce13f7SAndroid Build Coastguard Worker 
UInt4(RValue<UInt> rhs)2763*03ce13f7SAndroid Build Coastguard Worker UInt4::UInt4(RValue<UInt> rhs)
2764*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
2765*03ce13f7SAndroid Build Coastguard Worker {
2766*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2767*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = loadValue();
2768*03ce13f7SAndroid Build Coastguard Worker 	Value *insert = Nucleus::createInsertElement(vector, rhs.value(), 0);
2769*03ce13f7SAndroid Build Coastguard Worker 
2770*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0, 0, 0, 0 };
2771*03ce13f7SAndroid Build Coastguard Worker 	Value *replicate = Nucleus::createShuffleVector(insert, insert, swizzle);
2772*03ce13f7SAndroid Build Coastguard Worker 
2773*03ce13f7SAndroid Build Coastguard Worker 	storeValue(replicate);
2774*03ce13f7SAndroid Build Coastguard Worker }
2775*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<UInt4> lhs,unsigned char rhs)2776*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> operator<<(RValue<UInt4> lhs, unsigned char rhs)
2777*03ce13f7SAndroid Build Coastguard Worker {
2778*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2779*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2780*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt4>(x86::pslld(As<Int4>(lhs), rhs));
2781*03ce13f7SAndroid Build Coastguard Worker #else
2782*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt4>(V(lowerVectorShl(V(lhs.value()), rhs)));
2783*03ce13f7SAndroid Build Coastguard Worker #endif
2784*03ce13f7SAndroid Build Coastguard Worker }
2785*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<UInt4> lhs,unsigned char rhs)2786*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> operator>>(RValue<UInt4> lhs, unsigned char rhs)
2787*03ce13f7SAndroid Build Coastguard Worker {
2788*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2789*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2790*03ce13f7SAndroid Build Coastguard Worker 	return x86::psrld(lhs, rhs);
2791*03ce13f7SAndroid Build Coastguard Worker #else
2792*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt4>(V(lowerVectorLShr(V(lhs.value()), rhs)));
2793*03ce13f7SAndroid Build Coastguard Worker #endif
2794*03ce13f7SAndroid Build Coastguard Worker }
2795*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<UInt4> x,RValue<UInt4> y)2796*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpEQ(RValue<UInt4> x, RValue<UInt4> y)
2797*03ce13f7SAndroid Build Coastguard Worker {
2798*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2799*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpEQ(x.value(), y.value()), Int4::type()));
2800*03ce13f7SAndroid Build Coastguard Worker }
2801*03ce13f7SAndroid Build Coastguard Worker 
CmpLT(RValue<UInt4> x,RValue<UInt4> y)2802*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpLT(RValue<UInt4> x, RValue<UInt4> y)
2803*03ce13f7SAndroid Build Coastguard Worker {
2804*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2805*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpULT(x.value(), y.value()), Int4::type()));
2806*03ce13f7SAndroid Build Coastguard Worker }
2807*03ce13f7SAndroid Build Coastguard Worker 
CmpLE(RValue<UInt4> x,RValue<UInt4> y)2808*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpLE(RValue<UInt4> x, RValue<UInt4> y)
2809*03ce13f7SAndroid Build Coastguard Worker {
2810*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2811*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpULE(x.value(), y.value()), Int4::type()));
2812*03ce13f7SAndroid Build Coastguard Worker }
2813*03ce13f7SAndroid Build Coastguard Worker 
CmpNEQ(RValue<UInt4> x,RValue<UInt4> y)2814*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpNEQ(RValue<UInt4> x, RValue<UInt4> y)
2815*03ce13f7SAndroid Build Coastguard Worker {
2816*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2817*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpNE(x.value(), y.value()), Int4::type()));
2818*03ce13f7SAndroid Build Coastguard Worker }
2819*03ce13f7SAndroid Build Coastguard Worker 
CmpNLT(RValue<UInt4> x,RValue<UInt4> y)2820*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpNLT(RValue<UInt4> x, RValue<UInt4> y)
2821*03ce13f7SAndroid Build Coastguard Worker {
2822*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2823*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpUGE(x.value(), y.value()), Int4::type()));
2824*03ce13f7SAndroid Build Coastguard Worker }
2825*03ce13f7SAndroid Build Coastguard Worker 
CmpNLE(RValue<UInt4> x,RValue<UInt4> y)2826*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> CmpNLE(RValue<UInt4> x, RValue<UInt4> y)
2827*03ce13f7SAndroid Build Coastguard Worker {
2828*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2829*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpUGT(x.value(), y.value()), Int4::type()));
2830*03ce13f7SAndroid Build Coastguard Worker }
2831*03ce13f7SAndroid Build Coastguard Worker 
Max(RValue<UInt4> x,RValue<UInt4> y)2832*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Max(RValue<UInt4> x, RValue<UInt4> y)
2833*03ce13f7SAndroid Build Coastguard Worker {
2834*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2835*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2836*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
2837*03ce13f7SAndroid Build Coastguard Worker 	{
2838*03ce13f7SAndroid Build Coastguard Worker 		return x86::pmaxud(x, y);
2839*03ce13f7SAndroid Build Coastguard Worker 	}
2840*03ce13f7SAndroid Build Coastguard Worker 	else
2841*03ce13f7SAndroid Build Coastguard Worker #endif
2842*03ce13f7SAndroid Build Coastguard Worker 	{
2843*03ce13f7SAndroid Build Coastguard Worker 		RValue<UInt4> greater = CmpNLE(x, y);
2844*03ce13f7SAndroid Build Coastguard Worker 		return (x & greater) | (y & ~greater);
2845*03ce13f7SAndroid Build Coastguard Worker 	}
2846*03ce13f7SAndroid Build Coastguard Worker }
2847*03ce13f7SAndroid Build Coastguard Worker 
Min(RValue<UInt4> x,RValue<UInt4> y)2848*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Min(RValue<UInt4> x, RValue<UInt4> y)
2849*03ce13f7SAndroid Build Coastguard Worker {
2850*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2851*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2852*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
2853*03ce13f7SAndroid Build Coastguard Worker 	{
2854*03ce13f7SAndroid Build Coastguard Worker 		return x86::pminud(x, y);
2855*03ce13f7SAndroid Build Coastguard Worker 	}
2856*03ce13f7SAndroid Build Coastguard Worker 	else
2857*03ce13f7SAndroid Build Coastguard Worker #endif
2858*03ce13f7SAndroid Build Coastguard Worker 	{
2859*03ce13f7SAndroid Build Coastguard Worker 		RValue<UInt4> less = CmpLT(x, y);
2860*03ce13f7SAndroid Build Coastguard Worker 		return (x & less) | (y & ~less);
2861*03ce13f7SAndroid Build Coastguard Worker 	}
2862*03ce13f7SAndroid Build Coastguard Worker }
2863*03ce13f7SAndroid Build Coastguard Worker 
type()2864*03ce13f7SAndroid Build Coastguard Worker Type *UInt4::type()
2865*03ce13f7SAndroid Build Coastguard Worker {
2866*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(UInt::type()), 4, false));
2867*03ce13f7SAndroid Build Coastguard Worker }
2868*03ce13f7SAndroid Build Coastguard Worker 
type()2869*03ce13f7SAndroid Build Coastguard Worker Type *Half::type()
2870*03ce13f7SAndroid Build Coastguard Worker {
2871*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getInt16Ty(*jit->context));
2872*03ce13f7SAndroid Build Coastguard Worker }
2873*03ce13f7SAndroid Build Coastguard Worker 
HasRcpApprox()2874*03ce13f7SAndroid Build Coastguard Worker bool HasRcpApprox()
2875*03ce13f7SAndroid Build Coastguard Worker {
2876*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2877*03ce13f7SAndroid Build Coastguard Worker 	return true;
2878*03ce13f7SAndroid Build Coastguard Worker #else
2879*03ce13f7SAndroid Build Coastguard Worker 	return false;
2880*03ce13f7SAndroid Build Coastguard Worker #endif
2881*03ce13f7SAndroid Build Coastguard Worker }
2882*03ce13f7SAndroid Build Coastguard Worker 
RcpApprox(RValue<Float4> x,bool exactAtPow2)2883*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> RcpApprox(RValue<Float4> x, bool exactAtPow2)
2884*03ce13f7SAndroid Build Coastguard Worker {
2885*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2886*03ce13f7SAndroid Build Coastguard Worker 	if(exactAtPow2)
2887*03ce13f7SAndroid Build Coastguard Worker 	{
2888*03ce13f7SAndroid Build Coastguard Worker 		// rcpps uses a piecewise-linear approximation which minimizes the relative error
2889*03ce13f7SAndroid Build Coastguard Worker 		// but is not exact at power-of-two values. Rectify by multiplying by the inverse.
2890*03ce13f7SAndroid Build Coastguard Worker 		return x86::rcpps(x) * Float4(1.0f / _mm_cvtss_f32(_mm_rcp_ss(_mm_set_ps1(1.0f))));
2891*03ce13f7SAndroid Build Coastguard Worker 	}
2892*03ce13f7SAndroid Build Coastguard Worker 	return x86::rcpps(x);
2893*03ce13f7SAndroid Build Coastguard Worker #else
2894*03ce13f7SAndroid Build Coastguard Worker 	UNREACHABLE("RValue<Float4> RcpApprox() not available on this platform");
2895*03ce13f7SAndroid Build Coastguard Worker 	return { 0.0f };
2896*03ce13f7SAndroid Build Coastguard Worker #endif
2897*03ce13f7SAndroid Build Coastguard Worker }
2898*03ce13f7SAndroid Build Coastguard Worker 
RcpApprox(RValue<Float> x,bool exactAtPow2)2899*03ce13f7SAndroid Build Coastguard Worker RValue<Float> RcpApprox(RValue<Float> x, bool exactAtPow2)
2900*03ce13f7SAndroid Build Coastguard Worker {
2901*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2902*03ce13f7SAndroid Build Coastguard Worker 	if(exactAtPow2)
2903*03ce13f7SAndroid Build Coastguard Worker 	{
2904*03ce13f7SAndroid Build Coastguard Worker 		// rcpss uses a piecewise-linear approximation which minimizes the relative error
2905*03ce13f7SAndroid Build Coastguard Worker 		// but is not exact at power-of-two values. Rectify by multiplying by the inverse.
2906*03ce13f7SAndroid Build Coastguard Worker 		return x86::rcpss(x) * Float(1.0f / _mm_cvtss_f32(_mm_rcp_ss(_mm_set_ps1(1.0f))));
2907*03ce13f7SAndroid Build Coastguard Worker 	}
2908*03ce13f7SAndroid Build Coastguard Worker 	return x86::rcpss(x);
2909*03ce13f7SAndroid Build Coastguard Worker #else
2910*03ce13f7SAndroid Build Coastguard Worker 	UNREACHABLE("RValue<Float4> RcpApprox() not available on this platform");
2911*03ce13f7SAndroid Build Coastguard Worker 	return { 0.0f };
2912*03ce13f7SAndroid Build Coastguard Worker #endif
2913*03ce13f7SAndroid Build Coastguard Worker }
2914*03ce13f7SAndroid Build Coastguard Worker 
HasRcpSqrtApprox()2915*03ce13f7SAndroid Build Coastguard Worker bool HasRcpSqrtApprox()
2916*03ce13f7SAndroid Build Coastguard Worker {
2917*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2918*03ce13f7SAndroid Build Coastguard Worker 	return true;
2919*03ce13f7SAndroid Build Coastguard Worker #else
2920*03ce13f7SAndroid Build Coastguard Worker 	return false;
2921*03ce13f7SAndroid Build Coastguard Worker #endif
2922*03ce13f7SAndroid Build Coastguard Worker }
2923*03ce13f7SAndroid Build Coastguard Worker 
RcpSqrtApprox(RValue<Float4> x)2924*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> RcpSqrtApprox(RValue<Float4> x)
2925*03ce13f7SAndroid Build Coastguard Worker {
2926*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2927*03ce13f7SAndroid Build Coastguard Worker 	return x86::rsqrtps(x);
2928*03ce13f7SAndroid Build Coastguard Worker #else
2929*03ce13f7SAndroid Build Coastguard Worker 	UNREACHABLE("RValue<Float4> RcpSqrtApprox() not available on this platform");
2930*03ce13f7SAndroid Build Coastguard Worker 	return { 0.0f };
2931*03ce13f7SAndroid Build Coastguard Worker #endif
2932*03ce13f7SAndroid Build Coastguard Worker }
2933*03ce13f7SAndroid Build Coastguard Worker 
RcpSqrtApprox(RValue<Float> x)2934*03ce13f7SAndroid Build Coastguard Worker RValue<Float> RcpSqrtApprox(RValue<Float> x)
2935*03ce13f7SAndroid Build Coastguard Worker {
2936*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2937*03ce13f7SAndroid Build Coastguard Worker 	return x86::rsqrtss(x);
2938*03ce13f7SAndroid Build Coastguard Worker #else
2939*03ce13f7SAndroid Build Coastguard Worker 	UNREACHABLE("RValue<Float4> RcpSqrtApprox() not available on this platform");
2940*03ce13f7SAndroid Build Coastguard Worker 	return { 0.0f };
2941*03ce13f7SAndroid Build Coastguard Worker #endif
2942*03ce13f7SAndroid Build Coastguard Worker }
2943*03ce13f7SAndroid Build Coastguard Worker 
Sqrt(RValue<Float> x)2944*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Sqrt(RValue<Float> x)
2945*03ce13f7SAndroid Build Coastguard Worker {
2946*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2947*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2948*03ce13f7SAndroid Build Coastguard Worker 	return x86::sqrtss(x);
2949*03ce13f7SAndroid Build Coastguard Worker #else
2950*03ce13f7SAndroid Build Coastguard Worker 	return As<Float>(V(lowerSQRT(V(x.value()))));
2951*03ce13f7SAndroid Build Coastguard Worker #endif
2952*03ce13f7SAndroid Build Coastguard Worker }
2953*03ce13f7SAndroid Build Coastguard Worker 
Round(RValue<Float> x)2954*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Round(RValue<Float> x)
2955*03ce13f7SAndroid Build Coastguard Worker {
2956*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2957*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2958*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
2959*03ce13f7SAndroid Build Coastguard Worker 	{
2960*03ce13f7SAndroid Build Coastguard Worker 		return x86::roundss(x, 0);
2961*03ce13f7SAndroid Build Coastguard Worker 	}
2962*03ce13f7SAndroid Build Coastguard Worker 	else
2963*03ce13f7SAndroid Build Coastguard Worker 	{
2964*03ce13f7SAndroid Build Coastguard Worker 		return Float4(Round(Float4(x))).x;
2965*03ce13f7SAndroid Build Coastguard Worker 	}
2966*03ce13f7SAndroid Build Coastguard Worker #else
2967*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float>(V(lowerRound(V(x.value()))));
2968*03ce13f7SAndroid Build Coastguard Worker #endif
2969*03ce13f7SAndroid Build Coastguard Worker }
2970*03ce13f7SAndroid Build Coastguard Worker 
Trunc(RValue<Float> x)2971*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Trunc(RValue<Float> x)
2972*03ce13f7SAndroid Build Coastguard Worker {
2973*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2974*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2975*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
2976*03ce13f7SAndroid Build Coastguard Worker 	{
2977*03ce13f7SAndroid Build Coastguard Worker 		return x86::roundss(x, 3);
2978*03ce13f7SAndroid Build Coastguard Worker 	}
2979*03ce13f7SAndroid Build Coastguard Worker 	else
2980*03ce13f7SAndroid Build Coastguard Worker 	{
2981*03ce13f7SAndroid Build Coastguard Worker 		return Float(Int(x));  // Rounded toward zero
2982*03ce13f7SAndroid Build Coastguard Worker 	}
2983*03ce13f7SAndroid Build Coastguard Worker #else
2984*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float>(V(lowerTrunc(V(x.value()))));
2985*03ce13f7SAndroid Build Coastguard Worker #endif
2986*03ce13f7SAndroid Build Coastguard Worker }
2987*03ce13f7SAndroid Build Coastguard Worker 
Frac(RValue<Float> x)2988*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Frac(RValue<Float> x)
2989*03ce13f7SAndroid Build Coastguard Worker {
2990*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
2991*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
2992*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
2993*03ce13f7SAndroid Build Coastguard Worker 	{
2994*03ce13f7SAndroid Build Coastguard Worker 		return x - x86::floorss(x);
2995*03ce13f7SAndroid Build Coastguard Worker 	}
2996*03ce13f7SAndroid Build Coastguard Worker 	else
2997*03ce13f7SAndroid Build Coastguard Worker 	{
2998*03ce13f7SAndroid Build Coastguard Worker 		return Float4(Frac(Float4(x))).x;
2999*03ce13f7SAndroid Build Coastguard Worker 	}
3000*03ce13f7SAndroid Build Coastguard Worker #else
3001*03ce13f7SAndroid Build Coastguard Worker 	// x - floor(x) can be 1.0 for very small negative x.
3002*03ce13f7SAndroid Build Coastguard Worker 	// Clamp against the value just below 1.0.
3003*03ce13f7SAndroid Build Coastguard Worker 	return Min(x - Floor(x), As<Float>(Int(0x3F7FFFFF)));
3004*03ce13f7SAndroid Build Coastguard Worker #endif
3005*03ce13f7SAndroid Build Coastguard Worker }
3006*03ce13f7SAndroid Build Coastguard Worker 
Floor(RValue<Float> x)3007*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Floor(RValue<Float> x)
3008*03ce13f7SAndroid Build Coastguard Worker {
3009*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3010*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
3011*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
3012*03ce13f7SAndroid Build Coastguard Worker 	{
3013*03ce13f7SAndroid Build Coastguard Worker 		return x86::floorss(x);
3014*03ce13f7SAndroid Build Coastguard Worker 	}
3015*03ce13f7SAndroid Build Coastguard Worker 	else
3016*03ce13f7SAndroid Build Coastguard Worker 	{
3017*03ce13f7SAndroid Build Coastguard Worker 		return Float4(Floor(Float4(x))).x;
3018*03ce13f7SAndroid Build Coastguard Worker 	}
3019*03ce13f7SAndroid Build Coastguard Worker #else
3020*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float>(V(lowerFloor(V(x.value()))));
3021*03ce13f7SAndroid Build Coastguard Worker #endif
3022*03ce13f7SAndroid Build Coastguard Worker }
3023*03ce13f7SAndroid Build Coastguard Worker 
Ceil(RValue<Float> x)3024*03ce13f7SAndroid Build Coastguard Worker RValue<Float> Ceil(RValue<Float> x)
3025*03ce13f7SAndroid Build Coastguard Worker {
3026*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3027*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
3028*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
3029*03ce13f7SAndroid Build Coastguard Worker 	{
3030*03ce13f7SAndroid Build Coastguard Worker 		return x86::ceilss(x);
3031*03ce13f7SAndroid Build Coastguard Worker 	}
3032*03ce13f7SAndroid Build Coastguard Worker 	else
3033*03ce13f7SAndroid Build Coastguard Worker #endif
3034*03ce13f7SAndroid Build Coastguard Worker 	{
3035*03ce13f7SAndroid Build Coastguard Worker 		return Float4(Ceil(Float4(x))).x;
3036*03ce13f7SAndroid Build Coastguard Worker 	}
3037*03ce13f7SAndroid Build Coastguard Worker }
3038*03ce13f7SAndroid Build Coastguard Worker 
type()3039*03ce13f7SAndroid Build Coastguard Worker Type *Float::type()
3040*03ce13f7SAndroid Build Coastguard Worker {
3041*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::Type::getFloatTy(*jit->context));
3042*03ce13f7SAndroid Build Coastguard Worker }
3043*03ce13f7SAndroid Build Coastguard Worker 
type()3044*03ce13f7SAndroid Build Coastguard Worker Type *Float2::type()
3045*03ce13f7SAndroid Build Coastguard Worker {
3046*03ce13f7SAndroid Build Coastguard Worker 	return T(Type_v2f32);
3047*03ce13f7SAndroid Build Coastguard Worker }
3048*03ce13f7SAndroid Build Coastguard Worker 
Float4(RValue<Float> rhs)3049*03ce13f7SAndroid Build Coastguard Worker Float4::Float4(RValue<Float> rhs)
3050*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
3051*03ce13f7SAndroid Build Coastguard Worker {
3052*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3053*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = loadValue();
3054*03ce13f7SAndroid Build Coastguard Worker 	Value *insert = Nucleus::createInsertElement(vector, rhs.value(), 0);
3055*03ce13f7SAndroid Build Coastguard Worker 
3056*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0, 0, 0, 0 };
3057*03ce13f7SAndroid Build Coastguard Worker 	Value *replicate = Nucleus::createShuffleVector(insert, insert, swizzle);
3058*03ce13f7SAndroid Build Coastguard Worker 
3059*03ce13f7SAndroid Build Coastguard Worker 	storeValue(replicate);
3060*03ce13f7SAndroid Build Coastguard Worker }
3061*03ce13f7SAndroid Build Coastguard Worker 
MulAdd(RValue<Float4> x,RValue<Float4> y,RValue<Float4> z)3062*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> MulAdd(RValue<Float4> x, RValue<Float4> y, RValue<Float4> z)
3063*03ce13f7SAndroid Build Coastguard Worker {
3064*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::fmuladd, { T(Float4::type()) });
3065*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(V(jit->builder->CreateCall(func, { V(x.value()), V(y.value()), V(z.value()) })));
3066*03ce13f7SAndroid Build Coastguard Worker }
3067*03ce13f7SAndroid Build Coastguard Worker 
FMA(RValue<Float4> x,RValue<Float4> y,RValue<Float4> z)3068*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> FMA(RValue<Float4> x, RValue<Float4> y, RValue<Float4> z)
3069*03ce13f7SAndroid Build Coastguard Worker {
3070*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::fma, { T(Float4::type()) });
3071*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(V(jit->builder->CreateCall(func, { V(x.value()), V(y.value()), V(z.value()) })));
3072*03ce13f7SAndroid Build Coastguard Worker }
3073*03ce13f7SAndroid Build Coastguard Worker 
Abs(RValue<Float4> x)3074*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Abs(RValue<Float4> x)
3075*03ce13f7SAndroid Build Coastguard Worker {
3076*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::fabs, { V(x.value())->getType() });
3077*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(V(jit->builder->CreateCall(func, V(x.value()))));
3078*03ce13f7SAndroid Build Coastguard Worker }
3079*03ce13f7SAndroid Build Coastguard Worker 
Max(RValue<Float4> x,RValue<Float4> y)3080*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Max(RValue<Float4> x, RValue<Float4> y)
3081*03ce13f7SAndroid Build Coastguard Worker {
3082*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3083*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
3084*03ce13f7SAndroid Build Coastguard Worker 	return x86::maxps(x, y);
3085*03ce13f7SAndroid Build Coastguard Worker #else
3086*03ce13f7SAndroid Build Coastguard Worker 	return As<Float4>(V(lowerPFMINMAX(V(x.value()), V(y.value()), llvm::FCmpInst::FCMP_OGT)));
3087*03ce13f7SAndroid Build Coastguard Worker #endif
3088*03ce13f7SAndroid Build Coastguard Worker }
3089*03ce13f7SAndroid Build Coastguard Worker 
Min(RValue<Float4> x,RValue<Float4> y)3090*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Min(RValue<Float4> x, RValue<Float4> y)
3091*03ce13f7SAndroid Build Coastguard Worker {
3092*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3093*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
3094*03ce13f7SAndroid Build Coastguard Worker 	return x86::minps(x, y);
3095*03ce13f7SAndroid Build Coastguard Worker #else
3096*03ce13f7SAndroid Build Coastguard Worker 	return As<Float4>(V(lowerPFMINMAX(V(x.value()), V(y.value()), llvm::FCmpInst::FCMP_OLT)));
3097*03ce13f7SAndroid Build Coastguard Worker #endif
3098*03ce13f7SAndroid Build Coastguard Worker }
3099*03ce13f7SAndroid Build Coastguard Worker 
Sqrt(RValue<Float4> x)3100*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Sqrt(RValue<Float4> x)
3101*03ce13f7SAndroid Build Coastguard Worker {
3102*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3103*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
3104*03ce13f7SAndroid Build Coastguard Worker 	return x86::sqrtps(x);
3105*03ce13f7SAndroid Build Coastguard Worker #else
3106*03ce13f7SAndroid Build Coastguard Worker 	return As<Float4>(V(lowerSQRT(V(x.value()))));
3107*03ce13f7SAndroid Build Coastguard Worker #endif
3108*03ce13f7SAndroid Build Coastguard Worker }
3109*03ce13f7SAndroid Build Coastguard Worker 
SignMask(RValue<Float4> x)3110*03ce13f7SAndroid Build Coastguard Worker RValue<Int> SignMask(RValue<Float4> x)
3111*03ce13f7SAndroid Build Coastguard Worker {
3112*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3113*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
3114*03ce13f7SAndroid Build Coastguard Worker 	return x86::movmskps(x);
3115*03ce13f7SAndroid Build Coastguard Worker #else
3116*03ce13f7SAndroid Build Coastguard Worker 	return As<Int>(V(lowerFPSignMask(V(x.value()), T(Int::type()))));
3117*03ce13f7SAndroid Build Coastguard Worker #endif
3118*03ce13f7SAndroid Build Coastguard Worker }
3119*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<Float4> x,RValue<Float4> y)3120*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpEQ(RValue<Float4> x, RValue<Float4> y)
3121*03ce13f7SAndroid Build Coastguard Worker {
3122*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3123*03ce13f7SAndroid Build Coastguard Worker 	//	return As<Int4>(x86::cmpeqps(x, y));
3124*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOEQ(x.value(), y.value()), Int4::type()));
3125*03ce13f7SAndroid Build Coastguard Worker }
3126*03ce13f7SAndroid Build Coastguard Worker 
CmpLT(RValue<Float4> x,RValue<Float4> y)3127*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpLT(RValue<Float4> x, RValue<Float4> y)
3128*03ce13f7SAndroid Build Coastguard Worker {
3129*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3130*03ce13f7SAndroid Build Coastguard Worker 	//	return As<Int4>(x86::cmpltps(x, y));
3131*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOLT(x.value(), y.value()), Int4::type()));
3132*03ce13f7SAndroid Build Coastguard Worker }
3133*03ce13f7SAndroid Build Coastguard Worker 
CmpLE(RValue<Float4> x,RValue<Float4> y)3134*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpLE(RValue<Float4> x, RValue<Float4> y)
3135*03ce13f7SAndroid Build Coastguard Worker {
3136*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3137*03ce13f7SAndroid Build Coastguard Worker 	//	return As<Int4>(x86::cmpleps(x, y));
3138*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOLE(x.value(), y.value()), Int4::type()));
3139*03ce13f7SAndroid Build Coastguard Worker }
3140*03ce13f7SAndroid Build Coastguard Worker 
CmpNEQ(RValue<Float4> x,RValue<Float4> y)3141*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNEQ(RValue<Float4> x, RValue<Float4> y)
3142*03ce13f7SAndroid Build Coastguard Worker {
3143*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3144*03ce13f7SAndroid Build Coastguard Worker 	//	return As<Int4>(x86::cmpneqps(x, y));
3145*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpONE(x.value(), y.value()), Int4::type()));
3146*03ce13f7SAndroid Build Coastguard Worker }
3147*03ce13f7SAndroid Build Coastguard Worker 
CmpNLT(RValue<Float4> x,RValue<Float4> y)3148*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNLT(RValue<Float4> x, RValue<Float4> y)
3149*03ce13f7SAndroid Build Coastguard Worker {
3150*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3151*03ce13f7SAndroid Build Coastguard Worker 	//	return As<Int4>(x86::cmpnltps(x, y));
3152*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOGE(x.value(), y.value()), Int4::type()));
3153*03ce13f7SAndroid Build Coastguard Worker }
3154*03ce13f7SAndroid Build Coastguard Worker 
CmpNLE(RValue<Float4> x,RValue<Float4> y)3155*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpNLE(RValue<Float4> x, RValue<Float4> y)
3156*03ce13f7SAndroid Build Coastguard Worker {
3157*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3158*03ce13f7SAndroid Build Coastguard Worker 	//	return As<Int4>(x86::cmpnleps(x, y));
3159*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOGT(x.value(), y.value()), Int4::type()));
3160*03ce13f7SAndroid Build Coastguard Worker }
3161*03ce13f7SAndroid Build Coastguard Worker 
CmpUEQ(RValue<Float4> x,RValue<Float4> y)3162*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y)
3163*03ce13f7SAndroid Build Coastguard Worker {
3164*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3165*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUEQ(x.value(), y.value()), Int4::type()));
3166*03ce13f7SAndroid Build Coastguard Worker }
3167*03ce13f7SAndroid Build Coastguard Worker 
CmpULT(RValue<Float4> x,RValue<Float4> y)3168*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y)
3169*03ce13f7SAndroid Build Coastguard Worker {
3170*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3171*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpULT(x.value(), y.value()), Int4::type()));
3172*03ce13f7SAndroid Build Coastguard Worker }
3173*03ce13f7SAndroid Build Coastguard Worker 
CmpULE(RValue<Float4> x,RValue<Float4> y)3174*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y)
3175*03ce13f7SAndroid Build Coastguard Worker {
3176*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3177*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpULE(x.value(), y.value()), Int4::type()));
3178*03ce13f7SAndroid Build Coastguard Worker }
3179*03ce13f7SAndroid Build Coastguard Worker 
CmpUNEQ(RValue<Float4> x,RValue<Float4> y)3180*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y)
3181*03ce13f7SAndroid Build Coastguard Worker {
3182*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3183*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUNE(x.value(), y.value()), Int4::type()));
3184*03ce13f7SAndroid Build Coastguard Worker }
3185*03ce13f7SAndroid Build Coastguard Worker 
CmpUNLT(RValue<Float4> x,RValue<Float4> y)3186*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y)
3187*03ce13f7SAndroid Build Coastguard Worker {
3188*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3189*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUGE(x.value(), y.value()), Int4::type()));
3190*03ce13f7SAndroid Build Coastguard Worker }
3191*03ce13f7SAndroid Build Coastguard Worker 
CmpUNLE(RValue<Float4> x,RValue<Float4> y)3192*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y)
3193*03ce13f7SAndroid Build Coastguard Worker {
3194*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3195*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUGT(x.value(), y.value()), Int4::type()));
3196*03ce13f7SAndroid Build Coastguard Worker }
3197*03ce13f7SAndroid Build Coastguard Worker 
Round(RValue<Float4> x)3198*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Round(RValue<Float4> x)
3199*03ce13f7SAndroid Build Coastguard Worker {
3200*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3201*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(__x86_64__)) && !__has_feature(memory_sanitizer)
3202*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
3203*03ce13f7SAndroid Build Coastguard Worker 	{
3204*03ce13f7SAndroid Build Coastguard Worker 		return x86::roundps(x, 0);
3205*03ce13f7SAndroid Build Coastguard Worker 	}
3206*03ce13f7SAndroid Build Coastguard Worker 	else
3207*03ce13f7SAndroid Build Coastguard Worker 	{
3208*03ce13f7SAndroid Build Coastguard Worker 		return Float4(RoundInt(x));
3209*03ce13f7SAndroid Build Coastguard Worker 	}
3210*03ce13f7SAndroid Build Coastguard Worker #else
3211*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(V(lowerRound(V(x.value()))));
3212*03ce13f7SAndroid Build Coastguard Worker #endif
3213*03ce13f7SAndroid Build Coastguard Worker }
3214*03ce13f7SAndroid Build Coastguard Worker 
Trunc(RValue<Float4> x)3215*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Trunc(RValue<Float4> x)
3216*03ce13f7SAndroid Build Coastguard Worker {
3217*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3218*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(__x86_64__)) && !__has_feature(memory_sanitizer)
3219*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
3220*03ce13f7SAndroid Build Coastguard Worker 	{
3221*03ce13f7SAndroid Build Coastguard Worker 		return x86::roundps(x, 3);
3222*03ce13f7SAndroid Build Coastguard Worker 	}
3223*03ce13f7SAndroid Build Coastguard Worker 	else
3224*03ce13f7SAndroid Build Coastguard Worker 	{
3225*03ce13f7SAndroid Build Coastguard Worker 		return Float4(Int4(x));
3226*03ce13f7SAndroid Build Coastguard Worker 	}
3227*03ce13f7SAndroid Build Coastguard Worker #else
3228*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(V(lowerTrunc(V(x.value()))));
3229*03ce13f7SAndroid Build Coastguard Worker #endif
3230*03ce13f7SAndroid Build Coastguard Worker }
3231*03ce13f7SAndroid Build Coastguard Worker 
Frac(RValue<Float4> x)3232*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Frac(RValue<Float4> x)
3233*03ce13f7SAndroid Build Coastguard Worker {
3234*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3235*03ce13f7SAndroid Build Coastguard Worker 	Float4 frc;
3236*03ce13f7SAndroid Build Coastguard Worker 
3237*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(__x86_64__)) && !__has_feature(memory_sanitizer)
3238*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
3239*03ce13f7SAndroid Build Coastguard Worker 	{
3240*03ce13f7SAndroid Build Coastguard Worker 		frc = x - x86::floorps(x);
3241*03ce13f7SAndroid Build Coastguard Worker 	}
3242*03ce13f7SAndroid Build Coastguard Worker 	else
3243*03ce13f7SAndroid Build Coastguard Worker 	{
3244*03ce13f7SAndroid Build Coastguard Worker 		frc = x - Float4(Int4(x));  // Signed fractional part.
3245*03ce13f7SAndroid Build Coastguard Worker 
3246*03ce13f7SAndroid Build Coastguard Worker 		frc += As<Float4>(As<Int4>(CmpNLE(Float4(0.0f), frc)) & As<Int4>(Float4(1.0f)));  // Add 1.0 if negative.
3247*03ce13f7SAndroid Build Coastguard Worker 	}
3248*03ce13f7SAndroid Build Coastguard Worker #else
3249*03ce13f7SAndroid Build Coastguard Worker 	frc = x - Floor(x);
3250*03ce13f7SAndroid Build Coastguard Worker #endif
3251*03ce13f7SAndroid Build Coastguard Worker 
3252*03ce13f7SAndroid Build Coastguard Worker 	// x - floor(x) can be 1.0 for very small negative x.
3253*03ce13f7SAndroid Build Coastguard Worker 	// Clamp against the value just below 1.0.
3254*03ce13f7SAndroid Build Coastguard Worker 	return Min(frc, As<Float4>(Int4(0x3F7FFFFF)));
3255*03ce13f7SAndroid Build Coastguard Worker }
3256*03ce13f7SAndroid Build Coastguard Worker 
Floor(RValue<Float4> x)3257*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Floor(RValue<Float4> x)
3258*03ce13f7SAndroid Build Coastguard Worker {
3259*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3260*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(__x86_64__)) && !__has_feature(memory_sanitizer)
3261*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
3262*03ce13f7SAndroid Build Coastguard Worker 	{
3263*03ce13f7SAndroid Build Coastguard Worker 		return x86::floorps(x);
3264*03ce13f7SAndroid Build Coastguard Worker 	}
3265*03ce13f7SAndroid Build Coastguard Worker 	else
3266*03ce13f7SAndroid Build Coastguard Worker 	{
3267*03ce13f7SAndroid Build Coastguard Worker 		return x - Frac(x);
3268*03ce13f7SAndroid Build Coastguard Worker 	}
3269*03ce13f7SAndroid Build Coastguard Worker #else
3270*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(V(lowerFloor(V(x.value()))));
3271*03ce13f7SAndroid Build Coastguard Worker #endif
3272*03ce13f7SAndroid Build Coastguard Worker }
3273*03ce13f7SAndroid Build Coastguard Worker 
Ceil(RValue<Float4> x)3274*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Ceil(RValue<Float4> x)
3275*03ce13f7SAndroid Build Coastguard Worker {
3276*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3277*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(__x86_64__)) && !__has_feature(memory_sanitizer)
3278*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
3279*03ce13f7SAndroid Build Coastguard Worker 	{
3280*03ce13f7SAndroid Build Coastguard Worker 		return x86::ceilps(x);
3281*03ce13f7SAndroid Build Coastguard Worker 	}
3282*03ce13f7SAndroid Build Coastguard Worker 	else
3283*03ce13f7SAndroid Build Coastguard Worker #endif
3284*03ce13f7SAndroid Build Coastguard Worker 	{
3285*03ce13f7SAndroid Build Coastguard Worker 		return -Floor(-x);
3286*03ce13f7SAndroid Build Coastguard Worker 	}
3287*03ce13f7SAndroid Build Coastguard Worker }
3288*03ce13f7SAndroid Build Coastguard Worker 
Ctlz(RValue<UInt> v,bool isZeroUndef)3289*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> Ctlz(RValue<UInt> v, bool isZeroUndef)
3290*03ce13f7SAndroid Build Coastguard Worker {
3291*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3292*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::ctlz, { T(UInt::type()) });
3293*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt>(V(jit->builder->CreateCall(func, { V(v.value()),
3294*03ce13f7SAndroid Build Coastguard Worker 	                                                       isZeroUndef ? llvm::ConstantInt::getTrue(*jit->context) : llvm::ConstantInt::getFalse(*jit->context) })));
3295*03ce13f7SAndroid Build Coastguard Worker }
3296*03ce13f7SAndroid Build Coastguard Worker 
Ctlz(RValue<UInt4> v,bool isZeroUndef)3297*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Ctlz(RValue<UInt4> v, bool isZeroUndef)
3298*03ce13f7SAndroid Build Coastguard Worker {
3299*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3300*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::ctlz, { T(UInt4::type()) });
3301*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(V(jit->builder->CreateCall(func, { V(v.value()),
3302*03ce13f7SAndroid Build Coastguard Worker 	                                                        isZeroUndef ? llvm::ConstantInt::getTrue(*jit->context) : llvm::ConstantInt::getFalse(*jit->context) })));
3303*03ce13f7SAndroid Build Coastguard Worker }
3304*03ce13f7SAndroid Build Coastguard Worker 
Cttz(RValue<UInt> v,bool isZeroUndef)3305*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> Cttz(RValue<UInt> v, bool isZeroUndef)
3306*03ce13f7SAndroid Build Coastguard Worker {
3307*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3308*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::cttz, { T(UInt::type()) });
3309*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt>(V(jit->builder->CreateCall(func, { V(v.value()),
3310*03ce13f7SAndroid Build Coastguard Worker 	                                                       isZeroUndef ? llvm::ConstantInt::getTrue(*jit->context) : llvm::ConstantInt::getFalse(*jit->context) })));
3311*03ce13f7SAndroid Build Coastguard Worker }
3312*03ce13f7SAndroid Build Coastguard Worker 
Cttz(RValue<UInt4> v,bool isZeroUndef)3313*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Cttz(RValue<UInt4> v, bool isZeroUndef)
3314*03ce13f7SAndroid Build Coastguard Worker {
3315*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3316*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::cttz, { T(UInt4::type()) });
3317*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(V(jit->builder->CreateCall(func, { V(v.value()),
3318*03ce13f7SAndroid Build Coastguard Worker 	                                                        isZeroUndef ? llvm::ConstantInt::getTrue(*jit->context) : llvm::ConstantInt::getFalse(*jit->context) })));
3319*03ce13f7SAndroid Build Coastguard Worker }
3320*03ce13f7SAndroid Build Coastguard Worker 
MinAtomic(RValue<Pointer<Int>> x,RValue<Int> y,std::memory_order memoryOrder)3321*03ce13f7SAndroid Build Coastguard Worker RValue<Int> MinAtomic(RValue<Pointer<Int>> x, RValue<Int> y, std::memory_order memoryOrder)
3322*03ce13f7SAndroid Build Coastguard Worker {
3323*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int>(Nucleus::createAtomicMin(x.value(), y.value(), memoryOrder));
3324*03ce13f7SAndroid Build Coastguard Worker }
3325*03ce13f7SAndroid Build Coastguard Worker 
MinAtomic(RValue<Pointer<UInt>> x,RValue<UInt> y,std::memory_order memoryOrder)3326*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> MinAtomic(RValue<Pointer<UInt>> x, RValue<UInt> y, std::memory_order memoryOrder)
3327*03ce13f7SAndroid Build Coastguard Worker {
3328*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt>(Nucleus::createAtomicUMin(x.value(), y.value(), memoryOrder));
3329*03ce13f7SAndroid Build Coastguard Worker }
3330*03ce13f7SAndroid Build Coastguard Worker 
MaxAtomic(RValue<Pointer<Int>> x,RValue<Int> y,std::memory_order memoryOrder)3331*03ce13f7SAndroid Build Coastguard Worker RValue<Int> MaxAtomic(RValue<Pointer<Int>> x, RValue<Int> y, std::memory_order memoryOrder)
3332*03ce13f7SAndroid Build Coastguard Worker {
3333*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int>(Nucleus::createAtomicMax(x.value(), y.value(), memoryOrder));
3334*03ce13f7SAndroid Build Coastguard Worker }
3335*03ce13f7SAndroid Build Coastguard Worker 
MaxAtomic(RValue<Pointer<UInt>> x,RValue<UInt> y,std::memory_order memoryOrder)3336*03ce13f7SAndroid Build Coastguard Worker RValue<UInt> MaxAtomic(RValue<Pointer<UInt>> x, RValue<UInt> y, std::memory_order memoryOrder)
3337*03ce13f7SAndroid Build Coastguard Worker {
3338*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt>(Nucleus::createAtomicUMax(x.value(), y.value(), memoryOrder));
3339*03ce13f7SAndroid Build Coastguard Worker }
3340*03ce13f7SAndroid Build Coastguard Worker 
type()3341*03ce13f7SAndroid Build Coastguard Worker Type *Float4::type()
3342*03ce13f7SAndroid Build Coastguard Worker {
3343*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(Float::type()), 4, false));
3344*03ce13f7SAndroid Build Coastguard Worker }
3345*03ce13f7SAndroid Build Coastguard Worker 
Ticks()3346*03ce13f7SAndroid Build Coastguard Worker RValue<Long> Ticks()
3347*03ce13f7SAndroid Build Coastguard Worker {
3348*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3349*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *rdtsc = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::readcyclecounter);
3350*03ce13f7SAndroid Build Coastguard Worker 
3351*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Long>(V(jit->builder->CreateCall(rdtsc)));
3352*03ce13f7SAndroid Build Coastguard Worker }
3353*03ce13f7SAndroid Build Coastguard Worker 
ConstantPointer(const void * ptr)3354*03ce13f7SAndroid Build Coastguard Worker RValue<Pointer<Byte>> ConstantPointer(const void *ptr)
3355*03ce13f7SAndroid Build Coastguard Worker {
3356*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3357*03ce13f7SAndroid Build Coastguard Worker 	// Note: this should work for 32-bit pointers as well because 'inttoptr'
3358*03ce13f7SAndroid Build Coastguard Worker 	// is defined to truncate (and zero extend) if necessary.
3359*03ce13f7SAndroid Build Coastguard Worker 	auto ptrAsInt = llvm::ConstantInt::get(llvm::Type::getInt64Ty(*jit->context), reinterpret_cast<uintptr_t>(ptr));
3360*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Pointer<Byte>>(V(jit->builder->CreateIntToPtr(ptrAsInt, T(Pointer<Byte>::type()))));
3361*03ce13f7SAndroid Build Coastguard Worker }
3362*03ce13f7SAndroid Build Coastguard Worker 
ConstantData(const void * data,size_t size)3363*03ce13f7SAndroid Build Coastguard Worker RValue<Pointer<Byte>> ConstantData(const void *data, size_t size)
3364*03ce13f7SAndroid Build Coastguard Worker {
3365*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3366*03ce13f7SAndroid Build Coastguard Worker 	auto str = ::std::string(reinterpret_cast<const char *>(data), size);
3367*03ce13f7SAndroid Build Coastguard Worker 	auto ptr = jit->builder->CreateGlobalStringPtr(str);
3368*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Pointer<Byte>>(V(ptr));
3369*03ce13f7SAndroid Build Coastguard Worker }
3370*03ce13f7SAndroid Build Coastguard Worker 
Call(RValue<Pointer<Byte>> fptr,Type * retTy,std::initializer_list<Value * > args,std::initializer_list<Type * > argTys)3371*03ce13f7SAndroid Build Coastguard Worker Value *Call(RValue<Pointer<Byte>> fptr, Type *retTy, std::initializer_list<Value *> args, std::initializer_list<Type *> argTys)
3372*03ce13f7SAndroid Build Coastguard Worker {
3373*03ce13f7SAndroid Build Coastguard Worker 	// If this is a MemorySanitizer build, but Reactor routine instrumentation is not enabled,
3374*03ce13f7SAndroid Build Coastguard Worker 	// mark all call arguments as initialized by calling __msan_unpoison_param().
3375*03ce13f7SAndroid Build Coastguard Worker 	if(__has_feature(memory_sanitizer) && !jit->msanInstrumentation)
3376*03ce13f7SAndroid Build Coastguard Worker 	{
3377*03ce13f7SAndroid Build Coastguard Worker 		// void __msan_unpoison_param(size_t n)
3378*03ce13f7SAndroid Build Coastguard Worker 		auto voidTy = llvm::Type::getVoidTy(*jit->context);
3379*03ce13f7SAndroid Build Coastguard Worker 		auto sizetTy = llvm::IntegerType::get(*jit->context, sizeof(size_t) * 8);
3380*03ce13f7SAndroid Build Coastguard Worker 		auto funcTy = llvm::FunctionType::get(voidTy, { sizetTy }, false);
3381*03ce13f7SAndroid Build Coastguard Worker 		auto func = jit->module->getOrInsertFunction("__msan_unpoison_param", funcTy);
3382*03ce13f7SAndroid Build Coastguard Worker 
3383*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateCall(func, { llvm::ConstantInt::get(sizetTy, args.size()) });
3384*03ce13f7SAndroid Build Coastguard Worker 	}
3385*03ce13f7SAndroid Build Coastguard Worker 
3386*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3387*03ce13f7SAndroid Build Coastguard Worker 	llvm::SmallVector<llvm::Type *, 8> paramTys;
3388*03ce13f7SAndroid Build Coastguard Worker 	for(auto ty : argTys) { paramTys.push_back(T(ty)); }
3389*03ce13f7SAndroid Build Coastguard Worker 	auto funcTy = llvm::FunctionType::get(T(retTy), paramTys, false);
3390*03ce13f7SAndroid Build Coastguard Worker 
3391*03ce13f7SAndroid Build Coastguard Worker 	auto funcPtrTy = funcTy->getPointerTo();
3392*03ce13f7SAndroid Build Coastguard Worker 	auto funcPtr = jit->builder->CreatePointerCast(V(fptr.value()), funcPtrTy);
3393*03ce13f7SAndroid Build Coastguard Worker 
3394*03ce13f7SAndroid Build Coastguard Worker 	llvm::SmallVector<llvm::Value *, 8> arguments;
3395*03ce13f7SAndroid Build Coastguard Worker 	for(auto arg : args) { arguments.push_back(V(arg)); }
3396*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateCall(funcTy, funcPtr, arguments));
3397*03ce13f7SAndroid Build Coastguard Worker }
3398*03ce13f7SAndroid Build Coastguard Worker 
Breakpoint()3399*03ce13f7SAndroid Build Coastguard Worker void Breakpoint()
3400*03ce13f7SAndroid Build Coastguard Worker {
3401*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
3402*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *debugtrap = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::debugtrap);
3403*03ce13f7SAndroid Build Coastguard Worker 
3404*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateCall(debugtrap);
3405*03ce13f7SAndroid Build Coastguard Worker }
3406*03ce13f7SAndroid Build Coastguard Worker 
3407*03ce13f7SAndroid Build Coastguard Worker }  // namespace rr
3408*03ce13f7SAndroid Build Coastguard Worker 
3409*03ce13f7SAndroid Build Coastguard Worker namespace rr {
3410*03ce13f7SAndroid Build Coastguard Worker 
3411*03ce13f7SAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
3412*03ce13f7SAndroid Build Coastguard Worker namespace x86 {
3413*03ce13f7SAndroid Build Coastguard Worker 
3414*03ce13f7SAndroid Build Coastguard Worker // Differs from IRBuilder<>::CreateUnaryIntrinsic() in that it only accepts native instruction intrinsics which have
3415*03ce13f7SAndroid Build Coastguard Worker // implicit types, such as 'x86_sse_rcp_ps' operating on v4f32, while 'sqrt' requires explicitly specifying the operand type.
createInstruction(llvm::Intrinsic::ID id,Value * x)3416*03ce13f7SAndroid Build Coastguard Worker static Value *createInstruction(llvm::Intrinsic::ID id, Value *x)
3417*03ce13f7SAndroid Build Coastguard Worker {
3418*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *intrinsic = llvm::Intrinsic::getDeclaration(jit->module.get(), id);
3419*03ce13f7SAndroid Build Coastguard Worker 
3420*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateCall(intrinsic, V(x)));
3421*03ce13f7SAndroid Build Coastguard Worker }
3422*03ce13f7SAndroid Build Coastguard Worker 
3423*03ce13f7SAndroid Build Coastguard Worker // Differs from IRBuilder<>::CreateBinaryIntrinsic() in that it only accepts native instruction intrinsics which have
3424*03ce13f7SAndroid Build Coastguard Worker // implicit types, such as 'x86_sse_max_ps' operating on v4f32, while 'sadd_sat' requires explicitly specifying the operand types.
createInstruction(llvm::Intrinsic::ID id,Value * x,Value * y)3425*03ce13f7SAndroid Build Coastguard Worker static Value *createInstruction(llvm::Intrinsic::ID id, Value *x, Value *y)
3426*03ce13f7SAndroid Build Coastguard Worker {
3427*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *intrinsic = llvm::Intrinsic::getDeclaration(jit->module.get(), id);
3428*03ce13f7SAndroid Build Coastguard Worker 
3429*03ce13f7SAndroid Build Coastguard Worker 	return V(jit->builder->CreateCall(intrinsic, { V(x), V(y) }));
3430*03ce13f7SAndroid Build Coastguard Worker }
3431*03ce13f7SAndroid Build Coastguard Worker 
cvtss2si(RValue<Float> val)3432*03ce13f7SAndroid Build Coastguard Worker RValue<Int> cvtss2si(RValue<Float> val)
3433*03ce13f7SAndroid Build Coastguard Worker {
3434*03ce13f7SAndroid Build Coastguard Worker 	Float4 vector;
3435*03ce13f7SAndroid Build Coastguard Worker 	vector.x = val;
3436*03ce13f7SAndroid Build Coastguard Worker 
3437*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int>(createInstruction(llvm::Intrinsic::x86_sse_cvtss2si, RValue<Float4>(vector).value()));
3438*03ce13f7SAndroid Build Coastguard Worker }
3439*03ce13f7SAndroid Build Coastguard Worker 
cvtps2dq(RValue<Float4> val)3440*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> cvtps2dq(RValue<Float4> val)
3441*03ce13f7SAndroid Build Coastguard Worker {
3442*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(!__has_feature(memory_sanitizer));  // TODO(b/172238865): Not correctly instrumented by MemorySanitizer.
3443*03ce13f7SAndroid Build Coastguard Worker 
3444*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(createInstruction(llvm::Intrinsic::x86_sse2_cvtps2dq, val.value()));
3445*03ce13f7SAndroid Build Coastguard Worker }
3446*03ce13f7SAndroid Build Coastguard Worker 
rcpss(RValue<Float> val)3447*03ce13f7SAndroid Build Coastguard Worker RValue<Float> rcpss(RValue<Float> val)
3448*03ce13f7SAndroid Build Coastguard Worker {
3449*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = Nucleus::createInsertElement(V(llvm::UndefValue::get(T(Float4::type()))), val.value(), 0);
3450*03ce13f7SAndroid Build Coastguard Worker 
3451*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float>(Nucleus::createExtractElement(createInstruction(llvm::Intrinsic::x86_sse_rcp_ss, vector), Float::type(), 0));
3452*03ce13f7SAndroid Build Coastguard Worker }
3453*03ce13f7SAndroid Build Coastguard Worker 
sqrtss(RValue<Float> val)3454*03ce13f7SAndroid Build Coastguard Worker RValue<Float> sqrtss(RValue<Float> val)
3455*03ce13f7SAndroid Build Coastguard Worker {
3456*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float>(V(jit->builder->CreateUnaryIntrinsic(llvm::Intrinsic::sqrt, V(val.value()))));
3457*03ce13f7SAndroid Build Coastguard Worker }
3458*03ce13f7SAndroid Build Coastguard Worker 
rsqrtss(RValue<Float> val)3459*03ce13f7SAndroid Build Coastguard Worker RValue<Float> rsqrtss(RValue<Float> val)
3460*03ce13f7SAndroid Build Coastguard Worker {
3461*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = Nucleus::createInsertElement(V(llvm::UndefValue::get(T(Float4::type()))), val.value(), 0);
3462*03ce13f7SAndroid Build Coastguard Worker 
3463*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float>(Nucleus::createExtractElement(createInstruction(llvm::Intrinsic::x86_sse_rsqrt_ss, vector), Float::type(), 0));
3464*03ce13f7SAndroid Build Coastguard Worker }
3465*03ce13f7SAndroid Build Coastguard Worker 
rcpps(RValue<Float4> val)3466*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> rcpps(RValue<Float4> val)
3467*03ce13f7SAndroid Build Coastguard Worker {
3468*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(createInstruction(llvm::Intrinsic::x86_sse_rcp_ps, val.value()));
3469*03ce13f7SAndroid Build Coastguard Worker }
3470*03ce13f7SAndroid Build Coastguard Worker 
sqrtps(RValue<Float4> val)3471*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> sqrtps(RValue<Float4> val)
3472*03ce13f7SAndroid Build Coastguard Worker {
3473*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(V(jit->builder->CreateUnaryIntrinsic(llvm::Intrinsic::sqrt, V(val.value()))));
3474*03ce13f7SAndroid Build Coastguard Worker }
3475*03ce13f7SAndroid Build Coastguard Worker 
rsqrtps(RValue<Float4> val)3476*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> rsqrtps(RValue<Float4> val)
3477*03ce13f7SAndroid Build Coastguard Worker {
3478*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(createInstruction(llvm::Intrinsic::x86_sse_rsqrt_ps, val.value()));
3479*03ce13f7SAndroid Build Coastguard Worker }
3480*03ce13f7SAndroid Build Coastguard Worker 
maxps(RValue<Float4> x,RValue<Float4> y)3481*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> maxps(RValue<Float4> x, RValue<Float4> y)
3482*03ce13f7SAndroid Build Coastguard Worker {
3483*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(createInstruction(llvm::Intrinsic::x86_sse_max_ps, x.value(), y.value()));
3484*03ce13f7SAndroid Build Coastguard Worker }
3485*03ce13f7SAndroid Build Coastguard Worker 
minps(RValue<Float4> x,RValue<Float4> y)3486*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> minps(RValue<Float4> x, RValue<Float4> y)
3487*03ce13f7SAndroid Build Coastguard Worker {
3488*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(createInstruction(llvm::Intrinsic::x86_sse_min_ps, x.value(), y.value()));
3489*03ce13f7SAndroid Build Coastguard Worker }
3490*03ce13f7SAndroid Build Coastguard Worker 
roundss(RValue<Float> val,unsigned char imm)3491*03ce13f7SAndroid Build Coastguard Worker RValue<Float> roundss(RValue<Float> val, unsigned char imm)
3492*03ce13f7SAndroid Build Coastguard Worker {
3493*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *roundss = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::x86_sse41_round_ss);
3494*03ce13f7SAndroid Build Coastguard Worker 
3495*03ce13f7SAndroid Build Coastguard Worker 	Value *undef = V(llvm::UndefValue::get(T(Float4::type())));
3496*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = Nucleus::createInsertElement(undef, val.value(), 0);
3497*03ce13f7SAndroid Build Coastguard Worker 
3498*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float>(Nucleus::createExtractElement(V(jit->builder->CreateCall(roundss, { V(undef), V(vector), V(Nucleus::createConstantInt(imm)) })), Float::type(), 0));
3499*03ce13f7SAndroid Build Coastguard Worker }
3500*03ce13f7SAndroid Build Coastguard Worker 
floorss(RValue<Float> val)3501*03ce13f7SAndroid Build Coastguard Worker RValue<Float> floorss(RValue<Float> val)
3502*03ce13f7SAndroid Build Coastguard Worker {
3503*03ce13f7SAndroid Build Coastguard Worker 	return roundss(val, 1);
3504*03ce13f7SAndroid Build Coastguard Worker }
3505*03ce13f7SAndroid Build Coastguard Worker 
ceilss(RValue<Float> val)3506*03ce13f7SAndroid Build Coastguard Worker RValue<Float> ceilss(RValue<Float> val)
3507*03ce13f7SAndroid Build Coastguard Worker {
3508*03ce13f7SAndroid Build Coastguard Worker 	return roundss(val, 2);
3509*03ce13f7SAndroid Build Coastguard Worker }
3510*03ce13f7SAndroid Build Coastguard Worker 
roundps(RValue<Float4> val,unsigned char imm)3511*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> roundps(RValue<Float4> val, unsigned char imm)
3512*03ce13f7SAndroid Build Coastguard Worker {
3513*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(!__has_feature(memory_sanitizer));  // TODO(b/172238865): Not correctly instrumented by MemorySanitizer.
3514*03ce13f7SAndroid Build Coastguard Worker 
3515*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Float4>(createInstruction(llvm::Intrinsic::x86_sse41_round_ps, val.value(), Nucleus::createConstantInt(imm)));
3516*03ce13f7SAndroid Build Coastguard Worker }
3517*03ce13f7SAndroid Build Coastguard Worker 
floorps(RValue<Float4> val)3518*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> floorps(RValue<Float4> val)
3519*03ce13f7SAndroid Build Coastguard Worker {
3520*03ce13f7SAndroid Build Coastguard Worker 	return roundps(val, 1);
3521*03ce13f7SAndroid Build Coastguard Worker }
3522*03ce13f7SAndroid Build Coastguard Worker 
ceilps(RValue<Float4> val)3523*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> ceilps(RValue<Float4> val)
3524*03ce13f7SAndroid Build Coastguard Worker {
3525*03ce13f7SAndroid Build Coastguard Worker 	return roundps(val, 2);
3526*03ce13f7SAndroid Build Coastguard Worker }
3527*03ce13f7SAndroid Build Coastguard Worker 
paddsw(RValue<Short4> x,RValue<Short4> y)3528*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> paddsw(RValue<Short4> x, RValue<Short4> y)
3529*03ce13f7SAndroid Build Coastguard Worker {
3530*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPSADDSAT(V(x.value()), V(y.value()))));
3531*03ce13f7SAndroid Build Coastguard Worker }
3532*03ce13f7SAndroid Build Coastguard Worker 
psubsw(RValue<Short4> x,RValue<Short4> y)3533*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> psubsw(RValue<Short4> x, RValue<Short4> y)
3534*03ce13f7SAndroid Build Coastguard Worker {
3535*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPSSUBSAT(V(x.value()), V(y.value()))));
3536*03ce13f7SAndroid Build Coastguard Worker }
3537*03ce13f7SAndroid Build Coastguard Worker 
paddusw(RValue<UShort4> x,RValue<UShort4> y)3538*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> paddusw(RValue<UShort4> x, RValue<UShort4> y)
3539*03ce13f7SAndroid Build Coastguard Worker {
3540*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerPUADDSAT(V(x.value()), V(y.value()))));
3541*03ce13f7SAndroid Build Coastguard Worker }
3542*03ce13f7SAndroid Build Coastguard Worker 
psubusw(RValue<UShort4> x,RValue<UShort4> y)3543*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> psubusw(RValue<UShort4> x, RValue<UShort4> y)
3544*03ce13f7SAndroid Build Coastguard Worker {
3545*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerPUSUBSAT(V(x.value()), V(y.value()))));
3546*03ce13f7SAndroid Build Coastguard Worker }
3547*03ce13f7SAndroid Build Coastguard Worker 
paddsb(RValue<SByte8> x,RValue<SByte8> y)3548*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> paddsb(RValue<SByte8> x, RValue<SByte8> y)
3549*03ce13f7SAndroid Build Coastguard Worker {
3550*03ce13f7SAndroid Build Coastguard Worker 	return As<SByte8>(V(lowerPSADDSAT(V(x.value()), V(y.value()))));
3551*03ce13f7SAndroid Build Coastguard Worker }
3552*03ce13f7SAndroid Build Coastguard Worker 
psubsb(RValue<SByte8> x,RValue<SByte8> y)3553*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> psubsb(RValue<SByte8> x, RValue<SByte8> y)
3554*03ce13f7SAndroid Build Coastguard Worker {
3555*03ce13f7SAndroid Build Coastguard Worker 	return As<SByte8>(V(lowerPSSUBSAT(V(x.value()), V(y.value()))));
3556*03ce13f7SAndroid Build Coastguard Worker }
3557*03ce13f7SAndroid Build Coastguard Worker 
paddusb(RValue<Byte8> x,RValue<Byte8> y)3558*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> paddusb(RValue<Byte8> x, RValue<Byte8> y)
3559*03ce13f7SAndroid Build Coastguard Worker {
3560*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPUADDSAT(V(x.value()), V(y.value()))));
3561*03ce13f7SAndroid Build Coastguard Worker }
3562*03ce13f7SAndroid Build Coastguard Worker 
psubusb(RValue<Byte8> x,RValue<Byte8> y)3563*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> psubusb(RValue<Byte8> x, RValue<Byte8> y)
3564*03ce13f7SAndroid Build Coastguard Worker {
3565*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPUSUBSAT(V(x.value()), V(y.value()))));
3566*03ce13f7SAndroid Build Coastguard Worker }
3567*03ce13f7SAndroid Build Coastguard Worker 
pavgw(RValue<UShort4> x,RValue<UShort4> y)3568*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> pavgw(RValue<UShort4> x, RValue<UShort4> y)
3569*03ce13f7SAndroid Build Coastguard Worker {
3570*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(V(lowerPAVG(V(x.value()), V(y.value()))));
3571*03ce13f7SAndroid Build Coastguard Worker }
3572*03ce13f7SAndroid Build Coastguard Worker 
pmaxsw(RValue<Short4> x,RValue<Short4> y)3573*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> pmaxsw(RValue<Short4> x, RValue<Short4> y)
3574*03ce13f7SAndroid Build Coastguard Worker {
3575*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPMINMAX(V(x.value()), V(y.value()), llvm::ICmpInst::ICMP_SGT)));
3576*03ce13f7SAndroid Build Coastguard Worker }
3577*03ce13f7SAndroid Build Coastguard Worker 
pminsw(RValue<Short4> x,RValue<Short4> y)3578*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> pminsw(RValue<Short4> x, RValue<Short4> y)
3579*03ce13f7SAndroid Build Coastguard Worker {
3580*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPMINMAX(V(x.value()), V(y.value()), llvm::ICmpInst::ICMP_SLT)));
3581*03ce13f7SAndroid Build Coastguard Worker }
3582*03ce13f7SAndroid Build Coastguard Worker 
pcmpgtw(RValue<Short4> x,RValue<Short4> y)3583*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> pcmpgtw(RValue<Short4> x, RValue<Short4> y)
3584*03ce13f7SAndroid Build Coastguard Worker {
3585*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPCMP(llvm::ICmpInst::ICMP_SGT, V(x.value()), V(y.value()), T(Short4::type()))));
3586*03ce13f7SAndroid Build Coastguard Worker }
3587*03ce13f7SAndroid Build Coastguard Worker 
pcmpeqw(RValue<Short4> x,RValue<Short4> y)3588*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> pcmpeqw(RValue<Short4> x, RValue<Short4> y)
3589*03ce13f7SAndroid Build Coastguard Worker {
3590*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(V(lowerPCMP(llvm::ICmpInst::ICMP_EQ, V(x.value()), V(y.value()), T(Short4::type()))));
3591*03ce13f7SAndroid Build Coastguard Worker }
3592*03ce13f7SAndroid Build Coastguard Worker 
pcmpgtb(RValue<SByte8> x,RValue<SByte8> y)3593*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> pcmpgtb(RValue<SByte8> x, RValue<SByte8> y)
3594*03ce13f7SAndroid Build Coastguard Worker {
3595*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPCMP(llvm::ICmpInst::ICMP_SGT, V(x.value()), V(y.value()), T(Byte8::type()))));
3596*03ce13f7SAndroid Build Coastguard Worker }
3597*03ce13f7SAndroid Build Coastguard Worker 
pcmpeqb(RValue<Byte8> x,RValue<Byte8> y)3598*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> pcmpeqb(RValue<Byte8> x, RValue<Byte8> y)
3599*03ce13f7SAndroid Build Coastguard Worker {
3600*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(V(lowerPCMP(llvm::ICmpInst::ICMP_EQ, V(x.value()), V(y.value()), T(Byte8::type()))));
3601*03ce13f7SAndroid Build Coastguard Worker }
3602*03ce13f7SAndroid Build Coastguard Worker 
packssdw(RValue<Int2> x,RValue<Int2> y)3603*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> packssdw(RValue<Int2> x, RValue<Int2> y)
3604*03ce13f7SAndroid Build Coastguard Worker {
3605*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(createInstruction(llvm::Intrinsic::x86_sse2_packssdw_128, x.value(), y.value()));
3606*03ce13f7SAndroid Build Coastguard Worker }
3607*03ce13f7SAndroid Build Coastguard Worker 
packssdw(RValue<Int4> x,RValue<Int4> y)3608*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> packssdw(RValue<Int4> x, RValue<Int4> y)
3609*03ce13f7SAndroid Build Coastguard Worker {
3610*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Short8>(createInstruction(llvm::Intrinsic::x86_sse2_packssdw_128, x.value(), y.value()));
3611*03ce13f7SAndroid Build Coastguard Worker }
3612*03ce13f7SAndroid Build Coastguard Worker 
packsswb(RValue<Short4> x,RValue<Short4> y)3613*03ce13f7SAndroid Build Coastguard Worker RValue<SByte8> packsswb(RValue<Short4> x, RValue<Short4> y)
3614*03ce13f7SAndroid Build Coastguard Worker {
3615*03ce13f7SAndroid Build Coastguard Worker 	return As<SByte8>(createInstruction(llvm::Intrinsic::x86_sse2_packsswb_128, x.value(), y.value()));
3616*03ce13f7SAndroid Build Coastguard Worker }
3617*03ce13f7SAndroid Build Coastguard Worker 
packuswb(RValue<Short4> x,RValue<Short4> y)3618*03ce13f7SAndroid Build Coastguard Worker RValue<Byte8> packuswb(RValue<Short4> x, RValue<Short4> y)
3619*03ce13f7SAndroid Build Coastguard Worker {
3620*03ce13f7SAndroid Build Coastguard Worker 	return As<Byte8>(createInstruction(llvm::Intrinsic::x86_sse2_packuswb_128, x.value(), y.value()));
3621*03ce13f7SAndroid Build Coastguard Worker }
3622*03ce13f7SAndroid Build Coastguard Worker 
packusdw(RValue<Int4> x,RValue<Int4> y)3623*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> packusdw(RValue<Int4> x, RValue<Int4> y)
3624*03ce13f7SAndroid Build Coastguard Worker {
3625*03ce13f7SAndroid Build Coastguard Worker 	if(CPUID::supportsSSE4_1())
3626*03ce13f7SAndroid Build Coastguard Worker 	{
3627*03ce13f7SAndroid Build Coastguard Worker 		return RValue<UShort8>(createInstruction(llvm::Intrinsic::x86_sse41_packusdw, x.value(), y.value()));
3628*03ce13f7SAndroid Build Coastguard Worker 	}
3629*03ce13f7SAndroid Build Coastguard Worker 	else
3630*03ce13f7SAndroid Build Coastguard Worker 	{
3631*03ce13f7SAndroid Build Coastguard Worker 		RValue<Int4> bx = (x & ~(x >> 31)) - Int4(0x8000);
3632*03ce13f7SAndroid Build Coastguard Worker 		RValue<Int4> by = (y & ~(y >> 31)) - Int4(0x8000);
3633*03ce13f7SAndroid Build Coastguard Worker 
3634*03ce13f7SAndroid Build Coastguard Worker 		return As<UShort8>(packssdw(bx, by) + Short8(0x8000u));
3635*03ce13f7SAndroid Build Coastguard Worker 	}
3636*03ce13f7SAndroid Build Coastguard Worker }
3637*03ce13f7SAndroid Build Coastguard Worker 
psrlw(RValue<UShort4> x,unsigned char y)3638*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> psrlw(RValue<UShort4> x, unsigned char y)
3639*03ce13f7SAndroid Build Coastguard Worker {
3640*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(createInstruction(llvm::Intrinsic::x86_sse2_psrli_w, x.value(), Nucleus::createConstantInt(y)));
3641*03ce13f7SAndroid Build Coastguard Worker }
3642*03ce13f7SAndroid Build Coastguard Worker 
psrlw(RValue<UShort8> x,unsigned char y)3643*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> psrlw(RValue<UShort8> x, unsigned char y)
3644*03ce13f7SAndroid Build Coastguard Worker {
3645*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UShort8>(createInstruction(llvm::Intrinsic::x86_sse2_psrli_w, x.value(), Nucleus::createConstantInt(y)));
3646*03ce13f7SAndroid Build Coastguard Worker }
3647*03ce13f7SAndroid Build Coastguard Worker 
psraw(RValue<Short4> x,unsigned char y)3648*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> psraw(RValue<Short4> x, unsigned char y)
3649*03ce13f7SAndroid Build Coastguard Worker {
3650*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(createInstruction(llvm::Intrinsic::x86_sse2_psrai_w, x.value(), Nucleus::createConstantInt(y)));
3651*03ce13f7SAndroid Build Coastguard Worker }
3652*03ce13f7SAndroid Build Coastguard Worker 
psraw(RValue<Short8> x,unsigned char y)3653*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> psraw(RValue<Short8> x, unsigned char y)
3654*03ce13f7SAndroid Build Coastguard Worker {
3655*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Short8>(createInstruction(llvm::Intrinsic::x86_sse2_psrai_w, x.value(), Nucleus::createConstantInt(y)));
3656*03ce13f7SAndroid Build Coastguard Worker }
3657*03ce13f7SAndroid Build Coastguard Worker 
psllw(RValue<Short4> x,unsigned char y)3658*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> psllw(RValue<Short4> x, unsigned char y)
3659*03ce13f7SAndroid Build Coastguard Worker {
3660*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(createInstruction(llvm::Intrinsic::x86_sse2_pslli_w, x.value(), Nucleus::createConstantInt(y)));
3661*03ce13f7SAndroid Build Coastguard Worker }
3662*03ce13f7SAndroid Build Coastguard Worker 
psllw(RValue<Short8> x,unsigned char y)3663*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> psllw(RValue<Short8> x, unsigned char y)
3664*03ce13f7SAndroid Build Coastguard Worker {
3665*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Short8>(createInstruction(llvm::Intrinsic::x86_sse2_pslli_w, x.value(), Nucleus::createConstantInt(y)));
3666*03ce13f7SAndroid Build Coastguard Worker }
3667*03ce13f7SAndroid Build Coastguard Worker 
pslld(RValue<Int2> x,unsigned char y)3668*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> pslld(RValue<Int2> x, unsigned char y)
3669*03ce13f7SAndroid Build Coastguard Worker {
3670*03ce13f7SAndroid Build Coastguard Worker 	return As<Int2>(createInstruction(llvm::Intrinsic::x86_sse2_pslli_d, x.value(), Nucleus::createConstantInt(y)));
3671*03ce13f7SAndroid Build Coastguard Worker }
3672*03ce13f7SAndroid Build Coastguard Worker 
pslld(RValue<Int4> x,unsigned char y)3673*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> pslld(RValue<Int4> x, unsigned char y)
3674*03ce13f7SAndroid Build Coastguard Worker {
3675*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(createInstruction(llvm::Intrinsic::x86_sse2_pslli_d, x.value(), Nucleus::createConstantInt(y)));
3676*03ce13f7SAndroid Build Coastguard Worker }
3677*03ce13f7SAndroid Build Coastguard Worker 
psrad(RValue<Int2> x,unsigned char y)3678*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> psrad(RValue<Int2> x, unsigned char y)
3679*03ce13f7SAndroid Build Coastguard Worker {
3680*03ce13f7SAndroid Build Coastguard Worker 	return As<Int2>(createInstruction(llvm::Intrinsic::x86_sse2_psrai_d, x.value(), Nucleus::createConstantInt(y)));
3681*03ce13f7SAndroid Build Coastguard Worker }
3682*03ce13f7SAndroid Build Coastguard Worker 
psrad(RValue<Int4> x,unsigned char y)3683*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> psrad(RValue<Int4> x, unsigned char y)
3684*03ce13f7SAndroid Build Coastguard Worker {
3685*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(createInstruction(llvm::Intrinsic::x86_sse2_psrai_d, x.value(), Nucleus::createConstantInt(y)));
3686*03ce13f7SAndroid Build Coastguard Worker }
3687*03ce13f7SAndroid Build Coastguard Worker 
psrld(RValue<UInt2> x,unsigned char y)3688*03ce13f7SAndroid Build Coastguard Worker RValue<UInt2> psrld(RValue<UInt2> x, unsigned char y)
3689*03ce13f7SAndroid Build Coastguard Worker {
3690*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt2>(createInstruction(llvm::Intrinsic::x86_sse2_psrli_d, x.value(), Nucleus::createConstantInt(y)));
3691*03ce13f7SAndroid Build Coastguard Worker }
3692*03ce13f7SAndroid Build Coastguard Worker 
psrld(RValue<UInt4> x,unsigned char y)3693*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> psrld(RValue<UInt4> x, unsigned char y)
3694*03ce13f7SAndroid Build Coastguard Worker {
3695*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(createInstruction(llvm::Intrinsic::x86_sse2_psrli_d, x.value(), Nucleus::createConstantInt(y)));
3696*03ce13f7SAndroid Build Coastguard Worker }
3697*03ce13f7SAndroid Build Coastguard Worker 
pmaxsd(RValue<Int4> x,RValue<Int4> y)3698*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> pmaxsd(RValue<Int4> x, RValue<Int4> y)
3699*03ce13f7SAndroid Build Coastguard Worker {
3700*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(V(lowerPMINMAX(V(x.value()), V(y.value()), llvm::ICmpInst::ICMP_SGT)));
3701*03ce13f7SAndroid Build Coastguard Worker }
3702*03ce13f7SAndroid Build Coastguard Worker 
pminsd(RValue<Int4> x,RValue<Int4> y)3703*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> pminsd(RValue<Int4> x, RValue<Int4> y)
3704*03ce13f7SAndroid Build Coastguard Worker {
3705*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(V(lowerPMINMAX(V(x.value()), V(y.value()), llvm::ICmpInst::ICMP_SLT)));
3706*03ce13f7SAndroid Build Coastguard Worker }
3707*03ce13f7SAndroid Build Coastguard Worker 
pmaxud(RValue<UInt4> x,RValue<UInt4> y)3708*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> pmaxud(RValue<UInt4> x, RValue<UInt4> y)
3709*03ce13f7SAndroid Build Coastguard Worker {
3710*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(V(lowerPMINMAX(V(x.value()), V(y.value()), llvm::ICmpInst::ICMP_UGT)));
3711*03ce13f7SAndroid Build Coastguard Worker }
3712*03ce13f7SAndroid Build Coastguard Worker 
pminud(RValue<UInt4> x,RValue<UInt4> y)3713*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> pminud(RValue<UInt4> x, RValue<UInt4> y)
3714*03ce13f7SAndroid Build Coastguard Worker {
3715*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UInt4>(V(lowerPMINMAX(V(x.value()), V(y.value()), llvm::ICmpInst::ICMP_ULT)));
3716*03ce13f7SAndroid Build Coastguard Worker }
3717*03ce13f7SAndroid Build Coastguard Worker 
pmulhw(RValue<Short4> x,RValue<Short4> y)3718*03ce13f7SAndroid Build Coastguard Worker RValue<Short4> pmulhw(RValue<Short4> x, RValue<Short4> y)
3719*03ce13f7SAndroid Build Coastguard Worker {
3720*03ce13f7SAndroid Build Coastguard Worker 	return As<Short4>(createInstruction(llvm::Intrinsic::x86_sse2_pmulh_w, x.value(), y.value()));
3721*03ce13f7SAndroid Build Coastguard Worker }
3722*03ce13f7SAndroid Build Coastguard Worker 
pmulhuw(RValue<UShort4> x,RValue<UShort4> y)3723*03ce13f7SAndroid Build Coastguard Worker RValue<UShort4> pmulhuw(RValue<UShort4> x, RValue<UShort4> y)
3724*03ce13f7SAndroid Build Coastguard Worker {
3725*03ce13f7SAndroid Build Coastguard Worker 	return As<UShort4>(createInstruction(llvm::Intrinsic::x86_sse2_pmulhu_w, x.value(), y.value()));
3726*03ce13f7SAndroid Build Coastguard Worker }
3727*03ce13f7SAndroid Build Coastguard Worker 
pmaddwd(RValue<Short4> x,RValue<Short4> y)3728*03ce13f7SAndroid Build Coastguard Worker RValue<Int2> pmaddwd(RValue<Short4> x, RValue<Short4> y)
3729*03ce13f7SAndroid Build Coastguard Worker {
3730*03ce13f7SAndroid Build Coastguard Worker 	return As<Int2>(createInstruction(llvm::Intrinsic::x86_sse2_pmadd_wd, x.value(), y.value()));
3731*03ce13f7SAndroid Build Coastguard Worker }
3732*03ce13f7SAndroid Build Coastguard Worker 
pmulhw(RValue<Short8> x,RValue<Short8> y)3733*03ce13f7SAndroid Build Coastguard Worker RValue<Short8> pmulhw(RValue<Short8> x, RValue<Short8> y)
3734*03ce13f7SAndroid Build Coastguard Worker {
3735*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Short8>(createInstruction(llvm::Intrinsic::x86_sse2_pmulh_w, x.value(), y.value()));
3736*03ce13f7SAndroid Build Coastguard Worker }
3737*03ce13f7SAndroid Build Coastguard Worker 
pmulhuw(RValue<UShort8> x,RValue<UShort8> y)3738*03ce13f7SAndroid Build Coastguard Worker RValue<UShort8> pmulhuw(RValue<UShort8> x, RValue<UShort8> y)
3739*03ce13f7SAndroid Build Coastguard Worker {
3740*03ce13f7SAndroid Build Coastguard Worker 	return RValue<UShort8>(createInstruction(llvm::Intrinsic::x86_sse2_pmulhu_w, x.value(), y.value()));
3741*03ce13f7SAndroid Build Coastguard Worker }
3742*03ce13f7SAndroid Build Coastguard Worker 
pmaddwd(RValue<Short8> x,RValue<Short8> y)3743*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> pmaddwd(RValue<Short8> x, RValue<Short8> y)
3744*03ce13f7SAndroid Build Coastguard Worker {
3745*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int4>(createInstruction(llvm::Intrinsic::x86_sse2_pmadd_wd, x.value(), y.value()));
3746*03ce13f7SAndroid Build Coastguard Worker }
3747*03ce13f7SAndroid Build Coastguard Worker 
movmskps(RValue<Float4> x)3748*03ce13f7SAndroid Build Coastguard Worker RValue<Int> movmskps(RValue<Float4> x)
3749*03ce13f7SAndroid Build Coastguard Worker {
3750*03ce13f7SAndroid Build Coastguard Worker 	Value *v = x.value();
3751*03ce13f7SAndroid Build Coastguard Worker 
3752*03ce13f7SAndroid Build Coastguard Worker 	// TODO(b/172238865): MemorySanitizer does not support movmsk instructions,
3753*03ce13f7SAndroid Build Coastguard Worker 	// which makes it look at the entire 128-bit input for undefined bits. Mask off
3754*03ce13f7SAndroid Build Coastguard Worker 	// just the sign bits to avoid false positives.
3755*03ce13f7SAndroid Build Coastguard Worker 	if(__has_feature(memory_sanitizer))
3756*03ce13f7SAndroid Build Coastguard Worker 	{
3757*03ce13f7SAndroid Build Coastguard Worker 		v = As<Float4>(As<Int4>(v) & Int4(0x80000000u)).value();
3758*03ce13f7SAndroid Build Coastguard Worker 	}
3759*03ce13f7SAndroid Build Coastguard Worker 
3760*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int>(createInstruction(llvm::Intrinsic::x86_sse_movmsk_ps, v));
3761*03ce13f7SAndroid Build Coastguard Worker }
3762*03ce13f7SAndroid Build Coastguard Worker 
pmovmskb(RValue<Byte8> x)3763*03ce13f7SAndroid Build Coastguard Worker RValue<Int> pmovmskb(RValue<Byte8> x)
3764*03ce13f7SAndroid Build Coastguard Worker {
3765*03ce13f7SAndroid Build Coastguard Worker 	Value *v = x.value();
3766*03ce13f7SAndroid Build Coastguard Worker 
3767*03ce13f7SAndroid Build Coastguard Worker 	// TODO(b/172238865): MemorySanitizer does not support movmsk instructions,
3768*03ce13f7SAndroid Build Coastguard Worker 	// which makes it look at the entire 128-bit input for undefined bits. Mask off
3769*03ce13f7SAndroid Build Coastguard Worker 	// just the sign bits in the lower 64-bit vector to avoid false positives.
3770*03ce13f7SAndroid Build Coastguard Worker 	if(__has_feature(memory_sanitizer))
3771*03ce13f7SAndroid Build Coastguard Worker 	{
3772*03ce13f7SAndroid Build Coastguard Worker 		v = As<Byte16>(As<Int4>(v) & Int4(0x80808080u, 0x80808080u, 0, 0)).value();
3773*03ce13f7SAndroid Build Coastguard Worker 	}
3774*03ce13f7SAndroid Build Coastguard Worker 
3775*03ce13f7SAndroid Build Coastguard Worker 	return RValue<Int>(createInstruction(llvm::Intrinsic::x86_sse2_pmovmskb_128, v)) & 0xFF;
3776*03ce13f7SAndroid Build Coastguard Worker }
3777*03ce13f7SAndroid Build Coastguard Worker 
3778*03ce13f7SAndroid Build Coastguard Worker }  // namespace x86
3779*03ce13f7SAndroid Build Coastguard Worker #endif  // defined(__i386__) || defined(__x86_64__)
3780*03ce13f7SAndroid Build Coastguard Worker 
3781*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_PRINT
VPrintf(const std::vector<Value * > & vals)3782*03ce13f7SAndroid Build Coastguard Worker void VPrintf(const std::vector<Value *> &vals)
3783*03ce13f7SAndroid Build Coastguard Worker {
3784*03ce13f7SAndroid Build Coastguard Worker 	auto i32Ty = llvm::Type::getInt32Ty(*jit->context);
3785*03ce13f7SAndroid Build Coastguard Worker 	auto i8PtrTy = llvm::Type::getInt8PtrTy(*jit->context);
3786*03ce13f7SAndroid Build Coastguard Worker 	auto funcTy = llvm::FunctionType::get(i32Ty, { i8PtrTy }, true);
3787*03ce13f7SAndroid Build Coastguard Worker 	auto func = jit->module->getOrInsertFunction("rr::DebugPrintf", funcTy);
3788*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateCall(func, V(vals));
3789*03ce13f7SAndroid Build Coastguard Worker }
3790*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_PRINT
3791*03ce13f7SAndroid Build Coastguard Worker 
Nop()3792*03ce13f7SAndroid Build Coastguard Worker void Nop()
3793*03ce13f7SAndroid Build Coastguard Worker {
3794*03ce13f7SAndroid Build Coastguard Worker 	auto voidTy = llvm::Type::getVoidTy(*jit->context);
3795*03ce13f7SAndroid Build Coastguard Worker 	auto funcTy = llvm::FunctionType::get(voidTy, {}, false);
3796*03ce13f7SAndroid Build Coastguard Worker 	auto func = jit->module->getOrInsertFunction("nop", funcTy);
3797*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateCall(func);
3798*03ce13f7SAndroid Build Coastguard Worker }
3799*03ce13f7SAndroid Build Coastguard Worker 
EmitDebugLocation()3800*03ce13f7SAndroid Build Coastguard Worker void EmitDebugLocation()
3801*03ce13f7SAndroid Build Coastguard Worker {
3802*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
3803*03ce13f7SAndroid Build Coastguard Worker 	if(jit->debugInfo != nullptr)
3804*03ce13f7SAndroid Build Coastguard Worker 	{
3805*03ce13f7SAndroid Build Coastguard Worker 		jit->debugInfo->EmitLocation();
3806*03ce13f7SAndroid Build Coastguard Worker 	}
3807*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_DEBUG_INFO
3808*03ce13f7SAndroid Build Coastguard Worker }
3809*03ce13f7SAndroid Build Coastguard Worker 
EmitDebugVariable(Value * value)3810*03ce13f7SAndroid Build Coastguard Worker void EmitDebugVariable(Value *value)
3811*03ce13f7SAndroid Build Coastguard Worker {
3812*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
3813*03ce13f7SAndroid Build Coastguard Worker 	if(jit->debugInfo != nullptr)
3814*03ce13f7SAndroid Build Coastguard Worker 	{
3815*03ce13f7SAndroid Build Coastguard Worker 		jit->debugInfo->EmitVariable(value);
3816*03ce13f7SAndroid Build Coastguard Worker 	}
3817*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_DEBUG_INFO
3818*03ce13f7SAndroid Build Coastguard Worker }
3819*03ce13f7SAndroid Build Coastguard Worker 
FlushDebug()3820*03ce13f7SAndroid Build Coastguard Worker void FlushDebug()
3821*03ce13f7SAndroid Build Coastguard Worker {
3822*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
3823*03ce13f7SAndroid Build Coastguard Worker 	if(jit->debugInfo != nullptr)
3824*03ce13f7SAndroid Build Coastguard Worker 	{
3825*03ce13f7SAndroid Build Coastguard Worker 		jit->debugInfo->Flush();
3826*03ce13f7SAndroid Build Coastguard Worker 	}
3827*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_DEBUG_INFO
3828*03ce13f7SAndroid Build Coastguard Worker }
3829*03ce13f7SAndroid Build Coastguard Worker 
3830*03ce13f7SAndroid Build Coastguard Worker }  // namespace rr
3831*03ce13f7SAndroid Build Coastguard Worker 
3832*03ce13f7SAndroid Build Coastguard Worker // ------------------------------  Coroutines ------------------------------
3833*03ce13f7SAndroid Build Coastguard Worker 
3834*03ce13f7SAndroid Build Coastguard Worker namespace {
3835*03ce13f7SAndroid Build Coastguard Worker 
3836*03ce13f7SAndroid Build Coastguard Worker // Magic values retuned by llvm.coro.suspend.
3837*03ce13f7SAndroid Build Coastguard Worker // See: https://llvm.org/docs/Coroutines.html#llvm-coro-suspend-intrinsic
3838*03ce13f7SAndroid Build Coastguard Worker enum SuspendAction
3839*03ce13f7SAndroid Build Coastguard Worker {
3840*03ce13f7SAndroid Build Coastguard Worker 	SuspendActionSuspend = -1,
3841*03ce13f7SAndroid Build Coastguard Worker 	SuspendActionResume = 0,
3842*03ce13f7SAndroid Build Coastguard Worker 	SuspendActionDestroy = 1
3843*03ce13f7SAndroid Build Coastguard Worker };
3844*03ce13f7SAndroid Build Coastguard Worker 
promoteFunctionToCoroutine()3845*03ce13f7SAndroid Build Coastguard Worker void promoteFunctionToCoroutine()
3846*03ce13f7SAndroid Build Coastguard Worker {
3847*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(jit->coroutine.id == nullptr);
3848*03ce13f7SAndroid Build Coastguard Worker 
3849*03ce13f7SAndroid Build Coastguard Worker 	// Types
3850*03ce13f7SAndroid Build Coastguard Worker 	auto voidTy = llvm::Type::getVoidTy(*jit->context);
3851*03ce13f7SAndroid Build Coastguard Worker 	auto i1Ty = llvm::Type::getInt1Ty(*jit->context);
3852*03ce13f7SAndroid Build Coastguard Worker 	auto i8Ty = llvm::Type::getInt8Ty(*jit->context);
3853*03ce13f7SAndroid Build Coastguard Worker 	auto i32Ty = llvm::Type::getInt32Ty(*jit->context);
3854*03ce13f7SAndroid Build Coastguard Worker 	auto i8PtrTy = llvm::Type::getInt8PtrTy(*jit->context);
3855*03ce13f7SAndroid Build Coastguard Worker 	auto promiseTy = jit->coroutine.yieldType;
3856*03ce13f7SAndroid Build Coastguard Worker 	auto promisePtrTy = promiseTy->getPointerTo();
3857*03ce13f7SAndroid Build Coastguard Worker 
3858*03ce13f7SAndroid Build Coastguard Worker 	// LLVM intrinsics
3859*03ce13f7SAndroid Build Coastguard Worker 	auto coro_id = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_id);
3860*03ce13f7SAndroid Build Coastguard Worker 	auto coro_size = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_size, { i32Ty });
3861*03ce13f7SAndroid Build Coastguard Worker 	auto coro_begin = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_begin);
3862*03ce13f7SAndroid Build Coastguard Worker 	auto coro_resume = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_resume);
3863*03ce13f7SAndroid Build Coastguard Worker 	auto coro_end = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_end);
3864*03ce13f7SAndroid Build Coastguard Worker 	auto coro_free = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_free);
3865*03ce13f7SAndroid Build Coastguard Worker 	auto coro_destroy = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_destroy);
3866*03ce13f7SAndroid Build Coastguard Worker 	auto coro_promise = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_promise);
3867*03ce13f7SAndroid Build Coastguard Worker 	auto coro_done = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_done);
3868*03ce13f7SAndroid Build Coastguard Worker 	auto coro_suspend = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_suspend);
3869*03ce13f7SAndroid Build Coastguard Worker 
3870*03ce13f7SAndroid Build Coastguard Worker 	auto allocFrameTy = llvm::FunctionType::get(i8PtrTy, { i32Ty }, false);
3871*03ce13f7SAndroid Build Coastguard Worker 	auto allocFrame = jit->module->getOrInsertFunction("coroutine_alloc_frame", allocFrameTy);
3872*03ce13f7SAndroid Build Coastguard Worker 	auto freeFrameTy = llvm::FunctionType::get(voidTy, { i8PtrTy }, false);
3873*03ce13f7SAndroid Build Coastguard Worker 	auto freeFrame = jit->module->getOrInsertFunction("coroutine_free_frame", freeFrameTy);
3874*03ce13f7SAndroid Build Coastguard Worker 
3875*03ce13f7SAndroid Build Coastguard Worker 	auto oldInsertionPoint = jit->builder->saveIP();
3876*03ce13f7SAndroid Build Coastguard Worker 
3877*03ce13f7SAndroid Build Coastguard Worker 	// Build the coroutine_await() function:
3878*03ce13f7SAndroid Build Coastguard Worker 	//
3879*03ce13f7SAndroid Build Coastguard Worker 	//    bool coroutine_await(CoroutineHandle* handle, YieldType* out)
3880*03ce13f7SAndroid Build Coastguard Worker 	//    {
3881*03ce13f7SAndroid Build Coastguard Worker 	//        if(llvm.coro.done(handle))
3882*03ce13f7SAndroid Build Coastguard Worker 	//        {
3883*03ce13f7SAndroid Build Coastguard Worker 	//            return false;
3884*03ce13f7SAndroid Build Coastguard Worker 	//        }
3885*03ce13f7SAndroid Build Coastguard Worker 	//        else
3886*03ce13f7SAndroid Build Coastguard Worker 	//        {
3887*03ce13f7SAndroid Build Coastguard Worker 	//            *value = (T*)llvm.coro.promise(handle);
3888*03ce13f7SAndroid Build Coastguard Worker 	//            llvm.coro.resume(handle);
3889*03ce13f7SAndroid Build Coastguard Worker 	//            return true;
3890*03ce13f7SAndroid Build Coastguard Worker 	//        }
3891*03ce13f7SAndroid Build Coastguard Worker 	//    }
3892*03ce13f7SAndroid Build Coastguard Worker 	//
3893*03ce13f7SAndroid Build Coastguard Worker 	{
3894*03ce13f7SAndroid Build Coastguard Worker 		auto args = jit->coroutine.await->arg_begin();
3895*03ce13f7SAndroid Build Coastguard Worker 		auto handle = args++;
3896*03ce13f7SAndroid Build Coastguard Worker 		auto outPtr = args++;
3897*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->SetInsertPoint(llvm::BasicBlock::Create(*jit->context, "co_await", jit->coroutine.await));
3898*03ce13f7SAndroid Build Coastguard Worker 		auto doneBlock = llvm::BasicBlock::Create(*jit->context, "done", jit->coroutine.await);
3899*03ce13f7SAndroid Build Coastguard Worker 		auto resumeBlock = llvm::BasicBlock::Create(*jit->context, "resume", jit->coroutine.await);
3900*03ce13f7SAndroid Build Coastguard Worker 
3901*03ce13f7SAndroid Build Coastguard Worker 		auto done = jit->builder->CreateCall(coro_done, { handle }, "done");
3902*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateCondBr(done, doneBlock, resumeBlock);
3903*03ce13f7SAndroid Build Coastguard Worker 
3904*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->SetInsertPoint(doneBlock);
3905*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateRet(llvm::ConstantInt::getFalse(i1Ty));
3906*03ce13f7SAndroid Build Coastguard Worker 
3907*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->SetInsertPoint(resumeBlock);
3908*03ce13f7SAndroid Build Coastguard Worker 		auto promiseAlignment = llvm::ConstantInt::get(i32Ty, 4);  // TODO: Get correct alignment.
3909*03ce13f7SAndroid Build Coastguard Worker 		auto promisePtr = jit->builder->CreateCall(coro_promise, { handle, promiseAlignment, llvm::ConstantInt::get(i1Ty, 0) });
3910*03ce13f7SAndroid Build Coastguard Worker 		auto promise = jit->builder->CreateLoad(promiseTy, jit->builder->CreatePointerCast(promisePtr, promisePtrTy));
3911*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateStore(promise, outPtr);
3912*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateCall(coro_resume, { handle });
3913*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateRet(llvm::ConstantInt::getTrue(i1Ty));
3914*03ce13f7SAndroid Build Coastguard Worker 	}
3915*03ce13f7SAndroid Build Coastguard Worker 
3916*03ce13f7SAndroid Build Coastguard Worker 	// Build the coroutine_destroy() function:
3917*03ce13f7SAndroid Build Coastguard Worker 	//
3918*03ce13f7SAndroid Build Coastguard Worker 	//    void coroutine_destroy(CoroutineHandle* handle)
3919*03ce13f7SAndroid Build Coastguard Worker 	//    {
3920*03ce13f7SAndroid Build Coastguard Worker 	//        llvm.coro.destroy(handle);
3921*03ce13f7SAndroid Build Coastguard Worker 	//    }
3922*03ce13f7SAndroid Build Coastguard Worker 	//
3923*03ce13f7SAndroid Build Coastguard Worker 	{
3924*03ce13f7SAndroid Build Coastguard Worker 		auto handle = jit->coroutine.destroy->arg_begin();
3925*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->SetInsertPoint(llvm::BasicBlock::Create(*jit->context, "", jit->coroutine.destroy));
3926*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateCall(coro_destroy, { handle });
3927*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateRetVoid();
3928*03ce13f7SAndroid Build Coastguard Worker 	}
3929*03ce13f7SAndroid Build Coastguard Worker 
3930*03ce13f7SAndroid Build Coastguard Worker 	// Begin building the main coroutine_begin() function.
3931*03ce13f7SAndroid Build Coastguard Worker 	//
3932*03ce13f7SAndroid Build Coastguard Worker 	//    CoroutineHandle* coroutine_begin(<Arguments>)
3933*03ce13f7SAndroid Build Coastguard Worker 	//    {
3934*03ce13f7SAndroid Build Coastguard Worker 	//        YieldType promise;
3935*03ce13f7SAndroid Build Coastguard Worker 	//        auto id = llvm.coro.id(0, &promise, nullptr, nullptr);
3936*03ce13f7SAndroid Build Coastguard Worker 	//        void* frame = coroutine_alloc_frame(llvm.coro.size.i32());
3937*03ce13f7SAndroid Build Coastguard Worker 	//        CoroutineHandle *handle = llvm.coro.begin(id, frame);
3938*03ce13f7SAndroid Build Coastguard Worker 	//
3939*03ce13f7SAndroid Build Coastguard Worker 	//        ... <REACTOR CODE> ...
3940*03ce13f7SAndroid Build Coastguard Worker 	//
3941*03ce13f7SAndroid Build Coastguard Worker 	//    end:
3942*03ce13f7SAndroid Build Coastguard Worker 	//        SuspendAction action = llvm.coro.suspend(none, true /* final */);  // <-- RESUME POINT
3943*03ce13f7SAndroid Build Coastguard Worker 	//        switch(action)
3944*03ce13f7SAndroid Build Coastguard Worker 	//        {
3945*03ce13f7SAndroid Build Coastguard Worker 	//        case SuspendActionResume:
3946*03ce13f7SAndroid Build Coastguard Worker 	//            UNREACHABLE(); // Illegal to resume after final suspend.
3947*03ce13f7SAndroid Build Coastguard Worker 	//        case SuspendActionDestroy:
3948*03ce13f7SAndroid Build Coastguard Worker 	//            goto destroy;
3949*03ce13f7SAndroid Build Coastguard Worker 	//        default: // (SuspendActionSuspend)
3950*03ce13f7SAndroid Build Coastguard Worker 	//            goto suspend;
3951*03ce13f7SAndroid Build Coastguard Worker 	//        }
3952*03ce13f7SAndroid Build Coastguard Worker 	//
3953*03ce13f7SAndroid Build Coastguard Worker 	//    destroy:
3954*03ce13f7SAndroid Build Coastguard Worker 	//        coroutine_free_frame(llvm.coro.free(id, handle));
3955*03ce13f7SAndroid Build Coastguard Worker 	//        goto suspend;
3956*03ce13f7SAndroid Build Coastguard Worker 	//
3957*03ce13f7SAndroid Build Coastguard Worker 	//    suspend:
3958*03ce13f7SAndroid Build Coastguard Worker 	//        llvm.coro.end(handle, false);
3959*03ce13f7SAndroid Build Coastguard Worker 	//        return handle;
3960*03ce13f7SAndroid Build Coastguard Worker 	//    }
3961*03ce13f7SAndroid Build Coastguard Worker 	//
3962*03ce13f7SAndroid Build Coastguard Worker 
3963*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
3964*03ce13f7SAndroid Build Coastguard Worker 	jit->debugInfo = std::make_unique<rr::DebugInfo>(jit->builder.get(), jit->context.get(), jit->module.get(), jit->function);
3965*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_DEBUG_INFO
3966*03ce13f7SAndroid Build Coastguard Worker 
3967*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.suspendBlock = llvm::BasicBlock::Create(*jit->context, "suspend", jit->function);
3968*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.endBlock = llvm::BasicBlock::Create(*jit->context, "end", jit->function);
3969*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.destroyBlock = llvm::BasicBlock::Create(*jit->context, "destroy", jit->function);
3970*03ce13f7SAndroid Build Coastguard Worker 
3971*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->SetInsertPoint(jit->coroutine.entryBlock, jit->coroutine.entryBlock->begin());
3972*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.promise = jit->builder->CreateAlloca(promiseTy, nullptr, "promise");
3973*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.id = jit->builder->CreateCall(coro_id, {
3974*03ce13f7SAndroid Build Coastguard Worker 	                                                          llvm::ConstantInt::get(i32Ty, 0),
3975*03ce13f7SAndroid Build Coastguard Worker 	                                                          jit->builder->CreatePointerCast(jit->coroutine.promise, i8PtrTy),
3976*03ce13f7SAndroid Build Coastguard Worker 	                                                          llvm::ConstantPointerNull::get(i8PtrTy),
3977*03ce13f7SAndroid Build Coastguard Worker 	                                                          llvm::ConstantPointerNull::get(i8PtrTy),
3978*03ce13f7SAndroid Build Coastguard Worker 	                                                      });
3979*03ce13f7SAndroid Build Coastguard Worker 	auto size = jit->builder->CreateCall(coro_size, {});
3980*03ce13f7SAndroid Build Coastguard Worker 	auto frame = jit->builder->CreateCall(allocFrame, { size });
3981*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.handle = jit->builder->CreateCall(coro_begin, { jit->coroutine.id, frame });
3982*03ce13f7SAndroid Build Coastguard Worker 
3983*03ce13f7SAndroid Build Coastguard Worker 	// Build the suspend block
3984*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->SetInsertPoint(jit->coroutine.suspendBlock);
3985*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateCall(coro_end, { jit->coroutine.handle, llvm::ConstantInt::get(i1Ty, 0) });
3986*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateRet(jit->coroutine.handle);
3987*03ce13f7SAndroid Build Coastguard Worker 
3988*03ce13f7SAndroid Build Coastguard Worker 	// Build the end block
3989*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->SetInsertPoint(jit->coroutine.endBlock);
3990*03ce13f7SAndroid Build Coastguard Worker 	auto action = jit->builder->CreateCall(coro_suspend, {
3991*03ce13f7SAndroid Build Coastguard Worker 	                                                         llvm::ConstantTokenNone::get(*jit->context),
3992*03ce13f7SAndroid Build Coastguard Worker 	                                                         llvm::ConstantInt::get(i1Ty, 1),  // final: true
3993*03ce13f7SAndroid Build Coastguard Worker 	                                                     });
3994*03ce13f7SAndroid Build Coastguard Worker 	auto switch_ = jit->builder->CreateSwitch(action, jit->coroutine.suspendBlock, 3);
3995*03ce13f7SAndroid Build Coastguard Worker 	// switch_->addCase(llvm::ConstantInt::get(i8Ty, SuspendActionResume), trapBlock); // TODO: Trap attempting to resume after final suspend
3996*03ce13f7SAndroid Build Coastguard Worker 	switch_->addCase(llvm::ConstantInt::get(i8Ty, SuspendActionDestroy), jit->coroutine.destroyBlock);
3997*03ce13f7SAndroid Build Coastguard Worker 
3998*03ce13f7SAndroid Build Coastguard Worker 	// Build the destroy block
3999*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->SetInsertPoint(jit->coroutine.destroyBlock);
4000*03ce13f7SAndroid Build Coastguard Worker 	auto memory = jit->builder->CreateCall(coro_free, { jit->coroutine.id, jit->coroutine.handle });
4001*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateCall(freeFrame, { memory });
4002*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateBr(jit->coroutine.suspendBlock);
4003*03ce13f7SAndroid Build Coastguard Worker 
4004*03ce13f7SAndroid Build Coastguard Worker 	// Switch back to original insert point to continue building the coroutine.
4005*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->restoreIP(oldInsertionPoint);
4006*03ce13f7SAndroid Build Coastguard Worker }
4007*03ce13f7SAndroid Build Coastguard Worker 
4008*03ce13f7SAndroid Build Coastguard Worker }  // anonymous namespace
4009*03ce13f7SAndroid Build Coastguard Worker 
4010*03ce13f7SAndroid Build Coastguard Worker namespace rr {
4011*03ce13f7SAndroid Build Coastguard Worker 
createCoroutine(Type * YieldType,const std::vector<Type * > & Params)4012*03ce13f7SAndroid Build Coastguard Worker void Nucleus::createCoroutine(Type *YieldType, const std::vector<Type *> &Params)
4013*03ce13f7SAndroid Build Coastguard Worker {
4014*03ce13f7SAndroid Build Coastguard Worker 	// Coroutines are initially created as a regular function.
4015*03ce13f7SAndroid Build Coastguard Worker 	// Upon the first call to Yield(), the function is promoted to a true
4016*03ce13f7SAndroid Build Coastguard Worker 	// coroutine.
4017*03ce13f7SAndroid Build Coastguard Worker 	auto voidTy = llvm::Type::getVoidTy(*jit->context);
4018*03ce13f7SAndroid Build Coastguard Worker 	auto i1Ty = llvm::Type::getInt1Ty(*jit->context);
4019*03ce13f7SAndroid Build Coastguard Worker 	auto i8PtrTy = llvm::Type::getInt8PtrTy(*jit->context);
4020*03ce13f7SAndroid Build Coastguard Worker 	auto handleTy = i8PtrTy;
4021*03ce13f7SAndroid Build Coastguard Worker 	auto boolTy = i1Ty;
4022*03ce13f7SAndroid Build Coastguard Worker 	auto promiseTy = T(YieldType);
4023*03ce13f7SAndroid Build Coastguard Worker 	auto promisePtrTy = promiseTy->getPointerTo();
4024*03ce13f7SAndroid Build Coastguard Worker 
4025*03ce13f7SAndroid Build Coastguard Worker 	jit->function = rr::createFunction("coroutine_begin", handleTy, T(Params));
4026*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 16
4027*03ce13f7SAndroid Build Coastguard Worker 	jit->function->setPresplitCoroutine();
4028*03ce13f7SAndroid Build Coastguard Worker #else
4029*03ce13f7SAndroid Build Coastguard Worker 	jit->function->addFnAttr("coroutine.presplit", "0");
4030*03ce13f7SAndroid Build Coastguard Worker #endif
4031*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.await = rr::createFunction("coroutine_await", boolTy, { handleTy, promisePtrTy });
4032*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.destroy = rr::createFunction("coroutine_destroy", voidTy, { handleTy });
4033*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.yieldType = promiseTy;
4034*03ce13f7SAndroid Build Coastguard Worker 	jit->coroutine.entryBlock = llvm::BasicBlock::Create(*jit->context, "function", jit->function);
4035*03ce13f7SAndroid Build Coastguard Worker 
4036*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->SetInsertPoint(jit->coroutine.entryBlock);
4037*03ce13f7SAndroid Build Coastguard Worker }
4038*03ce13f7SAndroid Build Coastguard Worker 
yield(Value * val)4039*03ce13f7SAndroid Build Coastguard Worker void Nucleus::yield(Value *val)
4040*03ce13f7SAndroid Build Coastguard Worker {
4041*03ce13f7SAndroid Build Coastguard Worker 	if(jit->coroutine.id == nullptr)
4042*03ce13f7SAndroid Build Coastguard Worker 	{
4043*03ce13f7SAndroid Build Coastguard Worker 		// First call to yield().
4044*03ce13f7SAndroid Build Coastguard Worker 		// Promote the function to a full coroutine.
4045*03ce13f7SAndroid Build Coastguard Worker 		promoteFunctionToCoroutine();
4046*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(jit->coroutine.id != nullptr);
4047*03ce13f7SAndroid Build Coastguard Worker 	}
4048*03ce13f7SAndroid Build Coastguard Worker 
4049*03ce13f7SAndroid Build Coastguard Worker 	//      promise = val;
4050*03ce13f7SAndroid Build Coastguard Worker 	//
4051*03ce13f7SAndroid Build Coastguard Worker 	//      auto action = llvm.coro.suspend(none, false /* final */); // <-- RESUME POINT
4052*03ce13f7SAndroid Build Coastguard Worker 	//      switch(action)
4053*03ce13f7SAndroid Build Coastguard Worker 	//      {
4054*03ce13f7SAndroid Build Coastguard Worker 	//      case SuspendActionResume:
4055*03ce13f7SAndroid Build Coastguard Worker 	//          goto resume;
4056*03ce13f7SAndroid Build Coastguard Worker 	//      case SuspendActionDestroy:
4057*03ce13f7SAndroid Build Coastguard Worker 	//          goto destroy;
4058*03ce13f7SAndroid Build Coastguard Worker 	//      default: // (SuspendActionSuspend)
4059*03ce13f7SAndroid Build Coastguard Worker 	//          goto suspend;
4060*03ce13f7SAndroid Build Coastguard Worker 	//      }
4061*03ce13f7SAndroid Build Coastguard Worker 	//  resume:
4062*03ce13f7SAndroid Build Coastguard Worker 	//
4063*03ce13f7SAndroid Build Coastguard Worker 
4064*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4065*03ce13f7SAndroid Build Coastguard Worker 	Variable::materializeAll();
4066*03ce13f7SAndroid Build Coastguard Worker 
4067*03ce13f7SAndroid Build Coastguard Worker 	// Types
4068*03ce13f7SAndroid Build Coastguard Worker 	auto i1Ty = llvm::Type::getInt1Ty(*jit->context);
4069*03ce13f7SAndroid Build Coastguard Worker 	auto i8Ty = llvm::Type::getInt8Ty(*jit->context);
4070*03ce13f7SAndroid Build Coastguard Worker 
4071*03ce13f7SAndroid Build Coastguard Worker 	// Intrinsics
4072*03ce13f7SAndroid Build Coastguard Worker 	auto coro_suspend = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::coro_suspend);
4073*03ce13f7SAndroid Build Coastguard Worker 
4074*03ce13f7SAndroid Build Coastguard Worker 	// Create a block to resume execution.
4075*03ce13f7SAndroid Build Coastguard Worker 	auto resumeBlock = llvm::BasicBlock::Create(*jit->context, "resume", jit->function);
4076*03ce13f7SAndroid Build Coastguard Worker 
4077*03ce13f7SAndroid Build Coastguard Worker 	// Store the promise (yield value)
4078*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->CreateStore(V(val), jit->coroutine.promise);
4079*03ce13f7SAndroid Build Coastguard Worker 	auto action = jit->builder->CreateCall(coro_suspend, {
4080*03ce13f7SAndroid Build Coastguard Worker 	                                                         llvm::ConstantTokenNone::get(*jit->context),
4081*03ce13f7SAndroid Build Coastguard Worker 	                                                         llvm::ConstantInt::get(i1Ty, 0),  // final: true
4082*03ce13f7SAndroid Build Coastguard Worker 	                                                     });
4083*03ce13f7SAndroid Build Coastguard Worker 	auto switch_ = jit->builder->CreateSwitch(action, jit->coroutine.suspendBlock, 3);
4084*03ce13f7SAndroid Build Coastguard Worker 	switch_->addCase(llvm::ConstantInt::get(i8Ty, SuspendActionResume), resumeBlock);
4085*03ce13f7SAndroid Build Coastguard Worker 	switch_->addCase(llvm::ConstantInt::get(i8Ty, SuspendActionDestroy), jit->coroutine.destroyBlock);
4086*03ce13f7SAndroid Build Coastguard Worker 
4087*03ce13f7SAndroid Build Coastguard Worker 	// Continue building in the resume block.
4088*03ce13f7SAndroid Build Coastguard Worker 	jit->builder->SetInsertPoint(resumeBlock);
4089*03ce13f7SAndroid Build Coastguard Worker }
4090*03ce13f7SAndroid Build Coastguard Worker 
acquireCoroutine(const char * name)4091*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Routine> Nucleus::acquireCoroutine(const char *name)
4092*03ce13f7SAndroid Build Coastguard Worker {
4093*03ce13f7SAndroid Build Coastguard Worker 	if(jit->coroutine.id)
4094*03ce13f7SAndroid Build Coastguard Worker 	{
4095*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateBr(jit->coroutine.endBlock);
4096*03ce13f7SAndroid Build Coastguard Worker 	}
4097*03ce13f7SAndroid Build Coastguard Worker 	else
4098*03ce13f7SAndroid Build Coastguard Worker 	{
4099*03ce13f7SAndroid Build Coastguard Worker 		// Coroutine without a Yield acts as a regular function.
4100*03ce13f7SAndroid Build Coastguard Worker 		// The 'coroutine_begin' function returns a nullptr for the coroutine
4101*03ce13f7SAndroid Build Coastguard Worker 		// handle.
4102*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateRet(llvm::Constant::getNullValue(jit->function->getReturnType()));
4103*03ce13f7SAndroid Build Coastguard Worker 		// The 'coroutine_await' function always returns false (coroutine done).
4104*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->SetInsertPoint(llvm::BasicBlock::Create(*jit->context, "", jit->coroutine.await));
4105*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateRet(llvm::Constant::getNullValue(jit->coroutine.await->getReturnType()));
4106*03ce13f7SAndroid Build Coastguard Worker 		// The 'coroutine_destroy' does nothing, returns void.
4107*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->SetInsertPoint(llvm::BasicBlock::Create(*jit->context, "", jit->coroutine.destroy));
4108*03ce13f7SAndroid Build Coastguard Worker 		jit->builder->CreateRetVoid();
4109*03ce13f7SAndroid Build Coastguard Worker 	}
4110*03ce13f7SAndroid Build Coastguard Worker 
4111*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
4112*03ce13f7SAndroid Build Coastguard Worker 	if(jit->debugInfo != nullptr)
4113*03ce13f7SAndroid Build Coastguard Worker 	{
4114*03ce13f7SAndroid Build Coastguard Worker 		jit->debugInfo->Finalize();
4115*03ce13f7SAndroid Build Coastguard Worker 	}
4116*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_DEBUG_INFO
4117*03ce13f7SAndroid Build Coastguard Worker 
4118*03ce13f7SAndroid Build Coastguard Worker 	if(false)
4119*03ce13f7SAndroid Build Coastguard Worker 	{
4120*03ce13f7SAndroid Build Coastguard Worker 		std::error_code error;
4121*03ce13f7SAndroid Build Coastguard Worker 		llvm::raw_fd_ostream file(std::string(name) + "-llvm-dump-unopt.txt", error);
4122*03ce13f7SAndroid Build Coastguard Worker 		jit->module->print(file, 0);
4123*03ce13f7SAndroid Build Coastguard Worker 	}
4124*03ce13f7SAndroid Build Coastguard Worker 
4125*03ce13f7SAndroid Build Coastguard Worker 	jit->runPasses();
4126*03ce13f7SAndroid Build Coastguard Worker 
4127*03ce13f7SAndroid Build Coastguard Worker 	if(false)
4128*03ce13f7SAndroid Build Coastguard Worker 	{
4129*03ce13f7SAndroid Build Coastguard Worker 		std::error_code error;
4130*03ce13f7SAndroid Build Coastguard Worker 		llvm::raw_fd_ostream file(std::string(name) + "-llvm-dump-opt.txt", error);
4131*03ce13f7SAndroid Build Coastguard Worker 		jit->module->print(file, 0);
4132*03ce13f7SAndroid Build Coastguard Worker 	}
4133*03ce13f7SAndroid Build Coastguard Worker 
4134*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *funcs[Nucleus::CoroutineEntryCount];
4135*03ce13f7SAndroid Build Coastguard Worker 	funcs[Nucleus::CoroutineEntryBegin] = jit->function;
4136*03ce13f7SAndroid Build Coastguard Worker 	funcs[Nucleus::CoroutineEntryAwait] = jit->coroutine.await;
4137*03ce13f7SAndroid Build Coastguard Worker 	funcs[Nucleus::CoroutineEntryDestroy] = jit->coroutine.destroy;
4138*03ce13f7SAndroid Build Coastguard Worker 
4139*03ce13f7SAndroid Build Coastguard Worker 	auto routine = jit->acquireRoutine(name, funcs, Nucleus::CoroutineEntryCount);
4140*03ce13f7SAndroid Build Coastguard Worker 
4141*03ce13f7SAndroid Build Coastguard Worker 	delete jit;
4142*03ce13f7SAndroid Build Coastguard Worker 	jit = nullptr;
4143*03ce13f7SAndroid Build Coastguard Worker 
4144*03ce13f7SAndroid Build Coastguard Worker 	return routine;
4145*03ce13f7SAndroid Build Coastguard Worker }
4146*03ce13f7SAndroid Build Coastguard Worker 
invokeCoroutineBegin(Routine & routine,std::function<Nucleus::CoroutineHandle ()> func)4147*03ce13f7SAndroid Build Coastguard Worker Nucleus::CoroutineHandle Nucleus::invokeCoroutineBegin(Routine &routine, std::function<Nucleus::CoroutineHandle()> func)
4148*03ce13f7SAndroid Build Coastguard Worker {
4149*03ce13f7SAndroid Build Coastguard Worker 	return func();
4150*03ce13f7SAndroid Build Coastguard Worker }
4151*03ce13f7SAndroid Build Coastguard Worker 
Int(RValue<scalar::Int> rhs)4152*03ce13f7SAndroid Build Coastguard Worker SIMD::Int::Int(RValue<scalar::Int> rhs)
4153*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
4154*03ce13f7SAndroid Build Coastguard Worker {
4155*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4156*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = loadValue();
4157*03ce13f7SAndroid Build Coastguard Worker 	Value *insert = Nucleus::createInsertElement(vector, rhs.value(), 0);
4158*03ce13f7SAndroid Build Coastguard Worker 
4159*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0 };
4160*03ce13f7SAndroid Build Coastguard Worker 	Value *replicate = Nucleus::createShuffleVector(insert, insert, swizzle);
4161*03ce13f7SAndroid Build Coastguard Worker 
4162*03ce13f7SAndroid Build Coastguard Worker 	storeValue(replicate);
4163*03ce13f7SAndroid Build Coastguard Worker }
4164*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<SIMD::Int> lhs,unsigned char rhs)4165*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> operator<<(RValue<SIMD::Int> lhs, unsigned char rhs)
4166*03ce13f7SAndroid Build Coastguard Worker {
4167*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4168*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Int>(V(lowerVectorShl(V(lhs.value()), rhs)));
4169*03ce13f7SAndroid Build Coastguard Worker }
4170*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<SIMD::Int> lhs,unsigned char rhs)4171*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> operator>>(RValue<SIMD::Int> lhs, unsigned char rhs)
4172*03ce13f7SAndroid Build Coastguard Worker {
4173*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4174*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Int>(V(lowerVectorAShr(V(lhs.value()), rhs)));
4175*03ce13f7SAndroid Build Coastguard Worker }
4176*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4177*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpEQ(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4178*03ce13f7SAndroid Build Coastguard Worker {
4179*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4180*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createICmpEQ(x.value(), y.value()), SIMD::Int::type()));
4181*03ce13f7SAndroid Build Coastguard Worker }
4182*03ce13f7SAndroid Build Coastguard Worker 
CmpLT(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4183*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpLT(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4184*03ce13f7SAndroid Build Coastguard Worker {
4185*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4186*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createICmpSLT(x.value(), y.value()), SIMD::Int::type()));
4187*03ce13f7SAndroid Build Coastguard Worker }
4188*03ce13f7SAndroid Build Coastguard Worker 
CmpLE(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4189*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpLE(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4190*03ce13f7SAndroid Build Coastguard Worker {
4191*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4192*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createICmpSLE(x.value(), y.value()), SIMD::Int::type()));
4193*03ce13f7SAndroid Build Coastguard Worker }
4194*03ce13f7SAndroid Build Coastguard Worker 
CmpNEQ(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4195*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNEQ(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4196*03ce13f7SAndroid Build Coastguard Worker {
4197*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4198*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createICmpNE(x.value(), y.value()), SIMD::Int::type()));
4199*03ce13f7SAndroid Build Coastguard Worker }
4200*03ce13f7SAndroid Build Coastguard Worker 
CmpNLT(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4201*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNLT(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4202*03ce13f7SAndroid Build Coastguard Worker {
4203*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4204*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createICmpSGE(x.value(), y.value()), SIMD::Int::type()));
4205*03ce13f7SAndroid Build Coastguard Worker }
4206*03ce13f7SAndroid Build Coastguard Worker 
CmpNLE(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4207*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNLE(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4208*03ce13f7SAndroid Build Coastguard Worker {
4209*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4210*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createICmpSGT(x.value(), y.value()), SIMD::Int::type()));
4211*03ce13f7SAndroid Build Coastguard Worker }
4212*03ce13f7SAndroid Build Coastguard Worker 
Abs(RValue<SIMD::Int> x)4213*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Abs(RValue<SIMD::Int> x)
4214*03ce13f7SAndroid Build Coastguard Worker {
4215*03ce13f7SAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 12
4216*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::abs, { V(x.value())->getType() });
4217*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(V(jit->builder->CreateCall(func, { V(x.value()), llvm::ConstantInt::getFalse(*jit->context) })));
4218*03ce13f7SAndroid Build Coastguard Worker #else
4219*03ce13f7SAndroid Build Coastguard Worker 	auto negative = x >> 31;
4220*03ce13f7SAndroid Build Coastguard Worker 	return (x ^ negative) - negative;
4221*03ce13f7SAndroid Build Coastguard Worker #endif
4222*03ce13f7SAndroid Build Coastguard Worker }
4223*03ce13f7SAndroid Build Coastguard Worker 
Max(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4224*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Max(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4225*03ce13f7SAndroid Build Coastguard Worker {
4226*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4227*03ce13f7SAndroid Build Coastguard Worker 	RValue<SIMD::Int> greater = CmpNLE(x, y);
4228*03ce13f7SAndroid Build Coastguard Worker 	return (x & greater) | (y & ~greater);
4229*03ce13f7SAndroid Build Coastguard Worker }
4230*03ce13f7SAndroid Build Coastguard Worker 
Min(RValue<SIMD::Int> x,RValue<SIMD::Int> y)4231*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Min(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
4232*03ce13f7SAndroid Build Coastguard Worker {
4233*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4234*03ce13f7SAndroid Build Coastguard Worker 	RValue<SIMD::Int> less = CmpLT(x, y);
4235*03ce13f7SAndroid Build Coastguard Worker 	return (x & less) | (y & ~less);
4236*03ce13f7SAndroid Build Coastguard Worker }
4237*03ce13f7SAndroid Build Coastguard Worker 
RoundInt(RValue<SIMD::Float> cast)4238*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> RoundInt(RValue<SIMD::Float> cast)
4239*03ce13f7SAndroid Build Coastguard Worker {
4240*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4241*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Int>(V(lowerRoundInt(V(cast.value()), T(SIMD::Int::type()))));
4242*03ce13f7SAndroid Build Coastguard Worker }
4243*03ce13f7SAndroid Build Coastguard Worker 
RoundIntClamped(RValue<SIMD::Float> cast)4244*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> RoundIntClamped(RValue<SIMD::Float> cast)
4245*03ce13f7SAndroid Build Coastguard Worker {
4246*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4247*03ce13f7SAndroid Build Coastguard Worker 
4248*03ce13f7SAndroid Build Coastguard Worker // TODO(b/165000222): Check if fptosi_sat produces optimal code for x86 and ARM.
4249*03ce13f7SAndroid Build Coastguard Worker #if defined(__arm__) || defined(__aarch64__)
4250*03ce13f7SAndroid Build Coastguard Worker 	// ARM saturates to the largest positive or negative integer. Unit tests
4251*03ce13f7SAndroid Build Coastguard Worker 	// verify that lowerRoundInt() behaves as desired.
4252*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Int>(V(lowerRoundInt(V(cast.value()), T(SIMD::Int::type()))));
4253*03ce13f7SAndroid Build Coastguard Worker #elif LLVM_VERSION_MAJOR >= 14
4254*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *rounded = lowerRound(V(cast.value()));
4255*03ce13f7SAndroid Build Coastguard Worker 	llvm::Function *fptosi_sat = llvm::Intrinsic::getDeclaration(
4256*03ce13f7SAndroid Build Coastguard Worker 	    jit->module.get(), llvm::Intrinsic::fptosi_sat, { T(SIMD::Int::type()), T(SIMD::Float::type()) });
4257*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(V(jit->builder->CreateCall(fptosi_sat, { rounded })));
4258*03ce13f7SAndroid Build Coastguard Worker #else
4259*03ce13f7SAndroid Build Coastguard Worker 	RValue<SIMD::Float> clamped = Max(Min(cast, SIMD::Float(0x7FFFFF80)), SIMD::Float(static_cast<int>(0x80000000)));
4260*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Int>(V(lowerRoundInt(V(clamped.value()), T(SIMD::Int::type()))));
4261*03ce13f7SAndroid Build Coastguard Worker #endif
4262*03ce13f7SAndroid Build Coastguard Worker }
4263*03ce13f7SAndroid Build Coastguard Worker 
Extract128(RValue<SIMD::Int> val,int i)4264*03ce13f7SAndroid Build Coastguard Worker RValue<Int4> Extract128(RValue<SIMD::Int> val, int i)
4265*03ce13f7SAndroid Build Coastguard Worker {
4266*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *v128 = jit->builder->CreateBitCast(V(val.value()), llvm::FixedVectorType::get(llvm::IntegerType::get(*jit->context, 128), SIMD::Width / 4));
4267*03ce13f7SAndroid Build Coastguard Worker 
4268*03ce13f7SAndroid Build Coastguard Worker 	return As<Int4>(V(jit->builder->CreateExtractElement(v128, i)));
4269*03ce13f7SAndroid Build Coastguard Worker }
4270*03ce13f7SAndroid Build Coastguard Worker 
Insert128(RValue<SIMD::Int> val,RValue<Int4> element,int i)4271*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> Insert128(RValue<SIMD::Int> val, RValue<Int4> element, int i)
4272*03ce13f7SAndroid Build Coastguard Worker {
4273*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *v128 = jit->builder->CreateBitCast(V(val.value()), llvm::FixedVectorType::get(llvm::IntegerType::get(*jit->context, 128), SIMD::Width / 4));
4274*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *a = jit->builder->CreateBitCast(V(element.value()), llvm::IntegerType::get(*jit->context, 128));
4275*03ce13f7SAndroid Build Coastguard Worker 
4276*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Int>(V(jit->builder->CreateInsertElement(v128, a, i)));
4277*03ce13f7SAndroid Build Coastguard Worker }
4278*03ce13f7SAndroid Build Coastguard Worker 
type()4279*03ce13f7SAndroid Build Coastguard Worker Type *SIMD::Int::type()
4280*03ce13f7SAndroid Build Coastguard Worker {
4281*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(scalar::Int::type()), SIMD::Width, false));
4282*03ce13f7SAndroid Build Coastguard Worker }
4283*03ce13f7SAndroid Build Coastguard Worker 
UInt(RValue<SIMD::Float> cast)4284*03ce13f7SAndroid Build Coastguard Worker SIMD::UInt::UInt(RValue<SIMD::Float> cast)
4285*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
4286*03ce13f7SAndroid Build Coastguard Worker {
4287*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4288*03ce13f7SAndroid Build Coastguard Worker 	Value *xyzw = Nucleus::createFPToUI(cast.value(), SIMD::UInt::type());
4289*03ce13f7SAndroid Build Coastguard Worker 	storeValue(xyzw);
4290*03ce13f7SAndroid Build Coastguard Worker }
4291*03ce13f7SAndroid Build Coastguard Worker 
UInt(RValue<scalar::UInt> rhs)4292*03ce13f7SAndroid Build Coastguard Worker SIMD::UInt::UInt(RValue<scalar::UInt> rhs)
4293*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
4294*03ce13f7SAndroid Build Coastguard Worker {
4295*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4296*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = loadValue();
4297*03ce13f7SAndroid Build Coastguard Worker 	Value *insert = Nucleus::createInsertElement(vector, rhs.value(), 0);
4298*03ce13f7SAndroid Build Coastguard Worker 
4299*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0 };
4300*03ce13f7SAndroid Build Coastguard Worker 	Value *replicate = Nucleus::createShuffleVector(insert, insert, swizzle);
4301*03ce13f7SAndroid Build Coastguard Worker 
4302*03ce13f7SAndroid Build Coastguard Worker 	storeValue(replicate);
4303*03ce13f7SAndroid Build Coastguard Worker }
4304*03ce13f7SAndroid Build Coastguard Worker 
operator <<(RValue<SIMD::UInt> lhs,unsigned char rhs)4305*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> operator<<(RValue<SIMD::UInt> lhs, unsigned char rhs)
4306*03ce13f7SAndroid Build Coastguard Worker {
4307*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4308*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::UInt>(V(lowerVectorShl(V(lhs.value()), rhs)));
4309*03ce13f7SAndroid Build Coastguard Worker }
4310*03ce13f7SAndroid Build Coastguard Worker 
operator >>(RValue<SIMD::UInt> lhs,unsigned char rhs)4311*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> operator>>(RValue<SIMD::UInt> lhs, unsigned char rhs)
4312*03ce13f7SAndroid Build Coastguard Worker {
4313*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4314*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::UInt>(V(lowerVectorLShr(V(lhs.value()), rhs)));
4315*03ce13f7SAndroid Build Coastguard Worker }
4316*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4317*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpEQ(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4318*03ce13f7SAndroid Build Coastguard Worker {
4319*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4320*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::UInt>(Nucleus::createSExt(Nucleus::createICmpEQ(x.value(), y.value()), SIMD::Int::type()));
4321*03ce13f7SAndroid Build Coastguard Worker }
4322*03ce13f7SAndroid Build Coastguard Worker 
CmpLT(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4323*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpLT(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4324*03ce13f7SAndroid Build Coastguard Worker {
4325*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4326*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::UInt>(Nucleus::createSExt(Nucleus::createICmpULT(x.value(), y.value()), SIMD::Int::type()));
4327*03ce13f7SAndroid Build Coastguard Worker }
4328*03ce13f7SAndroid Build Coastguard Worker 
CmpLE(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4329*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpLE(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4330*03ce13f7SAndroid Build Coastguard Worker {
4331*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4332*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::UInt>(Nucleus::createSExt(Nucleus::createICmpULE(x.value(), y.value()), SIMD::Int::type()));
4333*03ce13f7SAndroid Build Coastguard Worker }
4334*03ce13f7SAndroid Build Coastguard Worker 
CmpNEQ(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4335*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpNEQ(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4336*03ce13f7SAndroid Build Coastguard Worker {
4337*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4338*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::UInt>(Nucleus::createSExt(Nucleus::createICmpNE(x.value(), y.value()), SIMD::Int::type()));
4339*03ce13f7SAndroid Build Coastguard Worker }
4340*03ce13f7SAndroid Build Coastguard Worker 
CmpNLT(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4341*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpNLT(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4342*03ce13f7SAndroid Build Coastguard Worker {
4343*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4344*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::UInt>(Nucleus::createSExt(Nucleus::createICmpUGE(x.value(), y.value()), SIMD::Int::type()));
4345*03ce13f7SAndroid Build Coastguard Worker }
4346*03ce13f7SAndroid Build Coastguard Worker 
CmpNLE(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4347*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> CmpNLE(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4348*03ce13f7SAndroid Build Coastguard Worker {
4349*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4350*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::UInt>(Nucleus::createSExt(Nucleus::createICmpUGT(x.value(), y.value()), SIMD::Int::type()));
4351*03ce13f7SAndroid Build Coastguard Worker }
4352*03ce13f7SAndroid Build Coastguard Worker 
Max(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4353*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> Max(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4354*03ce13f7SAndroid Build Coastguard Worker {
4355*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4356*03ce13f7SAndroid Build Coastguard Worker 	RValue<SIMD::UInt> greater = CmpNLE(x, y);
4357*03ce13f7SAndroid Build Coastguard Worker 	return (x & greater) | (y & ~greater);
4358*03ce13f7SAndroid Build Coastguard Worker }
4359*03ce13f7SAndroid Build Coastguard Worker 
Min(RValue<SIMD::UInt> x,RValue<SIMD::UInt> y)4360*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> Min(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
4361*03ce13f7SAndroid Build Coastguard Worker {
4362*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4363*03ce13f7SAndroid Build Coastguard Worker 	RValue<SIMD::UInt> less = CmpLT(x, y);
4364*03ce13f7SAndroid Build Coastguard Worker 	return (x & less) | (y & ~less);
4365*03ce13f7SAndroid Build Coastguard Worker }
4366*03ce13f7SAndroid Build Coastguard Worker 
Extract128(RValue<SIMD::UInt> val,int i)4367*03ce13f7SAndroid Build Coastguard Worker RValue<UInt4> Extract128(RValue<SIMD::UInt> val, int i)
4368*03ce13f7SAndroid Build Coastguard Worker {
4369*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *v128 = jit->builder->CreateBitCast(V(val.value()), llvm::FixedVectorType::get(llvm::IntegerType::get(*jit->context, 128), SIMD::Width / 4));
4370*03ce13f7SAndroid Build Coastguard Worker 
4371*03ce13f7SAndroid Build Coastguard Worker 	return As<UInt4>(V(jit->builder->CreateExtractElement(v128, i)));
4372*03ce13f7SAndroid Build Coastguard Worker }
4373*03ce13f7SAndroid Build Coastguard Worker 
Insert128(RValue<SIMD::UInt> val,RValue<UInt4> element,int i)4374*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::UInt> Insert128(RValue<SIMD::UInt> val, RValue<UInt4> element, int i)
4375*03ce13f7SAndroid Build Coastguard Worker {
4376*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *v128 = jit->builder->CreateBitCast(V(val.value()), llvm::FixedVectorType::get(llvm::IntegerType::get(*jit->context, 128), SIMD::Width / 4));
4377*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *a = jit->builder->CreateBitCast(V(element.value()), llvm::IntegerType::get(*jit->context, 128));
4378*03ce13f7SAndroid Build Coastguard Worker 
4379*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::UInt>(V(jit->builder->CreateInsertElement(v128, a, i)));
4380*03ce13f7SAndroid Build Coastguard Worker }
4381*03ce13f7SAndroid Build Coastguard Worker 
type()4382*03ce13f7SAndroid Build Coastguard Worker Type *SIMD::UInt::type()
4383*03ce13f7SAndroid Build Coastguard Worker {
4384*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(scalar::UInt::type()), SIMD::Width, false));
4385*03ce13f7SAndroid Build Coastguard Worker }
4386*03ce13f7SAndroid Build Coastguard Worker 
Float(RValue<scalar::Float> rhs)4387*03ce13f7SAndroid Build Coastguard Worker SIMD::Float::Float(RValue<scalar::Float> rhs)
4388*03ce13f7SAndroid Build Coastguard Worker     : XYZW(this)
4389*03ce13f7SAndroid Build Coastguard Worker {
4390*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4391*03ce13f7SAndroid Build Coastguard Worker 	Value *vector = loadValue();
4392*03ce13f7SAndroid Build Coastguard Worker 	Value *insert = Nucleus::createInsertElement(vector, rhs.value(), 0);
4393*03ce13f7SAndroid Build Coastguard Worker 
4394*03ce13f7SAndroid Build Coastguard Worker 	std::vector<int> swizzle = { 0 };
4395*03ce13f7SAndroid Build Coastguard Worker 	Value *replicate = Nucleus::createShuffleVector(insert, insert, swizzle);
4396*03ce13f7SAndroid Build Coastguard Worker 
4397*03ce13f7SAndroid Build Coastguard Worker 	storeValue(replicate);
4398*03ce13f7SAndroid Build Coastguard Worker }
4399*03ce13f7SAndroid Build Coastguard Worker 
operator %(RValue<SIMD::Float> lhs,RValue<SIMD::Float> rhs)4400*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> operator%(RValue<SIMD::Float> lhs, RValue<SIMD::Float> rhs)
4401*03ce13f7SAndroid Build Coastguard Worker {
4402*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Float>(Nucleus::createFRem(lhs.value(), rhs.value()));
4403*03ce13f7SAndroid Build Coastguard Worker }
4404*03ce13f7SAndroid Build Coastguard Worker 
MulAdd(RValue<SIMD::Float> x,RValue<SIMD::Float> y,RValue<SIMD::Float> z)4405*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> MulAdd(RValue<SIMD::Float> x, RValue<SIMD::Float> y, RValue<SIMD::Float> z)
4406*03ce13f7SAndroid Build Coastguard Worker {
4407*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::fmuladd, { T(SIMD::Float::type()) });
4408*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Float>(V(jit->builder->CreateCall(func, { V(x.value()), V(y.value()), V(z.value()) })));
4409*03ce13f7SAndroid Build Coastguard Worker }
4410*03ce13f7SAndroid Build Coastguard Worker 
FMA(RValue<SIMD::Float> x,RValue<SIMD::Float> y,RValue<SIMD::Float> z)4411*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> FMA(RValue<SIMD::Float> x, RValue<SIMD::Float> y, RValue<SIMD::Float> z)
4412*03ce13f7SAndroid Build Coastguard Worker {
4413*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::fma, { T(SIMD::Float::type()) });
4414*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Float>(V(jit->builder->CreateCall(func, { V(x.value()), V(y.value()), V(z.value()) })));
4415*03ce13f7SAndroid Build Coastguard Worker }
4416*03ce13f7SAndroid Build Coastguard Worker 
Abs(RValue<SIMD::Float> x)4417*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Abs(RValue<SIMD::Float> x)
4418*03ce13f7SAndroid Build Coastguard Worker {
4419*03ce13f7SAndroid Build Coastguard Worker 	auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::fabs, { V(x.value())->getType() });
4420*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Float>(V(jit->builder->CreateCall(func, V(x.value()))));
4421*03ce13f7SAndroid Build Coastguard Worker }
4422*03ce13f7SAndroid Build Coastguard Worker 
Max(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4423*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Max(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4424*03ce13f7SAndroid Build Coastguard Worker {
4425*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4426*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Float>(V(lowerPFMINMAX(V(x.value()), V(y.value()), llvm::FCmpInst::FCMP_OGT)));
4427*03ce13f7SAndroid Build Coastguard Worker }
4428*03ce13f7SAndroid Build Coastguard Worker 
Min(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4429*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Min(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4430*03ce13f7SAndroid Build Coastguard Worker {
4431*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4432*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Float>(V(lowerPFMINMAX(V(x.value()), V(y.value()), llvm::FCmpInst::FCMP_OLT)));
4433*03ce13f7SAndroid Build Coastguard Worker }
4434*03ce13f7SAndroid Build Coastguard Worker 
Sqrt(RValue<SIMD::Float> x)4435*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Sqrt(RValue<SIMD::Float> x)
4436*03ce13f7SAndroid Build Coastguard Worker {
4437*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4438*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Float>(V(lowerSQRT(V(x.value()))));
4439*03ce13f7SAndroid Build Coastguard Worker }
4440*03ce13f7SAndroid Build Coastguard Worker 
CmpEQ(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4441*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpEQ(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4442*03ce13f7SAndroid Build Coastguard Worker {
4443*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4444*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpOEQ(x.value(), y.value()), SIMD::Int::type()));
4445*03ce13f7SAndroid Build Coastguard Worker }
4446*03ce13f7SAndroid Build Coastguard Worker 
CmpLT(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4447*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpLT(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4448*03ce13f7SAndroid Build Coastguard Worker {
4449*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4450*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpOLT(x.value(), y.value()), SIMD::Int::type()));
4451*03ce13f7SAndroid Build Coastguard Worker }
4452*03ce13f7SAndroid Build Coastguard Worker 
CmpLE(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4453*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpLE(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4454*03ce13f7SAndroid Build Coastguard Worker {
4455*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4456*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpOLE(x.value(), y.value()), SIMD::Int::type()));
4457*03ce13f7SAndroid Build Coastguard Worker }
4458*03ce13f7SAndroid Build Coastguard Worker 
CmpNEQ(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4459*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNEQ(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4460*03ce13f7SAndroid Build Coastguard Worker {
4461*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4462*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpONE(x.value(), y.value()), SIMD::Int::type()));
4463*03ce13f7SAndroid Build Coastguard Worker }
4464*03ce13f7SAndroid Build Coastguard Worker 
CmpNLT(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4465*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNLT(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4466*03ce13f7SAndroid Build Coastguard Worker {
4467*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4468*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpOGE(x.value(), y.value()), SIMD::Int::type()));
4469*03ce13f7SAndroid Build Coastguard Worker }
4470*03ce13f7SAndroid Build Coastguard Worker 
CmpNLE(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4471*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpNLE(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4472*03ce13f7SAndroid Build Coastguard Worker {
4473*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4474*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpOGT(x.value(), y.value()), SIMD::Int::type()));
4475*03ce13f7SAndroid Build Coastguard Worker }
4476*03ce13f7SAndroid Build Coastguard Worker 
CmpUEQ(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4477*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpUEQ(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4478*03ce13f7SAndroid Build Coastguard Worker {
4479*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4480*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpUEQ(x.value(), y.value()), SIMD::Int::type()));
4481*03ce13f7SAndroid Build Coastguard Worker }
4482*03ce13f7SAndroid Build Coastguard Worker 
CmpULT(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4483*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpULT(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4484*03ce13f7SAndroid Build Coastguard Worker {
4485*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4486*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpULT(x.value(), y.value()), SIMD::Int::type()));
4487*03ce13f7SAndroid Build Coastguard Worker }
4488*03ce13f7SAndroid Build Coastguard Worker 
CmpULE(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4489*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpULE(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4490*03ce13f7SAndroid Build Coastguard Worker {
4491*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4492*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpULE(x.value(), y.value()), SIMD::Int::type()));
4493*03ce13f7SAndroid Build Coastguard Worker }
4494*03ce13f7SAndroid Build Coastguard Worker 
CmpUNEQ(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4495*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpUNEQ(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4496*03ce13f7SAndroid Build Coastguard Worker {
4497*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4498*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpUNE(x.value(), y.value()), SIMD::Int::type()));
4499*03ce13f7SAndroid Build Coastguard Worker }
4500*03ce13f7SAndroid Build Coastguard Worker 
CmpUNLT(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4501*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpUNLT(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4502*03ce13f7SAndroid Build Coastguard Worker {
4503*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4504*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpUGE(x.value(), y.value()), SIMD::Int::type()));
4505*03ce13f7SAndroid Build Coastguard Worker }
4506*03ce13f7SAndroid Build Coastguard Worker 
CmpUNLE(RValue<SIMD::Float> x,RValue<SIMD::Float> y)4507*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Int> CmpUNLE(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
4508*03ce13f7SAndroid Build Coastguard Worker {
4509*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4510*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Int>(Nucleus::createSExt(Nucleus::createFCmpUGT(x.value(), y.value()), SIMD::Int::type()));
4511*03ce13f7SAndroid Build Coastguard Worker }
4512*03ce13f7SAndroid Build Coastguard Worker 
Round(RValue<SIMD::Float> x)4513*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Round(RValue<SIMD::Float> x)
4514*03ce13f7SAndroid Build Coastguard Worker {
4515*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4516*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Float>(V(lowerRound(V(x.value()))));
4517*03ce13f7SAndroid Build Coastguard Worker }
4518*03ce13f7SAndroid Build Coastguard Worker 
Trunc(RValue<SIMD::Float> x)4519*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Trunc(RValue<SIMD::Float> x)
4520*03ce13f7SAndroid Build Coastguard Worker {
4521*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4522*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Float>(V(lowerTrunc(V(x.value()))));
4523*03ce13f7SAndroid Build Coastguard Worker }
4524*03ce13f7SAndroid Build Coastguard Worker 
Frac(RValue<SIMD::Float> x)4525*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Frac(RValue<SIMD::Float> x)
4526*03ce13f7SAndroid Build Coastguard Worker {
4527*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4528*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float frc = x - Floor(x);
4529*03ce13f7SAndroid Build Coastguard Worker 
4530*03ce13f7SAndroid Build Coastguard Worker 	// x - floor(x) can be 1.0 for very small negative x.
4531*03ce13f7SAndroid Build Coastguard Worker 	// Clamp against the value just below 1.0.
4532*03ce13f7SAndroid Build Coastguard Worker 	return Min(frc, As<SIMD::Float>(SIMD::Int(0x3F7FFFFF)));
4533*03ce13f7SAndroid Build Coastguard Worker }
4534*03ce13f7SAndroid Build Coastguard Worker 
Floor(RValue<SIMD::Float> x)4535*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Floor(RValue<SIMD::Float> x)
4536*03ce13f7SAndroid Build Coastguard Worker {
4537*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4538*03ce13f7SAndroid Build Coastguard Worker 	return RValue<SIMD::Float>(V(lowerFloor(V(x.value()))));
4539*03ce13f7SAndroid Build Coastguard Worker }
4540*03ce13f7SAndroid Build Coastguard Worker 
Ceil(RValue<SIMD::Float> x)4541*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Ceil(RValue<SIMD::Float> x)
4542*03ce13f7SAndroid Build Coastguard Worker {
4543*03ce13f7SAndroid Build Coastguard Worker 	RR_DEBUG_INFO_UPDATE_LOC();
4544*03ce13f7SAndroid Build Coastguard Worker 	return -Floor(-x);
4545*03ce13f7SAndroid Build Coastguard Worker }
4546*03ce13f7SAndroid Build Coastguard Worker 
Extract128(RValue<SIMD::Float> val,int i)4547*03ce13f7SAndroid Build Coastguard Worker RValue<Float4> Extract128(RValue<SIMD::Float> val, int i)
4548*03ce13f7SAndroid Build Coastguard Worker {
4549*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *v128 = jit->builder->CreateBitCast(V(val.value()), llvm::FixedVectorType::get(llvm::IntegerType::get(*jit->context, 128), SIMD::Width / 4));
4550*03ce13f7SAndroid Build Coastguard Worker 
4551*03ce13f7SAndroid Build Coastguard Worker 	return As<Float4>(V(jit->builder->CreateExtractElement(v128, i)));
4552*03ce13f7SAndroid Build Coastguard Worker }
4553*03ce13f7SAndroid Build Coastguard Worker 
Insert128(RValue<SIMD::Float> val,RValue<Float4> element,int i)4554*03ce13f7SAndroid Build Coastguard Worker RValue<SIMD::Float> Insert128(RValue<SIMD::Float> val, RValue<Float4> element, int i)
4555*03ce13f7SAndroid Build Coastguard Worker {
4556*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *v128 = jit->builder->CreateBitCast(V(val.value()), llvm::FixedVectorType::get(llvm::IntegerType::get(*jit->context, 128), SIMD::Width / 4));
4557*03ce13f7SAndroid Build Coastguard Worker 	llvm::Value *a = jit->builder->CreateBitCast(V(element.value()), llvm::IntegerType::get(*jit->context, 128));
4558*03ce13f7SAndroid Build Coastguard Worker 
4559*03ce13f7SAndroid Build Coastguard Worker 	return As<SIMD::Float>(V(jit->builder->CreateInsertElement(v128, a, i)));
4560*03ce13f7SAndroid Build Coastguard Worker }
4561*03ce13f7SAndroid Build Coastguard Worker 
type()4562*03ce13f7SAndroid Build Coastguard Worker Type *SIMD::Float::type()
4563*03ce13f7SAndroid Build Coastguard Worker {
4564*03ce13f7SAndroid Build Coastguard Worker 	return T(llvm::VectorType::get(T(scalar::Float::type()), SIMD::Width, false));
4565*03ce13f7SAndroid Build Coastguard Worker }
4566*03ce13f7SAndroid Build Coastguard Worker 
4567*03ce13f7SAndroid Build Coastguard Worker }  // namespace rr
4568