mirror of
https://github.com/RPCSX/llvm.git
synced 2025-03-01 01:15:55 +00:00
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251976 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
91c642526e
commit
1b506d8aa4
@ -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;
|
||||
|
17
test/Transforms/InstCombine/pow-exp-nofastmath.ll
Normal file
17
test/Transforms/InstCombine/pow-exp-nofastmath.ll
Normal file
@ -0,0 +1,17 @@
|
||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
|
||||
define double @mypow(double %x, double %y) #0 {
|
||||
entry:
|
||||
%call = call double @exp(double %x)
|
||||
%pow = call double @llvm.pow.f64(double %call, double %y)
|
||||
ret double %pow
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define double @mypow(
|
||||
; CHECK: %call = call double @exp(double %x)
|
||||
; CHECK: %pow = call double @llvm.pow.f64(double %call, double %y)
|
||||
; CHECK: ret double %pow
|
||||
; CHECK: }
|
||||
|
||||
declare double @exp(double) #1
|
||||
declare double @llvm.pow.f64(double, double)
|
19
test/Transforms/InstCombine/pow-exp.ll
Normal file
19
test/Transforms/InstCombine/pow-exp.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
|
||||
define double @mypow(double %x, double %y) #0 {
|
||||
entry:
|
||||
%call = call double @exp(double %x)
|
||||
%pow = call double @llvm.pow.f64(double %call, double %y)
|
||||
ret double %pow
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define double @mypow(
|
||||
; CHECK: %mul = fmul fast double %x, %y
|
||||
; CHECK: %exp = call double @exp(double %mul) #0
|
||||
; CHECK: ret double %exp
|
||||
; CHECK: }
|
||||
|
||||
declare double @exp(double) #1
|
||||
declare double @llvm.pow.f64(double, double)
|
||||
attributes #0 = { "unsafe-fp-math"="true" }
|
||||
attributes #1 = { "unsafe-fp-math"="true" }
|
19
test/Transforms/InstCombine/pow-exp2.ll
Normal file
19
test/Transforms/InstCombine/pow-exp2.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
|
||||
define double @mypow(double %x, double %y) #0 {
|
||||
entry:
|
||||
%call = call double @exp2(double %x)
|
||||
%pow = call double @llvm.pow.f64(double %call, double %y)
|
||||
ret double %pow
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define double @mypow(
|
||||
; CHECK: %mul = fmul fast double %x, %y
|
||||
; CHECK: %exp2 = call double @exp2(double %mul) #0
|
||||
; CHECK: ret double %exp2
|
||||
; CHECK: }
|
||||
|
||||
declare double @exp2(double) #1
|
||||
declare double @llvm.pow.f64(double, double)
|
||||
attributes #0 = { "unsafe-fp-math"="true" }
|
||||
attributes #1 = { "unsafe-fp-math"="true" }
|
Loading…
x
Reference in New Issue
Block a user