diff options
| author | David Bolvansky <david.bolvansky@gmail.com> | 2019-07-10 14:43:27 +0000 | 
|---|---|---|
| committer | David Bolvansky <david.bolvansky@gmail.com> | 2019-07-10 14:43:27 +0000 | 
| commit | 0735cc1954d84afa742abadf78e4136489f7cd0d (patch) | |
| tree | 34b46971f5c62bb14fd7ec7df7166e5542b6f988 /llvm/lib/Transforms/Utils | |
| parent | 9cd82a4fbd2ded1e4d6b3815d153b28057ee1e75 (diff) | |
| download | bcm5719-llvm-0735cc1954d84afa742abadf78e4136489f7cd0d.tar.gz bcm5719-llvm-0735cc1954d84afa742abadf78e4136489f7cd0d.zip  | |
[InstCombine] pow(C,x) -> exp2(log2(C)*x)
Summary:
Transform
pow(C,x) 
To
exp2(log2(C)*x) 
if C > 0, C != inf, C != NaN (and C is not power of 2, since we have some fold for such case already).
log(C) is folded by the compiler and exp2 is much faster to compute than pow.
Reviewers: spatel, efriedma, evandro
Reviewed By: evandro
Subscribers: lebedev.ri, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64099
llvm-svn: 365637
Diffstat (limited to 'llvm/lib/Transforms/Utils')
| -rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 25 | 
1 files changed, 24 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 54961f375d8..b481d2b50a8 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1235,7 +1235,8 @@ static Value *getPow(Value *InnerChain[33], unsigned Exp, IRBuilder<> &B) {  }  /// Use exp{,2}(x * y) for pow(exp{,2}(x), y); -/// exp2(n * x) for pow(2.0 ** n, x); exp10(x) for pow(10.0, x). +/// exp2(n * x) for pow(2.0 ** n, x); exp10(x) for pow(10.0, x); +/// exp2(log2(C)*x) for pow(C,x).  Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) {    Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);    AttributeList Attrs = Pow->getCalledFunction()->getAttributes(); @@ -1347,6 +1348,28 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) {      return emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10, LibFunc_exp10f,                                  LibFunc_exp10l, B, Attrs); +  // pow(C,x) -> exp2(log2(C)*x) +  if (Pow->hasOneUse() && Pow->hasApproxFunc() && Pow->hasNoNaNs() && +      Pow->hasNoInfs() && BaseF->isNormal() && !BaseF->isNegative()) { +    Value *Log = nullptr; +    if (Ty->isFloatTy()) +      Log = ConstantFP::get(Ty, std::log2(BaseF->convertToFloat())); +    else if (Ty->isDoubleTy()) +      Log = ConstantFP::get(Ty, std::log2(BaseF->convertToDouble())); + +    if (Log) { +      Value *FMul = B.CreateFMul(Log, Expo, "mul"); +      if (Pow->doesNotAccessMemory()) { +        return B.CreateCall(Intrinsic::getDeclaration(Mod, Intrinsic::exp2, Ty), +                            FMul, "exp2"); +      } else { +        if (hasUnaryFloatFn(TLI, Ty, LibFunc_exp2, LibFunc_exp2f, +                            LibFunc_exp2l)) +          return emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f, +                                      LibFunc_exp2l, B, Attrs); +      } +    } +  }    return nullptr;  }  | 

