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