diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -280,6 +280,13 @@ return B == OverrideAsUnavailable; } + /// Return true if the function type FTy is valid for the library function + /// F, regardless of whether the function is available. + bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F, + const Module &M) const { + return Impl->isValidProtoForLibFunc(FTy, F, M); + } + /// Searches for a particular function name. /// /// If it is one of the known library functions, return true and set F to the diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -363,6 +363,8 @@ /// In all cases, the returned value is a FunctionCallee wrapper around the /// 'FunctionType *T' passed in, as well as a 'Value*' either of the Function or /// the bitcast to the function. + /// + /// Note: For library calls getOrInsertLibFunc() should be used instead. FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList); diff --git a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h --- a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -22,23 +22,63 @@ class IRBuilderBase; /// Analyze the name and prototype of the given function and set any - /// applicable attributes. + /// applicable attributes. Note that this merely helps optimizations on an + /// already existing function but does not consider mandatory attributes. + /// /// If the library function is unavailable, this doesn't modify it. /// /// Returns true if any attributes were set and false otherwise. - bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI); - bool inferLibFuncAttributes(Module *M, StringRef Name, const TargetLibraryInfo &TLI); + bool inferNonMandatoryLibFuncAttrs(Module *M, StringRef Name, + const TargetLibraryInfo &TLI); + bool inferNonMandatoryLibFuncAttrs(Function &F, const TargetLibraryInfo &TLI); + + /// Calls getOrInsertFunction() and then makes sure to add mandatory + /// argument attributes. + FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, + LibFunc TheLibFunc, FunctionType *T, + AttributeList AttributeList); + FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, + LibFunc TheLibFunc, FunctionType *T); + template + FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, + LibFunc TheLibFunc, AttributeList AttributeList, + Type *RetTy, ArgsTy... Args) { + SmallVector ArgTys{Args...}; + return getOrInsertLibFunc(M, TLI, TheLibFunc, + FunctionType::get(RetTy, ArgTys, false), + AttributeList); + } + /// Same as above, but without the attributes. + template + FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, + LibFunc TheLibFunc, Type *RetTy, ArgsTy... Args) { + return getOrInsertLibFunc(M, TLI, TheLibFunc, AttributeList{}, RetTy, + Args...); + } + // Avoid an incorrect ordering that'd otherwise compile incorrectly. + template + FunctionCallee + getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, + LibFunc TheLibFunc, AttributeList AttributeList, + FunctionType *Invalid, ArgsTy... Args) = delete; + + /// Check whether the library function is available on target and also that + /// it in the current Module is a Function with the right type. + bool isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI, + LibFunc TheLibFunc); + bool isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI, + StringRef Name); /// Check whether the overloaded floating point function /// corresponding to \a Ty is available. - bool hasFloatFn(const TargetLibraryInfo *TLI, Type *Ty, + bool hasFloatFn(const Module *M, const TargetLibraryInfo *TLI, Type *Ty, LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn); /// Get the name of the overloaded floating point function - /// corresponding to \a Ty. - StringRef getFloatFnName(const TargetLibraryInfo *TLI, Type *Ty, - LibFunc DoubleFn, LibFunc FloatFn, - LibFunc LongDoubleFn); + /// corresponding to \a Ty. Return the LibFunc in \a TheLibFunc. + StringRef getFloatFn(const Module *M, const TargetLibraryInfo *TLI, Type *Ty, + LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn, + LibFunc &TheLibFunc); /// Return V if it is an i8*, otherwise cast it to i8*. Value *castToCStr(Value *V, IRBuilderBase &B); @@ -148,7 +188,8 @@ /// function is known to take a single of type matching 'Op' and returns one /// value with the same type. If 'Op' is a long double, 'l' is added as the /// suffix of name, if 'Op' is a float, we add a 'f' suffix. - Value *emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilderBase &B, + Value *emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI, + StringRef Name, IRBuilderBase &B, const AttributeList &Attrs); /// Emit a call to the unary function DoubleFn, FloatFn or LongDoubleFn, @@ -162,8 +203,10 @@ /// function is known to take type matching 'Op1' and 'Op2' and return one /// value with the same type. If 'Op1/Op2' are long double, 'l' is added as /// the suffix of name, if 'Op1/Op2' are float, we add a 'f' suffix. - Value *emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name, - IRBuilderBase &B, const AttributeList &Attrs); + Value *emitBinaryFloatFnCall(Value *Op1, Value *Op2, + const TargetLibraryInfo *TLI, + StringRef Name, IRBuilderBase &B, + const AttributeList &Attrs); /// Emit a call to the binary function DoubleFn, FloatFn or LongDoubleFn, /// depending of the type of Op1. diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h --- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -235,7 +235,7 @@ /// hasFloatVersion - Checks if there is a float version of the specified /// function by checking for an existing function with name FuncName + f - bool hasFloatVersion(StringRef FuncName); + bool hasFloatVersion(const Module *M, StringRef FuncName); /// Shared code to optimize strlen+wcslen and strnlen+wcsnlen. Value *optimizeStringLength(CallInst *CI, IRBuilderBase &B, unsigned CharSize, diff --git a/llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp b/llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp --- a/llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp @@ -29,7 +29,7 @@ // explicitly visited by CGSCC passes in the new pass manager.) if (F.isDeclaration() && !F.hasOptNone()) { if (!F.hasFnAttribute(Attribute::NoBuiltin)) - Changed |= inferLibFuncAttributes(F, GetTLI(F)); + Changed |= inferNonMandatoryLibFuncAttrs(F, GetTLI(F)); Changed |= inferAttributesFromOthers(F); } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1298,6 +1298,8 @@ } Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { + Module *M = I.getModule(); + if (Value *V = SimplifyFDivInst(I.getOperand(0), I.getOperand(1), I.getFastMathFlags(), SQ.getWithInstruction(&I))) @@ -1363,8 +1365,8 @@ !IsTan && match(Op0, m_Intrinsic(m_Value(X))) && match(Op1, m_Intrinsic(m_Specific(X))); - if ((IsTan || IsCot) && - hasFloatFn(&TLI, I.getType(), LibFunc_tan, LibFunc_tanf, LibFunc_tanl)) { + if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan, + LibFunc_tanf, LibFunc_tanl)) { IRBuilder<> B(&I); IRBuilder<>::FastMathFlagGuard FMFGuard(B); B.setFastMathFlags(I.getFastMathFlags()); diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp --- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -1100,6 +1100,7 @@ Value *StoredVal, Instruction *TheStore, SmallPtrSetImpl &Stores, const SCEVAddRecExpr *Ev, const SCEV *BECount, bool IsNegStride, bool IsLoopMemset) { + Module *M = TheStore->getModule(); Value *SplatValue = isBytewiseValue(StoredVal, *DL); Constant *PatternValue = nullptr; @@ -1182,15 +1183,14 @@ NewCall = Builder.CreateMemSet( BasePtr, SplatValue, NumBytes, MaybeAlign(StoreAlignment), /*isVolatile=*/false, AATags.TBAA, AATags.Scope, AATags.NoAlias); - } else { + } else if (isLibFuncEmittable(M, TLI, LibFunc_memset_pattern16)) { // Everything is emitted in default address space Type *Int8PtrTy = DestInt8PtrTy; - Module *M = TheStore->getModule(); StringRef FuncName = "memset_pattern16"; - FunctionCallee MSP = M->getOrInsertFunction(FuncName, Builder.getVoidTy(), - Int8PtrTy, Int8PtrTy, IntIdxTy); - inferLibFuncAttributes(M, FuncName, *TLI); + FunctionCallee MSP = getOrInsertLibFunc(M, *TLI, LibFunc_memset_pattern16, + Builder.getVoidTy(), Int8PtrTy, Int8PtrTy, IntIdxTy); + inferNonMandatoryLibFuncAttrs(M, FuncName, *TLI); // Otherwise we should form a memset_pattern16. PatternValue is known to be // an constant array of 16-bytes. Plop the value into a mergable global. @@ -1201,7 +1201,9 @@ GV->setAlignment(Align(16)); Value *PatternPtr = ConstantExpr::getBitCast(GV, Int8PtrTy); NewCall = Builder.CreateCall(MSP, {BasePtr, PatternPtr, NumBytes}); - } + } else + return Changed; + NewCall->setDebugLoc(TheStore->getDebugLoc()); if (MSSAU) { diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -39,7 +39,6 @@ STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind"); STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture"); STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly"); -STATISTIC(NumExtArg, "Number of arguments inferred as signext/zeroext."); STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly"); STATISTIC(NumNoAlias, "Number of function returns inferred as noalias"); STATISTIC(NumNoUndef, "Number of function returns inferred as noundef returns"); @@ -147,16 +146,6 @@ return true; } -static bool setArgExtAttr(Function &F, unsigned ArgNo, - const TargetLibraryInfo &TLI, bool Signed = true) { - Attribute::AttrKind ExtAttr = TLI.getExtAttrForI32Param(Signed); - if (ExtAttr == Attribute::None || F.hasParamAttribute(ArgNo, ExtAttr)) - return false; - F.addParamAttr(ArgNo, ExtAttr); - ++NumExtArg; - return true; -} - static bool setRetNoUndef(Function &F) { if (!F.getReturnType()->isVoidTy() && !F.hasRetAttribute(Attribute::NoUndef)) { @@ -254,15 +243,16 @@ return true; } -bool llvm::inferLibFuncAttributes(Module *M, StringRef Name, - const TargetLibraryInfo &TLI) { +bool llvm::inferNonMandatoryLibFuncAttrs(Module *M, StringRef Name, + const TargetLibraryInfo &TLI) { Function *F = M->getFunction(Name); if (!F) return false; - return inferLibFuncAttributes(*F, TLI); + return inferNonMandatoryLibFuncAttrs(*F, TLI); } -bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { +bool llvm::inferNonMandatoryLibFuncAttrs(Function &F, + const TargetLibraryInfo &TLI) { LibFunc TheLibFunc; if (!(TLI.getLibFunc(F, TheLibFunc) && TLI.has(TheLibFunc))) return false; @@ -875,7 +865,6 @@ case LibFunc_putchar: case LibFunc_putchar_unlocked: Changed |= setRetAndArgsNoUndef(F); - Changed |= setArgExtAttr(F, 0, TLI); Changed |= setDoesNotThrow(F); return Changed; case LibFunc_popen: @@ -1096,7 +1085,6 @@ case LibFunc_ldexp: case LibFunc_ldexpf: case LibFunc_ldexpl: - Changed |= setArgExtAttr(F, 1, TLI); Changed |= setWillReturn(F); return Changed; case LibFunc_abs: @@ -1233,34 +1221,141 @@ } } -bool llvm::hasFloatFn(const TargetLibraryInfo *TLI, Type *Ty, +static void setArgExtAttr(Function &F, unsigned ArgNo, + const TargetLibraryInfo &TLI, bool Signed = true) { + Attribute::AttrKind ExtAttr = TLI.getExtAttrForI32Param(Signed); + if (ExtAttr != Attribute::None && !F.hasParamAttribute(ArgNo, ExtAttr)) + F.addParamAttr(ArgNo, ExtAttr); +} + +FunctionCallee llvm::getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, + LibFunc TheLibFunc, FunctionType *T, + AttributeList AttributeList) { + assert(TLI.has(TheLibFunc) && + "Creating call to non-existing library function."); + StringRef Name = TLI.getName(TheLibFunc); + FunctionCallee C = M->getOrInsertFunction(Name, T, AttributeList); + + // Make sure any mandatory argument attributes are added. + + // Any outgoing i32 argument should be handled with setArgExtAttr() which + // will add an extension attribute if the target ABI requires it. Adding + // argument extensions is typically done by the front end but when an + // optimizer is building a library call on its own it has to take care of + // this. Each such generated function must be handled here with sign or + // zero extensions as needed. F is retreived with cast<> because we demand + // of the caller to have called isLibFuncEmittable() first. + Function *F = cast(C.getCallee()); + assert(F->getFunctionType() == T && "Function type does not match."); + switch (TheLibFunc) { + case LibFunc_fputc: + case LibFunc_putchar: + setArgExtAttr(*F, 0, TLI); + break; + case LibFunc_ldexp: + case LibFunc_ldexpf: + case LibFunc_ldexpl: + case LibFunc_memchr: + case LibFunc_strchr: + setArgExtAttr(*F, 1, TLI); + break; + case LibFunc_memccpy: + setArgExtAttr(*F, 2, TLI); + break; + + // These are functions that are known to not need any argument extension + // on any target: A size_t argument (which may be an i32 on some targets) + // should not trigger the assert below. + case LibFunc_bcmp: + case LibFunc_calloc: + case LibFunc_fwrite: + case LibFunc_malloc: + case LibFunc_memcmp: + case LibFunc_memcpy_chk: + case LibFunc_mempcpy: + case LibFunc_memset_pattern16: + case LibFunc_snprintf: + case LibFunc_stpncpy: + case LibFunc_strlcat: + case LibFunc_strlcpy: + case LibFunc_strncat: + case LibFunc_strncmp: + case LibFunc_strncpy: + case LibFunc_vsnprintf: + break; + + default: +#ifndef NDEBUG + for (unsigned i = 0; i < T->getNumParams(); i++) + assert(!isa(T->getParamType(i)) && + "Unhandled integer argument."); +#endif + break; + } + + return C; +} + +FunctionCallee llvm::getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, + LibFunc TheLibFunc, FunctionType *T) { + return getOrInsertLibFunc(M, TLI, TheLibFunc, T, AttributeList()); +} + +bool llvm::isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI, + LibFunc TheLibFunc) { + StringRef FuncName = TLI->getName(TheLibFunc); + if (!TLI->has(TheLibFunc)) + return false; + + // Check if the Module already has a GlobalValue with the same name, in + // which case it must be a Function with the expected type. + if (GlobalValue *GV = M->getNamedValue(FuncName)) { + if (auto *F = dyn_cast(GV)) + return TLI->isValidProtoForLibFunc(*F->getFunctionType(), TheLibFunc, *M); + return false; + } + + return true; +} + +bool llvm::isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI, + StringRef Name) { + LibFunc TheLibFunc; + return TLI->getLibFunc(Name, TheLibFunc) && + isLibFuncEmittable(M, TLI, TheLibFunc); +} + +bool llvm::hasFloatFn(const Module *M, const TargetLibraryInfo *TLI, Type *Ty, LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn) { switch (Ty->getTypeID()) { case Type::HalfTyID: return false; case Type::FloatTyID: - return TLI->has(FloatFn); + return isLibFuncEmittable(M, TLI, FloatFn); case Type::DoubleTyID: - return TLI->has(DoubleFn); + return isLibFuncEmittable(M, TLI, DoubleFn); default: - return TLI->has(LongDoubleFn); + return isLibFuncEmittable(M, TLI, LongDoubleFn); } } -StringRef llvm::getFloatFnName(const TargetLibraryInfo *TLI, Type *Ty, - LibFunc DoubleFn, LibFunc FloatFn, - LibFunc LongDoubleFn) { - assert(hasFloatFn(TLI, Ty, DoubleFn, FloatFn, LongDoubleFn) && +StringRef llvm::getFloatFn(const Module *M, const TargetLibraryInfo *TLI, + Type *Ty, LibFunc DoubleFn, LibFunc FloatFn, + LibFunc LongDoubleFn, LibFunc &TheLibFunc) { + assert(hasFloatFn(M, TLI, Ty, DoubleFn, FloatFn, LongDoubleFn) && "Cannot get name for unavailable function!"); switch (Ty->getTypeID()) { case Type::HalfTyID: llvm_unreachable("No name for HalfTy!"); case Type::FloatTyID: + TheLibFunc = FloatFn; return TLI->getName(FloatFn); case Type::DoubleTyID: + TheLibFunc = DoubleFn; return TLI->getName(DoubleFn); default: + TheLibFunc = LongDoubleFn; return TLI->getName(LongDoubleFn); } } @@ -1277,14 +1372,14 @@ ArrayRef Operands, IRBuilderBase &B, const TargetLibraryInfo *TLI, bool IsVaArgs = false) { - if (!TLI->has(TheLibFunc)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, TheLibFunc)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); StringRef FuncName = TLI->getName(TheLibFunc); FunctionType *FuncType = FunctionType::get(ReturnType, ParamTypes, IsVaArgs); - FunctionCallee Callee = M->getOrInsertFunction(FuncName, FuncType); - inferLibFuncAttributes(M, FuncName, *TLI); + FunctionCallee Callee = getOrInsertLibFunc(M, *TLI, TheLibFunc, FuncType); + inferNonMandatoryLibFuncAttrs(M, FuncName, *TLI); CallInst *CI = B.CreateCall(Callee, Operands, FuncName); if (const Function *F = dyn_cast(Callee.getCallee()->stripPointerCasts())) @@ -1353,16 +1448,16 @@ Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI) { - if (!TLI->has(LibFunc_memcpy_chk)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, LibFunc_memcpy_chk)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); AttributeList AS; AS = AttributeList::get(M->getContext(), AttributeList::FunctionIndex, Attribute::NoUnwind); LLVMContext &Context = B.GetInsertBlock()->getContext(); - FunctionCallee MemCpy = M->getOrInsertFunction( - "__memcpy_chk", AttributeList::get(M->getContext(), AS), B.getInt8PtrTy(), + FunctionCallee MemCpy = getOrInsertLibFunc(M, *TLI, LibFunc_memcpy_chk, + AttributeList::get(M->getContext(), AS), B.getInt8PtrTy(), B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context), DL.getIntPtrType(Context)); Dst = castToCStr(Dst, B); @@ -1496,14 +1591,15 @@ } } -static Value *emitUnaryFloatFnCallHelper(Value *Op, StringRef Name, - IRBuilderBase &B, - const AttributeList &Attrs) { +static Value *emitUnaryFloatFnCallHelper(Value *Op, LibFunc TheLibFunc, + StringRef Name, IRBuilderBase &B, + const AttributeList &Attrs, + const TargetLibraryInfo *TLI) { assert((Name != "") && "Must specify Name to emitUnaryFloatFnCall"); Module *M = B.GetInsertBlock()->getModule(); - FunctionCallee Callee = - M->getOrInsertFunction(Name, Op->getType(), Op->getType()); + FunctionCallee Callee = getOrInsertLibFunc(M, *TLI, TheLibFunc, Op->getType(), + Op->getType()); CallInst *CI = B.CreateCall(Callee, Op, Name); // The incoming attribute set may have come from a speculatable intrinsic, but @@ -1518,12 +1614,16 @@ return CI; } -Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilderBase &B, +Value *llvm::emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI, + StringRef Name, IRBuilderBase &B, const AttributeList &Attrs) { SmallString<20> NameBuffer; appendTypeSuffix(Op, Name, NameBuffer); - return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs); + LibFunc TheLibFunc; + TLI->getLibFunc(Name, TheLibFunc); + + return emitUnaryFloatFnCallHelper(Op, TheLibFunc, Name, B, Attrs, TLI); } Value *llvm::emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI, @@ -1531,23 +1631,25 @@ LibFunc LongDoubleFn, IRBuilderBase &B, const AttributeList &Attrs) { // Get the name of the function according to TLI. - StringRef Name = getFloatFnName(TLI, Op->getType(), - DoubleFn, FloatFn, LongDoubleFn); + Module *M = B.GetInsertBlock()->getModule(); + LibFunc TheLibFunc; + StringRef Name = getFloatFn(M, TLI, Op->getType(), DoubleFn, FloatFn, + LongDoubleFn, TheLibFunc); - return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs); + return emitUnaryFloatFnCallHelper(Op, TheLibFunc, Name, B, Attrs, TLI); } static Value *emitBinaryFloatFnCallHelper(Value *Op1, Value *Op2, + LibFunc TheLibFunc, StringRef Name, IRBuilderBase &B, const AttributeList &Attrs, - const TargetLibraryInfo *TLI = nullptr) { + const TargetLibraryInfo *TLI) { assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall"); Module *M = B.GetInsertBlock()->getModule(); - FunctionCallee Callee = M->getOrInsertFunction(Name, Op1->getType(), - Op1->getType(), Op2->getType()); - if (TLI != nullptr) - inferLibFuncAttributes(M, Name, *TLI); + FunctionCallee Callee = getOrInsertLibFunc(M, *TLI, TheLibFunc, Op1->getType(), + Op1->getType(), Op2->getType()); + inferNonMandatoryLibFuncAttrs(M, Name, *TLI); CallInst *CI = B.CreateCall(Callee, { Op1, Op2 }, Name); // The incoming attribute set may have come from a speculatable intrinsic, but @@ -1562,15 +1664,19 @@ return CI; } -Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name, - IRBuilderBase &B, +Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, + const TargetLibraryInfo *TLI, + StringRef Name, IRBuilderBase &B, const AttributeList &Attrs) { assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall"); SmallString<20> NameBuffer; appendTypeSuffix(Op1, Name, NameBuffer); - return emitBinaryFloatFnCallHelper(Op1, Op2, Name, B, Attrs); + LibFunc TheLibFunc; + TLI->getLibFunc(Name, TheLibFunc); + + return emitBinaryFloatFnCallHelper(Op1, Op2, TheLibFunc, Name, B, Attrs, TLI); } Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, @@ -1579,22 +1685,24 @@ LibFunc LongDoubleFn, IRBuilderBase &B, const AttributeList &Attrs) { // Get the name of the function according to TLI. - StringRef Name = getFloatFnName(TLI, Op1->getType(), - DoubleFn, FloatFn, LongDoubleFn); + Module *M = B.GetInsertBlock()->getModule(); + LibFunc TheLibFunc; + StringRef Name = getFloatFn(M, TLI, Op1->getType(), DoubleFn, FloatFn, + LongDoubleFn, TheLibFunc); - return emitBinaryFloatFnCallHelper(Op1, Op2, Name, B, Attrs, TLI); + return emitBinaryFloatFnCallHelper(Op1, Op2, TheLibFunc, Name, B, Attrs, TLI); } Value *llvm::emitPutChar(Value *Char, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - if (!TLI->has(LibFunc_putchar)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, LibFunc_putchar)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); StringRef PutCharName = TLI->getName(LibFunc_putchar); - FunctionCallee PutChar = - M->getOrInsertFunction(PutCharName, B.getInt32Ty(), B.getInt32Ty()); - inferLibFuncAttributes(M, PutCharName, *TLI); + FunctionCallee PutChar = getOrInsertLibFunc(M, *TLI, LibFunc_putchar, + B.getInt32Ty(), B.getInt32Ty()); + inferNonMandatoryLibFuncAttrs(M, PutCharName, *TLI); CallInst *CI = B.CreateCall(PutChar, B.CreateIntCast(Char, B.getInt32Ty(), @@ -1610,14 +1718,14 @@ Value *llvm::emitPutS(Value *Str, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - if (!TLI->has(LibFunc_puts)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, LibFunc_puts)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); StringRef PutsName = TLI->getName(LibFunc_puts); - FunctionCallee PutS = - M->getOrInsertFunction(PutsName, B.getInt32Ty(), B.getInt8PtrTy()); - inferLibFuncAttributes(M, PutsName, *TLI); + FunctionCallee PutS = getOrInsertLibFunc(M, *TLI, LibFunc_puts, B.getInt32Ty(), + B.getInt8PtrTy()); + inferNonMandatoryLibFuncAttrs(M, PutsName, *TLI); CallInst *CI = B.CreateCall(PutS, castToCStr(Str, B), PutsName); if (const Function *F = dyn_cast(PutS.getCallee()->stripPointerCasts())) @@ -1627,15 +1735,15 @@ Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - if (!TLI->has(LibFunc_fputc)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, LibFunc_fputc)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); StringRef FPutcName = TLI->getName(LibFunc_fputc); - FunctionCallee F = M->getOrInsertFunction(FPutcName, B.getInt32Ty(), - B.getInt32Ty(), File->getType()); + FunctionCallee F = getOrInsertLibFunc(M, *TLI, LibFunc_fputc, B.getInt32Ty(), + B.getInt32Ty(), File->getType()); if (File->getType()->isPointerTy()) - inferLibFuncAttributes(M, FPutcName, *TLI); + inferNonMandatoryLibFuncAttrs(M, FPutcName, *TLI); Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true, "chari"); CallInst *CI = B.CreateCall(F, {Char, File}, FPutcName); @@ -1648,15 +1756,15 @@ Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - if (!TLI->has(LibFunc_fputs)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, LibFunc_fputs)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); StringRef FPutsName = TLI->getName(LibFunc_fputs); - FunctionCallee F = M->getOrInsertFunction(FPutsName, B.getInt32Ty(), - B.getInt8PtrTy(), File->getType()); + FunctionCallee F = getOrInsertLibFunc(M, *TLI, LibFunc_fputs, B.getInt32Ty(), + B.getInt8PtrTy(), File->getType()); if (File->getType()->isPointerTy()) - inferLibFuncAttributes(M, FPutsName, *TLI); + inferNonMandatoryLibFuncAttrs(M, FPutsName, *TLI); CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, FPutsName); if (const Function *Fn = @@ -1667,18 +1775,18 @@ Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI) { - if (!TLI->has(LibFunc_fwrite)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, LibFunc_fwrite)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); LLVMContext &Context = B.GetInsertBlock()->getContext(); StringRef FWriteName = TLI->getName(LibFunc_fwrite); - FunctionCallee F = M->getOrInsertFunction( - FWriteName, DL.getIntPtrType(Context), B.getInt8PtrTy(), - DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType()); + FunctionCallee F = getOrInsertLibFunc(M, *TLI, LibFunc_fwrite, + DL.getIntPtrType(Context), B.getInt8PtrTy(), DL.getIntPtrType(Context), + DL.getIntPtrType(Context), File->getType()); if (File->getType()->isPointerTy()) - inferLibFuncAttributes(M, FWriteName, *TLI); + inferNonMandatoryLibFuncAttrs(M, FWriteName, *TLI); CallInst *CI = B.CreateCall(F, {castToCStr(Ptr, B), Size, ConstantInt::get(DL.getIntPtrType(Context), 1), File}); @@ -1691,15 +1799,15 @@ Value *llvm::emitMalloc(Value *Num, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI) { - if (!TLI->has(LibFunc_malloc)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, LibFunc_malloc)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); StringRef MallocName = TLI->getName(LibFunc_malloc); LLVMContext &Context = B.GetInsertBlock()->getContext(); - FunctionCallee Malloc = M->getOrInsertFunction(MallocName, B.getInt8PtrTy(), - DL.getIntPtrType(Context)); - inferLibFuncAttributes(M, MallocName, *TLI); + FunctionCallee Malloc = getOrInsertLibFunc(M, *TLI, LibFunc_malloc, + B.getInt8PtrTy(), DL.getIntPtrType(Context)); + inferNonMandatoryLibFuncAttrs(M, MallocName, *TLI); CallInst *CI = B.CreateCall(Malloc, Num, MallocName); if (const Function *F = @@ -1711,16 +1819,16 @@ Value *llvm::emitCalloc(Value *Num, Value *Size, IRBuilderBase &B, const TargetLibraryInfo &TLI) { - if (!TLI.has(LibFunc_calloc)) + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, &TLI, LibFunc_calloc)) return nullptr; - Module *M = B.GetInsertBlock()->getModule(); StringRef CallocName = TLI.getName(LibFunc_calloc); const DataLayout &DL = M->getDataLayout(); IntegerType *PtrType = DL.getIntPtrType((B.GetInsertBlock()->getContext())); - FunctionCallee Calloc = - M->getOrInsertFunction(CallocName, B.getInt8PtrTy(), PtrType, PtrType); - inferLibFuncAttributes(M, CallocName, TLI); + FunctionCallee Calloc = getOrInsertLibFunc(M, TLI, LibFunc_calloc, + B.getInt8PtrTy(), PtrType, PtrType); + inferNonMandatoryLibFuncAttrs(M, CallocName, TLI); CallInst *CI = B.CreateCall(Calloc, {Num, Size}, CallocName); if (const auto *F = diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1190,13 +1190,15 @@ } Value *LibCallSimplifier::optimizeMemCmp(CallInst *CI, IRBuilderBase &B) { + Module *M = CI->getModule(); if (Value *V = optimizeMemCmpBCmpCommon(CI, B)) return V; // memcmp(x, y, Len) == 0 -> bcmp(x, y, Len) == 0 // bcmp can be more efficient than memcmp because it only has to know that // there is a difference, not how different one is to the other. - if (TLI->has(LibFunc_bcmp) && isOnlyUsedInZeroEqualityComparison(CI)) { + if (isLibFuncEmittable(M, TLI, LibFunc_bcmp) && + isOnlyUsedInZeroEqualityComparison(CI)) { Value *LHS = CI->getArgOperand(0); Value *RHS = CI->getArgOperand(1); Value *Size = CI->getArgOperand(2); @@ -1360,7 +1362,8 @@ /// Shrink double -> float functions. static Value *optimizeDoubleFP(CallInst *CI, IRBuilderBase &B, - bool isBinary, bool isPrecise = false) { + bool isBinary, const TargetLibraryInfo *TLI, + bool isPrecise = false) { Function *CalleeFn = CI->getCalledFunction(); if (!CI->getType()->isDoubleTy() || !CalleeFn) return nullptr; @@ -1410,22 +1413,25 @@ R = isBinary ? B.CreateCall(Fn, V) : B.CreateCall(Fn, V[0]); } else { AttributeList CalleeAttrs = CalleeFn->getAttributes(); - R = isBinary ? emitBinaryFloatFnCall(V[0], V[1], CalleeName, B, CalleeAttrs) - : emitUnaryFloatFnCall(V[0], CalleeName, B, CalleeAttrs); + R = isBinary ? emitBinaryFloatFnCall(V[0], V[1], TLI, CalleeName, B, + CalleeAttrs) + : emitUnaryFloatFnCall(V[0], TLI, CalleeName, B, CalleeAttrs); } return B.CreateFPExt(R, B.getDoubleTy()); } /// Shrink double -> float for unary functions. static Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilderBase &B, + const TargetLibraryInfo *TLI, bool isPrecise = false) { - return optimizeDoubleFP(CI, B, false, isPrecise); + return optimizeDoubleFP(CI, B, false, TLI, isPrecise); } /// Shrink double -> float for binary functions. static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilderBase &B, + const TargetLibraryInfo *TLI, bool isPrecise = false) { - return optimizeDoubleFP(CI, B, true, isPrecise); + return optimizeDoubleFP(CI, B, true, TLI, isPrecise); } // cabs(z) -> sqrt((creal(z)*creal(z)) + (cimag(z)*cimag(z))) @@ -1541,6 +1547,7 @@ /// ldexp(1.0, x) for pow(2.0, itofp(x)); exp2(n * x) for pow(2.0 ** n, x); /// exp10(x) for pow(10.0, x); exp2(log2(n) * x) for pow(n, x). Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { + Module *M = Pow->getModule(); Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); AttributeList Attrs; // Attributes are only meaningful on the original call Module *Mod = Pow->getModule(); @@ -1568,7 +1575,8 @@ Function *CalleeFn = BaseFn->getCalledFunction(); if (CalleeFn && - TLI->getLibFunc(CalleeFn->getName(), LibFn) && TLI->has(LibFn)) { + TLI->getLibFunc(CalleeFn->getName(), LibFn) && + isLibFuncEmittable(M, TLI, LibFn)) { StringRef ExpName; Intrinsic::ID ID; Value *ExpFn; @@ -1620,7 +1628,7 @@ // pow(2.0, itofp(x)) -> ldexp(1.0, x) if (match(Base, m_SpecificFP(2.0)) && (isa(Expo) || isa(Expo)) && - hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { + hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { if (Value *ExpoI = getIntToFPVal(Expo, B, TLI->getIntSize())) return copyFlags(*Pow, emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), ExpoI, @@ -1629,7 +1637,7 @@ } // pow(2.0 ** n, x) -> exp2(n * x) - if (hasFloatFn(TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) { + if (hasFloatFn(M, TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) { APFloat BaseR = APFloat(1.0); BaseR.convert(BaseF->getSemantics(), APFloat::rmTowardZero, &Ignored); BaseR = BaseR / *BaseF; @@ -1656,7 +1664,7 @@ // pow(10.0, x) -> exp10(x) // TODO: There is no exp10() intrinsic yet, but some day there shall be one. if (match(Base, m_SpecificFP(10.0)) && - hasFloatFn(TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) + hasFloatFn(M, TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) return copyFlags(*Pow, emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l, B, Attrs)); @@ -1681,7 +1689,8 @@ return copyFlags(*Pow, B.CreateCall(Intrinsic::getDeclaration( Mod, Intrinsic::exp2, Ty), FMul, "exp2")); - else if (hasFloatFn(TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) + else if (hasFloatFn(M, TLI, Ty, LibFunc_exp2, LibFunc_exp2f, + LibFunc_exp2l)) return copyFlags(*Pow, emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l, B, Attrs)); @@ -1702,7 +1711,8 @@ } // Otherwise, use the libcall for sqrt(). - if (hasFloatFn(TLI, V->getType(), LibFunc_sqrt, LibFunc_sqrtf, LibFunc_sqrtl)) + if (hasFloatFn(M, TLI, V->getType(), LibFunc_sqrt, LibFunc_sqrtf, + LibFunc_sqrtl)) // TODO: We also should check that the target can in fact lower the sqrt() // libcall. We currently have no way to ask this question, so we ask if // the target has a sqrt() libcall, which is not exactly the same. @@ -1892,8 +1902,8 @@ // Shrink pow() to powf() if the arguments are single precision, // unless the result is expected to be double precision. if (UnsafeFPShrink && Name == TLI->getName(LibFunc_pow) && - hasFloatVersion(Name)) { - if (Value *Shrunk = optimizeBinaryDoubleFP(Pow, B, true)) + hasFloatVersion(M, Name)) { + if (Value *Shrunk = optimizeBinaryDoubleFP(Pow, B, TLI, true)) return Shrunk; } @@ -1901,13 +1911,14 @@ } Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { + Module *M = CI->getModule(); Function *Callee = CI->getCalledFunction(); AttributeList Attrs; // Attributes are only meaningful on the original call StringRef Name = Callee->getName(); Value *Ret = nullptr; if (UnsafeFPShrink && Name == TLI->getName(LibFunc_exp2) && - hasFloatVersion(Name)) - Ret = optimizeUnaryDoubleFP(CI, B, true); + hasFloatVersion(M, Name)) + Ret = optimizeUnaryDoubleFP(CI, B, TLI, true); Type *Ty = CI->getType(); Value *Op = CI->getArgOperand(0); @@ -1915,7 +1926,7 @@ // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= IntSize // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < IntSize if ((isa(Op) || isa(Op)) && - hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { + hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { if (Value *Exp = getIntToFPVal(Op, B, TLI->getIntSize())) return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, @@ -1926,12 +1937,14 @@ } Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) { + Module *M = CI->getModule(); + // If we can shrink the call to a float function rather than a double // function, do that first. Function *Callee = CI->getCalledFunction(); StringRef Name = Callee->getName(); - if ((Name == "fmin" || Name == "fmax") && hasFloatVersion(Name)) - if (Value *Ret = optimizeBinaryDoubleFP(CI, B)) + if ((Name == "fmin" || Name == "fmax") && hasFloatVersion(M, Name)) + if (Value *Ret = optimizeBinaryDoubleFP(CI, B, TLI)) return Ret; // The LLVM intrinsics minnum/maxnum correspond to fmin/fmax. Canonicalize to @@ -1962,8 +1975,8 @@ Type *Ty = Log->getType(); Value *Ret = nullptr; - if (UnsafeFPShrink && hasFloatVersion(LogNm)) - Ret = optimizeUnaryDoubleFP(Log, B, true); + if (UnsafeFPShrink && hasFloatVersion(Mod, LogNm)) + Ret = optimizeUnaryDoubleFP(Log, B, TLI, true); // The earlier call must also be 'fast' in order to do these transforms. CallInst *Arg = dyn_cast(Log->getArgOperand(0)); @@ -2071,7 +2084,7 @@ Log->doesNotAccessMemory() ? B.CreateCall(Intrinsic::getDeclaration(Mod, LogID, Ty), Arg->getOperand(0), "log") - : emitUnaryFloatFnCall(Arg->getOperand(0), LogNm, B, Attrs); + : emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, Attrs); Value *MulY = B.CreateFMul(Arg->getArgOperand(1), LogX, "mul"); // Since pow() may have side effects, e.g. errno, // dead code elimination may not be trusted to remove it. @@ -2094,7 +2107,7 @@ Value *LogE = Log->doesNotAccessMemory() ? B.CreateCall(Intrinsic::getDeclaration(Mod, LogID, Ty), Eul, "log") - : emitUnaryFloatFnCall(Eul, LogNm, B, Attrs); + : emitUnaryFloatFnCall(Eul, TLI, LogNm, B, Attrs); Value *MulY = B.CreateFMul(Arg->getArgOperand(0), LogE, "mul"); // Since exp() may have side effects, e.g. errno, // dead code elimination may not be trusted to remove it. @@ -2106,14 +2119,16 @@ } Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilderBase &B) { + Module *M = CI->getModule(); Function *Callee = CI->getCalledFunction(); Value *Ret = nullptr; // TODO: Once we have a way (other than checking for the existince of the // libcall) to tell whether our target can lower @llvm.sqrt, relax the // condition below. - if (TLI->has(LibFunc_sqrtf) && (Callee->getName() == "sqrt" || - Callee->getIntrinsicID() == Intrinsic::sqrt)) - Ret = optimizeUnaryDoubleFP(CI, B, true); + if (isLibFuncEmittable(M, TLI, LibFunc_sqrtf) && + (Callee->getName() == "sqrt" || + Callee->getIntrinsicID() == Intrinsic::sqrt)) + Ret = optimizeUnaryDoubleFP(CI, B, TLI, true); if (!CI->isFast()) return Ret; @@ -2158,7 +2173,6 @@ // If we found a repeated factor, hoist it out of the square root and // replace it with the fabs of that factor. - Module *M = Callee->getParent(); Type *ArgType = I->getType(); Function *Fabs = Intrinsic::getDeclaration(M, Intrinsic::fabs, ArgType); Value *FabsCall = B.CreateCall(Fabs, RepeatOp, "fabs"); @@ -2175,11 +2189,12 @@ // TODO: Generalize to handle any trig function and its inverse. Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilderBase &B) { + Module *M = CI->getModule(); Function *Callee = CI->getCalledFunction(); Value *Ret = nullptr; StringRef Name = Callee->getName(); - if (UnsafeFPShrink && Name == "tan" && hasFloatVersion(Name)) - Ret = optimizeUnaryDoubleFP(CI, B, true); + if (UnsafeFPShrink && Name == "tan" && hasFloatVersion(M, Name)) + Ret = optimizeUnaryDoubleFP(CI, B, TLI, true); Value *Op1 = CI->getArgOperand(0); auto *OpC = dyn_cast(Op1); @@ -2195,7 +2210,8 @@ // tanl(atanl(x)) -> x LibFunc Func; Function *F = OpC->getCalledFunction(); - if (F && TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) && + if (F && TLI->getLibFunc(F->getName(), Func) && + isLibFuncEmittable(M, TLI, Func) && ((Func == LibFunc_atan && Callee->getName() == "tan") || (Func == LibFunc_atanf && Callee->getName() == "tanf") || (Func == LibFunc_atanl && Callee->getName() == "tanl"))) @@ -2211,9 +2227,10 @@ CI->hasFnAttr(Attribute::ReadNone); } -static void insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value *Arg, +static bool insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value *Arg, bool UseFloat, Value *&Sin, Value *&Cos, - Value *&SinCos) { + Value *&SinCos, const TargetLibraryInfo *TLI) { + Module *M = OrigCallee->getParent(); Type *ArgTy = Arg->getType(); Type *ResTy; StringRef Name; @@ -2233,9 +2250,12 @@ ResTy = StructType::get(ArgTy, ArgTy); } - Module *M = OrigCallee->getParent(); - FunctionCallee Callee = - M->getOrInsertFunction(Name, OrigCallee->getAttributes(), ResTy, ArgTy); + if (!isLibFuncEmittable(M, TLI, Name)) + return false; + LibFunc TheLibFunc; + TLI->getLibFunc(Name, TheLibFunc); + FunctionCallee Callee = getOrInsertLibFunc( + M, *TLI, TheLibFunc, OrigCallee->getAttributes(), ResTy, ArgTy); if (Instruction *ArgInst = dyn_cast(Arg)) { // If the argument is an instruction, it must dominate all uses so put our @@ -2259,6 +2279,8 @@ Cos = B.CreateExtractElement(SinCos, ConstantInt::get(B.getInt32Ty(), 1), "cospi"); } + + return true; } Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, IRBuilderBase &B) { @@ -2286,7 +2308,9 @@ return nullptr; Value *Sin, *Cos, *SinCos; - insertSinCosCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos, SinCos); + if (!insertSinCosCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos, + SinCos, TLI)) + return nullptr; auto replaceTrigInsts = [this](SmallVectorImpl &Calls, Value *Res) { @@ -2307,6 +2331,7 @@ SmallVectorImpl &CosCalls, SmallVectorImpl &SinCosCalls) { CallInst *CI = dyn_cast(Val); + Module *M = CI->getModule(); if (!CI || CI->use_empty()) return; @@ -2317,7 +2342,8 @@ Function *Callee = CI->getCalledFunction(); LibFunc Func; - if (!Callee || !TLI->getLibFunc(*Callee, Func) || !TLI->has(Func) || + if (!Callee || !TLI->getLibFunc(*Callee, Func) || + !isLibFuncEmittable(M, TLI, Func) || !isTrigLibCall(CI)) return; @@ -2532,6 +2558,7 @@ Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilderBase &B) { + Module *M = CI->getModule(); Function *Callee = CI->getCalledFunction(); FunctionType *FT = Callee->getFunctionType(); if (Value *V = optimizePrintFString(CI, B)) { @@ -2540,10 +2567,10 @@ // printf(format, ...) -> iprintf(format, ...) if no floating point // arguments. - if (TLI->has(LibFunc_iprintf) && !callHasFloatingPointArgument(CI)) { - Module *M = B.GetInsertBlock()->getParent()->getParent(); - FunctionCallee IPrintFFn = - M->getOrInsertFunction("iprintf", FT, Callee->getAttributes()); + if (isLibFuncEmittable(M, TLI, LibFunc_iprintf) && + !callHasFloatingPointArgument(CI)) { + FunctionCallee IPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_iprintf, FT, + Callee->getAttributes()); CallInst *New = cast(CI->clone()); New->setCalledFunction(IPrintFFn); B.Insert(New); @@ -2552,11 +2579,10 @@ // printf(format, ...) -> __small_printf(format, ...) if no 128-bit floating point // arguments. - if (TLI->has(LibFunc_small_printf) && !callHasFP128Argument(CI)) { - Module *M = B.GetInsertBlock()->getParent()->getParent(); - auto SmallPrintFFn = - M->getOrInsertFunction(TLI->getName(LibFunc_small_printf), - FT, Callee->getAttributes()); + if (isLibFuncEmittable(M, TLI, LibFunc_small_printf) && + !callHasFP128Argument(CI)) { + auto SmallPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_small_printf, FT, + Callee->getAttributes()); CallInst *New = cast(CI->clone()); New->setCalledFunction(SmallPrintFFn); B.Insert(New); @@ -2655,6 +2681,7 @@ } Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilderBase &B) { + Module *M = CI->getModule(); Function *Callee = CI->getCalledFunction(); FunctionType *FT = Callee->getFunctionType(); if (Value *V = optimizeSPrintFString(CI, B)) { @@ -2663,10 +2690,10 @@ // sprintf(str, format, ...) -> siprintf(str, format, ...) if no floating // point arguments. - if (TLI->has(LibFunc_siprintf) && !callHasFloatingPointArgument(CI)) { - Module *M = B.GetInsertBlock()->getParent()->getParent(); - FunctionCallee SIPrintFFn = - M->getOrInsertFunction("siprintf", FT, Callee->getAttributes()); + if (isLibFuncEmittable(M, TLI, LibFunc_siprintf) && + !callHasFloatingPointArgument(CI)) { + FunctionCallee SIPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_siprintf, + FT, Callee->getAttributes()); CallInst *New = cast(CI->clone()); New->setCalledFunction(SIPrintFFn); B.Insert(New); @@ -2675,11 +2702,10 @@ // sprintf(str, format, ...) -> __small_sprintf(str, format, ...) if no 128-bit // floating point arguments. - if (TLI->has(LibFunc_small_sprintf) && !callHasFP128Argument(CI)) { - Module *M = B.GetInsertBlock()->getParent()->getParent(); - auto SmallSPrintFFn = - M->getOrInsertFunction(TLI->getName(LibFunc_small_sprintf), - FT, Callee->getAttributes()); + if (isLibFuncEmittable(M, TLI, LibFunc_small_sprintf) && + !callHasFP128Argument(CI)) { + auto SmallSPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_small_sprintf, FT, + Callee->getAttributes()); CallInst *New = cast(CI->clone()); New->setCalledFunction(SmallSPrintFFn); B.Insert(New); @@ -2835,6 +2861,7 @@ } Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilderBase &B) { + Module *M = CI->getModule(); Function *Callee = CI->getCalledFunction(); FunctionType *FT = Callee->getFunctionType(); if (Value *V = optimizeFPrintFString(CI, B)) { @@ -2843,10 +2870,10 @@ // fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if no // floating point arguments. - if (TLI->has(LibFunc_fiprintf) && !callHasFloatingPointArgument(CI)) { - Module *M = B.GetInsertBlock()->getParent()->getParent(); - FunctionCallee FIPrintFFn = - M->getOrInsertFunction("fiprintf", FT, Callee->getAttributes()); + if (isLibFuncEmittable(M, TLI, LibFunc_fiprintf) && + !callHasFloatingPointArgument(CI)) { + FunctionCallee FIPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_fiprintf, + FT, Callee->getAttributes()); CallInst *New = cast(CI->clone()); New->setCalledFunction(FIPrintFFn); B.Insert(New); @@ -2855,11 +2882,11 @@ // fprintf(stream, format, ...) -> __small_fprintf(stream, format, ...) if no // 128-bit floating point arguments. - if (TLI->has(LibFunc_small_fprintf) && !callHasFP128Argument(CI)) { - Module *M = B.GetInsertBlock()->getParent()->getParent(); + if (isLibFuncEmittable(M, TLI, LibFunc_small_fprintf) && + !callHasFP128Argument(CI)) { auto SmallFPrintFFn = - M->getOrInsertFunction(TLI->getName(LibFunc_small_fprintf), - FT, Callee->getAttributes()); + getOrInsertLibFunc(M, *TLI, LibFunc_small_fprintf, FT, + Callee->getAttributes()); CallInst *New = cast(CI->clone()); New->setCalledFunction(SmallFPrintFFn); B.Insert(New); @@ -2944,21 +2971,19 @@ CI->getArgOperand(2))); } -bool LibCallSimplifier::hasFloatVersion(StringRef FuncName) { - LibFunc Func; +bool LibCallSimplifier::hasFloatVersion(const Module *M, StringRef FuncName) { SmallString<20> FloatFuncName = FuncName; FloatFuncName += 'f'; - if (TLI->getLibFunc(FloatFuncName, Func)) - return TLI->has(Func); - return false; + return isLibFuncEmittable(M, TLI, FloatFuncName); } Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI, IRBuilderBase &Builder) { + Module *M = CI->getModule(); LibFunc Func; Function *Callee = CI->getCalledFunction(); // Check for string/memory library functions. - if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) { + if (TLI->getLibFunc(*Callee, Func) && isLibFuncEmittable(M, TLI, Func)) { // Make sure we never change the calling convention. assert( (ignoreCallingConv(Func) || @@ -3039,6 +3064,8 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI, LibFunc Func, IRBuilderBase &Builder) { + const Module *M = CI->getModule(); + // Don't optimize calls that require strict floating point semantics. if (CI->isStrictFP()) return nullptr; @@ -3117,12 +3144,12 @@ case LibFunc_sin: case LibFunc_sinh: case LibFunc_tanh: - if (UnsafeFPShrink && hasFloatVersion(CI->getCalledFunction()->getName())) - return optimizeUnaryDoubleFP(CI, Builder, true); + if (UnsafeFPShrink && hasFloatVersion(M, CI->getCalledFunction()->getName())) + return optimizeUnaryDoubleFP(CI, Builder, TLI, true); return nullptr; case LibFunc_copysign: - if (hasFloatVersion(CI->getCalledFunction()->getName())) - return optimizeBinaryDoubleFP(CI, Builder); + if (hasFloatVersion(M, CI->getCalledFunction()->getName())) + return optimizeBinaryDoubleFP(CI, Builder, TLI); return nullptr; case LibFunc_fminf: case LibFunc_fmin: @@ -3141,6 +3168,7 @@ } Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) { + Module *M = CI->getModule(); assert(!CI->isMustTailCall() && "These transforms aren't musttail safe."); // TODO: Split out the code below that operates on FP calls so that @@ -3219,7 +3247,7 @@ } // Then check for known library functions. - if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) { + if (TLI->getLibFunc(*Callee, Func) && isLibFuncEmittable(M, TLI, Func)) { // We never change the calling convention. if (!ignoreCallingConv(Func) && !IsCallingConvC) return nullptr; diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll --- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -3,7 +3,6 @@ ; RUN: opt < %s -mtriple=x86_64-apple-macosx10.8.0 -inferattrs -S | FileCheck --match-full-lines --check-prefixes=CHECK,CHECK-KNOWN,CHECK-NOLINUX,CHECK-OPEN,CHECK-DARWIN %s ; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -inferattrs -S | FileCheck --match-full-lines --check-prefixes=CHECK,CHECK-KNOWN,CHECK-LINUX %s ; RUN: opt < %s -mtriple=nvptx -inferattrs -S | FileCheck --match-full-lines --check-prefixes=CHECK-NOLINUX,CHECK-NVPTX %s -; RUN: opt < %s -mtriple=s390x-linux-gnu -inferattrs -S | FileCheck --check-prefixes=CHECK-SYSTEMZ %s declare i32 @__nvvm_reflect(i8*) ; CHECK-NVPTX: declare noundef i32 @__nvvm_reflect(i8* noundef) [[NOFREE_NOUNWIND_READNONE:#[0-9]+]] @@ -592,11 +591,9 @@ declare i32 @lchown(i8*, i32, i32) ; CHECK: declare double @ldexp(double, i32) [[NOFREE_WILLRETURN:#[0-9]+]] -; CHECK-SYSTEMZ: declare double @ldexp(double, i32 signext) declare double @ldexp(double, i32) ; CHECK: declare float @ldexpf(float, i32) [[NOFREE_WILLRETURN]] -; CHECK-SYSTEMZ: declare float @ldexpf(float, i32 signext) declare float @ldexpf(float, i32) ; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32) [[NOFREE_WILLRETURN]] @@ -756,12 +753,10 @@ declare i32 @putc(i32, %opaque*) ; CHECK: declare noundef i32 @putchar(i32 noundef) [[NOFREE_NOUNWIND]] -; CHECK-SYSTEMZ: declare noundef i32 @putchar(i32 noundef signext) declare i32 @putchar(i32) ; CHECK-KNOWN: declare noundef i32 @putchar_unlocked(i32 noundef) [[NOFREE_NOUNWIND]] ; CHECK-UNKNOWN: declare i32 @putchar_unlocked(i32){{$}} -; CHECK-SYSTEMZ: declare noundef i32 @putchar_unlocked(i32 noundef signext) declare i32 @putchar_unlocked(i32) ; CHECK: declare noundef i32 @puts(i8* nocapture noundef readonly) [[NOFREE_NOUNWIND]] diff --git a/llvm/test/Transforms/InstCombine/SystemZ/libcall-arg-exts.ll b/llvm/test/Transforms/InstCombine/SystemZ/libcall-arg-exts.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/SystemZ/libcall-arg-exts.ll @@ -0,0 +1,98 @@ +; RUN: opt < %s -passes=instcombine -S -mtriple=systemz-unknown | FileCheck %s +; +; Check that i32 arguments to generated libcalls have the proper extension +; attributes. + + +declare double @exp2(double) +declare float @exp2f(float) +declare fp128 @exp2l(fp128) + +define double @fun1(i32 %x) { +; CHECK-LABEL: @fun1 +; CHECK: call double @ldexp + %conv = sitofp i32 %x to double + %ret = call double @exp2(double %conv) + ret double %ret +} + +define float @fun2(i32 %x) { +; CHECK-LABEL: @fun2 +; CHECK: call float @ldexpf + %conv = sitofp i32 %x to float + %ret = call float @exp2f(float %conv) + ret float %ret +} + +define fp128 @fun3(i8 zeroext %x) { +; CHECK-LABEL: @fun3 +; CHECK: call fp128 @ldexpl + %conv = uitofp i8 %x to fp128 + %ret = call fp128 @exp2l(fp128 %conv) + ret fp128 %ret +} + +@a = common global [60 x i8] zeroinitializer, align 1 +@b = common global [60 x i8] zeroinitializer, align 1 +declare i8* @__memccpy_chk(i8*, i8*, i32, i64, i64) +define i8* @fun4() { +; CHECK-LABEL: @fun4 +; CHECK: call i8* @memccpy + %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 + %ret = call i8* @__memccpy_chk(i8* %dst, i8* %src, i32 0, i64 60, i64 -1) + ret i8* %ret +} + +%FILE = type { } +@A = constant [2 x i8] c"A\00" +declare i32 @fputs(i8*, %FILE*) +define void @fun5(%FILE* %fp) { +; CHECK-LABEL: @fun5 +; CHECK: call i32 @fputc + %str = getelementptr [2 x i8], [2 x i8]* @A, i32 0, i32 0 + call i32 @fputs(i8* %str, %FILE* %fp) + ret void +} + +@empty = constant [1 x i8] zeroinitializer +declare i32 @puts(i8*) +define void @fun6() { +; CHECK-LABEL: @fun6 +; CHECK: call i32 @putchar + %str = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0 + call i32 @puts(i8* %str) + ret void +} + +@.str1 = private constant [2 x i8] c"a\00" +declare i8* @strstr(i8*, i8*) +define i8* @fun7(i8* %str) { +; CHECK-LABEL: @fun7 +; CHECK: call i8* @strchr + %pat = getelementptr inbounds [2 x i8], [2 x i8]* @.str1, i32 0, i32 0 + %ret = call i8* @strstr(i8* %str, i8* %pat) + ret i8* %ret +} + +; CHECK: declare i8* @strchr(i8*, i32 signext) + +@hello = constant [14 x i8] c"hello world\5Cn\00" +@chp = global i8* zeroinitializer +declare i8* @strchr(i8*, i32) +define void @fun8(i32 %chr) { +; CHECK-LABEL: @fun8 +; CHECK: call i8* @memchr + %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8* @strchr(i8* %src, i32 %chr) + store i8* %dst, i8** @chp + ret void +} + +; CHECK: declare double @ldexp(double, i32 signext) +; CHECK: declare float @ldexpf(float, i32 signext) +; CHECK: declare fp128 @ldexpl(fp128, i32 signext) +; CHECK: declare i8* @memccpy(i8* noalias writeonly, i8* noalias nocapture readonly, i32 signext, i64) +; CHECK: declare noundef i32 @fputc(i32 noundef signext, %FILE* nocapture noundef) +; CHECK: declare noundef i32 @putchar(i32 noundef signext) +; CHECK: declare i8* @memchr(i8*, i32 signext, i64) diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll --- a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll +++ b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll @@ -346,7 +346,7 @@ ; LINUX-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) ; LINUX-NEXT: ret float [[LOGBF]] ; MS32: [[POWF:%.*]] = call fast double @logb(double [[F:%.*]]) -; MS64-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) +; MS64-NEXT: [[LOGBF:%.*]] = call fast float @_logbf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @logb(double %conv) diff --git a/llvm/test/Transforms/InstCombine/pr39177.ll b/llvm/test/Transforms/InstCombine/pr39177.ll --- a/llvm/test/Transforms/InstCombine/pr39177.ll +++ b/llvm/test/Transforms/InstCombine/pr39177.ll @@ -1,5 +1,7 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s +; +; Check that SimplifyLibCalls do not (crash or) emit a library call if user +; has made a function alias with the same name. %struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] } %struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 } @@ -28,10 +30,8 @@ define void @foo() { ; CHECK-LABEL: @foo( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load %struct._IO_FILE*, %struct._IO_FILE** @stderr, align 8 -; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fwrite(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i64 7, i64 1, %struct._IO_FILE* [[TMP0]]) -; CHECK-NEXT: ret void +; CHECK-NOT: call i64 @fwrite( +; CHECK: call {{.*}} @fprintf( ; entry: %retval = alloca i32, align 4 diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll --- a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll +++ b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll @@ -242,5 +242,18 @@ ret i4 0 } +; Test emission of stpncpy. +@a = dso_local global [4 x i8] c"123\00" +@b = dso_local global [5 x i8] zeroinitializer +declare i8* @__stpncpy_chk(i8* noundef, i8* noundef, i32 noundef, i32 noundef) +define signext i32 @emit_stpncpy() { +; CHECK-LABEL: @emit_stpncpy( +; CHECK-NEXT: call i8* @stpncpy({{.*}} @b, {{.*}} @a, {{.*}} i32 2) + %call = call i8* @__stpncpy_chk(i8* noundef getelementptr inbounds ([5 x i8], [5 x i8]* @b, i32 0, i32 0), + i8* noundef getelementptr inbounds ([4 x i8], [4 x i8]* @a, i32 0, i32 0), + i32 noundef 2, i32 noundef 5) + ret i32 0 +} + attributes #0 = { nobuiltin } attributes #1 = { builtin }