xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/IntrinsicLowering.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the IntrinsicLowering class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/CodeGen/IntrinsicLowering.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
150b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
160b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
170b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
180b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
190b57cec5SDimitry Andric #include "llvm/IR/Module.h"
200b57cec5SDimitry Andric #include "llvm/IR/Type.h"
210b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric /// This function is used when we want to lower an intrinsic call to a call of
260b57cec5SDimitry Andric /// an external function. This handles hard cases such as when there was already
270b57cec5SDimitry Andric /// a prototype for the external function, but that prototype doesn't match the
280b57cec5SDimitry Andric /// arguments we expect to pass in.
290b57cec5SDimitry Andric template <class ArgIt>
300b57cec5SDimitry Andric static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
310b57cec5SDimitry Andric                                  ArgIt ArgBegin, ArgIt ArgEnd,
320b57cec5SDimitry Andric                                  Type *RetTy) {
330b57cec5SDimitry Andric   // If we haven't already looked up this function, check to see if the
340b57cec5SDimitry Andric   // program already contains a function with this name.
350b57cec5SDimitry Andric   Module *M = CI->getModule();
360b57cec5SDimitry Andric   // Get or insert the definition now.
370b57cec5SDimitry Andric   std::vector<Type *> ParamTys;
380b57cec5SDimitry Andric   for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
390b57cec5SDimitry Andric     ParamTys.push_back((*I)->getType());
400b57cec5SDimitry Andric   FunctionCallee FCache =
410b57cec5SDimitry Andric       M->getOrInsertFunction(NewFn, FunctionType::get(RetTy, ParamTys, false));
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   IRBuilder<> Builder(CI->getParent(), CI->getIterator());
440b57cec5SDimitry Andric   SmallVector<Value *, 8> Args(ArgBegin, ArgEnd);
450b57cec5SDimitry Andric   CallInst *NewCI = Builder.CreateCall(FCache, Args);
460b57cec5SDimitry Andric   NewCI->setName(CI->getName());
470b57cec5SDimitry Andric   if (!CI->use_empty())
480b57cec5SDimitry Andric     CI->replaceAllUsesWith(NewCI);
490b57cec5SDimitry Andric   return NewCI;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric /// Emit the code to lower bswap of V before the specified instruction IP.
530b57cec5SDimitry Andric static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) {
540b57cec5SDimitry Andric   assert(V->getType()->isIntOrIntVectorTy() && "Can't bswap a non-integer type!");
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   unsigned BitSize = V->getType()->getScalarSizeInBits();
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   IRBuilder<> Builder(IP);
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   switch(BitSize) {
610b57cec5SDimitry Andric   default: llvm_unreachable("Unhandled type size of value to byteswap!");
620b57cec5SDimitry Andric   case 16: {
630b57cec5SDimitry Andric     Value *Tmp1 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
640b57cec5SDimitry Andric                                     "bswap.2");
650b57cec5SDimitry Andric     Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
660b57cec5SDimitry Andric                                      "bswap.1");
670b57cec5SDimitry Andric     V = Builder.CreateOr(Tmp1, Tmp2, "bswap.i16");
680b57cec5SDimitry Andric     break;
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric   case 32: {
710b57cec5SDimitry Andric     Value *Tmp4 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24),
720b57cec5SDimitry Andric                                     "bswap.4");
730b57cec5SDimitry Andric     Value *Tmp3 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
740b57cec5SDimitry Andric                                     "bswap.3");
750b57cec5SDimitry Andric     Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
760b57cec5SDimitry Andric                                      "bswap.2");
770b57cec5SDimitry Andric     Value *Tmp1 = Builder.CreateLShr(V,ConstantInt::get(V->getType(), 24),
780b57cec5SDimitry Andric                                      "bswap.1");
790b57cec5SDimitry Andric     Tmp3 = Builder.CreateAnd(Tmp3,
800b57cec5SDimitry Andric                          ConstantInt::get(V->getType(), 0xFF0000),
810b57cec5SDimitry Andric                              "bswap.and3");
820b57cec5SDimitry Andric     Tmp2 = Builder.CreateAnd(Tmp2,
830b57cec5SDimitry Andric                            ConstantInt::get(V->getType(), 0xFF00),
840b57cec5SDimitry Andric                              "bswap.and2");
850b57cec5SDimitry Andric     Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or1");
860b57cec5SDimitry Andric     Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or2");
870b57cec5SDimitry Andric     V = Builder.CreateOr(Tmp4, Tmp2, "bswap.i32");
880b57cec5SDimitry Andric     break;
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric   case 64: {
910b57cec5SDimitry Andric     Value *Tmp8 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 56),
920b57cec5SDimitry Andric                                     "bswap.8");
930b57cec5SDimitry Andric     Value *Tmp7 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 40),
940b57cec5SDimitry Andric                                     "bswap.7");
950b57cec5SDimitry Andric     Value *Tmp6 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24),
960b57cec5SDimitry Andric                                     "bswap.6");
970b57cec5SDimitry Andric     Value *Tmp5 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),
980b57cec5SDimitry Andric                                     "bswap.5");
990b57cec5SDimitry Andric     Value* Tmp4 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),
1000b57cec5SDimitry Andric                                      "bswap.4");
1010b57cec5SDimitry Andric     Value* Tmp3 = Builder.CreateLShr(V,
1020b57cec5SDimitry Andric                                      ConstantInt::get(V->getType(), 24),
1030b57cec5SDimitry Andric                                      "bswap.3");
1040b57cec5SDimitry Andric     Value* Tmp2 = Builder.CreateLShr(V,
1050b57cec5SDimitry Andric                                      ConstantInt::get(V->getType(), 40),
1060b57cec5SDimitry Andric                                      "bswap.2");
1070b57cec5SDimitry Andric     Value* Tmp1 = Builder.CreateLShr(V,
1080b57cec5SDimitry Andric                                      ConstantInt::get(V->getType(), 56),
1090b57cec5SDimitry Andric                                      "bswap.1");
1100b57cec5SDimitry Andric     Tmp7 = Builder.CreateAnd(Tmp7,
1110b57cec5SDimitry Andric                              ConstantInt::get(V->getType(),
1120b57cec5SDimitry Andric                                               0xFF000000000000ULL),
1130b57cec5SDimitry Andric                              "bswap.and7");
1140b57cec5SDimitry Andric     Tmp6 = Builder.CreateAnd(Tmp6,
1150b57cec5SDimitry Andric                              ConstantInt::get(V->getType(),
1160b57cec5SDimitry Andric                                               0xFF0000000000ULL),
1170b57cec5SDimitry Andric                              "bswap.and6");
1180b57cec5SDimitry Andric     Tmp5 = Builder.CreateAnd(Tmp5,
1190b57cec5SDimitry Andric                         ConstantInt::get(V->getType(),
1200b57cec5SDimitry Andric                              0xFF00000000ULL),
1210b57cec5SDimitry Andric                              "bswap.and5");
1220b57cec5SDimitry Andric     Tmp4 = Builder.CreateAnd(Tmp4,
1230b57cec5SDimitry Andric                         ConstantInt::get(V->getType(),
1240b57cec5SDimitry Andric                              0xFF000000ULL),
1250b57cec5SDimitry Andric                              "bswap.and4");
1260b57cec5SDimitry Andric     Tmp3 = Builder.CreateAnd(Tmp3,
1270b57cec5SDimitry Andric                              ConstantInt::get(V->getType(),
1280b57cec5SDimitry Andric                              0xFF0000ULL),
1290b57cec5SDimitry Andric                              "bswap.and3");
1300b57cec5SDimitry Andric     Tmp2 = Builder.CreateAnd(Tmp2,
1310b57cec5SDimitry Andric                              ConstantInt::get(V->getType(),
1320b57cec5SDimitry Andric                              0xFF00ULL),
1330b57cec5SDimitry Andric                              "bswap.and2");
1340b57cec5SDimitry Andric     Tmp8 = Builder.CreateOr(Tmp8, Tmp7, "bswap.or1");
1350b57cec5SDimitry Andric     Tmp6 = Builder.CreateOr(Tmp6, Tmp5, "bswap.or2");
1360b57cec5SDimitry Andric     Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or3");
1370b57cec5SDimitry Andric     Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or4");
1380b57cec5SDimitry Andric     Tmp8 = Builder.CreateOr(Tmp8, Tmp6, "bswap.or5");
1390b57cec5SDimitry Andric     Tmp4 = Builder.CreateOr(Tmp4, Tmp2, "bswap.or6");
1400b57cec5SDimitry Andric     V = Builder.CreateOr(Tmp8, Tmp4, "bswap.i64");
1410b57cec5SDimitry Andric     break;
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric   return V;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric /// Emit the code to lower ctpop of V before the specified instruction IP.
1480b57cec5SDimitry Andric static Value *LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP) {
1490b57cec5SDimitry Andric   assert(V->getType()->isIntegerTy() && "Can't ctpop a non-integer type!");
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   static const uint64_t MaskValues[6] = {
1520b57cec5SDimitry Andric     0x5555555555555555ULL, 0x3333333333333333ULL,
1530b57cec5SDimitry Andric     0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
1540b57cec5SDimitry Andric     0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
1550b57cec5SDimitry Andric   };
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   IRBuilder<> Builder(IP);
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
1600b57cec5SDimitry Andric   unsigned WordSize = (BitSize + 63) / 64;
1610b57cec5SDimitry Andric   Value *Count = ConstantInt::get(V->getType(), 0);
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   for (unsigned n = 0; n < WordSize; ++n) {
1640b57cec5SDimitry Andric     Value *PartValue = V;
1650b57cec5SDimitry Andric     for (unsigned i = 1, ct = 0; i < (BitSize>64 ? 64 : BitSize);
1660b57cec5SDimitry Andric          i <<= 1, ++ct) {
1670b57cec5SDimitry Andric       Value *MaskCst = ConstantInt::get(V->getType(), MaskValues[ct]);
1680b57cec5SDimitry Andric       Value *LHS = Builder.CreateAnd(PartValue, MaskCst, "cppop.and1");
1690b57cec5SDimitry Andric       Value *VShift = Builder.CreateLShr(PartValue,
1700b57cec5SDimitry Andric                                         ConstantInt::get(V->getType(), i),
1710b57cec5SDimitry Andric                                          "ctpop.sh");
1720b57cec5SDimitry Andric       Value *RHS = Builder.CreateAnd(VShift, MaskCst, "cppop.and2");
1730b57cec5SDimitry Andric       PartValue = Builder.CreateAdd(LHS, RHS, "ctpop.step");
1740b57cec5SDimitry Andric     }
1750b57cec5SDimitry Andric     Count = Builder.CreateAdd(PartValue, Count, "ctpop.part");
1760b57cec5SDimitry Andric     if (BitSize > 64) {
1770b57cec5SDimitry Andric       V = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 64),
1780b57cec5SDimitry Andric                              "ctpop.part.sh");
1790b57cec5SDimitry Andric       BitSize -= 64;
1800b57cec5SDimitry Andric     }
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   return Count;
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric /// Emit the code to lower ctlz of V before the specified instruction IP.
1870b57cec5SDimitry Andric static Value *LowerCTLZ(LLVMContext &Context, Value *V, Instruction *IP) {
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   IRBuilder<> Builder(IP);
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
1920b57cec5SDimitry Andric   for (unsigned i = 1; i < BitSize; i <<= 1) {
1930b57cec5SDimitry Andric     Value *ShVal = ConstantInt::get(V->getType(), i);
1940b57cec5SDimitry Andric     ShVal = Builder.CreateLShr(V, ShVal, "ctlz.sh");
1950b57cec5SDimitry Andric     V = Builder.CreateOr(V, ShVal, "ctlz.step");
1960b57cec5SDimitry Andric   }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   V = Builder.CreateNot(V);
1990b57cec5SDimitry Andric   return LowerCTPOP(Context, V, IP);
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric static void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname,
2030b57cec5SDimitry Andric                                        const char *Dname,
2040b57cec5SDimitry Andric                                        const char *LDname) {
2050b57cec5SDimitry Andric   switch (CI->getArgOperand(0)->getType()->getTypeID()) {
2060b57cec5SDimitry Andric   default: llvm_unreachable("Invalid type in intrinsic");
2070b57cec5SDimitry Andric   case Type::FloatTyID:
2085ffd83dbSDimitry Andric     ReplaceCallWith(Fname, CI, CI->arg_begin(), CI->arg_end(),
2090b57cec5SDimitry Andric                     Type::getFloatTy(CI->getContext()));
2100b57cec5SDimitry Andric     break;
2110b57cec5SDimitry Andric   case Type::DoubleTyID:
2125ffd83dbSDimitry Andric     ReplaceCallWith(Dname, CI, CI->arg_begin(), CI->arg_end(),
2130b57cec5SDimitry Andric                     Type::getDoubleTy(CI->getContext()));
2140b57cec5SDimitry Andric     break;
2150b57cec5SDimitry Andric   case Type::X86_FP80TyID:
2160b57cec5SDimitry Andric   case Type::FP128TyID:
2170b57cec5SDimitry Andric   case Type::PPC_FP128TyID:
2185ffd83dbSDimitry Andric     ReplaceCallWith(LDname, CI, CI->arg_begin(), CI->arg_end(),
2190b57cec5SDimitry Andric                     CI->getArgOperand(0)->getType());
2200b57cec5SDimitry Andric     break;
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
2250b57cec5SDimitry Andric   IRBuilder<> Builder(CI);
2260b57cec5SDimitry Andric   LLVMContext &Context = CI->getContext();
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   const Function *Callee = CI->getCalledFunction();
2290b57cec5SDimitry Andric   assert(Callee && "Cannot lower an indirect call!");
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   switch (Callee->getIntrinsicID()) {
2320b57cec5SDimitry Andric   case Intrinsic::not_intrinsic:
2330b57cec5SDimitry Andric     report_fatal_error("Cannot lower a call to a non-intrinsic function '"+
2340b57cec5SDimitry Andric                       Callee->getName() + "'!");
2350b57cec5SDimitry Andric   default:
2360b57cec5SDimitry Andric     report_fatal_error("Code generator does not support intrinsic function '"+
2370b57cec5SDimitry Andric                       Callee->getName()+"'!");
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   case Intrinsic::expect: {
2400b57cec5SDimitry Andric     // Just replace __builtin_expect(exp, c) with EXP.
2410b57cec5SDimitry Andric     Value *V = CI->getArgOperand(0);
2420b57cec5SDimitry Andric     CI->replaceAllUsesWith(V);
2430b57cec5SDimitry Andric     break;
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
246*0fca6ea1SDimitry Andric   case Intrinsic::allow_runtime_check:
247*0fca6ea1SDimitry Andric   case Intrinsic::allow_ubsan_check:
248*0fca6ea1SDimitry Andric     CI->replaceAllUsesWith(ConstantInt::getTrue(CI->getType()));
249*0fca6ea1SDimitry Andric     return;
250*0fca6ea1SDimitry Andric 
2510b57cec5SDimitry Andric   case Intrinsic::ctpop:
2520b57cec5SDimitry Andric     CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getArgOperand(0), CI));
2530b57cec5SDimitry Andric     break;
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   case Intrinsic::bswap:
2560b57cec5SDimitry Andric     CI->replaceAllUsesWith(LowerBSWAP(Context, CI->getArgOperand(0), CI));
2570b57cec5SDimitry Andric     break;
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   case Intrinsic::ctlz:
2600b57cec5SDimitry Andric     CI->replaceAllUsesWith(LowerCTLZ(Context, CI->getArgOperand(0), CI));
2610b57cec5SDimitry Andric     break;
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   case Intrinsic::cttz: {
2640b57cec5SDimitry Andric     // cttz(x) -> ctpop(~X & (X-1))
2650b57cec5SDimitry Andric     Value *Src = CI->getArgOperand(0);
2660b57cec5SDimitry Andric     Value *NotSrc = Builder.CreateNot(Src);
2670b57cec5SDimitry Andric     NotSrc->setName(Src->getName() + ".not");
2680b57cec5SDimitry Andric     Value *SrcM1 = ConstantInt::get(Src->getType(), 1);
2690b57cec5SDimitry Andric     SrcM1 = Builder.CreateSub(Src, SrcM1);
2700b57cec5SDimitry Andric     Src = LowerCTPOP(Context, Builder.CreateAnd(NotSrc, SrcM1), CI);
2710b57cec5SDimitry Andric     CI->replaceAllUsesWith(Src);
2720b57cec5SDimitry Andric     break;
2730b57cec5SDimitry Andric   }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   case Intrinsic::stacksave:
2760b57cec5SDimitry Andric   case Intrinsic::stackrestore: {
2770b57cec5SDimitry Andric     if (!Warned)
2780b57cec5SDimitry Andric       errs() << "WARNING: this target does not support the llvm.stack"
2790b57cec5SDimitry Andric              << (Callee->getIntrinsicID() == Intrinsic::stacksave ?
2800b57cec5SDimitry Andric                "save" : "restore") << " intrinsic.\n";
2810b57cec5SDimitry Andric     Warned = true;
2820b57cec5SDimitry Andric     if (Callee->getIntrinsicID() == Intrinsic::stacksave)
2830b57cec5SDimitry Andric       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
2840b57cec5SDimitry Andric     break;
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   case Intrinsic::get_dynamic_area_offset:
2880b57cec5SDimitry Andric     errs() << "WARNING: this target does not support the custom llvm.get."
2890b57cec5SDimitry Andric               "dynamic.area.offset.  It is being lowered to a constant 0\n";
2900b57cec5SDimitry Andric     // Just lower it to a constant 0 because for most targets
2910b57cec5SDimitry Andric     // @llvm.get.dynamic.area.offset is lowered to zero.
2920b57cec5SDimitry Andric     CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0));
2930b57cec5SDimitry Andric     break;
2940b57cec5SDimitry Andric   case Intrinsic::returnaddress:
2950b57cec5SDimitry Andric   case Intrinsic::frameaddress:
2960b57cec5SDimitry Andric     errs() << "WARNING: this target does not support the llvm."
2970b57cec5SDimitry Andric            << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
2980b57cec5SDimitry Andric              "return" : "frame") << "address intrinsic.\n";
2990b57cec5SDimitry Andric     CI->replaceAllUsesWith(
3000b57cec5SDimitry Andric         ConstantPointerNull::get(cast<PointerType>(CI->getType())));
3010b57cec5SDimitry Andric     break;
3020b57cec5SDimitry Andric   case Intrinsic::addressofreturnaddress:
3030b57cec5SDimitry Andric     errs() << "WARNING: this target does not support the "
3040b57cec5SDimitry Andric               "llvm.addressofreturnaddress intrinsic.\n";
3050b57cec5SDimitry Andric     CI->replaceAllUsesWith(
3060b57cec5SDimitry Andric         ConstantPointerNull::get(cast<PointerType>(CI->getType())));
3070b57cec5SDimitry Andric     break;
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   case Intrinsic::prefetch:
3100b57cec5SDimitry Andric     break;    // Simply strip out prefetches on unsupported architectures
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   case Intrinsic::pcmarker:
3130b57cec5SDimitry Andric     break;    // Simply strip out pcmarker on unsupported architectures
3140b57cec5SDimitry Andric   case Intrinsic::readcyclecounter: {
3150b57cec5SDimitry Andric     errs() << "WARNING: this target does not support the llvm.readcyclecoun"
3160b57cec5SDimitry Andric            << "ter intrinsic.  It is being lowered to a constant 0\n";
3170b57cec5SDimitry Andric     CI->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context), 0));
3180b57cec5SDimitry Andric     break;
3190b57cec5SDimitry Andric   }
320*0fca6ea1SDimitry Andric   case Intrinsic::readsteadycounter: {
321*0fca6ea1SDimitry Andric     errs() << "WARNING: this target does not support the llvm.readsteadycounter"
322*0fca6ea1SDimitry Andric            << " intrinsic.  It is being lowered to a constant 0\n";
323*0fca6ea1SDimitry Andric     CI->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context), 0));
324*0fca6ea1SDimitry Andric     break;
325*0fca6ea1SDimitry Andric   }
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   case Intrinsic::dbg_declare:
3280b57cec5SDimitry Andric   case Intrinsic::dbg_label:
3290b57cec5SDimitry Andric     break;    // Simply strip out debugging intrinsics
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   case Intrinsic::eh_typeid_for:
3320b57cec5SDimitry Andric     // Return something different to eh_selector.
3330b57cec5SDimitry Andric     CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
3340b57cec5SDimitry Andric     break;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   case Intrinsic::annotation:
3370b57cec5SDimitry Andric   case Intrinsic::ptr_annotation:
3380b57cec5SDimitry Andric     // Just drop the annotation, but forward the value
3390b57cec5SDimitry Andric     CI->replaceAllUsesWith(CI->getOperand(0));
3400b57cec5SDimitry Andric     break;
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   case Intrinsic::assume:
343e8d8bef9SDimitry Andric   case Intrinsic::experimental_noalias_scope_decl:
3440b57cec5SDimitry Andric   case Intrinsic::var_annotation:
3450b57cec5SDimitry Andric     break;   // Strip out these intrinsics
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   case Intrinsic::memcpy: {
3480b57cec5SDimitry Andric     Type *IntPtr = DL.getIntPtrType(Context);
3490b57cec5SDimitry Andric     Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
3500b57cec5SDimitry Andric                                         /* isSigned */ false);
3510b57cec5SDimitry Andric     Value *Ops[3];
3520b57cec5SDimitry Andric     Ops[0] = CI->getArgOperand(0);
3530b57cec5SDimitry Andric     Ops[1] = CI->getArgOperand(1);
3540b57cec5SDimitry Andric     Ops[2] = Size;
3550b57cec5SDimitry Andric     ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
3560b57cec5SDimitry Andric     break;
3570b57cec5SDimitry Andric   }
3580b57cec5SDimitry Andric   case Intrinsic::memmove: {
3590b57cec5SDimitry Andric     Type *IntPtr = DL.getIntPtrType(Context);
3600b57cec5SDimitry Andric     Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
3610b57cec5SDimitry Andric                                         /* isSigned */ false);
3620b57cec5SDimitry Andric     Value *Ops[3];
3630b57cec5SDimitry Andric     Ops[0] = CI->getArgOperand(0);
3640b57cec5SDimitry Andric     Ops[1] = CI->getArgOperand(1);
3650b57cec5SDimitry Andric     Ops[2] = Size;
3660b57cec5SDimitry Andric     ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
3670b57cec5SDimitry Andric     break;
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric   case Intrinsic::memset: {
3700b57cec5SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3710b57cec5SDimitry Andric     Type *IntPtr = DL.getIntPtrType(Op0->getType());
3720b57cec5SDimitry Andric     Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr,
3730b57cec5SDimitry Andric                                         /* isSigned */ false);
3740b57cec5SDimitry Andric     Value *Ops[3];
3750b57cec5SDimitry Andric     Ops[0] = Op0;
3760b57cec5SDimitry Andric     // Extend the amount to i32.
3770b57cec5SDimitry Andric     Ops[1] = Builder.CreateIntCast(CI->getArgOperand(1),
3780b57cec5SDimitry Andric                                    Type::getInt32Ty(Context),
3790b57cec5SDimitry Andric                                    /* isSigned */ false);
3800b57cec5SDimitry Andric     Ops[2] = Size;
3810b57cec5SDimitry Andric     ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
3820b57cec5SDimitry Andric     break;
3830b57cec5SDimitry Andric   }
3840b57cec5SDimitry Andric   case Intrinsic::sqrt: {
3850b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "sqrtf", "sqrt", "sqrtl");
3860b57cec5SDimitry Andric     break;
3870b57cec5SDimitry Andric   }
3880b57cec5SDimitry Andric   case Intrinsic::log: {
3890b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "logf", "log", "logl");
3900b57cec5SDimitry Andric     break;
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric   case Intrinsic::log2: {
3930b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "log2f", "log2", "log2l");
3940b57cec5SDimitry Andric     break;
3950b57cec5SDimitry Andric   }
3960b57cec5SDimitry Andric   case Intrinsic::log10: {
3970b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "log10f", "log10", "log10l");
3980b57cec5SDimitry Andric     break;
3990b57cec5SDimitry Andric   }
4000b57cec5SDimitry Andric   case Intrinsic::exp: {
4010b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "expf", "exp", "expl");
4020b57cec5SDimitry Andric     break;
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric   case Intrinsic::exp2: {
4050b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "exp2f", "exp2", "exp2l");
4060b57cec5SDimitry Andric     break;
4070b57cec5SDimitry Andric   }
4080b57cec5SDimitry Andric   case Intrinsic::pow: {
4090b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "powf", "pow", "powl");
4100b57cec5SDimitry Andric     break;
4110b57cec5SDimitry Andric   }
4120b57cec5SDimitry Andric   case Intrinsic::sin: {
4130b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "sinf", "sin", "sinl");
4140b57cec5SDimitry Andric     break;
4150b57cec5SDimitry Andric   }
4160b57cec5SDimitry Andric   case Intrinsic::cos: {
4170b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "cosf", "cos", "cosl");
4180b57cec5SDimitry Andric     break;
4190b57cec5SDimitry Andric   }
4200b57cec5SDimitry Andric   case Intrinsic::floor: {
4210b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "floorf", "floor", "floorl");
4220b57cec5SDimitry Andric     break;
4230b57cec5SDimitry Andric   }
4240b57cec5SDimitry Andric   case Intrinsic::ceil: {
4250b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "ceilf", "ceil", "ceill");
4260b57cec5SDimitry Andric     break;
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric   case Intrinsic::trunc: {
4290b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "truncf", "trunc", "truncl");
4300b57cec5SDimitry Andric     break;
4310b57cec5SDimitry Andric   }
4320b57cec5SDimitry Andric   case Intrinsic::round: {
4330b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "roundf", "round", "roundl");
4340b57cec5SDimitry Andric     break;
4350b57cec5SDimitry Andric   }
4365ffd83dbSDimitry Andric   case Intrinsic::roundeven: {
4375ffd83dbSDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "roundevenf", "roundeven", "roundevenl");
4385ffd83dbSDimitry Andric     break;
4395ffd83dbSDimitry Andric   }
4400b57cec5SDimitry Andric   case Intrinsic::copysign: {
4410b57cec5SDimitry Andric     ReplaceFPIntrinsicWithCall(CI, "copysignf", "copysign", "copysignl");
4420b57cec5SDimitry Andric     break;
4430b57cec5SDimitry Andric   }
444bdd1243dSDimitry Andric   case Intrinsic::get_rounding:
4450b57cec5SDimitry Andric      // Lower to "round to the nearest"
4460b57cec5SDimitry Andric      if (!CI->getType()->isVoidTy())
4470b57cec5SDimitry Andric        CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1));
4480b57cec5SDimitry Andric      break;
4490b57cec5SDimitry Andric   case Intrinsic::invariant_start:
4500b57cec5SDimitry Andric   case Intrinsic::lifetime_start:
4510b57cec5SDimitry Andric     // Discard region information.
4520b57cec5SDimitry Andric     CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
4530b57cec5SDimitry Andric     break;
4540b57cec5SDimitry Andric   case Intrinsic::invariant_end:
4550b57cec5SDimitry Andric   case Intrinsic::lifetime_end:
4560b57cec5SDimitry Andric     // Discard region information.
4570b57cec5SDimitry Andric     break;
4580b57cec5SDimitry Andric   }
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   assert(CI->use_empty() &&
4610b57cec5SDimitry Andric          "Lowering should have eliminated any uses of the intrinsic call!");
4620b57cec5SDimitry Andric   CI->eraseFromParent();
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric bool IntrinsicLowering::LowerToByteSwap(CallInst *CI) {
4660b57cec5SDimitry Andric   // Verify this is a simple bswap.
467349cc55cSDimitry Andric   if (CI->arg_size() != 1 || CI->getType() != CI->getArgOperand(0)->getType() ||
4680b57cec5SDimitry Andric       !CI->getType()->isIntegerTy())
4690b57cec5SDimitry Andric     return false;
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
4720b57cec5SDimitry Andric   if (!Ty)
4730b57cec5SDimitry Andric     return false;
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   // Okay, we can do this xform, do so now.
4760b57cec5SDimitry Andric   Module *M = CI->getModule();
4770b57cec5SDimitry Andric   Function *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Ty);
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   Value *Op = CI->getArgOperand(0);
480*0fca6ea1SDimitry Andric   Op = CallInst::Create(Int, Op, CI->getName(), CI->getIterator());
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   CI->replaceAllUsesWith(Op);
4830b57cec5SDimitry Andric   CI->eraseFromParent();
4840b57cec5SDimitry Andric   return true;
4850b57cec5SDimitry Andric }
486