diff options
author | Davide Italiano <davide@freebsd.org> | 2015-11-04 23:36:56 +0000 |
---|---|---|
committer | Davide Italiano <davide@freebsd.org> | 2015-11-04 23:36:56 +0000 |
commit | 51507d2ad84683daa77d202141d0a63ff94ae9d6 (patch) | |
tree | 799c6d45abf918129bbe43185c05850c8f91e0fa /llvm/lib/Transforms | |
parent | e692621a9dc6eff696939a552fe7aa1fed4300ad (diff) | |
download | bcm5719-llvm-51507d2ad84683daa77d202141d0a63ff94ae9d6.tar.gz bcm5719-llvm-51507d2ad84683daa77d202141d0a63ff94ae9d6.zip |
[SimplifyLibCalls] New transformation: tan(atan(x)) -> x
This is enabled only under -ffast-math.
So, instead of emitting:
4007b0: 50 push %rax
4007b1: e8 8a fd ff ff callq 400540 <atanf@plt>
4007b6: 58 pop %rax
4007b7: e9 94 fd ff ff jmpq 400550 <tanf@plt>
4007bc: 0f 1f 40 00 nopl 0x0(%rax)
for:
float mytan(float x) {
return tanf(atanf(x));
}
we emit a single retq.
Differential Revision: http://reviews.llvm.org/D14302
llvm-svn: 252098
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 14a0a57ce30..6e9eacc4d2a 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1359,6 +1359,40 @@ Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) { return Ret; } +Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilder<> &B) { + Function *Callee = CI->getCalledFunction(); + Value *Ret = nullptr; + if (UnsafeFPShrink && Callee->getName() == "tan" && TLI->has(LibFunc::tanf)) + Ret = optimizeUnaryDoubleFP(CI, B, true); + FunctionType *FT = Callee->getFunctionType(); + + // Just make sure this has 1 argument of FP type, which matches the + // result type. + if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) || + !FT->getParamType(0)->isFloatingPointTy()) + return Ret; + + if (!canUseUnsafeFPMath(CI->getParent()->getParent())) + return Ret; + Value *Op1 = CI->getArgOperand(0); + auto *OpC = dyn_cast<CallInst>(Op1); + if (!OpC) + return Ret; + + // tan(atan(x)) -> x + // tanf(atanf(x)) -> x + // tanl(atanl(x)) -> x + LibFunc::Func Func; + Function *F = OpC->getCalledFunction(); + StringRef FuncName = F->getName(); + if (TLI->getLibFunc(FuncName, Func) && TLI->has(Func) && + ((Func == LibFunc::atan && Callee->getName() == "tan") || + (Func == LibFunc::atanf && Callee->getName() == "tanf") || + (Func == LibFunc::atanl && Callee->getName() == "tanl"))) + Ret = OpC->getArgOperand(0); + return Ret; +} + static bool isTrigLibCall(CallInst *CI); static void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value *Arg, bool UseFloat, Value *&Sin, Value *&Cos, @@ -2146,6 +2180,10 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) { return optimizeFPuts(CI, Builder); case LibFunc::puts: return optimizePuts(CI, Builder); + case LibFunc::tan: + case LibFunc::tanf: + case LibFunc::tanl: + return optimizeTan(CI, Builder); case LibFunc::perror: return optimizeErrorReporting(CI, Builder); case LibFunc::vfprintf: @@ -2180,7 +2218,6 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) { case LibFunc::logb: case LibFunc::sin: case LibFunc::sinh: - case LibFunc::tan: case LibFunc::tanh: if (UnsafeFPShrink && hasFloatVersion(FuncName)) return optimizeUnaryDoubleFP(CI, Builder, true); |