mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
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
4a88cf2c20
commit
925deed9df
@ -37,6 +37,12 @@ namespace llvm {
|
|||||||
LibFunc DoubleFn, LibFunc FloatFn,
|
LibFunc DoubleFn, LibFunc FloatFn,
|
||||||
LibFunc LongDoubleFn);
|
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*.
|
/// Return V if it is an i8*, otherwise cast it to i8*.
|
||||||
Value *castToCStr(Value *V, IRBuilder<> &B);
|
Value *castToCStr(Value *V, IRBuilder<> &B);
|
||||||
|
|
||||||
@ -94,6 +100,13 @@ namespace llvm {
|
|||||||
Value *emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
|
Value *emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
|
||||||
const AttributeList &Attrs);
|
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
|
/// 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
|
/// 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
|
/// 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);
|
IRBuilder<>::FastMathFlagGuard FMFGuard(B);
|
||||||
B.setFastMathFlags(I.getFastMathFlags());
|
B.setFastMathFlags(I.getFastMathFlags());
|
||||||
AttributeList Attrs = CallSite(Op0).getCalledFunction()->getAttributes();
|
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)
|
if (IsCot)
|
||||||
Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res);
|
Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res);
|
||||||
return replaceInstUsesWith(I, 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 ------------------------------------------------------------//
|
//- Emit LibCalls ------------------------------------------------------------//
|
||||||
|
|
||||||
Value *llvm::castToCStr(Value *V, IRBuilder<> &B) {
|
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,
|
static Value *emitUnaryFloatFnCallHelper(Value *Op, StringRef Name,
|
||||||
const AttributeList &Attrs) {
|
IRBuilder<> &B,
|
||||||
SmallString<20> NameBuffer;
|
const AttributeList &Attrs) {
|
||||||
appendTypeSuffix(Op, Name, NameBuffer);
|
assert((Name != "") && "Must specify Name to emitUnaryFloatFnCall");
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getModule();
|
Module *M = B.GetInsertBlock()->getModule();
|
||||||
Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
|
Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
|
||||||
@ -964,8 +982,29 @@ Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
|
|||||||
return CI;
|
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,
|
Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
|
||||||
IRBuilder<> &B, const AttributeList &Attrs) {
|
IRBuilder<> &B, const AttributeList &Attrs) {
|
||||||
|
assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall");
|
||||||
|
|
||||||
SmallString<20> NameBuffer;
|
SmallString<20> NameBuffer;
|
||||||
appendTypeSuffix(Op1, Name, NameBuffer);
|
appendTypeSuffix(Op1, Name, NameBuffer);
|
||||||
|
|
||||||
|
@ -1219,17 +1219,26 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) {
|
|||||||
StringRef ExpName;
|
StringRef ExpName;
|
||||||
Intrinsic::ID ID;
|
Intrinsic::ID ID;
|
||||||
Value *ExpFn;
|
Value *ExpFn;
|
||||||
|
LibFunc LibFnFloat;
|
||||||
|
LibFunc LibFnDouble;
|
||||||
|
LibFunc LibFnLongDouble;
|
||||||
|
|
||||||
switch (LibFn) {
|
switch (LibFn) {
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case LibFunc_expf: case LibFunc_exp: case LibFunc_expl:
|
case LibFunc_expf: case LibFunc_exp: case LibFunc_expl:
|
||||||
ExpName = TLI->getName(LibFunc_exp);
|
ExpName = "exp";
|
||||||
ID = Intrinsic::exp;
|
ID = Intrinsic::exp;
|
||||||
|
LibFnFloat = LibFunc_expf;
|
||||||
|
LibFnDouble = LibFunc_exp;
|
||||||
|
LibFnLongDouble = LibFunc_expl;
|
||||||
break;
|
break;
|
||||||
case LibFunc_exp2f: case LibFunc_exp2: case LibFunc_exp2l:
|
case LibFunc_exp2f: case LibFunc_exp2: case LibFunc_exp2l:
|
||||||
ExpName = TLI->getName(LibFunc_exp2);
|
ExpName = "exp2";
|
||||||
ID = Intrinsic::exp2;
|
ID = Intrinsic::exp2;
|
||||||
|
LibFnFloat = LibFunc_exp2f;
|
||||||
|
LibFnDouble = LibFunc_exp2;
|
||||||
|
LibFnLongDouble = LibFunc_exp2l;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1238,7 +1247,9 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) {
|
|||||||
ExpFn = BaseFn->doesNotAccessMemory()
|
ExpFn = BaseFn->doesNotAccessMemory()
|
||||||
? B.CreateCall(Intrinsic::getDeclaration(Mod, ID, Ty),
|
? B.CreateCall(Intrinsic::getDeclaration(Mod, ID, Ty),
|
||||||
FMul, ExpName)
|
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
|
// 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
|
// 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),
|
return B.CreateCall(Intrinsic::getDeclaration(Mod, Intrinsic::exp2, Ty),
|
||||||
FMul, "exp2");
|
FMul, "exp2");
|
||||||
else
|
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.
|
// TODO: There is no exp10() intrinsic yet, but some day there shall be one.
|
||||||
if (match(Base, m_SpecificFP(10.0)) &&
|
if (match(Base, m_SpecificFP(10.0)) &&
|
||||||
hasUnaryFloatFn(TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l))
|
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;
|
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()
|
// 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
|
// 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.
|
// 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user