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