summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShuxin Yang <shuxin.llvm@gmail.com>2013-09-19 21:13:46 +0000
committerShuxin Yang <shuxin.llvm@gmail.com>2013-09-19 21:13:46 +0000
commitb1ccfb3a548e122e282cd62c534c4d47f5310bf6 (patch)
tree39cebad965612ce61b118f5ad31abbd08026a31b
parentbf22298093d7069fbf3a3149d26fbcb4ad453ceb (diff)
downloadllvm-b1ccfb3a548e122e282cd62c534c4d47f5310bf6.tar.gz
llvm-b1ccfb3a548e122e282cd62c534c4d47f5310bf6.tar.bz2
llvm-b1ccfb3a548e122e282cd62c534c4d47f5310bf6.tar.xz
[Fast-math] Disable "(C1/X)*C2 => (C1*C2)/X" if C1/X has multiple uses.
If "C1/X" were having multiple uses, the only benefit of this transformation is to potentially shorten critical path. But it is at the cost of instroducing additional div. The additional div may or may not incur cost depending on how div is implemented. If it is implemented using Newton–Raphson iteration, it dosen't seem to incur any cost (FIXME). However, if the div blocks the entire pipeline, that sounds to be pretty expensive. Let CodeGen to take care this transformation. This patch sees 6% on a benchmark. rdar://15032743 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191037 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/InstCombine/InstCombineMulDivRem.cpp9
-rw-r--r--test/Transforms/InstCombine/fast-math.ll12
2 files changed, 18 insertions, 3 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index cc6a301540..9c310f04dc 100644
--- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -374,9 +374,12 @@ Value *InstCombiner::foldFMulConst(Instruction *FMulOrDiv, ConstantFP *C,
} else {
if (C0) {
// (C0 / X) * C => (C0 * C) / X
- ConstantFP *F = cast<ConstantFP>(ConstantExpr::getFMul(C0, C));
- if (isNormalFp(F))
- R = BinaryOperator::CreateFDiv(F, Opnd1);
+ if (FMulOrDiv->hasOneUse()) {
+ // It would otherwise introduce another div.
+ ConstantFP *F = cast<ConstantFP>(ConstantExpr::getFMul(C0, C));
+ if (isNormalFp(F))
+ R = BinaryOperator::CreateFDiv(F, Opnd1);
+ }
} else {
// (X / C1) * C => X * (C/C1) if C/C1 is not a denormal
ConstantFP *F = cast<ConstantFP>(ConstantExpr::getFDiv(C, C1));
diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll
index a9a7015f62..d8ba2a59ff 100644
--- a/test/Transforms/InstCombine/fast-math.ll
+++ b/test/Transforms/InstCombine/fast-math.ll
@@ -202,6 +202,18 @@ define float @fmul2(float %f1) {
; CHECK: fdiv fast float 1.200000e+07, %f1
}
+; X/C1 * C2 => X * (C2/C1) is disabled if X/C1 has multiple uses
+@fmul2_external = external global float
+define float @fmul2_disable(float %f1) {
+ %div = fdiv fast float 1.000000e+00, %f1
+ store float %div, float* @fmul2_external
+ %mul = fmul fast float %div, 2.000000e+00
+ ret float %mul
+; CHECK-LABEL: @fmul2_disable
+; CHECK: store
+; CHECK: fmul fast
+}
+
; X/C1 * C2 => X * (C2/C1) (if C2/C1 is normal Fp)
define float @fmul3(float %f1, float %f2) {
%t1 = fdiv float %f1, 2.0e+3