1*9880d681SAndroid Build Coastguard Worker //===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the IntrinsicLowering class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/IntrinsicLowering.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallSite.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Type.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
25*9880d681SAndroid Build Coastguard Worker using namespace llvm;
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker template <class ArgIt>
EnsureFunctionExists(Module & M,const char * Name,ArgIt ArgBegin,ArgIt ArgEnd,Type * RetTy)28*9880d681SAndroid Build Coastguard Worker static void EnsureFunctionExists(Module &M, const char *Name,
29*9880d681SAndroid Build Coastguard Worker ArgIt ArgBegin, ArgIt ArgEnd,
30*9880d681SAndroid Build Coastguard Worker Type *RetTy) {
31*9880d681SAndroid Build Coastguard Worker // Insert a correctly-typed definition now.
32*9880d681SAndroid Build Coastguard Worker std::vector<Type *> ParamTys;
33*9880d681SAndroid Build Coastguard Worker for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
34*9880d681SAndroid Build Coastguard Worker ParamTys.push_back(I->getType());
35*9880d681SAndroid Build Coastguard Worker M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
36*9880d681SAndroid Build Coastguard Worker }
37*9880d681SAndroid Build Coastguard Worker
EnsureFPIntrinsicsExist(Module & M,Function & Fn,const char * FName,const char * DName,const char * LDName)38*9880d681SAndroid Build Coastguard Worker static void EnsureFPIntrinsicsExist(Module &M, Function &Fn,
39*9880d681SAndroid Build Coastguard Worker const char *FName,
40*9880d681SAndroid Build Coastguard Worker const char *DName, const char *LDName) {
41*9880d681SAndroid Build Coastguard Worker // Insert definitions for all the floating point types.
42*9880d681SAndroid Build Coastguard Worker switch((int)Fn.arg_begin()->getType()->getTypeID()) {
43*9880d681SAndroid Build Coastguard Worker case Type::FloatTyID:
44*9880d681SAndroid Build Coastguard Worker EnsureFunctionExists(M, FName, Fn.arg_begin(), Fn.arg_end(),
45*9880d681SAndroid Build Coastguard Worker Type::getFloatTy(M.getContext()));
46*9880d681SAndroid Build Coastguard Worker break;
47*9880d681SAndroid Build Coastguard Worker case Type::DoubleTyID:
48*9880d681SAndroid Build Coastguard Worker EnsureFunctionExists(M, DName, Fn.arg_begin(), Fn.arg_end(),
49*9880d681SAndroid Build Coastguard Worker Type::getDoubleTy(M.getContext()));
50*9880d681SAndroid Build Coastguard Worker break;
51*9880d681SAndroid Build Coastguard Worker case Type::X86_FP80TyID:
52*9880d681SAndroid Build Coastguard Worker case Type::FP128TyID:
53*9880d681SAndroid Build Coastguard Worker case Type::PPC_FP128TyID:
54*9880d681SAndroid Build Coastguard Worker EnsureFunctionExists(M, LDName, Fn.arg_begin(), Fn.arg_end(),
55*9880d681SAndroid Build Coastguard Worker Fn.arg_begin()->getType());
56*9880d681SAndroid Build Coastguard Worker break;
57*9880d681SAndroid Build Coastguard Worker }
58*9880d681SAndroid Build Coastguard Worker }
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker /// ReplaceCallWith - This function is used when we want to lower an intrinsic
61*9880d681SAndroid Build Coastguard Worker /// call to a call of an external function. This handles hard cases such as
62*9880d681SAndroid Build Coastguard Worker /// when there was already a prototype for the external function, and if that
63*9880d681SAndroid Build Coastguard Worker /// prototype doesn't match the arguments we expect to pass in.
64*9880d681SAndroid Build Coastguard Worker template <class ArgIt>
ReplaceCallWith(const char * NewFn,CallInst * CI,ArgIt ArgBegin,ArgIt ArgEnd,Type * RetTy)65*9880d681SAndroid Build Coastguard Worker static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
66*9880d681SAndroid Build Coastguard Worker ArgIt ArgBegin, ArgIt ArgEnd,
67*9880d681SAndroid Build Coastguard Worker Type *RetTy) {
68*9880d681SAndroid Build Coastguard Worker // If we haven't already looked up this function, check to see if the
69*9880d681SAndroid Build Coastguard Worker // program already contains a function with this name.
70*9880d681SAndroid Build Coastguard Worker Module *M = CI->getModule();
71*9880d681SAndroid Build Coastguard Worker // Get or insert the definition now.
72*9880d681SAndroid Build Coastguard Worker std::vector<Type *> ParamTys;
73*9880d681SAndroid Build Coastguard Worker for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
74*9880d681SAndroid Build Coastguard Worker ParamTys.push_back((*I)->getType());
75*9880d681SAndroid Build Coastguard Worker Constant* FCache = M->getOrInsertFunction(NewFn,
76*9880d681SAndroid Build Coastguard Worker FunctionType::get(RetTy, ParamTys, false));
77*9880d681SAndroid Build Coastguard Worker
78*9880d681SAndroid Build Coastguard Worker IRBuilder<> Builder(CI->getParent(), CI->getIterator());
79*9880d681SAndroid Build Coastguard Worker SmallVector<Value *, 8> Args(ArgBegin, ArgEnd);
80*9880d681SAndroid Build Coastguard Worker CallInst *NewCI = Builder.CreateCall(FCache, Args);
81*9880d681SAndroid Build Coastguard Worker NewCI->setName(CI->getName());
82*9880d681SAndroid Build Coastguard Worker if (!CI->use_empty())
83*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(NewCI);
84*9880d681SAndroid Build Coastguard Worker return NewCI;
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Worker // VisualStudio defines setjmp as _setjmp
88*9880d681SAndroid Build Coastguard Worker #if defined(_MSC_VER) && defined(setjmp) && \
89*9880d681SAndroid Build Coastguard Worker !defined(setjmp_undefined_for_msvc)
90*9880d681SAndroid Build Coastguard Worker # pragma push_macro("setjmp")
91*9880d681SAndroid Build Coastguard Worker # undef setjmp
92*9880d681SAndroid Build Coastguard Worker # define setjmp_undefined_for_msvc
93*9880d681SAndroid Build Coastguard Worker #endif
94*9880d681SAndroid Build Coastguard Worker
AddPrototypes(Module & M)95*9880d681SAndroid Build Coastguard Worker void IntrinsicLowering::AddPrototypes(Module &M) {
96*9880d681SAndroid Build Coastguard Worker LLVMContext &Context = M.getContext();
97*9880d681SAndroid Build Coastguard Worker for (auto &F : M)
98*9880d681SAndroid Build Coastguard Worker if (F.isDeclaration() && !F.use_empty())
99*9880d681SAndroid Build Coastguard Worker switch (F.getIntrinsicID()) {
100*9880d681SAndroid Build Coastguard Worker default: break;
101*9880d681SAndroid Build Coastguard Worker case Intrinsic::setjmp:
102*9880d681SAndroid Build Coastguard Worker EnsureFunctionExists(M, "setjmp", F.arg_begin(), F.arg_end(),
103*9880d681SAndroid Build Coastguard Worker Type::getInt32Ty(M.getContext()));
104*9880d681SAndroid Build Coastguard Worker break;
105*9880d681SAndroid Build Coastguard Worker case Intrinsic::longjmp:
106*9880d681SAndroid Build Coastguard Worker EnsureFunctionExists(M, "longjmp", F.arg_begin(), F.arg_end(),
107*9880d681SAndroid Build Coastguard Worker Type::getVoidTy(M.getContext()));
108*9880d681SAndroid Build Coastguard Worker break;
109*9880d681SAndroid Build Coastguard Worker case Intrinsic::siglongjmp:
110*9880d681SAndroid Build Coastguard Worker EnsureFunctionExists(M, "abort", F.arg_end(), F.arg_end(),
111*9880d681SAndroid Build Coastguard Worker Type::getVoidTy(M.getContext()));
112*9880d681SAndroid Build Coastguard Worker break;
113*9880d681SAndroid Build Coastguard Worker case Intrinsic::memcpy:
114*9880d681SAndroid Build Coastguard Worker M.getOrInsertFunction("memcpy",
115*9880d681SAndroid Build Coastguard Worker Type::getInt8PtrTy(Context),
116*9880d681SAndroid Build Coastguard Worker Type::getInt8PtrTy(Context),
117*9880d681SAndroid Build Coastguard Worker Type::getInt8PtrTy(Context),
118*9880d681SAndroid Build Coastguard Worker DL.getIntPtrType(Context), nullptr);
119*9880d681SAndroid Build Coastguard Worker break;
120*9880d681SAndroid Build Coastguard Worker case Intrinsic::memmove:
121*9880d681SAndroid Build Coastguard Worker M.getOrInsertFunction("memmove",
122*9880d681SAndroid Build Coastguard Worker Type::getInt8PtrTy(Context),
123*9880d681SAndroid Build Coastguard Worker Type::getInt8PtrTy(Context),
124*9880d681SAndroid Build Coastguard Worker Type::getInt8PtrTy(Context),
125*9880d681SAndroid Build Coastguard Worker DL.getIntPtrType(Context), nullptr);
126*9880d681SAndroid Build Coastguard Worker break;
127*9880d681SAndroid Build Coastguard Worker case Intrinsic::memset:
128*9880d681SAndroid Build Coastguard Worker M.getOrInsertFunction("memset",
129*9880d681SAndroid Build Coastguard Worker Type::getInt8PtrTy(Context),
130*9880d681SAndroid Build Coastguard Worker Type::getInt8PtrTy(Context),
131*9880d681SAndroid Build Coastguard Worker Type::getInt32Ty(M.getContext()),
132*9880d681SAndroid Build Coastguard Worker DL.getIntPtrType(Context), nullptr);
133*9880d681SAndroid Build Coastguard Worker break;
134*9880d681SAndroid Build Coastguard Worker case Intrinsic::sqrt:
135*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "sqrtf", "sqrt", "sqrtl");
136*9880d681SAndroid Build Coastguard Worker break;
137*9880d681SAndroid Build Coastguard Worker case Intrinsic::sin:
138*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "sinf", "sin", "sinl");
139*9880d681SAndroid Build Coastguard Worker break;
140*9880d681SAndroid Build Coastguard Worker case Intrinsic::cos:
141*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "cosf", "cos", "cosl");
142*9880d681SAndroid Build Coastguard Worker break;
143*9880d681SAndroid Build Coastguard Worker case Intrinsic::pow:
144*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "powf", "pow", "powl");
145*9880d681SAndroid Build Coastguard Worker break;
146*9880d681SAndroid Build Coastguard Worker case Intrinsic::log:
147*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "logf", "log", "logl");
148*9880d681SAndroid Build Coastguard Worker break;
149*9880d681SAndroid Build Coastguard Worker case Intrinsic::log2:
150*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "log2f", "log2", "log2l");
151*9880d681SAndroid Build Coastguard Worker break;
152*9880d681SAndroid Build Coastguard Worker case Intrinsic::log10:
153*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "log10f", "log10", "log10l");
154*9880d681SAndroid Build Coastguard Worker break;
155*9880d681SAndroid Build Coastguard Worker case Intrinsic::exp:
156*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "expf", "exp", "expl");
157*9880d681SAndroid Build Coastguard Worker break;
158*9880d681SAndroid Build Coastguard Worker case Intrinsic::exp2:
159*9880d681SAndroid Build Coastguard Worker EnsureFPIntrinsicsExist(M, F, "exp2f", "exp2", "exp2l");
160*9880d681SAndroid Build Coastguard Worker break;
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker /// LowerBSWAP - Emit the code to lower bswap of V before the specified
165*9880d681SAndroid Build Coastguard Worker /// instruction IP.
LowerBSWAP(LLVMContext & Context,Value * V,Instruction * IP)166*9880d681SAndroid Build Coastguard Worker static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) {
167*9880d681SAndroid Build Coastguard Worker assert(V->getType()->isIntegerTy() && "Can't bswap a non-integer type!");
168*9880d681SAndroid Build Coastguard Worker
169*9880d681SAndroid Build Coastguard Worker unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker IRBuilder<> Builder(IP);
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker switch(BitSize) {
174*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unhandled type size of value to byteswap!");
175*9880d681SAndroid Build Coastguard Worker case 16: {
176*9880d681SAndroid Build Coastguard Worker Value *Tmp1 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
177*9880d681SAndroid Build Coastguard Worker "bswap.2");
178*9880d681SAndroid Build Coastguard Worker Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
179*9880d681SAndroid Build Coastguard Worker "bswap.1");
180*9880d681SAndroid Build Coastguard Worker V = Builder.CreateOr(Tmp1, Tmp2, "bswap.i16");
181*9880d681SAndroid Build Coastguard Worker break;
182*9880d681SAndroid Build Coastguard Worker }
183*9880d681SAndroid Build Coastguard Worker case 32: {
184*9880d681SAndroid Build Coastguard Worker Value *Tmp4 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24),
185*9880d681SAndroid Build Coastguard Worker "bswap.4");
186*9880d681SAndroid Build Coastguard Worker Value *Tmp3 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
187*9880d681SAndroid Build Coastguard Worker "bswap.3");
188*9880d681SAndroid Build Coastguard Worker Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
189*9880d681SAndroid Build Coastguard Worker "bswap.2");
190*9880d681SAndroid Build Coastguard Worker Value *Tmp1 = Builder.CreateLShr(V,ConstantInt::get(V->getType(), 24),
191*9880d681SAndroid Build Coastguard Worker "bswap.1");
192*9880d681SAndroid Build Coastguard Worker Tmp3 = Builder.CreateAnd(Tmp3,
193*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Type::getInt32Ty(Context), 0xFF0000),
194*9880d681SAndroid Build Coastguard Worker "bswap.and3");
195*9880d681SAndroid Build Coastguard Worker Tmp2 = Builder.CreateAnd(Tmp2,
196*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Type::getInt32Ty(Context), 0xFF00),
197*9880d681SAndroid Build Coastguard Worker "bswap.and2");
198*9880d681SAndroid Build Coastguard Worker Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or1");
199*9880d681SAndroid Build Coastguard Worker Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or2");
200*9880d681SAndroid Build Coastguard Worker V = Builder.CreateOr(Tmp4, Tmp2, "bswap.i32");
201*9880d681SAndroid Build Coastguard Worker break;
202*9880d681SAndroid Build Coastguard Worker }
203*9880d681SAndroid Build Coastguard Worker case 64: {
204*9880d681SAndroid Build Coastguard Worker Value *Tmp8 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 56),
205*9880d681SAndroid Build Coastguard Worker "bswap.8");
206*9880d681SAndroid Build Coastguard Worker Value *Tmp7 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 40),
207*9880d681SAndroid Build Coastguard Worker "bswap.7");
208*9880d681SAndroid Build Coastguard Worker Value *Tmp6 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24),
209*9880d681SAndroid Build Coastguard Worker "bswap.6");
210*9880d681SAndroid Build Coastguard Worker Value *Tmp5 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
211*9880d681SAndroid Build Coastguard Worker "bswap.5");
212*9880d681SAndroid Build Coastguard Worker Value* Tmp4 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
213*9880d681SAndroid Build Coastguard Worker "bswap.4");
214*9880d681SAndroid Build Coastguard Worker Value* Tmp3 = Builder.CreateLShr(V,
215*9880d681SAndroid Build Coastguard Worker ConstantInt::get(V->getType(), 24),
216*9880d681SAndroid Build Coastguard Worker "bswap.3");
217*9880d681SAndroid Build Coastguard Worker Value* Tmp2 = Builder.CreateLShr(V,
218*9880d681SAndroid Build Coastguard Worker ConstantInt::get(V->getType(), 40),
219*9880d681SAndroid Build Coastguard Worker "bswap.2");
220*9880d681SAndroid Build Coastguard Worker Value* Tmp1 = Builder.CreateLShr(V,
221*9880d681SAndroid Build Coastguard Worker ConstantInt::get(V->getType(), 56),
222*9880d681SAndroid Build Coastguard Worker "bswap.1");
223*9880d681SAndroid Build Coastguard Worker Tmp7 = Builder.CreateAnd(Tmp7,
224*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Type::getInt64Ty(Context),
225*9880d681SAndroid Build Coastguard Worker 0xFF000000000000ULL),
226*9880d681SAndroid Build Coastguard Worker "bswap.and7");
227*9880d681SAndroid Build Coastguard Worker Tmp6 = Builder.CreateAnd(Tmp6,
228*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Type::getInt64Ty(Context),
229*9880d681SAndroid Build Coastguard Worker 0xFF0000000000ULL),
230*9880d681SAndroid Build Coastguard Worker "bswap.and6");
231*9880d681SAndroid Build Coastguard Worker Tmp5 = Builder.CreateAnd(Tmp5,
232*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Type::getInt64Ty(Context),
233*9880d681SAndroid Build Coastguard Worker 0xFF00000000ULL),
234*9880d681SAndroid Build Coastguard Worker "bswap.and5");
235*9880d681SAndroid Build Coastguard Worker Tmp4 = Builder.CreateAnd(Tmp4,
236*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Type::getInt64Ty(Context),
237*9880d681SAndroid Build Coastguard Worker 0xFF000000ULL),
238*9880d681SAndroid Build Coastguard Worker "bswap.and4");
239*9880d681SAndroid Build Coastguard Worker Tmp3 = Builder.CreateAnd(Tmp3,
240*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Type::getInt64Ty(Context),
241*9880d681SAndroid Build Coastguard Worker 0xFF0000ULL),
242*9880d681SAndroid Build Coastguard Worker "bswap.and3");
243*9880d681SAndroid Build Coastguard Worker Tmp2 = Builder.CreateAnd(Tmp2,
244*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Type::getInt64Ty(Context),
245*9880d681SAndroid Build Coastguard Worker 0xFF00ULL),
246*9880d681SAndroid Build Coastguard Worker "bswap.and2");
247*9880d681SAndroid Build Coastguard Worker Tmp8 = Builder.CreateOr(Tmp8, Tmp7, "bswap.or1");
248*9880d681SAndroid Build Coastguard Worker Tmp6 = Builder.CreateOr(Tmp6, Tmp5, "bswap.or2");
249*9880d681SAndroid Build Coastguard Worker Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or3");
250*9880d681SAndroid Build Coastguard Worker Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or4");
251*9880d681SAndroid Build Coastguard Worker Tmp8 = Builder.CreateOr(Tmp8, Tmp6, "bswap.or5");
252*9880d681SAndroid Build Coastguard Worker Tmp4 = Builder.CreateOr(Tmp4, Tmp2, "bswap.or6");
253*9880d681SAndroid Build Coastguard Worker V = Builder.CreateOr(Tmp8, Tmp4, "bswap.i64");
254*9880d681SAndroid Build Coastguard Worker break;
255*9880d681SAndroid Build Coastguard Worker }
256*9880d681SAndroid Build Coastguard Worker }
257*9880d681SAndroid Build Coastguard Worker return V;
258*9880d681SAndroid Build Coastguard Worker }
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker /// LowerCTPOP - Emit the code to lower ctpop of V before the specified
261*9880d681SAndroid Build Coastguard Worker /// instruction IP.
LowerCTPOP(LLVMContext & Context,Value * V,Instruction * IP)262*9880d681SAndroid Build Coastguard Worker static Value *LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP) {
263*9880d681SAndroid Build Coastguard Worker assert(V->getType()->isIntegerTy() && "Can't ctpop a non-integer type!");
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker static const uint64_t MaskValues[6] = {
266*9880d681SAndroid Build Coastguard Worker 0x5555555555555555ULL, 0x3333333333333333ULL,
267*9880d681SAndroid Build Coastguard Worker 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
268*9880d681SAndroid Build Coastguard Worker 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
269*9880d681SAndroid Build Coastguard Worker };
270*9880d681SAndroid Build Coastguard Worker
271*9880d681SAndroid Build Coastguard Worker IRBuilder<> Builder(IP);
272*9880d681SAndroid Build Coastguard Worker
273*9880d681SAndroid Build Coastguard Worker unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
274*9880d681SAndroid Build Coastguard Worker unsigned WordSize = (BitSize + 63) / 64;
275*9880d681SAndroid Build Coastguard Worker Value *Count = ConstantInt::get(V->getType(), 0);
276*9880d681SAndroid Build Coastguard Worker
277*9880d681SAndroid Build Coastguard Worker for (unsigned n = 0; n < WordSize; ++n) {
278*9880d681SAndroid Build Coastguard Worker Value *PartValue = V;
279*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, ct = 0; i < (BitSize>64 ? 64 : BitSize);
280*9880d681SAndroid Build Coastguard Worker i <<= 1, ++ct) {
281*9880d681SAndroid Build Coastguard Worker Value *MaskCst = ConstantInt::get(V->getType(), MaskValues[ct]);
282*9880d681SAndroid Build Coastguard Worker Value *LHS = Builder.CreateAnd(PartValue, MaskCst, "cppop.and1");
283*9880d681SAndroid Build Coastguard Worker Value *VShift = Builder.CreateLShr(PartValue,
284*9880d681SAndroid Build Coastguard Worker ConstantInt::get(V->getType(), i),
285*9880d681SAndroid Build Coastguard Worker "ctpop.sh");
286*9880d681SAndroid Build Coastguard Worker Value *RHS = Builder.CreateAnd(VShift, MaskCst, "cppop.and2");
287*9880d681SAndroid Build Coastguard Worker PartValue = Builder.CreateAdd(LHS, RHS, "ctpop.step");
288*9880d681SAndroid Build Coastguard Worker }
289*9880d681SAndroid Build Coastguard Worker Count = Builder.CreateAdd(PartValue, Count, "ctpop.part");
290*9880d681SAndroid Build Coastguard Worker if (BitSize > 64) {
291*9880d681SAndroid Build Coastguard Worker V = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 64),
292*9880d681SAndroid Build Coastguard Worker "ctpop.part.sh");
293*9880d681SAndroid Build Coastguard Worker BitSize -= 64;
294*9880d681SAndroid Build Coastguard Worker }
295*9880d681SAndroid Build Coastguard Worker }
296*9880d681SAndroid Build Coastguard Worker
297*9880d681SAndroid Build Coastguard Worker return Count;
298*9880d681SAndroid Build Coastguard Worker }
299*9880d681SAndroid Build Coastguard Worker
300*9880d681SAndroid Build Coastguard Worker /// LowerCTLZ - Emit the code to lower ctlz of V before the specified
301*9880d681SAndroid Build Coastguard Worker /// instruction IP.
LowerCTLZ(LLVMContext & Context,Value * V,Instruction * IP)302*9880d681SAndroid Build Coastguard Worker static Value *LowerCTLZ(LLVMContext &Context, Value *V, Instruction *IP) {
303*9880d681SAndroid Build Coastguard Worker
304*9880d681SAndroid Build Coastguard Worker IRBuilder<> Builder(IP);
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
307*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1; i < BitSize; i <<= 1) {
308*9880d681SAndroid Build Coastguard Worker Value *ShVal = ConstantInt::get(V->getType(), i);
309*9880d681SAndroid Build Coastguard Worker ShVal = Builder.CreateLShr(V, ShVal, "ctlz.sh");
310*9880d681SAndroid Build Coastguard Worker V = Builder.CreateOr(V, ShVal, "ctlz.step");
311*9880d681SAndroid Build Coastguard Worker }
312*9880d681SAndroid Build Coastguard Worker
313*9880d681SAndroid Build Coastguard Worker V = Builder.CreateNot(V);
314*9880d681SAndroid Build Coastguard Worker return LowerCTPOP(Context, V, IP);
315*9880d681SAndroid Build Coastguard Worker }
316*9880d681SAndroid Build Coastguard Worker
ReplaceFPIntrinsicWithCall(CallInst * CI,const char * Fname,const char * Dname,const char * LDname)317*9880d681SAndroid Build Coastguard Worker static void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname,
318*9880d681SAndroid Build Coastguard Worker const char *Dname,
319*9880d681SAndroid Build Coastguard Worker const char *LDname) {
320*9880d681SAndroid Build Coastguard Worker CallSite CS(CI);
321*9880d681SAndroid Build Coastguard Worker switch (CI->getArgOperand(0)->getType()->getTypeID()) {
322*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Invalid type in intrinsic");
323*9880d681SAndroid Build Coastguard Worker case Type::FloatTyID:
324*9880d681SAndroid Build Coastguard Worker ReplaceCallWith(Fname, CI, CS.arg_begin(), CS.arg_end(),
325*9880d681SAndroid Build Coastguard Worker Type::getFloatTy(CI->getContext()));
326*9880d681SAndroid Build Coastguard Worker break;
327*9880d681SAndroid Build Coastguard Worker case Type::DoubleTyID:
328*9880d681SAndroid Build Coastguard Worker ReplaceCallWith(Dname, CI, CS.arg_begin(), CS.arg_end(),
329*9880d681SAndroid Build Coastguard Worker Type::getDoubleTy(CI->getContext()));
330*9880d681SAndroid Build Coastguard Worker break;
331*9880d681SAndroid Build Coastguard Worker case Type::X86_FP80TyID:
332*9880d681SAndroid Build Coastguard Worker case Type::FP128TyID:
333*9880d681SAndroid Build Coastguard Worker case Type::PPC_FP128TyID:
334*9880d681SAndroid Build Coastguard Worker ReplaceCallWith(LDname, CI, CS.arg_begin(), CS.arg_end(),
335*9880d681SAndroid Build Coastguard Worker CI->getArgOperand(0)->getType());
336*9880d681SAndroid Build Coastguard Worker break;
337*9880d681SAndroid Build Coastguard Worker }
338*9880d681SAndroid Build Coastguard Worker }
339*9880d681SAndroid Build Coastguard Worker
LowerIntrinsicCall(CallInst * CI)340*9880d681SAndroid Build Coastguard Worker void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
341*9880d681SAndroid Build Coastguard Worker IRBuilder<> Builder(CI);
342*9880d681SAndroid Build Coastguard Worker LLVMContext &Context = CI->getContext();
343*9880d681SAndroid Build Coastguard Worker
344*9880d681SAndroid Build Coastguard Worker const Function *Callee = CI->getCalledFunction();
345*9880d681SAndroid Build Coastguard Worker assert(Callee && "Cannot lower an indirect call!");
346*9880d681SAndroid Build Coastguard Worker
347*9880d681SAndroid Build Coastguard Worker CallSite CS(CI);
348*9880d681SAndroid Build Coastguard Worker switch (Callee->getIntrinsicID()) {
349*9880d681SAndroid Build Coastguard Worker case Intrinsic::not_intrinsic:
350*9880d681SAndroid Build Coastguard Worker report_fatal_error("Cannot lower a call to a non-intrinsic function '"+
351*9880d681SAndroid Build Coastguard Worker Callee->getName() + "'!");
352*9880d681SAndroid Build Coastguard Worker default:
353*9880d681SAndroid Build Coastguard Worker report_fatal_error("Code generator does not support intrinsic function '"+
354*9880d681SAndroid Build Coastguard Worker Callee->getName()+"'!");
355*9880d681SAndroid Build Coastguard Worker
356*9880d681SAndroid Build Coastguard Worker case Intrinsic::expect: {
357*9880d681SAndroid Build Coastguard Worker // Just replace __builtin_expect(exp, c) with EXP.
358*9880d681SAndroid Build Coastguard Worker Value *V = CI->getArgOperand(0);
359*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(V);
360*9880d681SAndroid Build Coastguard Worker break;
361*9880d681SAndroid Build Coastguard Worker }
362*9880d681SAndroid Build Coastguard Worker
363*9880d681SAndroid Build Coastguard Worker // The setjmp/longjmp intrinsics should only exist in the code if it was
364*9880d681SAndroid Build Coastguard Worker // never optimized (ie, right out of the CFE), or if it has been hacked on
365*9880d681SAndroid Build Coastguard Worker // by the lowerinvoke pass. In both cases, the right thing to do is to
366*9880d681SAndroid Build Coastguard Worker // convert the call to an explicit setjmp or longjmp call.
367*9880d681SAndroid Build Coastguard Worker case Intrinsic::setjmp: {
368*9880d681SAndroid Build Coastguard Worker Value *V = ReplaceCallWith("setjmp", CI, CS.arg_begin(), CS.arg_end(),
369*9880d681SAndroid Build Coastguard Worker Type::getInt32Ty(Context));
370*9880d681SAndroid Build Coastguard Worker if (!CI->getType()->isVoidTy())
371*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(V);
372*9880d681SAndroid Build Coastguard Worker break;
373*9880d681SAndroid Build Coastguard Worker }
374*9880d681SAndroid Build Coastguard Worker case Intrinsic::sigsetjmp:
375*9880d681SAndroid Build Coastguard Worker if (!CI->getType()->isVoidTy())
376*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
377*9880d681SAndroid Build Coastguard Worker break;
378*9880d681SAndroid Build Coastguard Worker
379*9880d681SAndroid Build Coastguard Worker case Intrinsic::longjmp: {
380*9880d681SAndroid Build Coastguard Worker ReplaceCallWith("longjmp", CI, CS.arg_begin(), CS.arg_end(),
381*9880d681SAndroid Build Coastguard Worker Type::getVoidTy(Context));
382*9880d681SAndroid Build Coastguard Worker break;
383*9880d681SAndroid Build Coastguard Worker }
384*9880d681SAndroid Build Coastguard Worker
385*9880d681SAndroid Build Coastguard Worker case Intrinsic::siglongjmp: {
386*9880d681SAndroid Build Coastguard Worker // Insert the call to abort
387*9880d681SAndroid Build Coastguard Worker ReplaceCallWith("abort", CI, CS.arg_end(), CS.arg_end(),
388*9880d681SAndroid Build Coastguard Worker Type::getVoidTy(Context));
389*9880d681SAndroid Build Coastguard Worker break;
390*9880d681SAndroid Build Coastguard Worker }
391*9880d681SAndroid Build Coastguard Worker case Intrinsic::ctpop:
392*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getArgOperand(0), CI));
393*9880d681SAndroid Build Coastguard Worker break;
394*9880d681SAndroid Build Coastguard Worker
395*9880d681SAndroid Build Coastguard Worker case Intrinsic::bswap:
396*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(LowerBSWAP(Context, CI->getArgOperand(0), CI));
397*9880d681SAndroid Build Coastguard Worker break;
398*9880d681SAndroid Build Coastguard Worker
399*9880d681SAndroid Build Coastguard Worker case Intrinsic::ctlz:
400*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(LowerCTLZ(Context, CI->getArgOperand(0), CI));
401*9880d681SAndroid Build Coastguard Worker break;
402*9880d681SAndroid Build Coastguard Worker
403*9880d681SAndroid Build Coastguard Worker case Intrinsic::cttz: {
404*9880d681SAndroid Build Coastguard Worker // cttz(x) -> ctpop(~X & (X-1))
405*9880d681SAndroid Build Coastguard Worker Value *Src = CI->getArgOperand(0);
406*9880d681SAndroid Build Coastguard Worker Value *NotSrc = Builder.CreateNot(Src);
407*9880d681SAndroid Build Coastguard Worker NotSrc->setName(Src->getName() + ".not");
408*9880d681SAndroid Build Coastguard Worker Value *SrcM1 = ConstantInt::get(Src->getType(), 1);
409*9880d681SAndroid Build Coastguard Worker SrcM1 = Builder.CreateSub(Src, SrcM1);
410*9880d681SAndroid Build Coastguard Worker Src = LowerCTPOP(Context, Builder.CreateAnd(NotSrc, SrcM1), CI);
411*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(Src);
412*9880d681SAndroid Build Coastguard Worker break;
413*9880d681SAndroid Build Coastguard Worker }
414*9880d681SAndroid Build Coastguard Worker
415*9880d681SAndroid Build Coastguard Worker case Intrinsic::stacksave:
416*9880d681SAndroid Build Coastguard Worker case Intrinsic::stackrestore: {
417*9880d681SAndroid Build Coastguard Worker if (!Warned)
418*9880d681SAndroid Build Coastguard Worker errs() << "WARNING: this target does not support the llvm.stack"
419*9880d681SAndroid Build Coastguard Worker << (Callee->getIntrinsicID() == Intrinsic::stacksave ?
420*9880d681SAndroid Build Coastguard Worker "save" : "restore") << " intrinsic.\n";
421*9880d681SAndroid Build Coastguard Worker Warned = true;
422*9880d681SAndroid Build Coastguard Worker if (Callee->getIntrinsicID() == Intrinsic::stacksave)
423*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
424*9880d681SAndroid Build Coastguard Worker break;
425*9880d681SAndroid Build Coastguard Worker }
426*9880d681SAndroid Build Coastguard Worker
427*9880d681SAndroid Build Coastguard Worker case Intrinsic::get_dynamic_area_offset:
428*9880d681SAndroid Build Coastguard Worker errs() << "WARNING: this target does not support the custom llvm.get."
429*9880d681SAndroid Build Coastguard Worker "dynamic.area.offset. It is being lowered to a constant 0\n";
430*9880d681SAndroid Build Coastguard Worker // Just lower it to a constant 0 because for most targets
431*9880d681SAndroid Build Coastguard Worker // @llvm.get.dynamic.area.offset is lowered to zero.
432*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0));
433*9880d681SAndroid Build Coastguard Worker break;
434*9880d681SAndroid Build Coastguard Worker case Intrinsic::returnaddress:
435*9880d681SAndroid Build Coastguard Worker case Intrinsic::frameaddress:
436*9880d681SAndroid Build Coastguard Worker errs() << "WARNING: this target does not support the llvm."
437*9880d681SAndroid Build Coastguard Worker << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
438*9880d681SAndroid Build Coastguard Worker "return" : "frame") << "address intrinsic.\n";
439*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(ConstantPointerNull::get(
440*9880d681SAndroid Build Coastguard Worker cast<PointerType>(CI->getType())));
441*9880d681SAndroid Build Coastguard Worker break;
442*9880d681SAndroid Build Coastguard Worker
443*9880d681SAndroid Build Coastguard Worker case Intrinsic::prefetch:
444*9880d681SAndroid Build Coastguard Worker break; // Simply strip out prefetches on unsupported architectures
445*9880d681SAndroid Build Coastguard Worker
446*9880d681SAndroid Build Coastguard Worker case Intrinsic::pcmarker:
447*9880d681SAndroid Build Coastguard Worker break; // Simply strip out pcmarker on unsupported architectures
448*9880d681SAndroid Build Coastguard Worker case Intrinsic::readcyclecounter: {
449*9880d681SAndroid Build Coastguard Worker errs() << "WARNING: this target does not support the llvm.readcyclecoun"
450*9880d681SAndroid Build Coastguard Worker << "ter intrinsic. It is being lowered to a constant 0\n";
451*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context), 0));
452*9880d681SAndroid Build Coastguard Worker break;
453*9880d681SAndroid Build Coastguard Worker }
454*9880d681SAndroid Build Coastguard Worker
455*9880d681SAndroid Build Coastguard Worker case Intrinsic::dbg_declare:
456*9880d681SAndroid Build Coastguard Worker break; // Simply strip out debugging intrinsics
457*9880d681SAndroid Build Coastguard Worker
458*9880d681SAndroid Build Coastguard Worker case Intrinsic::eh_typeid_for:
459*9880d681SAndroid Build Coastguard Worker // Return something different to eh_selector.
460*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
461*9880d681SAndroid Build Coastguard Worker break;
462*9880d681SAndroid Build Coastguard Worker
463*9880d681SAndroid Build Coastguard Worker case Intrinsic::annotation:
464*9880d681SAndroid Build Coastguard Worker case Intrinsic::ptr_annotation:
465*9880d681SAndroid Build Coastguard Worker // Just drop the annotation, but forward the value
466*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(CI->getOperand(0));
467*9880d681SAndroid Build Coastguard Worker break;
468*9880d681SAndroid Build Coastguard Worker
469*9880d681SAndroid Build Coastguard Worker case Intrinsic::assume:
470*9880d681SAndroid Build Coastguard Worker case Intrinsic::var_annotation:
471*9880d681SAndroid Build Coastguard Worker break; // Strip out these intrinsics
472*9880d681SAndroid Build Coastguard Worker
473*9880d681SAndroid Build Coastguard Worker case Intrinsic::memcpy: {
474*9880d681SAndroid Build Coastguard Worker Type *IntPtr = DL.getIntPtrType(Context);
475*9880d681SAndroid Build Coastguard Worker Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
476*9880d681SAndroid Build Coastguard Worker /* isSigned */ false);
477*9880d681SAndroid Build Coastguard Worker Value *Ops[3];
478*9880d681SAndroid Build Coastguard Worker Ops[0] = CI->getArgOperand(0);
479*9880d681SAndroid Build Coastguard Worker Ops[1] = CI->getArgOperand(1);
480*9880d681SAndroid Build Coastguard Worker Ops[2] = Size;
481*9880d681SAndroid Build Coastguard Worker ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
482*9880d681SAndroid Build Coastguard Worker break;
483*9880d681SAndroid Build Coastguard Worker }
484*9880d681SAndroid Build Coastguard Worker case Intrinsic::memmove: {
485*9880d681SAndroid Build Coastguard Worker Type *IntPtr = DL.getIntPtrType(Context);
486*9880d681SAndroid Build Coastguard Worker Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
487*9880d681SAndroid Build Coastguard Worker /* isSigned */ false);
488*9880d681SAndroid Build Coastguard Worker Value *Ops[3];
489*9880d681SAndroid Build Coastguard Worker Ops[0] = CI->getArgOperand(0);
490*9880d681SAndroid Build Coastguard Worker Ops[1] = CI->getArgOperand(1);
491*9880d681SAndroid Build Coastguard Worker Ops[2] = Size;
492*9880d681SAndroid Build Coastguard Worker ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
493*9880d681SAndroid Build Coastguard Worker break;
494*9880d681SAndroid Build Coastguard Worker }
495*9880d681SAndroid Build Coastguard Worker case Intrinsic::memset: {
496*9880d681SAndroid Build Coastguard Worker Value *Op0 = CI->getArgOperand(0);
497*9880d681SAndroid Build Coastguard Worker Type *IntPtr = DL.getIntPtrType(Op0->getType());
498*9880d681SAndroid Build Coastguard Worker Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
499*9880d681SAndroid Build Coastguard Worker /* isSigned */ false);
500*9880d681SAndroid Build Coastguard Worker Value *Ops[3];
501*9880d681SAndroid Build Coastguard Worker Ops[0] = Op0;
502*9880d681SAndroid Build Coastguard Worker // Extend the amount to i32.
503*9880d681SAndroid Build Coastguard Worker Ops[1] = Builder.CreateIntCast(CI->getArgOperand(1),
504*9880d681SAndroid Build Coastguard Worker Type::getInt32Ty(Context),
505*9880d681SAndroid Build Coastguard Worker /* isSigned */ false);
506*9880d681SAndroid Build Coastguard Worker Ops[2] = Size;
507*9880d681SAndroid Build Coastguard Worker ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
508*9880d681SAndroid Build Coastguard Worker break;
509*9880d681SAndroid Build Coastguard Worker }
510*9880d681SAndroid Build Coastguard Worker case Intrinsic::sqrt: {
511*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "sqrtf", "sqrt", "sqrtl");
512*9880d681SAndroid Build Coastguard Worker break;
513*9880d681SAndroid Build Coastguard Worker }
514*9880d681SAndroid Build Coastguard Worker case Intrinsic::log: {
515*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "logf", "log", "logl");
516*9880d681SAndroid Build Coastguard Worker break;
517*9880d681SAndroid Build Coastguard Worker }
518*9880d681SAndroid Build Coastguard Worker case Intrinsic::log2: {
519*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "log2f", "log2", "log2l");
520*9880d681SAndroid Build Coastguard Worker break;
521*9880d681SAndroid Build Coastguard Worker }
522*9880d681SAndroid Build Coastguard Worker case Intrinsic::log10: {
523*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "log10f", "log10", "log10l");
524*9880d681SAndroid Build Coastguard Worker break;
525*9880d681SAndroid Build Coastguard Worker }
526*9880d681SAndroid Build Coastguard Worker case Intrinsic::exp: {
527*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "expf", "exp", "expl");
528*9880d681SAndroid Build Coastguard Worker break;
529*9880d681SAndroid Build Coastguard Worker }
530*9880d681SAndroid Build Coastguard Worker case Intrinsic::exp2: {
531*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "exp2f", "exp2", "exp2l");
532*9880d681SAndroid Build Coastguard Worker break;
533*9880d681SAndroid Build Coastguard Worker }
534*9880d681SAndroid Build Coastguard Worker case Intrinsic::pow: {
535*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "powf", "pow", "powl");
536*9880d681SAndroid Build Coastguard Worker break;
537*9880d681SAndroid Build Coastguard Worker }
538*9880d681SAndroid Build Coastguard Worker case Intrinsic::sin: {
539*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "sinf", "sin", "sinl");
540*9880d681SAndroid Build Coastguard Worker break;
541*9880d681SAndroid Build Coastguard Worker }
542*9880d681SAndroid Build Coastguard Worker case Intrinsic::cos: {
543*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "cosf", "cos", "cosl");
544*9880d681SAndroid Build Coastguard Worker break;
545*9880d681SAndroid Build Coastguard Worker }
546*9880d681SAndroid Build Coastguard Worker case Intrinsic::floor: {
547*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "floorf", "floor", "floorl");
548*9880d681SAndroid Build Coastguard Worker break;
549*9880d681SAndroid Build Coastguard Worker }
550*9880d681SAndroid Build Coastguard Worker case Intrinsic::ceil: {
551*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "ceilf", "ceil", "ceill");
552*9880d681SAndroid Build Coastguard Worker break;
553*9880d681SAndroid Build Coastguard Worker }
554*9880d681SAndroid Build Coastguard Worker case Intrinsic::trunc: {
555*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "truncf", "trunc", "truncl");
556*9880d681SAndroid Build Coastguard Worker break;
557*9880d681SAndroid Build Coastguard Worker }
558*9880d681SAndroid Build Coastguard Worker case Intrinsic::round: {
559*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "roundf", "round", "roundl");
560*9880d681SAndroid Build Coastguard Worker break;
561*9880d681SAndroid Build Coastguard Worker }
562*9880d681SAndroid Build Coastguard Worker case Intrinsic::copysign: {
563*9880d681SAndroid Build Coastguard Worker ReplaceFPIntrinsicWithCall(CI, "copysignf", "copysign", "copysignl");
564*9880d681SAndroid Build Coastguard Worker break;
565*9880d681SAndroid Build Coastguard Worker }
566*9880d681SAndroid Build Coastguard Worker case Intrinsic::flt_rounds:
567*9880d681SAndroid Build Coastguard Worker // Lower to "round to the nearest"
568*9880d681SAndroid Build Coastguard Worker if (!CI->getType()->isVoidTy())
569*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
570*9880d681SAndroid Build Coastguard Worker break;
571*9880d681SAndroid Build Coastguard Worker case Intrinsic::invariant_start:
572*9880d681SAndroid Build Coastguard Worker case Intrinsic::lifetime_start:
573*9880d681SAndroid Build Coastguard Worker // Discard region information.
574*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
575*9880d681SAndroid Build Coastguard Worker break;
576*9880d681SAndroid Build Coastguard Worker case Intrinsic::invariant_end:
577*9880d681SAndroid Build Coastguard Worker case Intrinsic::lifetime_end:
578*9880d681SAndroid Build Coastguard Worker // Discard region information.
579*9880d681SAndroid Build Coastguard Worker break;
580*9880d681SAndroid Build Coastguard Worker }
581*9880d681SAndroid Build Coastguard Worker
582*9880d681SAndroid Build Coastguard Worker assert(CI->use_empty() &&
583*9880d681SAndroid Build Coastguard Worker "Lowering should have eliminated any uses of the intrinsic call!");
584*9880d681SAndroid Build Coastguard Worker CI->eraseFromParent();
585*9880d681SAndroid Build Coastguard Worker }
586*9880d681SAndroid Build Coastguard Worker
LowerToByteSwap(CallInst * CI)587*9880d681SAndroid Build Coastguard Worker bool IntrinsicLowering::LowerToByteSwap(CallInst *CI) {
588*9880d681SAndroid Build Coastguard Worker // Verify this is a simple bswap.
589*9880d681SAndroid Build Coastguard Worker if (CI->getNumArgOperands() != 1 ||
590*9880d681SAndroid Build Coastguard Worker CI->getType() != CI->getArgOperand(0)->getType() ||
591*9880d681SAndroid Build Coastguard Worker !CI->getType()->isIntegerTy())
592*9880d681SAndroid Build Coastguard Worker return false;
593*9880d681SAndroid Build Coastguard Worker
594*9880d681SAndroid Build Coastguard Worker IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
595*9880d681SAndroid Build Coastguard Worker if (!Ty)
596*9880d681SAndroid Build Coastguard Worker return false;
597*9880d681SAndroid Build Coastguard Worker
598*9880d681SAndroid Build Coastguard Worker // Okay, we can do this xform, do so now.
599*9880d681SAndroid Build Coastguard Worker Module *M = CI->getModule();
600*9880d681SAndroid Build Coastguard Worker Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Ty);
601*9880d681SAndroid Build Coastguard Worker
602*9880d681SAndroid Build Coastguard Worker Value *Op = CI->getArgOperand(0);
603*9880d681SAndroid Build Coastguard Worker Op = CallInst::Create(Int, Op, CI->getName(), CI);
604*9880d681SAndroid Build Coastguard Worker
605*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(Op);
606*9880d681SAndroid Build Coastguard Worker CI->eraseFromParent();
607*9880d681SAndroid Build Coastguard Worker return true;
608*9880d681SAndroid Build Coastguard Worker }
609