forked from OSchip/llvm-project
[SimplifyLibCalls] Tranform log(pow(x, y)) -> y*log(x).
This one is enabled only under -ffast-math. There are cases where the difference between the value computed and the correct value is huge even for ffast-math, e.g. as Steven pointed out: x = -1, y = -4 log(pow(-1), 4) = 0 4*log(-1) = NaN I checked what GCC does and apparently they do the same optimization (which result in the dramatic difference). Future work might try to make this (slightly) less worse. Differential Revision: http://reviews.llvm.org/D14400 llvm-svn: 254263
This commit is contained in:
parent
a5c0493ddb
commit
b8b7133c94
|
@ -132,6 +132,7 @@ private:
|
||||||
Value *optimizeExp2(CallInst *CI, IRBuilder<> &B);
|
Value *optimizeExp2(CallInst *CI, IRBuilder<> &B);
|
||||||
Value *optimizeFabs(CallInst *CI, IRBuilder<> &B);
|
Value *optimizeFabs(CallInst *CI, IRBuilder<> &B);
|
||||||
Value *optimizeFMinFMax(CallInst *CI, IRBuilder<> &B);
|
Value *optimizeFMinFMax(CallInst *CI, IRBuilder<> &B);
|
||||||
|
Value *optimizeLog(CallInst *CI, IRBuilder<> &B);
|
||||||
Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B);
|
Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B);
|
||||||
Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B);
|
Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B);
|
||||||
Value *optimizeTan(CallInst *CI, IRBuilder<> &B);
|
Value *optimizeTan(CallInst *CI, IRBuilder<> &B);
|
||||||
|
|
|
@ -1284,6 +1284,48 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilder<> &B) {
|
||||||
return B.CreateSelect(Cmp, Op0, Op1);
|
return B.CreateSelect(Cmp, Op0, Op1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) {
|
||||||
|
Function *Callee = CI->getCalledFunction();
|
||||||
|
Value *Ret = nullptr;
|
||||||
|
StringRef Name = Callee->getName();
|
||||||
|
if (UnsafeFPShrink && hasFloatVersion(Name))
|
||||||
|
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;
|
||||||
|
|
||||||
|
// log(pow(x,y)) -> y*log(x)
|
||||||
|
// This is only applicable to log, log2, log10.
|
||||||
|
if (Name != "log" && Name != "log2" && Name != "log10")
|
||||||
|
return Ret;
|
||||||
|
|
||||||
|
IRBuilder<>::FastMathFlagGuard Guard(B);
|
||||||
|
FastMathFlags FMF;
|
||||||
|
FMF.setUnsafeAlgebra();
|
||||||
|
B.SetFastMathFlags(FMF);
|
||||||
|
|
||||||
|
LibFunc::Func Func;
|
||||||
|
Function *F = OpC->getCalledFunction();
|
||||||
|
StringRef FuncName = F->getName();
|
||||||
|
if ((TLI->getLibFunc(FuncName, Func) && TLI->has(Func) &&
|
||||||
|
Func == LibFunc::pow) || F->getIntrinsicID() == Intrinsic::pow)
|
||||||
|
return B.CreateFMul(OpC->getArgOperand(1),
|
||||||
|
EmitUnaryFloatFnCall(OpC->getOperand(0), Callee->getName(), B,
|
||||||
|
Callee->getAttributes()), "mul");
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) {
|
Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) {
|
||||||
Function *Callee = CI->getCalledFunction();
|
Function *Callee = CI->getCalledFunction();
|
||||||
|
|
||||||
|
@ -2088,6 +2130,8 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
|
||||||
return optimizeExp2(CI, Builder);
|
return optimizeExp2(CI, Builder);
|
||||||
case Intrinsic::fabs:
|
case Intrinsic::fabs:
|
||||||
return optimizeFabs(CI, Builder);
|
return optimizeFabs(CI, Builder);
|
||||||
|
case Intrinsic::log:
|
||||||
|
return optimizeLog(CI, Builder);
|
||||||
case Intrinsic::sqrt:
|
case Intrinsic::sqrt:
|
||||||
return optimizeSqrt(CI, Builder);
|
return optimizeSqrt(CI, Builder);
|
||||||
default:
|
default:
|
||||||
|
@ -2170,6 +2214,12 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
|
||||||
return optimizeFWrite(CI, Builder);
|
return optimizeFWrite(CI, Builder);
|
||||||
case LibFunc::fputs:
|
case LibFunc::fputs:
|
||||||
return optimizeFPuts(CI, Builder);
|
return optimizeFPuts(CI, Builder);
|
||||||
|
case LibFunc::log:
|
||||||
|
case LibFunc::log10:
|
||||||
|
case LibFunc::log1p:
|
||||||
|
case LibFunc::log2:
|
||||||
|
case LibFunc::logb:
|
||||||
|
return optimizeLog(CI, Builder);
|
||||||
case LibFunc::puts:
|
case LibFunc::puts:
|
||||||
return optimizePuts(CI, Builder);
|
return optimizePuts(CI, Builder);
|
||||||
case LibFunc::tan:
|
case LibFunc::tan:
|
||||||
|
@ -2203,11 +2253,6 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
|
||||||
case LibFunc::exp:
|
case LibFunc::exp:
|
||||||
case LibFunc::exp10:
|
case LibFunc::exp10:
|
||||||
case LibFunc::expm1:
|
case LibFunc::expm1:
|
||||||
case LibFunc::log:
|
|
||||||
case LibFunc::log10:
|
|
||||||
case LibFunc::log1p:
|
|
||||||
case LibFunc::log2:
|
|
||||||
case LibFunc::logb:
|
|
||||||
case LibFunc::sin:
|
case LibFunc::sin:
|
||||||
case LibFunc::sinh:
|
case LibFunc::sinh:
|
||||||
case LibFunc::tanh:
|
case LibFunc::tanh:
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||||
|
|
||||||
|
define double @mylog(double %x, double %y) #0 {
|
||||||
|
entry:
|
||||||
|
%pow = call double @llvm.pow.f64(double %x, double %y)
|
||||||
|
%call = call double @log(double %pow) #0
|
||||||
|
ret double %call
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define double @mylog(
|
||||||
|
; CHECK: %pow = call double @llvm.pow.f64(double %x, double %y)
|
||||||
|
; CHECK: %call = call double @log(double %pow)
|
||||||
|
; CHECK: ret double %call
|
||||||
|
; CHECK: }
|
||||||
|
|
||||||
|
declare double @log(double) #0
|
||||||
|
declare double @llvm.pow.f64(double, double)
|
|
@ -0,0 +1,19 @@
|
||||||
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||||
|
|
||||||
|
define double @mylog(double %x, double %y) #0 {
|
||||||
|
entry:
|
||||||
|
%pow = call double @llvm.pow.f64(double %x, double %y)
|
||||||
|
%call = call double @log(double %pow) #0
|
||||||
|
ret double %call
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define double @mylog(
|
||||||
|
; CHECK: %log = call double @log(double %x) #0
|
||||||
|
; CHECK: %mul = fmul fast double %log, %y
|
||||||
|
; CHECK: ret double %mul
|
||||||
|
; CHECK: }
|
||||||
|
|
||||||
|
declare double @log(double) #0
|
||||||
|
declare double @llvm.pow.f64(double, double)
|
||||||
|
|
||||||
|
attributes #0 = { "unsafe-fp-math"="true" }
|
Loading…
Reference in New Issue