From e3605d0f7038e5dab1994282a77831a9b4a72c4c Mon Sep 17 00:00:00 2001 From: Mikael Holmen Date: Thu, 18 Oct 2018 06:27:53 +0000 Subject: [PATCH] Add a emitUnaryFloatFnCall version that fetches the function name from TLI Summary: In several places in the code we use the following pattern: if (hasUnaryFloatFn(&TLI, Ty, LibFunc_tan, LibFunc_tanf, LibFunc_tanl)) { [...] Value *Res = emitUnaryFloatFnCall(X, TLI.getName(LibFunc_tan), B, Attrs); [...] } In short, we check if there is a lib-function for a certain type, and then we _always_ fetch the name of the "double" version of the lib function and construct a call to the appropriate function, that we just checked exists, using that "double" name as a basis. This is of course a problem in cases where the target doesn't support the "double" version, but e.g. only the "float" version. In that case TLI.getName(LibFunc_tan) returns "", and emitUnaryFloatFnCall happily appends an "f" to "", and we erroneously end up with a call to a function called "f". To solve this, the above pattern is changed to if (hasUnaryFloatFn(&TLI, Ty, LibFunc_tan, LibFunc_tanf, LibFunc_tanl)) { [...] Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf, LibFunc_tanl, B, Attrs); [...] } I.e instead of first fetching the name of the "double" version and then letting emitUnaryFloatFnCall() add the final "f" or "l", we let emitUnaryFloatFnCall() fetch the right name from TLI. Reviewers: eli.friedman, efriedma Reviewed By: efriedma Subscribers: efriedma, bjope, llvm-commits Differential Revision: https://reviews.llvm.org/D53370 llvm-svn: 344725 --- llvm/include/llvm/Transforms/Utils/BuildLibCalls.h | 13 ++++++ .../InstCombine/InstCombineMulDivRem.cpp | 3 +- llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 47 ++++++++++++++++++++-- llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 26 +++++++++--- 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h index eafe07f..28efce6 100644 --- a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -37,6 +37,12 @@ namespace llvm { LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn); + /// Get the name of the overloaded unary floating point function + /// corresponding to \a Ty. + StringRef getUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty, + LibFunc DoubleFn, LibFunc FloatFn, + LibFunc LongDoubleFn); + /// Return V if it is an i8*, otherwise cast it to i8*. Value *castToCStr(Value *V, IRBuilder<> &B); @@ -94,6 +100,13 @@ namespace llvm { Value *emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, const AttributeList &Attrs); + /// Emit a call to the unary function DoubleFn, FloatFn or LongDoubleFn, + /// depending of the type of Op. + Value *emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI, + LibFunc DoubleFn, LibFunc FloatFn, + LibFunc LongDoubleFn, IRBuilder<> &B, + const AttributeList &Attrs); + /// Emit a call to the binary function named 'Name' (e.g. 'fmin'). This /// 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 diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 6427c81..c348aec 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1157,7 +1157,8 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { IRBuilder<>::FastMathFlagGuard FMFGuard(B); B.setFastMathFlags(I.getFastMathFlags()); AttributeList Attrs = CallSite(Op0).getCalledFunction()->getAttributes(); - Value *Res = emitUnaryFloatFnCall(X, TLI.getName(LibFunc_tan), B, Attrs); + Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf, + LibFunc_tanl, B, Attrs); if (IsCot) Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res); return replaceInstUsesWith(I, Res); diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index 06d197b..3466ded 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -765,6 +765,24 @@ bool llvm::hasUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty, } } +StringRef llvm::getUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty, + LibFunc DoubleFn, LibFunc FloatFn, + LibFunc LongDoubleFn) { + assert(hasUnaryFloatFn(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: + return TLI->getName(FloatFn); + case Type::DoubleTyID: + return TLI->getName(DoubleFn); + default: + return TLI->getName(LongDoubleFn); + } +} + //- Emit LibCalls ------------------------------------------------------------// Value *llvm::castToCStr(Value *V, IRBuilder<> &B) { @@ -942,10 +960,10 @@ static void appendTypeSuffix(Value *Op, StringRef &Name, } } -Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, - const AttributeList &Attrs) { - SmallString<20> NameBuffer; - appendTypeSuffix(Op, Name, NameBuffer); +static Value *emitUnaryFloatFnCallHelper(Value *Op, StringRef Name, + IRBuilder<> &B, + const AttributeList &Attrs) { + assert((Name != "") && "Must specify Name to emitUnaryFloatFnCall"); Module *M = B.GetInsertBlock()->getModule(); Value *Callee = M->getOrInsertFunction(Name, Op->getType(), @@ -964,8 +982,29 @@ Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, return CI; } +Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, + const AttributeList &Attrs) { + SmallString<20> NameBuffer; + appendTypeSuffix(Op, Name, NameBuffer); + + return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs); +} + +Value *llvm::emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI, + LibFunc DoubleFn, LibFunc FloatFn, + LibFunc LongDoubleFn, IRBuilder<> &B, + const AttributeList &Attrs) { + // Get the name of the function according to TLI. + StringRef Name = getUnaryFloatFn(TLI, Op->getType(), + DoubleFn, FloatFn, LongDoubleFn); + + return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs); +} + Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name, IRBuilder<> &B, const AttributeList &Attrs) { + assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall"); + SmallString<20> NameBuffer; appendTypeSuffix(Op1, Name, NameBuffer); diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 41a495a..63229bf 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1219,17 +1219,26 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) { StringRef ExpName; Intrinsic::ID ID; Value *ExpFn; + LibFunc LibFnFloat; + LibFunc LibFnDouble; + LibFunc LibFnLongDouble; switch (LibFn) { default: return nullptr; case LibFunc_expf: case LibFunc_exp: case LibFunc_expl: - ExpName = TLI->getName(LibFunc_exp); + ExpName = "exp"; ID = Intrinsic::exp; + LibFnFloat = LibFunc_expf; + LibFnDouble = LibFunc_exp; + LibFnLongDouble = LibFunc_expl; break; case LibFunc_exp2f: case LibFunc_exp2: case LibFunc_exp2l: - ExpName = TLI->getName(LibFunc_exp2); + ExpName = "exp2"; ID = Intrinsic::exp2; + LibFnFloat = LibFunc_exp2f; + LibFnDouble = LibFunc_exp2; + LibFnLongDouble = LibFunc_exp2l; break; } @@ -1238,7 +1247,9 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) { ExpFn = BaseFn->doesNotAccessMemory() ? B.CreateCall(Intrinsic::getDeclaration(Mod, ID, Ty), FMul, ExpName) - : emitUnaryFloatFnCall(FMul, ExpName, B, BaseFn->getAttributes()); + : emitUnaryFloatFnCall(FMul, TLI, LibFnDouble, LibFnFloat, + LibFnLongDouble, B, + BaseFn->getAttributes()); // Since the new exp{,2}() is different from the original one, dead code // elimination cannot be trusted to remove it, since it may have side @@ -1275,7 +1286,8 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) { return B.CreateCall(Intrinsic::getDeclaration(Mod, Intrinsic::exp2, Ty), FMul, "exp2"); else - return emitUnaryFloatFnCall(FMul, TLI->getName(LibFunc_exp2), B, Attrs); + return emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f, + LibFunc_exp2l, B, Attrs); } } @@ -1283,7 +1295,8 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) { // TODO: There is no exp10() intrinsic yet, but some day there shall be one. if (match(Base, m_SpecificFP(10.0)) && hasUnaryFloatFn(TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) - return emitUnaryFloatFnCall(Expo, TLI->getName(LibFunc_exp10), B, Attrs); + return emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10, LibFunc_exp10f, + LibFunc_exp10l, B, Attrs); return nullptr; } @@ -1304,7 +1317,8 @@ static Value *getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno, // 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. - return emitUnaryFloatFnCall(V, TLI->getName(LibFunc_sqrt), B, Attrs); + return emitUnaryFloatFnCall(V, TLI, LibFunc_sqrt, LibFunc_sqrtf, + LibFunc_sqrtl, B, Attrs); return nullptr; } -- 2.7.4