IntrinsicLowering.cpp revision 691ef2ba066dda14ae4ac0ad645054fbc967785a
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 default intrinsic lowering implementation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/CodeGen/IntrinsicLowering.h"
15#include "llvm/Constants.h"
16#include "llvm/DerivedTypes.h"
17#include "llvm/Module.h"
18#include "llvm/Instructions.h"
19#include "llvm/Type.h"
20#include <iostream>
21
22using namespace llvm;
23
24template <class ArgIt>
25static Function *EnsureFunctionExists(Module &M, const char *Name,
26                                      ArgIt ArgBegin, ArgIt ArgEnd,
27                                      const Type *RetTy) {
28  if (Function *F = M.getNamedFunction(Name)) return F;
29  // It doesn't already exist in the program, insert a new definition now.
30  std::vector<const Type *> ParamTys;
31  for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
32    ParamTys.push_back(I->getType());
33  return M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
34}
35
36/// ReplaceCallWith - This function is used when we want to lower an intrinsic
37/// call to a call of an external function.  This handles hard cases such as
38/// when there was already a prototype for the external function, and if that
39/// prototype doesn't match the arguments we expect to pass in.
40template <class ArgIt>
41static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
42                                 ArgIt ArgBegin, ArgIt ArgEnd,
43                                 const Type *RetTy, Function *&FCache) {
44  if (!FCache) {
45    // If we haven't already looked up this function, check to see if the
46    // program already contains a function with this name.
47    Module *M = CI->getParent()->getParent()->getParent();
48    FCache = M->getNamedFunction(NewFn);
49    if (!FCache) {
50      // It doesn't already exist in the program, insert a new definition now.
51      std::vector<const Type *> ParamTys;
52      for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
53        ParamTys.push_back((*I)->getType());
54      FCache = M->getOrInsertFunction(NewFn,
55                                     FunctionType::get(RetTy, ParamTys, false));
56    }
57   }
58
59  const FunctionType *FT = FCache->getFunctionType();
60  std::vector<Value*> Operands;
61  unsigned ArgNo = 0;
62  for (ArgIt I = ArgBegin; I != ArgEnd && ArgNo != FT->getNumParams();
63       ++I, ++ArgNo) {
64    Value *Arg = *I;
65    if (Arg->getType() != FT->getParamType(ArgNo))
66      Arg = new CastInst(Arg, FT->getParamType(ArgNo), Arg->getName(), CI);
67    Operands.push_back(Arg);
68  }
69  // Pass nulls into any additional arguments...
70  for (; ArgNo != FT->getNumParams(); ++ArgNo)
71    Operands.push_back(Constant::getNullValue(FT->getParamType(ArgNo)));
72
73  std::string Name = CI->getName(); CI->setName("");
74  if (FT->getReturnType() == Type::VoidTy) Name.clear();
75  CallInst *NewCI = new CallInst(FCache, Operands, Name, CI);
76  if (!CI->use_empty()) {
77    Value *V = NewCI;
78    if (CI->getType() != NewCI->getType())
79      V = new CastInst(NewCI, CI->getType(), Name, CI);
80    CI->replaceAllUsesWith(V);
81  }
82  return NewCI;
83}
84
85void DefaultIntrinsicLowering::AddPrototypes(Module &M) {
86  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
87    if (I->isExternal() && !I->use_empty())
88      switch (I->getIntrinsicID()) {
89      default: break;
90      case Intrinsic::setjmp:
91        EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), Type::IntTy);
92        break;
93      case Intrinsic::longjmp:
94        EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),Type::VoidTy);
95        break;
96      case Intrinsic::siglongjmp:
97        EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(), Type::VoidTy);
98        break;
99      case Intrinsic::memcpy:
100        EnsureFunctionExists(M, "memcpy", I->arg_begin(), --I->arg_end(),
101                             I->arg_begin()->getType());
102        break;
103      case Intrinsic::memmove:
104        EnsureFunctionExists(M, "memmove", I->arg_begin(), --I->arg_end(),
105                             I->arg_begin()->getType());
106        break;
107      case Intrinsic::memset:
108        EnsureFunctionExists(M, "memset", I->arg_begin(), --I->arg_end(),
109                             I->arg_begin()->getType());
110        break;
111      case Intrinsic::isunordered:
112        EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(), Type::BoolTy);
113        break;
114      case Intrinsic::sqrt:
115        if(I->arg_begin()->getType() == Type::FloatTy)
116          EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(), Type::FloatTy);
117        else
118          EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(), Type::DoubleTy);
119        break;
120      }
121}
122
123void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
124  Function *Callee = CI->getCalledFunction();
125  assert(Callee && "Cannot lower an indirect call!");
126
127  switch (Callee->getIntrinsicID()) {
128  case Intrinsic::not_intrinsic:
129    std::cerr << "Cannot lower a call to a non-intrinsic function '"
130              << Callee->getName() << "'!\n";
131    abort();
132  default:
133    std::cerr << "Error: Code generator does not support intrinsic function '"
134              << Callee->getName() << "'!\n";
135    abort();
136
137    // The setjmp/longjmp intrinsics should only exist in the code if it was
138    // never optimized (ie, right out of the CFE), or if it has been hacked on
139    // by the lowerinvoke pass.  In both cases, the right thing to do is to
140    // convert the call to an explicit setjmp or longjmp call.
141  case Intrinsic::setjmp: {
142    static Function *SetjmpFCache = 0;
143    Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
144                               Type::IntTy, SetjmpFCache);
145    if (CI->getType() != Type::VoidTy)
146      CI->replaceAllUsesWith(V);
147    break;
148  }
149  case Intrinsic::sigsetjmp:
150     if (CI->getType() != Type::VoidTy)
151       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
152     break;
153
154  case Intrinsic::longjmp: {
155    static Function *LongjmpFCache = 0;
156    ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
157                    Type::VoidTy, LongjmpFCache);
158    break;
159  }
160
161  case Intrinsic::siglongjmp: {
162    // Insert the call to abort
163    static Function *AbortFCache = 0;
164    ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), Type::VoidTy,
165                    AbortFCache);
166    break;
167  }
168  case Intrinsic::ctpop: {
169    Value *Src = CI->getOperand(1);
170    switch (CI->getOperand(0)->getType()->getTypeID())
171    {
172    case Type::SByteTyID:
173    case Type::UByteTyID:
174      {
175        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
176        Value* MA = ConstantUInt::get(Type::UIntTy, 0x55);
177        Src = BinaryOperator::create(Instruction::Add,
178                BinaryOperator::create(Instruction::And, Src, MA),
179                BinaryOperator::create(Instruction::And,
180                                       new ShiftInst(Instruction::Shr, Src, SA),
181                                       MA));
182        SA = ConstantUInt::get(Type::UByteTy, 2);
183        MA = ConstantUInt::get(Type::UIntTy, 0x33);
184        Src = BinaryOperator::create(Instruction::Add,
185                BinaryOperator::create(Instruction::And, Src, MA),
186                BinaryOperator::create(Instruction::And,
187                                       new ShiftInst(Instruction::Shr, Src, SA),
188                                       MA));
189        SA = ConstantUInt::get(Type::UByteTy, 4);
190        MA = ConstantUInt::get(Type::UIntTy, 0x0F);
191        Src = BinaryOperator::create(Instruction::Add,
192                BinaryOperator::create(Instruction::And, Src, MA),
193                BinaryOperator::create(Instruction::And,
194                                       new ShiftInst(Instruction::Shr, Src, SA),
195                                       MA), "ctpop");
196      }
197      break;
198    case Type::ShortTyID:
199    case Type::UShortTyID:
200      {
201        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
202        Value* MA = ConstantUInt::get(Type::UIntTy, 0x5555);
203        Src = BinaryOperator::create(Instruction::Add,
204                BinaryOperator::create(Instruction::And, Src, MA),
205                BinaryOperator::create(Instruction::And,
206                                       new ShiftInst(Instruction::Shr, Src, SA),
207                                       MA));
208        SA = ConstantUInt::get(Type::UByteTy, 2);
209        MA = ConstantUInt::get(Type::UIntTy, 0x3333);
210        Src = BinaryOperator::create(Instruction::Add,
211                BinaryOperator::create(Instruction::And, Src, MA),
212                BinaryOperator::create(Instruction::And,
213                                       new ShiftInst(Instruction::Shr, Src, SA),
214                                       MA));
215        SA = ConstantUInt::get(Type::UByteTy, 4);
216        MA = ConstantUInt::get(Type::UIntTy, 0x0F0F);
217        Src = BinaryOperator::create(Instruction::Add,
218                BinaryOperator::create(Instruction::And, Src, MA),
219                BinaryOperator::create(Instruction::And,
220                                       new ShiftInst(Instruction::Shr, Src, SA),
221                                       MA));
222        SA = ConstantUInt::get(Type::UByteTy, 8);
223        MA = ConstantUInt::get(Type::UIntTy, 0x00FF);
224        Src = BinaryOperator::create(Instruction::Add,
225                BinaryOperator::create(Instruction::And, Src, MA),
226                BinaryOperator::create(Instruction::And,
227                                       new ShiftInst(Instruction::Shr, Src, SA),
228                                       MA), "ctpop");
229
230      }
231      break;
232    case Type::IntTyID:
233    case Type::UIntTyID:
234      {
235        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
236        Value* MA = ConstantUInt::get(Type::UIntTy, 0x55555555);
237        Src = BinaryOperator::create(Instruction::Add,
238                BinaryOperator::create(Instruction::And, Src, MA),
239                BinaryOperator::create(Instruction::And,
240                                       new ShiftInst(Instruction::Shr, Src, SA),
241                                       MA));
242        SA = ConstantUInt::get(Type::UByteTy, 2);
243        MA = ConstantUInt::get(Type::UIntTy, 0x33333333);
244        Src = BinaryOperator::create(Instruction::Add,
245                BinaryOperator::create(Instruction::And, Src, MA),
246                BinaryOperator::create(Instruction::And,
247                                       new ShiftInst(Instruction::Shr, Src, SA),
248                                       MA));
249        SA = ConstantUInt::get(Type::UByteTy, 4);
250        MA = ConstantUInt::get(Type::UIntTy, 0x0F0F0F0F);
251        Src = BinaryOperator::create(Instruction::Add,
252                BinaryOperator::create(Instruction::And, Src, MA),
253                BinaryOperator::create(Instruction::And,
254                                       new ShiftInst(Instruction::Shr, Src, SA),
255                                       MA));
256        SA = ConstantUInt::get(Type::UByteTy, 8);
257        MA = ConstantUInt::get(Type::UIntTy, 0x00FF00FF);
258        Src = BinaryOperator::create(Instruction::Add,
259                BinaryOperator::create(Instruction::And, Src, MA),
260                BinaryOperator::create(Instruction::And,
261                                       new ShiftInst(Instruction::Shr, Src, SA),
262                                       MA));
263        SA = ConstantUInt::get(Type::UByteTy, 8);
264        MA = ConstantUInt::get(Type::UIntTy, 0x0000FFFF);
265        Src = BinaryOperator::create(Instruction::Add,
266                BinaryOperator::create(Instruction::And, Src, MA),
267                BinaryOperator::create(Instruction::And,
268                                       new ShiftInst(Instruction::Shr, Src, SA),
269                                       MA), "ctpop");
270      }
271      break;
272    case Type::LongTyID:
273    case Type::ULongTyID:
274      {
275        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
276        Value* MA = ConstantUInt::get(Type::ULongTy, 0x5555555555555555ULL);
277        Src = BinaryOperator::create(Instruction::Add,
278                BinaryOperator::create(Instruction::And, Src, MA),
279                BinaryOperator::create(Instruction::And,
280                                       new ShiftInst(Instruction::Shr, Src, SA),
281                                       MA));
282        SA = ConstantUInt::get(Type::UByteTy, 2);
283        MA = ConstantUInt::get(Type::ULongTy, 0x3333333333333333ULL);
284        Src = BinaryOperator::create(Instruction::Add,
285                BinaryOperator::create(Instruction::And, Src, MA),
286                BinaryOperator::create(Instruction::And,
287                                       new ShiftInst(Instruction::Shr, Src, SA),
288                                       MA));
289        SA = ConstantUInt::get(Type::UByteTy, 4);
290        MA = ConstantUInt::get(Type::ULongTy, 0x0F0F0F0F0F0F0F0FULL);
291        Src = BinaryOperator::create(Instruction::Add,
292                BinaryOperator::create(Instruction::And, Src, MA),
293                BinaryOperator::create(Instruction::And,
294                                       new ShiftInst(Instruction::Shr, Src, SA),
295                                       MA));
296        SA = ConstantUInt::get(Type::UByteTy, 8);
297        MA = ConstantUInt::get(Type::ULongTy, 0x00FF00FF00FF00FFULL);
298        Src = BinaryOperator::create(Instruction::Add,
299                BinaryOperator::create(Instruction::And, Src, MA),
300                BinaryOperator::create(Instruction::And,
301                                       new ShiftInst(Instruction::Shr, Src, SA),
302                                       MA));
303        SA = ConstantUInt::get(Type::UByteTy, 16);
304        MA = ConstantUInt::get(Type::ULongTy, 0x00000000FFFFFFFFULL);
305        Src = BinaryOperator::create(Instruction::Add,
306                BinaryOperator::create(Instruction::And, Src, MA),
307                BinaryOperator::create(Instruction::And,
308                                       new ShiftInst(Instruction::Shr, Src, SA),
309                                       MA), "ctpop");
310      }
311      break;
312    default:
313      abort();
314    }
315
316    CI->replaceAllUsesWith(Src);
317    break;
318  }
319  case Intrinsic::ctlz: {
320    Value *Src = CI->getOperand(1);
321    Value* SA;
322    switch (CI->getOperand(0)->getType()->getTypeID())
323    {
324    case Type::LongTyID:
325    case Type::ULongTyID:
326      SA = ConstantUInt::get(Type::UByteTy, 32);
327      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
328    case Type::IntTyID:
329    case Type::UIntTyID:
330      SA = ConstantUInt::get(Type::UByteTy, 16);
331      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
332    case Type::ShortTyID:
333    case Type::UShortTyID:
334      SA = ConstantUInt::get(Type::UByteTy, 8);
335      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
336    default:
337      SA = ConstantUInt::get(Type::UByteTy, 1);
338      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
339      SA = ConstantUInt::get(Type::UByteTy, 2);
340      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
341      SA = ConstantUInt::get(Type::UByteTy, 4);
342      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
343    };
344    Src = BinaryOperator::createNot(Src);
345
346    Src = new CallInst(new Function(CI->getCalledFunction()->getFunctionType(),
347                                    CI->getCalledFunction()->getLinkage(),
348                                    "llvm.ctpop"), Src);
349    CI->replaceAllUsesWith(Src);
350    break;
351  }
352  case Intrinsic::cttz: {
353    Value *Src = CI->getOperand(1);
354    Src = BinaryOperator::create(Instruction::And, BinaryOperator::createNot(Src),
355            BinaryOperator::create(Instruction::Sub, Src,
356                            ConstantUInt::get(CI->getOperand(0)->getType(), 1)));
357    Src = new CallInst(new Function(CI->getCalledFunction()->getFunctionType(),
358                                    CI->getCalledFunction()->getLinkage(),
359                                    "llvm.ctpop"), Src);
360    CI->replaceAllUsesWith(Src);
361    break;
362  }
363
364  case Intrinsic::returnaddress:
365  case Intrinsic::frameaddress:
366    std::cerr << "WARNING: this target does not support the llvm."
367              << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
368                  "return" : "frame") << "address intrinsic.\n";
369    CI->replaceAllUsesWith(ConstantPointerNull::get(
370                                            cast<PointerType>(CI->getType())));
371    break;
372
373  case Intrinsic::prefetch:
374    break;    // Simply strip out prefetches on unsupported architectures
375
376  case Intrinsic::pcmarker:
377    break;    // Simply strip out pcmarker on unsupported architectures
378
379  case Intrinsic::dbg_stoppoint:
380  case Intrinsic::dbg_region_start:
381  case Intrinsic::dbg_region_end:
382  case Intrinsic::dbg_declare:
383  case Intrinsic::dbg_func_start:
384    if (CI->getType() != Type::VoidTy)
385      CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
386    break;    // Simply strip out debugging intrinsics
387
388  case Intrinsic::memcpy: {
389    // The memcpy intrinsic take an extra alignment argument that the memcpy
390    // libc function does not.
391    static Function *MemcpyFCache = 0;
392    ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
393                    (*(CI->op_begin()+1))->getType(), MemcpyFCache);
394    break;
395  }
396  case Intrinsic::memmove: {
397    // The memmove intrinsic take an extra alignment argument that the memmove
398    // libc function does not.
399    static Function *MemmoveFCache = 0;
400    ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
401                    (*(CI->op_begin()+1))->getType(), MemmoveFCache);
402    break;
403  }
404  case Intrinsic::memset: {
405    // The memset intrinsic take an extra alignment argument that the memset
406    // libc function does not.
407    static Function *MemsetFCache = 0;
408    ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
409                    (*(CI->op_begin()+1))->getType(), MemsetFCache);
410    break;
411  }
412  case Intrinsic::isunordered: {
413    Value *L = CI->getOperand(1);
414    Value *R = CI->getOperand(2);
415
416    Value *LIsNan = new SetCondInst(Instruction::SetNE, L, L, "LIsNan", CI);
417    Value *RIsNan = new SetCondInst(Instruction::SetNE, R, R, "RIsNan", CI);
418    CI->replaceAllUsesWith(
419      BinaryOperator::create(Instruction::Or, LIsNan, RIsNan,
420                             "isunordered", CI));
421    break;
422  }
423  case Intrinsic::sqrt: {
424    static Function *sqrtFCache = 0;
425    static Function *sqrtfFCache = 0;
426    if(CI->getType() == Type::FloatTy)
427      ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(),
428                      Type::FloatTy, sqrtfFCache);
429    else
430      ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(),
431                      Type::DoubleTy, sqrtFCache);
432    break;
433  }
434  }
435
436  assert(CI->use_empty() &&
437         "Lowering should have eliminated any uses of the intrinsic call!");
438  CI->getParent()->getInstList().erase(CI);
439}
440