summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
diff options
context:
space:
mode:
authorDavid Bolvansky <david.bolvansky@gmail.com>2019-07-10 14:43:27 +0000
committerDavid Bolvansky <david.bolvansky@gmail.com>2019-07-10 14:43:27 +0000
commit0735cc1954d84afa742abadf78e4136489f7cd0d (patch)
tree34b46971f5c62bb14fd7ec7df7166e5542b6f988 /llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
parent9cd82a4fbd2ded1e4d6b3815d153b28057ee1e75 (diff)
downloadbcm5719-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/SimplifyLibCalls.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp25
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;
}
OpenPOWER on IntegriCloud