diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp')
| -rw-r--r-- | contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp | 509 |
1 files changed, 0 insertions, 509 deletions
diff --git a/contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp b/contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp deleted file mode 100644 index 8cbd8bcaeabb..000000000000 --- a/contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ /dev/null @@ -1,509 +0,0 @@ -//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the IntrinsicLowering class. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/IntrinsicLowering.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -/// This function is used when we want to lower an intrinsic call to a call of -/// an external function. This handles hard cases such as when there was already -/// a prototype for the external function, but that prototype doesn't match the -/// arguments we expect to pass in. -template <class ArgIt> -static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI, - ArgIt ArgBegin, ArgIt ArgEnd, - Type *RetTy) { - // If we haven't already looked up this function, check to see if the - // program already contains a function with this name. - Module *M = CI->getModule(); - // Get or insert the definition now. - std::vector<Type *> ParamTys; - for (ArgIt I = ArgBegin; I != ArgEnd; ++I) - ParamTys.push_back((*I)->getType()); - FunctionCallee FCache = - M->getOrInsertFunction(NewFn, FunctionType::get(RetTy, ParamTys, false)); - - IRBuilder<> Builder(CI->getParent(), CI->getIterator()); - SmallVector<Value *, 8> Args(ArgBegin, ArgEnd); - CallInst *NewCI = Builder.CreateCall(FCache, Args); - NewCI->setName(CI->getName()); - if (!CI->use_empty()) - CI->replaceAllUsesWith(NewCI); - return NewCI; -} - -// VisualStudio defines setjmp as _setjmp -#if defined(_MSC_VER) && defined(setjmp) && \ - !defined(setjmp_undefined_for_msvc) -# pragma push_macro("setjmp") -# undef setjmp -# define setjmp_undefined_for_msvc -#endif - -/// Emit the code to lower bswap of V before the specified instruction IP. -static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) { - assert(V->getType()->isIntOrIntVectorTy() && "Can't bswap a non-integer type!"); - - unsigned BitSize = V->getType()->getScalarSizeInBits(); - - IRBuilder<> Builder(IP); - - switch(BitSize) { - default: llvm_unreachable("Unhandled type size of value to byteswap!"); - case 16: { - Value *Tmp1 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), - "bswap.2"); - Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), - "bswap.1"); - V = Builder.CreateOr(Tmp1, Tmp2, "bswap.i16"); - break; - } - case 32: { - Value *Tmp4 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24), - "bswap.4"); - Value *Tmp3 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), - "bswap.3"); - Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), - "bswap.2"); - Value *Tmp1 = Builder.CreateLShr(V,ConstantInt::get(V->getType(), 24), - "bswap.1"); - Tmp3 = Builder.CreateAnd(Tmp3, - ConstantInt::get(V->getType(), 0xFF0000), - "bswap.and3"); - Tmp2 = Builder.CreateAnd(Tmp2, - ConstantInt::get(V->getType(), 0xFF00), - "bswap.and2"); - Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or1"); - Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or2"); - V = Builder.CreateOr(Tmp4, Tmp2, "bswap.i32"); - break; - } - case 64: { - Value *Tmp8 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 56), - "bswap.8"); - Value *Tmp7 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 40), - "bswap.7"); - Value *Tmp6 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24), - "bswap.6"); - Value *Tmp5 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), - "bswap.5"); - Value* Tmp4 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), - "bswap.4"); - Value* Tmp3 = Builder.CreateLShr(V, - ConstantInt::get(V->getType(), 24), - "bswap.3"); - Value* Tmp2 = Builder.CreateLShr(V, - ConstantInt::get(V->getType(), 40), - "bswap.2"); - Value* Tmp1 = Builder.CreateLShr(V, - ConstantInt::get(V->getType(), 56), - "bswap.1"); - Tmp7 = Builder.CreateAnd(Tmp7, - ConstantInt::get(V->getType(), - 0xFF000000000000ULL), - "bswap.and7"); - Tmp6 = Builder.CreateAnd(Tmp6, - ConstantInt::get(V->getType(), - 0xFF0000000000ULL), - "bswap.and6"); - Tmp5 = Builder.CreateAnd(Tmp5, - ConstantInt::get(V->getType(), - 0xFF00000000ULL), - "bswap.and5"); - Tmp4 = Builder.CreateAnd(Tmp4, - ConstantInt::get(V->getType(), - 0xFF000000ULL), - "bswap.and4"); - Tmp3 = Builder.CreateAnd(Tmp3, - ConstantInt::get(V->getType(), - 0xFF0000ULL), - "bswap.and3"); - Tmp2 = Builder.CreateAnd(Tmp2, - ConstantInt::get(V->getType(), - 0xFF00ULL), - "bswap.and2"); - Tmp8 = Builder.CreateOr(Tmp8, Tmp7, "bswap.or1"); - Tmp6 = Builder.CreateOr(Tmp6, Tmp5, "bswap.or2"); - Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or3"); - Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or4"); - Tmp8 = Builder.CreateOr(Tmp8, Tmp6, "bswap.or5"); - Tmp4 = Builder.CreateOr(Tmp4, Tmp2, "bswap.or6"); - V = Builder.CreateOr(Tmp8, Tmp4, "bswap.i64"); - break; - } - } - return V; -} - -/// Emit the code to lower ctpop of V before the specified instruction IP. -static Value *LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP) { - assert(V->getType()->isIntegerTy() && "Can't ctpop a non-integer type!"); - - static const uint64_t MaskValues[6] = { - 0x5555555555555555ULL, 0x3333333333333333ULL, - 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL, - 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL - }; - - IRBuilder<> Builder(IP); - - unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); - unsigned WordSize = (BitSize + 63) / 64; - Value *Count = ConstantInt::get(V->getType(), 0); - - for (unsigned n = 0; n < WordSize; ++n) { - Value *PartValue = V; - for (unsigned i = 1, ct = 0; i < (BitSize>64 ? 64 : BitSize); - i <<= 1, ++ct) { - Value *MaskCst = ConstantInt::get(V->getType(), MaskValues[ct]); - Value *LHS = Builder.CreateAnd(PartValue, MaskCst, "cppop.and1"); - Value *VShift = Builder.CreateLShr(PartValue, - ConstantInt::get(V->getType(), i), - "ctpop.sh"); - Value *RHS = Builder.CreateAnd(VShift, MaskCst, "cppop.and2"); - PartValue = Builder.CreateAdd(LHS, RHS, "ctpop.step"); - } - Count = Builder.CreateAdd(PartValue, Count, "ctpop.part"); - if (BitSize > 64) { - V = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 64), - "ctpop.part.sh"); - BitSize -= 64; - } - } - - return Count; -} - -/// Emit the code to lower ctlz of V before the specified instruction IP. -static Value *LowerCTLZ(LLVMContext &Context, Value *V, Instruction *IP) { - - IRBuilder<> Builder(IP); - - unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); - for (unsigned i = 1; i < BitSize; i <<= 1) { - Value *ShVal = ConstantInt::get(V->getType(), i); - ShVal = Builder.CreateLShr(V, ShVal, "ctlz.sh"); - V = Builder.CreateOr(V, ShVal, "ctlz.step"); - } - - V = Builder.CreateNot(V); - return LowerCTPOP(Context, V, IP); -} - -static void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname, - const char *Dname, - const char *LDname) { - CallSite CS(CI); - switch (CI->getArgOperand(0)->getType()->getTypeID()) { - default: llvm_unreachable("Invalid type in intrinsic"); - case Type::FloatTyID: - ReplaceCallWith(Fname, CI, CS.arg_begin(), CS.arg_end(), - Type::getFloatTy(CI->getContext())); - break; - case Type::DoubleTyID: - ReplaceCallWith(Dname, CI, CS.arg_begin(), CS.arg_end(), - Type::getDoubleTy(CI->getContext())); - break; - case Type::X86_FP80TyID: - case Type::FP128TyID: - case Type::PPC_FP128TyID: - ReplaceCallWith(LDname, CI, CS.arg_begin(), CS.arg_end(), - CI->getArgOperand(0)->getType()); - break; - } -} - -void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { - IRBuilder<> Builder(CI); - LLVMContext &Context = CI->getContext(); - - const Function *Callee = CI->getCalledFunction(); - assert(Callee && "Cannot lower an indirect call!"); - - CallSite CS(CI); - switch (Callee->getIntrinsicID()) { - case Intrinsic::not_intrinsic: - report_fatal_error("Cannot lower a call to a non-intrinsic function '"+ - Callee->getName() + "'!"); - default: - report_fatal_error("Code generator does not support intrinsic function '"+ - Callee->getName()+"'!"); - - case Intrinsic::expect: { - // Just replace __builtin_expect(exp, c) with EXP. - Value *V = CI->getArgOperand(0); - CI->replaceAllUsesWith(V); - break; - } - - // The setjmp/longjmp intrinsics should only exist in the code if it was - // never optimized (ie, right out of the CFE), or if it has been hacked on - // by the lowerinvoke pass. In both cases, the right thing to do is to - // convert the call to an explicit setjmp or longjmp call. - case Intrinsic::setjmp: { - Value *V = ReplaceCallWith("setjmp", CI, CS.arg_begin(), CS.arg_end(), - Type::getInt32Ty(Context)); - if (!CI->getType()->isVoidTy()) - CI->replaceAllUsesWith(V); - break; - } - case Intrinsic::sigsetjmp: - if (!CI->getType()->isVoidTy()) - CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); - break; - - case Intrinsic::longjmp: { - ReplaceCallWith("longjmp", CI, CS.arg_begin(), CS.arg_end(), - Type::getVoidTy(Context)); - break; - } - - case Intrinsic::siglongjmp: { - // Insert the call to abort - ReplaceCallWith("abort", CI, CS.arg_end(), CS.arg_end(), - Type::getVoidTy(Context)); - break; - } - case Intrinsic::ctpop: - CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getArgOperand(0), CI)); - break; - - case Intrinsic::bswap: - CI->replaceAllUsesWith(LowerBSWAP(Context, CI->getArgOperand(0), CI)); - break; - - case Intrinsic::ctlz: - CI->replaceAllUsesWith(LowerCTLZ(Context, CI->getArgOperand(0), CI)); - break; - - case Intrinsic::cttz: { - // cttz(x) -> ctpop(~X & (X-1)) - Value *Src = CI->getArgOperand(0); - Value *NotSrc = Builder.CreateNot(Src); - NotSrc->setName(Src->getName() + ".not"); - Value *SrcM1 = ConstantInt::get(Src->getType(), 1); - SrcM1 = Builder.CreateSub(Src, SrcM1); - Src = LowerCTPOP(Context, Builder.CreateAnd(NotSrc, SrcM1), CI); - CI->replaceAllUsesWith(Src); - break; - } - - case Intrinsic::stacksave: - case Intrinsic::stackrestore: { - if (!Warned) - errs() << "WARNING: this target does not support the llvm.stack" - << (Callee->getIntrinsicID() == Intrinsic::stacksave ? - "save" : "restore") << " intrinsic.\n"; - Warned = true; - if (Callee->getIntrinsicID() == Intrinsic::stacksave) - CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); - break; - } - - case Intrinsic::get_dynamic_area_offset: - errs() << "WARNING: this target does not support the custom llvm.get." - "dynamic.area.offset. It is being lowered to a constant 0\n"; - // Just lower it to a constant 0 because for most targets - // @llvm.get.dynamic.area.offset is lowered to zero. - CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0)); - break; - case Intrinsic::returnaddress: - case Intrinsic::frameaddress: - errs() << "WARNING: this target does not support the llvm." - << (Callee->getIntrinsicID() == Intrinsic::returnaddress ? - "return" : "frame") << "address intrinsic.\n"; - CI->replaceAllUsesWith( - ConstantPointerNull::get(cast<PointerType>(CI->getType()))); - break; - case Intrinsic::addressofreturnaddress: - errs() << "WARNING: this target does not support the " - "llvm.addressofreturnaddress intrinsic.\n"; - CI->replaceAllUsesWith( - ConstantPointerNull::get(cast<PointerType>(CI->getType()))); - break; - - case Intrinsic::prefetch: - break; // Simply strip out prefetches on unsupported architectures - - case Intrinsic::pcmarker: - break; // Simply strip out pcmarker on unsupported architectures - case Intrinsic::readcyclecounter: { - errs() << "WARNING: this target does not support the llvm.readcyclecoun" - << "ter intrinsic. It is being lowered to a constant 0\n"; - CI->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context), 0)); - break; - } - - case Intrinsic::dbg_declare: - case Intrinsic::dbg_label: - break; // Simply strip out debugging intrinsics - - case Intrinsic::eh_typeid_for: - // Return something different to eh_selector. - CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1)); - break; - - case Intrinsic::annotation: - case Intrinsic::ptr_annotation: - // Just drop the annotation, but forward the value - CI->replaceAllUsesWith(CI->getOperand(0)); - break; - - case Intrinsic::assume: - case Intrinsic::var_annotation: - break; // Strip out these intrinsics - - case Intrinsic::memcpy: { - Type *IntPtr = DL.getIntPtrType(Context); - Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, - /* isSigned */ false); - Value *Ops[3]; - Ops[0] = CI->getArgOperand(0); - Ops[1] = CI->getArgOperand(1); - Ops[2] = Size; - ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getArgOperand(0)->getType()); - break; - } - case Intrinsic::memmove: { - Type *IntPtr = DL.getIntPtrType(Context); - Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, - /* isSigned */ false); - Value *Ops[3]; - Ops[0] = CI->getArgOperand(0); - Ops[1] = CI->getArgOperand(1); - Ops[2] = Size; - ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getArgOperand(0)->getType()); - break; - } - case Intrinsic::memset: { - Value *Op0 = CI->getArgOperand(0); - Type *IntPtr = DL.getIntPtrType(Op0->getType()); - Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, - /* isSigned */ false); - Value *Ops[3]; - Ops[0] = Op0; - // Extend the amount to i32. - Ops[1] = Builder.CreateIntCast(CI->getArgOperand(1), - Type::getInt32Ty(Context), - /* isSigned */ false); - Ops[2] = Size; - ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getArgOperand(0)->getType()); - break; - } - case Intrinsic::sqrt: { - ReplaceFPIntrinsicWithCall(CI, "sqrtf", "sqrt", "sqrtl"); - break; - } - case Intrinsic::log: { - ReplaceFPIntrinsicWithCall(CI, "logf", "log", "logl"); - break; - } - case Intrinsic::log2: { - ReplaceFPIntrinsicWithCall(CI, "log2f", "log2", "log2l"); - break; - } - case Intrinsic::log10: { - ReplaceFPIntrinsicWithCall(CI, "log10f", "log10", "log10l"); - break; - } - case Intrinsic::exp: { - ReplaceFPIntrinsicWithCall(CI, "expf", "exp", "expl"); - break; - } - case Intrinsic::exp2: { - ReplaceFPIntrinsicWithCall(CI, "exp2f", "exp2", "exp2l"); - break; - } - case Intrinsic::pow: { - ReplaceFPIntrinsicWithCall(CI, "powf", "pow", "powl"); - break; - } - case Intrinsic::sin: { - ReplaceFPIntrinsicWithCall(CI, "sinf", "sin", "sinl"); - break; - } - case Intrinsic::cos: { - ReplaceFPIntrinsicWithCall(CI, "cosf", "cos", "cosl"); - break; - } - case Intrinsic::floor: { - ReplaceFPIntrinsicWithCall(CI, "floorf", "floor", "floorl"); - break; - } - case Intrinsic::ceil: { - ReplaceFPIntrinsicWithCall(CI, "ceilf", "ceil", "ceill"); - break; - } - case Intrinsic::trunc: { - ReplaceFPIntrinsicWithCall(CI, "truncf", "trunc", "truncl"); - break; - } - case Intrinsic::round: { - ReplaceFPIntrinsicWithCall(CI, "roundf", "round", "roundl"); - break; - } - case Intrinsic::copysign: { - ReplaceFPIntrinsicWithCall(CI, "copysignf", "copysign", "copysignl"); - break; - } - case Intrinsic::flt_rounds: - // Lower to "round to the nearest" - if (!CI->getType()->isVoidTy()) - CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1)); - break; - case Intrinsic::invariant_start: - case Intrinsic::lifetime_start: - // Discard region information. - CI->replaceAllUsesWith(UndefValue::get(CI->getType())); - break; - case Intrinsic::invariant_end: - case Intrinsic::lifetime_end: - // Discard region information. - break; - } - - assert(CI->use_empty() && - "Lowering should have eliminated any uses of the intrinsic call!"); - CI->eraseFromParent(); -} - -bool IntrinsicLowering::LowerToByteSwap(CallInst *CI) { - // Verify this is a simple bswap. - if (CI->getNumArgOperands() != 1 || - CI->getType() != CI->getArgOperand(0)->getType() || - !CI->getType()->isIntegerTy()) - return false; - - IntegerType *Ty = dyn_cast<IntegerType>(CI->getType()); - if (!Ty) - return false; - - // Okay, we can do this xform, do so now. - Module *M = CI->getModule(); - Function *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Ty); - - Value *Op = CI->getArgOperand(0); - Op = CallInst::Create(Int, Op, CI->getName(), CI); - - CI->replaceAllUsesWith(Op); - CI->eraseFromParent(); - return true; -} |
