summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
diff options
context:
space:
mode:
authorEvandro Menezes <e.menezes@samsung.com>2018-08-30 19:04:51 +0000
committerEvandro Menezes <e.menezes@samsung.com>2018-08-30 19:04:51 +0000
commit2123ea7d5c722e98ce0f047c8baa3fb3db23e6b3 (patch)
treec93e4b2f1371be6daca0e61f94a12ad710487349 /llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
parent94d3e4dd77f253d728432ce0341f2f3e49a47c05 (diff)
downloadbcm5719-llvm-2123ea7d5c722e98ce0f047c8baa3fb3db23e6b3.tar.gz
bcm5719-llvm-2123ea7d5c722e98ce0f047c8baa3fb3db23e6b3.zip
[InstCombine] Expand the simplification of pow() into exp2()
Generalize the simplification of `pow(2.0, y)` to `pow(2.0 ** n, y)` for all scalar and vector types. This improvement helps some benchmarks in SPEC CPU2000 and CPU2006, such as 252.eon, 447.dealII, 453.povray. Otherwise, no significant regressions on x86-64 or A64. Differential revision: https://reviews.llvm.org/D49273 llvm-svn: 341095
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp32
1 files changed, 27 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index efa097e141d..84b61798c6c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/SimplifyLibCalls.h"
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Triple.h"
@@ -1183,12 +1184,13 @@ static Value *getPow(Value *InnerChain[33], unsigned Exp, IRBuilder<> &B) {
}
/// Use exp{,2}(x * y) for pow(exp{,2}(x), y);
-/// exp2(x) for pow(2.0, x); exp10(x) for pow(10.0, x).
+/// exp2(n * x) for pow(2.0 ** n, x); exp10(x) for pow(10.0, x).
Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) {
Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
AttributeList Attrs = Pow->getCalledFunction()->getAttributes();
Module *Mod = Pow->getModule();
Type *Ty = Pow->getType();
+ bool Ignored;
// Evaluate special cases related to a nested function as the base.
@@ -1249,10 +1251,30 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) {
// Evaluate special cases related to a constant base.
- // pow(2.0, x) -> exp2(x)
- if (match(Base, m_SpecificFP(2.0))) {
- Value *Exp2 = Intrinsic::getDeclaration(Mod, Intrinsic::exp2, Ty);
- return B.CreateCall(Exp2, Expo, "exp2");
+ const APFloat *BaseF;
+ if (!match(Pow->getArgOperand(0), m_APFloat(BaseF)))
+ return nullptr;
+
+ // pow(2.0 ** n, x) -> exp2(n * x)
+ if (hasUnaryFloatFn(TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) {
+ APFloat BaseR = APFloat(1.0);
+ BaseR.convert(BaseF->getSemantics(), APFloat::rmTowardZero, &Ignored);
+ BaseR = BaseR / *BaseF;
+ bool IsInteger = BaseF->isInteger(),
+ IsReciprocal = BaseR.isInteger();
+ const APFloat *NF = IsReciprocal ? &BaseR : BaseF;
+ APSInt NI(64, false);
+ if ((IsInteger || IsReciprocal) &&
+ !NF->convertToInteger(NI, APFloat::rmTowardZero, &Ignored) &&
+ NI > 1 && NI.isPowerOf2()) {
+ double N = NI.logBase2() * (IsReciprocal ? -1.0 : 1.0);
+ Value *FMul = B.CreateFMul(Expo, ConstantFP::get(Ty, N), "mul");
+ if (Pow->doesNotAccessMemory())
+ return B.CreateCall(Intrinsic::getDeclaration(Mod, Intrinsic::exp2, Ty),
+ FMul, "exp2");
+ else
+ return emitUnaryFloatFnCall(FMul, TLI->getName(LibFunc_exp2), B, Attrs);
+ }
}
// pow(10.0, x) -> exp10(x)
OpenPOWER on IntegriCloud