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