forked from OSchip/llvm-project
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
This commit is contained in:
parent
fa41add2e5
commit
e3605d0f70
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue