summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorDavide Italiano <davide@freebsd.org>2015-11-03 20:32:23 +0000
committerDavide Italiano <davide@freebsd.org>2015-11-03 20:32:23 +0000
commitc8a7913f23460112182b5216fa2cde084886cad4 (patch)
tree185f7290a7891906d1949db19f21cd2105f57683 /llvm/lib
parente88dc04c4854124c6cf4c2d0fc554029ea190846 (diff)
downloadbcm5719-llvm-c8a7913f23460112182b5216fa2cde084886cad4.tar.gz
bcm5719-llvm-c8a7913f23460112182b5216fa2cde084886cad4.zip
[SimplifyLibCalls] Add a new transformation: pow(exp(x), y) -> exp(x*y)
This one is enabled only under -ffast-math (due to rounding/overflows) but allows us to emit shorter code. Before (on FreeBSD x86-64): 4007f0: 50 push %rax 4007f1: f2 0f 11 0c 24 movsd %xmm1,(%rsp) 4007f6: e8 75 fd ff ff callq 400570 <exp2@plt> 4007fb: f2 0f 10 0c 24 movsd (%rsp),%xmm1 400800: 58 pop %rax 400801: e9 7a fd ff ff jmpq 400580 <pow@plt> 400806: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 40080d: 00 00 00 After: 4007b0: f2 0f 59 c1 mulsd %xmm1,%xmm0 4007b4: e9 87 fd ff ff jmpq 400540 <exp2@plt> 4007b9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) Differential Revision: http://reviews.llvm.org/D14045 llvm-svn: 251976
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp26
1 files changed, 26 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 9fabf5de7f4..14a0a57ce30 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -1103,6 +1103,32 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) {
Callee->getAttributes());
}
+ // pow(exp(x), y) -> exp(x*y)
+ // pow(exp2(x), y) -> exp2(x * y)
+ // We enable these only under fast-math. Besides rounding
+ // differences the transformation changes overflow and
+ // underflow behavior quite dramatically.
+ // Example: x = 1000, y = 0.001.
+ // pow(exp(x), y) = pow(inf, 0.001) = inf, whereas exp(x*y) = exp(1).
+ if (canUseUnsafeFPMath(CI->getParent()->getParent())) {
+ if (auto *OpC = dyn_cast<CallInst>(Op1)) {
+ IRBuilder<>::FastMathFlagGuard Guard(B);
+ FastMathFlags FMF;
+ FMF.setUnsafeAlgebra();
+ B.SetFastMathFlags(FMF);
+
+ LibFunc::Func Func;
+ Function *Callee = OpC->getCalledFunction();
+ StringRef FuncName = Callee->getName();
+
+ if (TLI->getLibFunc(FuncName, Func) && TLI->has(Func) &&
+ (Func == LibFunc::exp || Func == LibFunc::exp2))
+ return EmitUnaryFloatFnCall(
+ B.CreateFMul(OpC->getArgOperand(0), Op2, "mul"), FuncName, B,
+ Callee->getAttributes());
+ }
+ }
+
ConstantFP *Op2C = dyn_cast<ConstantFP>(Op2);
if (!Op2C)
return Ret;
OpenPOWER on IntegriCloud