IntrinsicLowering.cpp revision 218893
1193323Sed//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file implements the IntrinsicLowering class.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#include "llvm/Constants.h"
15193323Sed#include "llvm/DerivedTypes.h"
16193323Sed#include "llvm/Module.h"
17193323Sed#include "llvm/Type.h"
18193323Sed#include "llvm/CodeGen/IntrinsicLowering.h"
19210299Sed#include "llvm/Support/CallSite.h"
20198090Srdivacky#include "llvm/Support/ErrorHandling.h"
21193323Sed#include "llvm/Support/IRBuilder.h"
22198090Srdivacky#include "llvm/Support/raw_ostream.h"
23193323Sed#include "llvm/Target/TargetData.h"
24193323Sed#include "llvm/ADT/SmallVector.h"
25193323Sedusing namespace llvm;
26193323Sed
27193323Sedtemplate <class ArgIt>
28193323Sedstatic void EnsureFunctionExists(Module &M, const char *Name,
29193323Sed                                 ArgIt ArgBegin, ArgIt ArgEnd,
30193323Sed                                 const Type *RetTy) {
31193323Sed  // Insert a correctly-typed definition now.
32193323Sed  std::vector<const Type *> ParamTys;
33193323Sed  for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
34193323Sed    ParamTys.push_back(I->getType());
35193323Sed  M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
36193323Sed}
37193323Sed
38193323Sedstatic void EnsureFPIntrinsicsExist(Module &M, Function *Fn,
39193323Sed                                    const char *FName,
40193323Sed                                    const char *DName, const char *LDName) {
41193323Sed  // Insert definitions for all the floating point types.
42193323Sed  switch((int)Fn->arg_begin()->getType()->getTypeID()) {
43193323Sed  case Type::FloatTyID:
44193323Sed    EnsureFunctionExists(M, FName, Fn->arg_begin(), Fn->arg_end(),
45198090Srdivacky                         Type::getFloatTy(M.getContext()));
46193323Sed    break;
47193323Sed  case Type::DoubleTyID:
48193323Sed    EnsureFunctionExists(M, DName, Fn->arg_begin(), Fn->arg_end(),
49198090Srdivacky                         Type::getDoubleTy(M.getContext()));
50193323Sed    break;
51193323Sed  case Type::X86_FP80TyID:
52193323Sed  case Type::FP128TyID:
53193323Sed  case Type::PPC_FP128TyID:
54193323Sed    EnsureFunctionExists(M, LDName, Fn->arg_begin(), Fn->arg_end(),
55193323Sed                         Fn->arg_begin()->getType());
56193323Sed    break;
57193323Sed  }
58193323Sed}
59193323Sed
60193323Sed/// ReplaceCallWith - This function is used when we want to lower an intrinsic
61193323Sed/// call to a call of an external function.  This handles hard cases such as
62193323Sed/// when there was already a prototype for the external function, and if that
63193323Sed/// prototype doesn't match the arguments we expect to pass in.
64193323Sedtemplate <class ArgIt>
65193323Sedstatic CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
66193323Sed                                 ArgIt ArgBegin, ArgIt ArgEnd,
67195098Sed                                 const Type *RetTy) {
68195098Sed  // If we haven't already looked up this function, check to see if the
69195098Sed  // program already contains a function with this name.
70195098Sed  Module *M = CI->getParent()->getParent()->getParent();
71195098Sed  // Get or insert the definition now.
72195098Sed  std::vector<const Type *> ParamTys;
73195098Sed  for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
74195098Sed    ParamTys.push_back((*I)->getType());
75195098Sed  Constant* FCache = M->getOrInsertFunction(NewFn,
76195098Sed                                  FunctionType::get(RetTy, ParamTys, false));
77193323Sed
78193323Sed  IRBuilder<> Builder(CI->getParent(), CI);
79193323Sed  SmallVector<Value *, 8> Args(ArgBegin, ArgEnd);
80193323Sed  CallInst *NewCI = Builder.CreateCall(FCache, Args.begin(), Args.end());
81193323Sed  NewCI->setName(CI->getName());
82193323Sed  if (!CI->use_empty())
83193323Sed    CI->replaceAllUsesWith(NewCI);
84193323Sed  return NewCI;
85193323Sed}
86193323Sed
87208599Srdivacky// VisualStudio defines setjmp as _setjmp
88218893Sdim#if defined(_MSC_VER) && defined(setjmp) && \
89218893Sdim                         !defined(setjmp_undefined_for_msvc)
90218893Sdim#  pragma push_macro("setjmp")
91218893Sdim#  undef setjmp
92218893Sdim#  define setjmp_undefined_for_msvc
93208599Srdivacky#endif
94208599Srdivacky
95193323Sedvoid IntrinsicLowering::AddPrototypes(Module &M) {
96198090Srdivacky  LLVMContext &Context = M.getContext();
97193323Sed  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
98193323Sed    if (I->isDeclaration() && !I->use_empty())
99193323Sed      switch (I->getIntrinsicID()) {
100193323Sed      default: break;
101193323Sed      case Intrinsic::setjmp:
102193323Sed        EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(),
103198090Srdivacky                             Type::getInt32Ty(M.getContext()));
104193323Sed        break;
105193323Sed      case Intrinsic::longjmp:
106193323Sed        EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),
107198090Srdivacky                             Type::getVoidTy(M.getContext()));
108193323Sed        break;
109193323Sed      case Intrinsic::siglongjmp:
110193323Sed        EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(),
111198090Srdivacky                             Type::getVoidTy(M.getContext()));
112193323Sed        break;
113193323Sed      case Intrinsic::memcpy:
114198090Srdivacky        M.getOrInsertFunction("memcpy",
115198090Srdivacky          Type::getInt8PtrTy(Context),
116198090Srdivacky                              Type::getInt8PtrTy(Context),
117198090Srdivacky                              Type::getInt8PtrTy(Context),
118198090Srdivacky                              TD.getIntPtrType(Context), (Type *)0);
119193323Sed        break;
120193323Sed      case Intrinsic::memmove:
121198090Srdivacky        M.getOrInsertFunction("memmove",
122198090Srdivacky          Type::getInt8PtrTy(Context),
123198090Srdivacky                              Type::getInt8PtrTy(Context),
124198090Srdivacky                              Type::getInt8PtrTy(Context),
125198090Srdivacky                              TD.getIntPtrType(Context), (Type *)0);
126193323Sed        break;
127193323Sed      case Intrinsic::memset:
128198090Srdivacky        M.getOrInsertFunction("memset",
129198090Srdivacky          Type::getInt8PtrTy(Context),
130198090Srdivacky                              Type::getInt8PtrTy(Context),
131198090Srdivacky                              Type::getInt32Ty(M.getContext()),
132198090Srdivacky                              TD.getIntPtrType(Context), (Type *)0);
133193323Sed        break;
134193323Sed      case Intrinsic::sqrt:
135193323Sed        EnsureFPIntrinsicsExist(M, I, "sqrtf", "sqrt", "sqrtl");
136193323Sed        break;
137193323Sed      case Intrinsic::sin:
138193323Sed        EnsureFPIntrinsicsExist(M, I, "sinf", "sin", "sinl");
139193323Sed        break;
140193323Sed      case Intrinsic::cos:
141193323Sed        EnsureFPIntrinsicsExist(M, I, "cosf", "cos", "cosl");
142193323Sed        break;
143193323Sed      case Intrinsic::pow:
144193323Sed        EnsureFPIntrinsicsExist(M, I, "powf", "pow", "powl");
145193323Sed        break;
146193323Sed      case Intrinsic::log:
147193323Sed        EnsureFPIntrinsicsExist(M, I, "logf", "log", "logl");
148193323Sed        break;
149193323Sed      case Intrinsic::log2:
150193323Sed        EnsureFPIntrinsicsExist(M, I, "log2f", "log2", "log2l");
151193323Sed        break;
152193323Sed      case Intrinsic::log10:
153193323Sed        EnsureFPIntrinsicsExist(M, I, "log10f", "log10", "log10l");
154193323Sed        break;
155193323Sed      case Intrinsic::exp:
156193323Sed        EnsureFPIntrinsicsExist(M, I, "expf", "exp", "expl");
157193323Sed        break;
158193323Sed      case Intrinsic::exp2:
159193323Sed        EnsureFPIntrinsicsExist(M, I, "exp2f", "exp2", "exp2l");
160193323Sed        break;
161193323Sed      }
162193323Sed}
163193323Sed
164193323Sed/// LowerBSWAP - Emit the code to lower bswap of V before the specified
165193323Sed/// instruction IP.
166198090Srdivackystatic Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) {
167203954Srdivacky  assert(V->getType()->isIntegerTy() && "Can't bswap a non-integer type!");
168193323Sed
169193323Sed  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
170193323Sed
171193323Sed  IRBuilder<> Builder(IP->getParent(), IP);
172193323Sed
173193323Sed  switch(BitSize) {
174198090Srdivacky  default: llvm_unreachable("Unhandled type size of value to byteswap!");
175193323Sed  case 16: {
176193323Sed    Value *Tmp1 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
177193323Sed                                    "bswap.2");
178193323Sed    Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
179193323Sed                                     "bswap.1");
180193323Sed    V = Builder.CreateOr(Tmp1, Tmp2, "bswap.i16");
181193323Sed    break;
182193323Sed  }
183193323Sed  case 32: {
184193323Sed    Value *Tmp4 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24),
185193323Sed                                    "bswap.4");
186193323Sed    Value *Tmp3 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
187193323Sed                                    "bswap.3");
188193323Sed    Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
189193323Sed                                     "bswap.2");
190198090Srdivacky    Value *Tmp1 = Builder.CreateLShr(V,ConstantInt::get(V->getType(), 24),
191193323Sed                                     "bswap.1");
192198090Srdivacky    Tmp3 = Builder.CreateAnd(Tmp3,
193198090Srdivacky                         ConstantInt::get(Type::getInt32Ty(Context), 0xFF0000),
194193323Sed                             "bswap.and3");
195198090Srdivacky    Tmp2 = Builder.CreateAnd(Tmp2,
196198090Srdivacky                           ConstantInt::get(Type::getInt32Ty(Context), 0xFF00),
197193323Sed                             "bswap.and2");
198193323Sed    Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or1");
199193323Sed    Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or2");
200193323Sed    V = Builder.CreateOr(Tmp4, Tmp2, "bswap.i32");
201193323Sed    break;
202193323Sed  }
203193323Sed  case 64: {
204193323Sed    Value *Tmp8 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 56),
205193323Sed                                    "bswap.8");
206193323Sed    Value *Tmp7 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 40),
207193323Sed                                    "bswap.7");
208193323Sed    Value *Tmp6 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24),
209193323Sed                                    "bswap.6");
210193323Sed    Value *Tmp5 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
211193323Sed                                    "bswap.5");
212193323Sed    Value* Tmp4 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
213193323Sed                                     "bswap.4");
214198090Srdivacky    Value* Tmp3 = Builder.CreateLShr(V,
215198090Srdivacky                                     ConstantInt::get(V->getType(), 24),
216193323Sed                                     "bswap.3");
217198090Srdivacky    Value* Tmp2 = Builder.CreateLShr(V,
218198090Srdivacky                                     ConstantInt::get(V->getType(), 40),
219193323Sed                                     "bswap.2");
220198090Srdivacky    Value* Tmp1 = Builder.CreateLShr(V,
221198090Srdivacky                                     ConstantInt::get(V->getType(), 56),
222193323Sed                                     "bswap.1");
223193323Sed    Tmp7 = Builder.CreateAnd(Tmp7,
224198090Srdivacky                             ConstantInt::get(Type::getInt64Ty(Context),
225193323Sed                                              0xFF000000000000ULL),
226193323Sed                             "bswap.and7");
227193323Sed    Tmp6 = Builder.CreateAnd(Tmp6,
228198090Srdivacky                             ConstantInt::get(Type::getInt64Ty(Context),
229193323Sed                                              0xFF0000000000ULL),
230193323Sed                             "bswap.and6");
231193323Sed    Tmp5 = Builder.CreateAnd(Tmp5,
232198090Srdivacky                        ConstantInt::get(Type::getInt64Ty(Context),
233198090Srdivacky                             0xFF00000000ULL),
234193323Sed                             "bswap.and5");
235193323Sed    Tmp4 = Builder.CreateAnd(Tmp4,
236198090Srdivacky                        ConstantInt::get(Type::getInt64Ty(Context),
237198090Srdivacky                             0xFF000000ULL),
238193323Sed                             "bswap.and4");
239193323Sed    Tmp3 = Builder.CreateAnd(Tmp3,
240198090Srdivacky                             ConstantInt::get(Type::getInt64Ty(Context),
241198090Srdivacky                             0xFF0000ULL),
242193323Sed                             "bswap.and3");
243193323Sed    Tmp2 = Builder.CreateAnd(Tmp2,
244198090Srdivacky                             ConstantInt::get(Type::getInt64Ty(Context),
245198090Srdivacky                             0xFF00ULL),
246193323Sed                             "bswap.and2");
247193323Sed    Tmp8 = Builder.CreateOr(Tmp8, Tmp7, "bswap.or1");
248193323Sed    Tmp6 = Builder.CreateOr(Tmp6, Tmp5, "bswap.or2");
249193323Sed    Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or3");
250193323Sed    Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or4");
251193323Sed    Tmp8 = Builder.CreateOr(Tmp8, Tmp6, "bswap.or5");
252193323Sed    Tmp4 = Builder.CreateOr(Tmp4, Tmp2, "bswap.or6");
253193323Sed    V = Builder.CreateOr(Tmp8, Tmp4, "bswap.i64");
254193323Sed    break;
255193323Sed  }
256193323Sed  }
257193323Sed  return V;
258193323Sed}
259193323Sed
260193323Sed/// LowerCTPOP - Emit the code to lower ctpop of V before the specified
261193323Sed/// instruction IP.
262198090Srdivackystatic Value *LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP) {
263203954Srdivacky  assert(V->getType()->isIntegerTy() && "Can't ctpop a non-integer type!");
264193323Sed
265193323Sed  static const uint64_t MaskValues[6] = {
266193323Sed    0x5555555555555555ULL, 0x3333333333333333ULL,
267193323Sed    0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
268193323Sed    0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
269193323Sed  };
270193323Sed
271193323Sed  IRBuilder<> Builder(IP->getParent(), IP);
272193323Sed
273193323Sed  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
274193323Sed  unsigned WordSize = (BitSize + 63) / 64;
275193323Sed  Value *Count = ConstantInt::get(V->getType(), 0);
276193323Sed
277193323Sed  for (unsigned n = 0; n < WordSize; ++n) {
278193323Sed    Value *PartValue = V;
279193323Sed    for (unsigned i = 1, ct = 0; i < (BitSize>64 ? 64 : BitSize);
280193323Sed         i <<= 1, ++ct) {
281193323Sed      Value *MaskCst = ConstantInt::get(V->getType(), MaskValues[ct]);
282193323Sed      Value *LHS = Builder.CreateAnd(PartValue, MaskCst, "cppop.and1");
283193323Sed      Value *VShift = Builder.CreateLShr(PartValue,
284198090Srdivacky                                        ConstantInt::get(V->getType(), i),
285193323Sed                                         "ctpop.sh");
286193323Sed      Value *RHS = Builder.CreateAnd(VShift, MaskCst, "cppop.and2");
287193323Sed      PartValue = Builder.CreateAdd(LHS, RHS, "ctpop.step");
288193323Sed    }
289193323Sed    Count = Builder.CreateAdd(PartValue, Count, "ctpop.part");
290193323Sed    if (BitSize > 64) {
291193323Sed      V = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 64),
292193323Sed                             "ctpop.part.sh");
293193323Sed      BitSize -= 64;
294193323Sed    }
295193323Sed  }
296193323Sed
297193323Sed  return Count;
298193323Sed}
299193323Sed
300193323Sed/// LowerCTLZ - Emit the code to lower ctlz of V before the specified
301193323Sed/// instruction IP.
302198090Srdivackystatic Value *LowerCTLZ(LLVMContext &Context, Value *V, Instruction *IP) {
303193323Sed
304193323Sed  IRBuilder<> Builder(IP->getParent(), IP);
305193323Sed
306193323Sed  unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
307193323Sed  for (unsigned i = 1; i < BitSize; i <<= 1) {
308193323Sed    Value *ShVal = ConstantInt::get(V->getType(), i);
309193323Sed    ShVal = Builder.CreateLShr(V, ShVal, "ctlz.sh");
310193323Sed    V = Builder.CreateOr(V, ShVal, "ctlz.step");
311193323Sed  }
312193323Sed
313193323Sed  V = Builder.CreateNot(V);
314198090Srdivacky  return LowerCTPOP(Context, V, IP);
315193323Sed}
316193323Sed
317195098Sedstatic void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname,
318195098Sed                                       const char *Dname,
319193323Sed                                       const char *LDname) {
320210299Sed  CallSite CS(CI);
321210299Sed  switch (CI->getArgOperand(0)->getType()->getTypeID()) {
322198090Srdivacky  default: llvm_unreachable("Invalid type in intrinsic");
323193323Sed  case Type::FloatTyID:
324210299Sed    ReplaceCallWith(Fname, CI, CS.arg_begin(), CS.arg_end(),
325198090Srdivacky                  Type::getFloatTy(CI->getContext()));
326193323Sed    break;
327193323Sed  case Type::DoubleTyID:
328210299Sed    ReplaceCallWith(Dname, CI, CS.arg_begin(), CS.arg_end(),
329198090Srdivacky                  Type::getDoubleTy(CI->getContext()));
330193323Sed    break;
331193323Sed  case Type::X86_FP80TyID:
332193323Sed  case Type::FP128TyID:
333193323Sed  case Type::PPC_FP128TyID:
334210299Sed    ReplaceCallWith(LDname, CI, CS.arg_begin(), CS.arg_end(),
335210299Sed                  CI->getArgOperand(0)->getType());
336193323Sed    break;
337193323Sed  }
338193323Sed}
339193323Sed
340193323Sedvoid IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
341193323Sed  IRBuilder<> Builder(CI->getParent(), CI);
342198090Srdivacky  LLVMContext &Context = CI->getContext();
343193323Sed
344207618Srdivacky  const Function *Callee = CI->getCalledFunction();
345193323Sed  assert(Callee && "Cannot lower an indirect call!");
346193323Sed
347210299Sed  CallSite CS(CI);
348193323Sed  switch (Callee->getIntrinsicID()) {
349193323Sed  case Intrinsic::not_intrinsic:
350207618Srdivacky    report_fatal_error("Cannot lower a call to a non-intrinsic function '"+
351198090Srdivacky                      Callee->getName() + "'!");
352193323Sed  default:
353207618Srdivacky    report_fatal_error("Code generator does not support intrinsic function '"+
354198090Srdivacky                      Callee->getName()+"'!");
355193323Sed
356193323Sed    // The setjmp/longjmp intrinsics should only exist in the code if it was
357193323Sed    // never optimized (ie, right out of the CFE), or if it has been hacked on
358193323Sed    // by the lowerinvoke pass.  In both cases, the right thing to do is to
359193323Sed    // convert the call to an explicit setjmp or longjmp call.
360193323Sed  case Intrinsic::setjmp: {
361210299Sed    Value *V = ReplaceCallWith("setjmp", CI, CS.arg_begin(), CS.arg_end(),
362198090Srdivacky                               Type::getInt32Ty(Context));
363202375Srdivacky    if (!CI->getType()->isVoidTy())
364193323Sed      CI->replaceAllUsesWith(V);
365193323Sed    break;
366193323Sed  }
367193323Sed  case Intrinsic::sigsetjmp:
368202375Srdivacky     if (!CI->getType()->isVoidTy())
369193323Sed       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
370193323Sed     break;
371193323Sed
372193323Sed  case Intrinsic::longjmp: {
373210299Sed    ReplaceCallWith("longjmp", CI, CS.arg_begin(), CS.arg_end(),
374198090Srdivacky                    Type::getVoidTy(Context));
375193323Sed    break;
376193323Sed  }
377193323Sed
378193323Sed  case Intrinsic::siglongjmp: {
379193323Sed    // Insert the call to abort
380210299Sed    ReplaceCallWith("abort", CI, CS.arg_end(), CS.arg_end(),
381198090Srdivacky                    Type::getVoidTy(Context));
382193323Sed    break;
383193323Sed  }
384193323Sed  case Intrinsic::ctpop:
385210299Sed    CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getArgOperand(0), CI));
386193323Sed    break;
387193323Sed
388193323Sed  case Intrinsic::bswap:
389210299Sed    CI->replaceAllUsesWith(LowerBSWAP(Context, CI->getArgOperand(0), CI));
390193323Sed    break;
391193323Sed
392193323Sed  case Intrinsic::ctlz:
393210299Sed    CI->replaceAllUsesWith(LowerCTLZ(Context, CI->getArgOperand(0), CI));
394193323Sed    break;
395193323Sed
396193323Sed  case Intrinsic::cttz: {
397193323Sed    // cttz(x) -> ctpop(~X & (X-1))
398210299Sed    Value *Src = CI->getArgOperand(0);
399193323Sed    Value *NotSrc = Builder.CreateNot(Src);
400193323Sed    NotSrc->setName(Src->getName() + ".not");
401193323Sed    Value *SrcM1 = ConstantInt::get(Src->getType(), 1);
402193323Sed    SrcM1 = Builder.CreateSub(Src, SrcM1);
403198090Srdivacky    Src = LowerCTPOP(Context, Builder.CreateAnd(NotSrc, SrcM1), CI);
404193323Sed    CI->replaceAllUsesWith(Src);
405193323Sed    break;
406193323Sed  }
407193323Sed
408193323Sed  case Intrinsic::stacksave:
409193323Sed  case Intrinsic::stackrestore: {
410193323Sed    if (!Warned)
411198090Srdivacky      errs() << "WARNING: this target does not support the llvm.stack"
412198090Srdivacky             << (Callee->getIntrinsicID() == Intrinsic::stacksave ?
413193323Sed               "save" : "restore") << " intrinsic.\n";
414193323Sed    Warned = true;
415193323Sed    if (Callee->getIntrinsicID() == Intrinsic::stacksave)
416193323Sed      CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
417193323Sed    break;
418193323Sed  }
419193323Sed
420193323Sed  case Intrinsic::returnaddress:
421193323Sed  case Intrinsic::frameaddress:
422198090Srdivacky    errs() << "WARNING: this target does not support the llvm."
423198090Srdivacky           << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
424193323Sed             "return" : "frame") << "address intrinsic.\n";
425193323Sed    CI->replaceAllUsesWith(ConstantPointerNull::get(
426193323Sed                                            cast<PointerType>(CI->getType())));
427193323Sed    break;
428193323Sed
429193323Sed  case Intrinsic::prefetch:
430193323Sed    break;    // Simply strip out prefetches on unsupported architectures
431193323Sed
432193323Sed  case Intrinsic::pcmarker:
433193323Sed    break;    // Simply strip out pcmarker on unsupported architectures
434193323Sed  case Intrinsic::readcyclecounter: {
435198090Srdivacky    errs() << "WARNING: this target does not support the llvm.readcyclecoun"
436198090Srdivacky           << "ter intrinsic.  It is being lowered to a constant 0\n";
437198090Srdivacky    CI->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context), 0));
438193323Sed    break;
439193323Sed  }
440193323Sed
441193323Sed  case Intrinsic::dbg_declare:
442193323Sed    break;    // Simply strip out debugging intrinsics
443193323Sed
444193323Sed  case Intrinsic::eh_exception:
445198090Srdivacky  case Intrinsic::eh_selector:
446193323Sed    CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
447193323Sed    break;
448193323Sed
449198090Srdivacky  case Intrinsic::eh_typeid_for:
450193323Sed    // Return something different to eh_selector.
451193323Sed    CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
452193323Sed    break;
453193323Sed
454193323Sed  case Intrinsic::var_annotation:
455193323Sed    break;   // Strip out annotate intrinsic
456193323Sed
457193323Sed  case Intrinsic::memcpy: {
458198090Srdivacky    const IntegerType *IntPtr = TD.getIntPtrType(Context);
459210299Sed    Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
460193323Sed                                        /* isSigned */ false);
461193323Sed    Value *Ops[3];
462210299Sed    Ops[0] = CI->getArgOperand(0);
463210299Sed    Ops[1] = CI->getArgOperand(1);
464193323Sed    Ops[2] = Size;
465210299Sed    ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
466193323Sed    break;
467193323Sed  }
468193323Sed  case Intrinsic::memmove: {
469198090Srdivacky    const IntegerType *IntPtr = TD.getIntPtrType(Context);
470210299Sed    Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
471193323Sed                                        /* isSigned */ false);
472193323Sed    Value *Ops[3];
473210299Sed    Ops[0] = CI->getArgOperand(0);
474210299Sed    Ops[1] = CI->getArgOperand(1);
475193323Sed    Ops[2] = Size;
476210299Sed    ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
477193323Sed    break;
478193323Sed  }
479193323Sed  case Intrinsic::memset: {
480198090Srdivacky    const IntegerType *IntPtr = TD.getIntPtrType(Context);
481210299Sed    Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
482193323Sed                                        /* isSigned */ false);
483193323Sed    Value *Ops[3];
484210299Sed    Ops[0] = CI->getArgOperand(0);
485193323Sed    // Extend the amount to i32.
486212904Sdim    Ops[1] = Builder.CreateIntCast(CI->getArgOperand(1),
487212904Sdim                                   Type::getInt32Ty(Context),
488193323Sed                                   /* isSigned */ false);
489193323Sed    Ops[2] = Size;
490210299Sed    ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
491193323Sed    break;
492193323Sed  }
493193323Sed  case Intrinsic::sqrt: {
494195098Sed    ReplaceFPIntrinsicWithCall(CI, "sqrtf", "sqrt", "sqrtl");
495193323Sed    break;
496193323Sed  }
497193323Sed  case Intrinsic::log: {
498195098Sed    ReplaceFPIntrinsicWithCall(CI, "logf", "log", "logl");
499193323Sed    break;
500193323Sed  }
501193323Sed  case Intrinsic::log2: {
502195098Sed    ReplaceFPIntrinsicWithCall(CI, "log2f", "log2", "log2l");
503193323Sed    break;
504193323Sed  }
505193323Sed  case Intrinsic::log10: {
506195098Sed    ReplaceFPIntrinsicWithCall(CI, "log10f", "log10", "log10l");
507193323Sed    break;
508193323Sed  }
509193323Sed  case Intrinsic::exp: {
510195098Sed    ReplaceFPIntrinsicWithCall(CI, "expf", "exp", "expl");
511193323Sed    break;
512193323Sed  }
513193323Sed  case Intrinsic::exp2: {
514195098Sed    ReplaceFPIntrinsicWithCall(CI, "exp2f", "exp2", "exp2l");
515193323Sed    break;
516193323Sed  }
517193323Sed  case Intrinsic::pow: {
518195098Sed    ReplaceFPIntrinsicWithCall(CI, "powf", "pow", "powl");
519193323Sed    break;
520193323Sed  }
521193323Sed  case Intrinsic::flt_rounds:
522193323Sed     // Lower to "round to the nearest"
523202375Srdivacky     if (!CI->getType()->isVoidTy())
524193323Sed       CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
525193323Sed     break;
526199481Srdivacky  case Intrinsic::invariant_start:
527199481Srdivacky  case Intrinsic::lifetime_start:
528199481Srdivacky    // Discard region information.
529199481Srdivacky    CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
530199481Srdivacky    break;
531199481Srdivacky  case Intrinsic::invariant_end:
532199481Srdivacky  case Intrinsic::lifetime_end:
533199481Srdivacky    // Discard region information.
534199481Srdivacky    break;
535193323Sed  }
536193323Sed
537193323Sed  assert(CI->use_empty() &&
538193323Sed         "Lowering should have eliminated any uses of the intrinsic call!");
539193323Sed  CI->eraseFromParent();
540193323Sed}
541218893Sdim
542218893Sdimbool IntrinsicLowering::LowerToByteSwap(CallInst *CI) {
543218893Sdim  // Verify this is a simple bswap.
544218893Sdim  if (CI->getNumArgOperands() != 1 ||
545218893Sdim      CI->getType() != CI->getArgOperand(0)->getType() ||
546218893Sdim      !CI->getType()->isIntegerTy())
547218893Sdim    return false;
548218893Sdim
549218893Sdim  const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
550218893Sdim  if (!Ty)
551218893Sdim    return false;
552218893Sdim
553218893Sdim  // Okay, we can do this xform, do so now.
554218893Sdim  const Type *Tys[] = { Ty };
555218893Sdim  Module *M = CI->getParent()->getParent()->getParent();
556218893Sdim  Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1);
557218893Sdim
558218893Sdim  Value *Op = CI->getArgOperand(0);
559218893Sdim  Op = CallInst::Create(Int, Op, CI->getName(), CI);
560218893Sdim
561218893Sdim  CI->replaceAllUsesWith(Op);
562218893Sdim  CI->eraseFromParent();
563218893Sdim  return true;
564218893Sdim}
565