IntrinsicLowering.cpp revision 0ee69bbd333c22198344e7336ae74767ca9381cc
1//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the IntrinsicLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Constants.h"
15#include "llvm/DerivedTypes.h"
16#include "llvm/Module.h"
17#include "llvm/Instructions.h"
18#include "llvm/Type.h"
19#include "llvm/CodeGen/IntrinsicLowering.h"
20#include "llvm/Support/Streams.h"
21using namespace llvm;
22
23template <class ArgIt>
24static void EnsureFunctionExists(Module &M, const char *Name,
25                                 ArgIt ArgBegin, ArgIt ArgEnd,
26                                 const Type *RetTy) {
27  // Insert a correctly-typed definition now.
28  std::vector<const Type *> ParamTys;
29  for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
30    ParamTys.push_back(I->getType());
31  M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
32}
33
34/// ReplaceCallWith - This function is used when we want to lower an intrinsic
35/// call to a call of an external function.  This handles hard cases such as
36/// when there was already a prototype for the external function, and if that
37/// prototype doesn't match the arguments we expect to pass in.
38template <class ArgIt>
39static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
40                                 ArgIt ArgBegin, ArgIt ArgEnd,
41                                 const Type *RetTy, Constant *&FCache) {
42  if (!FCache) {
43    // If we haven't already looked up this function, check to see if the
44    // program already contains a function with this name.
45    Module *M = CI->getParent()->getParent()->getParent();
46    // Get or insert the definition now.
47    std::vector<const Type *> ParamTys;
48    for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
49      ParamTys.push_back((*I)->getType());
50    FCache = M->getOrInsertFunction(NewFn,
51                                    FunctionType::get(RetTy, ParamTys, false));
52  }
53
54  std::vector<Value*> Operands(ArgBegin, ArgEnd);
55  CallInst *NewCI = new CallInst(FCache, Operands, CI->getName(), CI);
56  if (!CI->use_empty())
57    CI->replaceAllUsesWith(NewCI);
58  return NewCI;
59}
60
61void IntrinsicLowering::AddPrototypes(Module &M) {
62  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
63    if (I->isExternal() && !I->use_empty())
64      switch (I->getIntrinsicID()) {
65      default: break;
66      case Intrinsic::setjmp:
67        EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(),
68                             Type::Int32Ty);
69        break;
70      case Intrinsic::longjmp:
71        EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),
72                             Type::VoidTy);
73        break;
74      case Intrinsic::siglongjmp:
75        EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(),
76                             Type::VoidTy);
77        break;
78      case Intrinsic::memcpy_i32:
79      case Intrinsic::memcpy_i64:
80        EnsureFunctionExists(M, "memcpy", I->arg_begin(), --I->arg_end(),
81                             I->arg_begin()->getType());
82        break;
83      case Intrinsic::memmove_i32:
84      case Intrinsic::memmove_i64:
85        EnsureFunctionExists(M, "memmove", I->arg_begin(), --I->arg_end(),
86                             I->arg_begin()->getType());
87        break;
88      case Intrinsic::memset_i32:
89      case Intrinsic::memset_i64:
90        M.getOrInsertFunction("memset", PointerType::get(Type::Int8Ty),
91                              PointerType::get(Type::Int8Ty),
92                              Type::Int32Ty, (--(--I->arg_end()))->getType(),
93                              (Type *)0);
94        break;
95      case Intrinsic::sqrt_f32:
96      case Intrinsic::sqrt_f64:
97        if(I->arg_begin()->getType() == Type::FloatTy)
98          EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(),
99                               Type::FloatTy);
100        else
101          EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(),
102                               Type::DoubleTy);
103        break;
104      }
105}
106
107/// LowerBSWAP - Emit the code to lower bswap of V before the specified
108/// instruction IP.
109static Value *LowerBSWAP(Value *V, Instruction *IP) {
110  assert(V->getType()->isIntegral() && "Can't bswap a non-integer type!");
111
112  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
113
114  switch(BitSize) {
115  default: assert(0 && "Unhandled type size of value to byteswap!");
116  case 16: {
117    Value *Tmp1 = new ShiftInst(Instruction::Shl, V,
118                                ConstantInt::get(Type::Int8Ty,8),"bswap.2",IP);
119    Value *Tmp2 = new ShiftInst(Instruction::LShr, V,
120                                ConstantInt::get(Type::Int8Ty,8),"bswap.1",IP);
121    V = BinaryOperator::createOr(Tmp1, Tmp2, "bswap.i16", IP);
122    break;
123  }
124  case 32: {
125    Value *Tmp4 = new ShiftInst(Instruction::Shl, V,
126                              ConstantInt::get(Type::Int8Ty,24),"bswap.4", IP);
127    Value *Tmp3 = new ShiftInst(Instruction::Shl, V,
128                              ConstantInt::get(Type::Int8Ty,8),"bswap.3",IP);
129    Value *Tmp2 = new ShiftInst(Instruction::LShr, V,
130                              ConstantInt::get(Type::Int8Ty,8),"bswap.2",IP);
131    Value *Tmp1 = new ShiftInst(Instruction::LShr, V,
132                              ConstantInt::get(Type::Int8Ty,24),"bswap.1", IP);
133    Tmp3 = BinaryOperator::createAnd(Tmp3,
134                                     ConstantInt::get(Type::Int32Ty, 0xFF0000),
135                                     "bswap.and3", IP);
136    Tmp2 = BinaryOperator::createAnd(Tmp2,
137                                     ConstantInt::get(Type::Int32Ty, 0xFF00),
138                                     "bswap.and2", IP);
139    Tmp4 = BinaryOperator::createOr(Tmp4, Tmp3, "bswap.or1", IP);
140    Tmp2 = BinaryOperator::createOr(Tmp2, Tmp1, "bswap.or2", IP);
141    V = BinaryOperator::createOr(Tmp4, Tmp3, "bswap.i32", IP);
142    break;
143  }
144  case 64: {
145    Value *Tmp8 = new ShiftInst(Instruction::Shl, V,
146                              ConstantInt::get(Type::Int8Ty,56),"bswap.8", IP);
147    Value *Tmp7 = new ShiftInst(Instruction::Shl, V,
148                              ConstantInt::get(Type::Int8Ty,40),"bswap.7", IP);
149    Value *Tmp6 = new ShiftInst(Instruction::Shl, V,
150                              ConstantInt::get(Type::Int8Ty,24),"bswap.6", IP);
151    Value *Tmp5 = new ShiftInst(Instruction::Shl, V,
152                              ConstantInt::get(Type::Int8Ty,8),"bswap.5", IP);
153    Value* Tmp4 = new ShiftInst(Instruction::LShr, V,
154                              ConstantInt::get(Type::Int8Ty,8),"bswap.4", IP);
155    Value* Tmp3 = new ShiftInst(Instruction::LShr, V,
156                              ConstantInt::get(Type::Int8Ty,24),"bswap.3", IP);
157    Value* Tmp2 = new ShiftInst(Instruction::LShr, V,
158                              ConstantInt::get(Type::Int8Ty,40),"bswap.2", IP);
159    Value* Tmp1 = new ShiftInst(Instruction::LShr, V,
160                              ConstantInt::get(Type::Int8Ty,56),"bswap.1", IP);
161    Tmp7 = BinaryOperator::createAnd(Tmp7,
162                             ConstantInt::get(Type::Int64Ty,
163                               0xFF000000000000ULL),
164                             "bswap.and7", IP);
165    Tmp6 = BinaryOperator::createAnd(Tmp6,
166                             ConstantInt::get(Type::Int64Ty, 0xFF0000000000ULL),
167                             "bswap.and6", IP);
168    Tmp5 = BinaryOperator::createAnd(Tmp5,
169                             ConstantInt::get(Type::Int64Ty, 0xFF00000000ULL),
170                             "bswap.and5", IP);
171    Tmp4 = BinaryOperator::createAnd(Tmp4,
172                             ConstantInt::get(Type::Int64Ty, 0xFF000000ULL),
173                             "bswap.and4", IP);
174    Tmp3 = BinaryOperator::createAnd(Tmp3,
175                             ConstantInt::get(Type::Int64Ty, 0xFF0000ULL),
176                             "bswap.and3", IP);
177    Tmp2 = BinaryOperator::createAnd(Tmp2,
178                             ConstantInt::get(Type::Int64Ty, 0xFF00ULL),
179                             "bswap.and2", IP);
180    Tmp8 = BinaryOperator::createOr(Tmp8, Tmp7, "bswap.or1", IP);
181    Tmp6 = BinaryOperator::createOr(Tmp6, Tmp5, "bswap.or2", IP);
182    Tmp4 = BinaryOperator::createOr(Tmp4, Tmp3, "bswap.or3", IP);
183    Tmp2 = BinaryOperator::createOr(Tmp2, Tmp1, "bswap.or4", IP);
184    Tmp8 = BinaryOperator::createOr(Tmp8, Tmp6, "bswap.or5", IP);
185    Tmp4 = BinaryOperator::createOr(Tmp4, Tmp2, "bswap.or6", IP);
186    V = BinaryOperator::createOr(Tmp8, Tmp4, "bswap.i64", IP);
187    break;
188  }
189  }
190  return V;
191}
192
193/// LowerCTPOP - Emit the code to lower ctpop of V before the specified
194/// instruction IP.
195static Value *LowerCTPOP(Value *V, Instruction *IP) {
196  assert(V->getType()->isIntegral() && "Can't ctpop a non-integer type!");
197
198  static const uint64_t MaskValues[6] = {
199    0x5555555555555555ULL, 0x3333333333333333ULL,
200    0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
201    0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
202  };
203
204  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
205
206  for (unsigned i = 1, ct = 0; i != BitSize; i <<= 1, ++ct) {
207    Value *MaskCst = ConstantInt::get(V->getType(), MaskValues[ct]);
208    Value *LHS = BinaryOperator::createAnd(V, MaskCst, "cppop.and1", IP);
209    Value *VShift = new ShiftInst(Instruction::LShr, V,
210                      ConstantInt::get(Type::Int8Ty, i), "ctpop.sh", IP);
211    Value *RHS = BinaryOperator::createAnd(VShift, MaskCst, "cppop.and2", IP);
212    V = BinaryOperator::createAdd(LHS, RHS, "ctpop.step", IP);
213  }
214
215  return V;
216}
217
218/// LowerCTLZ - Emit the code to lower ctlz of V before the specified
219/// instruction IP.
220static Value *LowerCTLZ(Value *V, Instruction *IP) {
221
222  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
223  for (unsigned i = 1; i != BitSize; i <<= 1) {
224    Value *ShVal = ConstantInt::get(Type::Int8Ty, i);
225    ShVal = new ShiftInst(Instruction::LShr, V, ShVal, "ctlz.sh", IP);
226    V = BinaryOperator::createOr(V, ShVal, "ctlz.step", IP);
227  }
228
229  V = BinaryOperator::createNot(V, "", IP);
230  return LowerCTPOP(V, IP);
231}
232
233
234
235void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
236  Function *Callee = CI->getCalledFunction();
237  assert(Callee && "Cannot lower an indirect call!");
238
239  switch (Callee->getIntrinsicID()) {
240  case Intrinsic::not_intrinsic:
241    cerr << "Cannot lower a call to a non-intrinsic function '"
242         << Callee->getName() << "'!\n";
243    abort();
244  default:
245    cerr << "Error: Code generator does not support intrinsic function '"
246         << Callee->getName() << "'!\n";
247    abort();
248
249    // The setjmp/longjmp intrinsics should only exist in the code if it was
250    // never optimized (ie, right out of the CFE), or if it has been hacked on
251    // by the lowerinvoke pass.  In both cases, the right thing to do is to
252    // convert the call to an explicit setjmp or longjmp call.
253  case Intrinsic::setjmp: {
254    static Constant *SetjmpFCache = 0;
255    Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
256                               Type::Int32Ty, SetjmpFCache);
257    if (CI->getType() != Type::VoidTy)
258      CI->replaceAllUsesWith(V);
259    break;
260  }
261  case Intrinsic::sigsetjmp:
262     if (CI->getType() != Type::VoidTy)
263       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
264     break;
265
266  case Intrinsic::longjmp: {
267    static Constant *LongjmpFCache = 0;
268    ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
269                    Type::VoidTy, LongjmpFCache);
270    break;
271  }
272
273  case Intrinsic::siglongjmp: {
274    // Insert the call to abort
275    static Constant *AbortFCache = 0;
276    ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(),
277                    Type::VoidTy, AbortFCache);
278    break;
279  }
280  case Intrinsic::ctpop_i8:
281  case Intrinsic::ctpop_i16:
282  case Intrinsic::ctpop_i32:
283  case Intrinsic::ctpop_i64:
284    CI->replaceAllUsesWith(LowerCTPOP(CI->getOperand(1), CI));
285    break;
286
287  case Intrinsic::bswap_i16:
288  case Intrinsic::bswap_i32:
289  case Intrinsic::bswap_i64:
290    CI->replaceAllUsesWith(LowerBSWAP(CI->getOperand(1), CI));
291    break;
292
293  case Intrinsic::ctlz_i8:
294  case Intrinsic::ctlz_i16:
295  case Intrinsic::ctlz_i32:
296  case Intrinsic::ctlz_i64:
297    CI->replaceAllUsesWith(LowerCTLZ(CI->getOperand(1), CI));
298    break;
299
300  case Intrinsic::cttz_i8:
301  case Intrinsic::cttz_i16:
302  case Intrinsic::cttz_i32:
303  case Intrinsic::cttz_i64: {
304    // cttz(x) -> ctpop(~X & (X-1))
305    Value *Src = CI->getOperand(1);
306    Value *NotSrc = BinaryOperator::createNot(Src, Src->getName()+".not", CI);
307    Value *SrcM1  = ConstantInt::get(Src->getType(), 1);
308    SrcM1 = BinaryOperator::createSub(Src, SrcM1, "", CI);
309    Src = LowerCTPOP(BinaryOperator::createAnd(NotSrc, SrcM1, "", CI), CI);
310    CI->replaceAllUsesWith(Src);
311    break;
312  }
313
314  case Intrinsic::stacksave:
315  case Intrinsic::stackrestore: {
316    static bool Warned = false;
317    if (!Warned)
318      cerr << "WARNING: this target does not support the llvm.stack"
319           << (Callee->getIntrinsicID() == Intrinsic::stacksave ?
320               "save" : "restore") << " intrinsic.\n";
321    Warned = true;
322    if (Callee->getIntrinsicID() == Intrinsic::stacksave)
323      CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
324    break;
325  }
326
327  case Intrinsic::returnaddress:
328  case Intrinsic::frameaddress:
329    cerr << "WARNING: this target does not support the llvm."
330         << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
331             "return" : "frame") << "address intrinsic.\n";
332    CI->replaceAllUsesWith(ConstantPointerNull::get(
333                                            cast<PointerType>(CI->getType())));
334    break;
335
336  case Intrinsic::prefetch:
337    break;    // Simply strip out prefetches on unsupported architectures
338
339  case Intrinsic::pcmarker:
340    break;    // Simply strip out pcmarker on unsupported architectures
341  case Intrinsic::readcyclecounter: {
342    cerr << "WARNING: this target does not support the llvm.readcyclecoun"
343         << "ter intrinsic.  It is being lowered to a constant 0\n";
344    CI->replaceAllUsesWith(ConstantInt::get(Type::Int64Ty, 0));
345    break;
346  }
347
348  case Intrinsic::dbg_stoppoint:
349  case Intrinsic::dbg_region_start:
350  case Intrinsic::dbg_region_end:
351  case Intrinsic::dbg_func_start:
352  case Intrinsic::dbg_declare:
353    break;    // Simply strip out debugging intrinsics
354
355  case Intrinsic::memcpy_i32: {
356    static Constant *MemcpyFCache = 0;
357    ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
358                    (*(CI->op_begin()+1))->getType(), MemcpyFCache);
359    break;
360  }
361  case Intrinsic::memcpy_i64: {
362    static Constant *MemcpyFCache = 0;
363    ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
364                     (*(CI->op_begin()+1))->getType(), MemcpyFCache);
365    break;
366  }
367  case Intrinsic::memmove_i32: {
368    static Constant *MemmoveFCache = 0;
369    ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
370                    (*(CI->op_begin()+1))->getType(), MemmoveFCache);
371    break;
372  }
373  case Intrinsic::memmove_i64: {
374    static Constant *MemmoveFCache = 0;
375    ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
376                    (*(CI->op_begin()+1))->getType(), MemmoveFCache);
377    break;
378  }
379  case Intrinsic::memset_i32: {
380    static Constant *MemsetFCache = 0;
381    ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
382                    (*(CI->op_begin()+1))->getType(), MemsetFCache);
383  }
384  case Intrinsic::memset_i64: {
385    static Constant *MemsetFCache = 0;
386    ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
387                    (*(CI->op_begin()+1))->getType(), MemsetFCache);
388    break;
389  }
390  case Intrinsic::sqrt_f32: {
391    static Constant *sqrtfFCache = 0;
392    ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(),
393                    Type::FloatTy, sqrtfFCache);
394    break;
395  }
396  case Intrinsic::sqrt_f64: {
397    static Constant *sqrtFCache = 0;
398    ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(),
399                    Type::DoubleTy, sqrtFCache);
400    break;
401  }
402  }
403
404  assert(CI->use_empty() &&
405         "Lowering should have eliminated any uses of the intrinsic call!");
406  CI->eraseFromParent();
407}
408