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
14245431Sdim#include "llvm/CodeGen/IntrinsicLowering.h"
15245431Sdim#include "llvm/ADT/SmallVector.h"
16252723Sdim#include "llvm/IR/Constants.h"
17252723Sdim#include "llvm/IR/DataLayout.h"
18252723Sdim#include "llvm/IR/DerivedTypes.h"
19252723Sdim#include "llvm/IR/IRBuilder.h"
20252723Sdim#include "llvm/IR/Module.h"
21252723Sdim#include "llvm/IR/Type.h"
22210299Sed#include "llvm/Support/CallSite.h"
23198090Srdivacky#include "llvm/Support/ErrorHandling.h"
24198090Srdivacky#include "llvm/Support/raw_ostream.h"
25193323Sedusing namespace llvm;
26193323Sed
27193323Sedtemplate <class ArgIt>
28193323Sedstatic void EnsureFunctionExists(Module &M, const char *Name,
29193323Sed                                 ArgIt ArgBegin, ArgIt ArgEnd,
30226890Sdim                                 Type *RetTy) {
31193323Sed  // Insert a correctly-typed definition now.
32224145Sdim  std::vector<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,
67226890Sdim                                 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.
72224145Sdim  std::vector<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);
80224145Sdim  CallInst *NewCI = Builder.CreateCall(FCache, Args);
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
356224145Sdim  case Intrinsic::expect: {
357224145Sdim    // Just replace __builtin_expect(exp, c) with EXP.
358224145Sdim    Value *V = CI->getArgOperand(0);
359224145Sdim    CI->replaceAllUsesWith(V);
360224145Sdim    break;
361224145Sdim  }
362224145Sdim
363193323Sed    // The setjmp/longjmp intrinsics should only exist in the code if it was
364193323Sed    // never optimized (ie, right out of the CFE), or if it has been hacked on
365193323Sed    // by the lowerinvoke pass.  In both cases, the right thing to do is to
366193323Sed    // convert the call to an explicit setjmp or longjmp call.
367193323Sed  case Intrinsic::setjmp: {
368210299Sed    Value *V = ReplaceCallWith("setjmp", CI, CS.arg_begin(), CS.arg_end(),
369198090Srdivacky                               Type::getInt32Ty(Context));
370202375Srdivacky    if (!CI->getType()->isVoidTy())
371193323Sed      CI->replaceAllUsesWith(V);
372193323Sed    break;
373193323Sed  }
374193323Sed  case Intrinsic::sigsetjmp:
375202375Srdivacky     if (!CI->getType()->isVoidTy())
376193323Sed       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
377193323Sed     break;
378193323Sed
379193323Sed  case Intrinsic::longjmp: {
380210299Sed    ReplaceCallWith("longjmp", CI, CS.arg_begin(), CS.arg_end(),
381198090Srdivacky                    Type::getVoidTy(Context));
382193323Sed    break;
383193323Sed  }
384193323Sed
385193323Sed  case Intrinsic::siglongjmp: {
386193323Sed    // Insert the call to abort
387210299Sed    ReplaceCallWith("abort", CI, CS.arg_end(), CS.arg_end(),
388198090Srdivacky                    Type::getVoidTy(Context));
389193323Sed    break;
390193323Sed  }
391193323Sed  case Intrinsic::ctpop:
392210299Sed    CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getArgOperand(0), CI));
393193323Sed    break;
394193323Sed
395193323Sed  case Intrinsic::bswap:
396210299Sed    CI->replaceAllUsesWith(LowerBSWAP(Context, CI->getArgOperand(0), CI));
397193323Sed    break;
398193323Sed
399193323Sed  case Intrinsic::ctlz:
400210299Sed    CI->replaceAllUsesWith(LowerCTLZ(Context, CI->getArgOperand(0), CI));
401193323Sed    break;
402193323Sed
403193323Sed  case Intrinsic::cttz: {
404193323Sed    // cttz(x) -> ctpop(~X & (X-1))
405210299Sed    Value *Src = CI->getArgOperand(0);
406193323Sed    Value *NotSrc = Builder.CreateNot(Src);
407193323Sed    NotSrc->setName(Src->getName() + ".not");
408193323Sed    Value *SrcM1 = ConstantInt::get(Src->getType(), 1);
409193323Sed    SrcM1 = Builder.CreateSub(Src, SrcM1);
410198090Srdivacky    Src = LowerCTPOP(Context, Builder.CreateAnd(NotSrc, SrcM1), CI);
411193323Sed    CI->replaceAllUsesWith(Src);
412193323Sed    break;
413193323Sed  }
414193323Sed
415193323Sed  case Intrinsic::stacksave:
416193323Sed  case Intrinsic::stackrestore: {
417193323Sed    if (!Warned)
418198090Srdivacky      errs() << "WARNING: this target does not support the llvm.stack"
419198090Srdivacky             << (Callee->getIntrinsicID() == Intrinsic::stacksave ?
420193323Sed               "save" : "restore") << " intrinsic.\n";
421193323Sed    Warned = true;
422193323Sed    if (Callee->getIntrinsicID() == Intrinsic::stacksave)
423193323Sed      CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
424193323Sed    break;
425193323Sed  }
426193323Sed
427193323Sed  case Intrinsic::returnaddress:
428193323Sed  case Intrinsic::frameaddress:
429198090Srdivacky    errs() << "WARNING: this target does not support the llvm."
430198090Srdivacky           << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
431193323Sed             "return" : "frame") << "address intrinsic.\n";
432193323Sed    CI->replaceAllUsesWith(ConstantPointerNull::get(
433193323Sed                                            cast<PointerType>(CI->getType())));
434193323Sed    break;
435193323Sed
436193323Sed  case Intrinsic::prefetch:
437193323Sed    break;    // Simply strip out prefetches on unsupported architectures
438193323Sed
439193323Sed  case Intrinsic::pcmarker:
440193323Sed    break;    // Simply strip out pcmarker on unsupported architectures
441193323Sed  case Intrinsic::readcyclecounter: {
442198090Srdivacky    errs() << "WARNING: this target does not support the llvm.readcyclecoun"
443198090Srdivacky           << "ter intrinsic.  It is being lowered to a constant 0\n";
444198090Srdivacky    CI->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context), 0));
445193323Sed    break;
446193323Sed  }
447193323Sed
448193323Sed  case Intrinsic::dbg_declare:
449193323Sed    break;    // Simply strip out debugging intrinsics
450193323Sed
451198090Srdivacky  case Intrinsic::eh_typeid_for:
452193323Sed    // Return something different to eh_selector.
453193323Sed    CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
454193323Sed    break;
455193323Sed
456252723Sdim  case Intrinsic::annotation:
457252723Sdim  case Intrinsic::ptr_annotation:
458252723Sdim    // Just drop the annotation, but forward the value
459252723Sdim    CI->replaceAllUsesWith(CI->getOperand(0));
460252723Sdim    break;
461252723Sdim
462193323Sed  case Intrinsic::var_annotation:
463193323Sed    break;   // Strip out annotate intrinsic
464193323Sed
465193323Sed  case Intrinsic::memcpy: {
466245431Sdim    Type *IntPtr = TD.getIntPtrType(Context);
467210299Sed    Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
468193323Sed                                        /* isSigned */ false);
469193323Sed    Value *Ops[3];
470210299Sed    Ops[0] = CI->getArgOperand(0);
471210299Sed    Ops[1] = CI->getArgOperand(1);
472193323Sed    Ops[2] = Size;
473210299Sed    ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
474193323Sed    break;
475193323Sed  }
476193323Sed  case Intrinsic::memmove: {
477245431Sdim    Type *IntPtr = TD.getIntPtrType(Context);
478210299Sed    Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
479193323Sed                                        /* isSigned */ false);
480193323Sed    Value *Ops[3];
481210299Sed    Ops[0] = CI->getArgOperand(0);
482210299Sed    Ops[1] = CI->getArgOperand(1);
483193323Sed    Ops[2] = Size;
484210299Sed    ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
485193323Sed    break;
486193323Sed  }
487193323Sed  case Intrinsic::memset: {
488263509Sdim    Value *Op0 = CI->getArgOperand(0);
489263509Sdim    Type *IntPtr = TD.getIntPtrType(Op0->getType());
490210299Sed    Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
491193323Sed                                        /* isSigned */ false);
492193323Sed    Value *Ops[3];
493263509Sdim    Ops[0] = Op0;
494193323Sed    // Extend the amount to i32.
495212904Sdim    Ops[1] = Builder.CreateIntCast(CI->getArgOperand(1),
496212904Sdim                                   Type::getInt32Ty(Context),
497193323Sed                                   /* isSigned */ false);
498193323Sed    Ops[2] = Size;
499210299Sed    ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
500193323Sed    break;
501193323Sed  }
502193323Sed  case Intrinsic::sqrt: {
503195098Sed    ReplaceFPIntrinsicWithCall(CI, "sqrtf", "sqrt", "sqrtl");
504193323Sed    break;
505193323Sed  }
506193323Sed  case Intrinsic::log: {
507195098Sed    ReplaceFPIntrinsicWithCall(CI, "logf", "log", "logl");
508193323Sed    break;
509193323Sed  }
510193323Sed  case Intrinsic::log2: {
511195098Sed    ReplaceFPIntrinsicWithCall(CI, "log2f", "log2", "log2l");
512193323Sed    break;
513193323Sed  }
514193323Sed  case Intrinsic::log10: {
515195098Sed    ReplaceFPIntrinsicWithCall(CI, "log10f", "log10", "log10l");
516193323Sed    break;
517193323Sed  }
518193323Sed  case Intrinsic::exp: {
519195098Sed    ReplaceFPIntrinsicWithCall(CI, "expf", "exp", "expl");
520193323Sed    break;
521193323Sed  }
522193323Sed  case Intrinsic::exp2: {
523195098Sed    ReplaceFPIntrinsicWithCall(CI, "exp2f", "exp2", "exp2l");
524193323Sed    break;
525193323Sed  }
526193323Sed  case Intrinsic::pow: {
527195098Sed    ReplaceFPIntrinsicWithCall(CI, "powf", "pow", "powl");
528193323Sed    break;
529193323Sed  }
530193323Sed  case Intrinsic::flt_rounds:
531193323Sed     // Lower to "round to the nearest"
532202375Srdivacky     if (!CI->getType()->isVoidTy())
533193323Sed       CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
534193323Sed     break;
535199481Srdivacky  case Intrinsic::invariant_start:
536199481Srdivacky  case Intrinsic::lifetime_start:
537199481Srdivacky    // Discard region information.
538199481Srdivacky    CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
539199481Srdivacky    break;
540199481Srdivacky  case Intrinsic::invariant_end:
541199481Srdivacky  case Intrinsic::lifetime_end:
542199481Srdivacky    // Discard region information.
543199481Srdivacky    break;
544193323Sed  }
545193323Sed
546193323Sed  assert(CI->use_empty() &&
547193323Sed         "Lowering should have eliminated any uses of the intrinsic call!");
548193323Sed  CI->eraseFromParent();
549193323Sed}
550218893Sdim
551218893Sdimbool IntrinsicLowering::LowerToByteSwap(CallInst *CI) {
552218893Sdim  // Verify this is a simple bswap.
553218893Sdim  if (CI->getNumArgOperands() != 1 ||
554218893Sdim      CI->getType() != CI->getArgOperand(0)->getType() ||
555218893Sdim      !CI->getType()->isIntegerTy())
556218893Sdim    return false;
557218893Sdim
558224145Sdim  IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
559218893Sdim  if (!Ty)
560218893Sdim    return false;
561218893Sdim
562218893Sdim  // Okay, we can do this xform, do so now.
563218893Sdim  Module *M = CI->getParent()->getParent()->getParent();
564224145Sdim  Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Ty);
565218893Sdim
566218893Sdim  Value *Op = CI->getArgOperand(0);
567218893Sdim  Op = CallInst::Create(Int, Op, CI->getName(), CI);
568218893Sdim
569218893Sdim  CI->replaceAllUsesWith(Op);
570218893Sdim  CI->eraseFromParent();
571218893Sdim  return true;
572218893Sdim}
573