summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-03-13 14:46:32 +0000
committerSanjay Patel <spatel@rotateright.com>2018-03-13 14:46:32 +0000
commit204edeca5661d7dc80139d43507a0e268afff330 (patch)
treed6b61f8781dc0c400d3828e709083ce521372382
parent476ed8f26e91bce8144b4df4c20eb1c990383ba3 (diff)
downloadbcm5719-llvm-204edeca5661d7dc80139d43507a0e268afff330.tar.gz
bcm5719-llvm-204edeca5661d7dc80139d43507a0e268afff330.zip
[InstCombine] fix fmul reassociation to avoid creating an extra fdiv
This was supposed to be an NFC refactoring that will eventually allow eliminating the isFast() predicate, but there's a rare possibility that we would pessimize the code as shown in the test case because we failed to check 'hasOneUse()' properly. This version also removes an inefficiency of the old code; we would look for: (X * C) * C1 --> X * (C * C1) ...but that pattern is always handled by SimplifyAssociativeOrCommutative(). llvm-svn: 327404
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp26
-rw-r--r--llvm/test/Transforms/InstCombine/fmul.ll26
2 files changed, 33 insertions, 19 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 47d5d5f0c0a..56de5ed006d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -557,14 +557,28 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
// Reassociate constant RHS with another constant to form constant expression.
if (I.isFast() && match(Op1, m_Constant(C)) && C->isFiniteNonZeroFP()) {
+ Constant *C1;
+ if (match(Op0, m_OneUse(m_FDiv(m_Constant(C1), m_Value(X))))) {
+ // (C1 / X) * C --> (C * C1) / X
+ Constant *CC1 = ConstantExpr::getFMul(C, C1);
+ if (CC1->isNormalFP())
+ return BinaryOperator::CreateFDivFMF(CC1, X, &I);
+ }
+ if (match(Op0, m_FDiv(m_Value(X), m_Constant(C1)))) {
+ // (X / C1) * C --> X * (C / C1)
+ Constant *CDivC1 = ConstantExpr::getFDiv(C, C1);
+ if (CDivC1->isNormalFP())
+ return BinaryOperator::CreateFMulFMF(X, CDivC1, &I);
+
+ // If the constant was a denormal, try reassociating differently.
+ // (X / C1) * C --> X / (C1 / C)
+ Constant *C1DivC = ConstantExpr::getFDiv(C1, C);
+ if (Op0->hasOneUse() && C1DivC->isNormalFP())
+ return BinaryOperator::CreateFDivFMF(X, C1DivC, &I);
+ }
+
// Let MDC denote an expression in one of these forms:
// X * C, C/X, X/C, where C is a constant.
- //
- // Try to simplify "MDC * Constant"
- if (isFMulOrFDivWithConstant(Op0))
- if (Value *V = foldFMulConst(cast<Instruction>(Op0), C, &I))
- return replaceInstUsesWith(I, V);
-
// (MDC +/- C1) * C => (MDC * C) +/- (C1 * C)
Instruction *FAddSub = dyn_cast<Instruction>(Op0);
if (FAddSub &&
diff --git a/llvm/test/Transforms/InstCombine/fmul.ll b/llvm/test/Transforms/InstCombine/fmul.ll
index 0cfcb336c73..10ae53e2455 100644
--- a/llvm/test/Transforms/InstCombine/fmul.ll
+++ b/llvm/test/Transforms/InstCombine/fmul.ll
@@ -336,8 +336,8 @@ define float @log2half_commute(float %x1, float %y) {
define float @fdiv_constant_numerator_fmul(float %x) {
; CHECK-LABEL: @fdiv_constant_numerator_fmul(
-; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float 1.200000e+07, [[X:%.*]]
-; CHECK-NEXT: ret float [[TMP1]]
+; CHECK-NEXT: [[T3:%.*]] = fdiv fast float 1.200000e+07, [[X:%.*]]
+; CHECK-NEXT: ret float [[T3]]
;
%t1 = fdiv float 2.0e+3, %x
%t3 = fmul fast float %t1, 6.0e+3
@@ -365,8 +365,8 @@ define float @fdiv_constant_numerator_fmul_extra_use(float %x) {
define float @fdiv_constant_denominator_fmul(float %x) {
; CHECK-LABEL: @fdiv_constant_denominator_fmul(
-; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[X:%.*]], 3.000000e+00
-; CHECK-NEXT: ret float [[TMP1]]
+; CHECK-NEXT: [[T3:%.*]] = fmul fast float [[X:%.*]], 3.000000e+00
+; CHECK-NEXT: ret float [[T3]]
;
%t1 = fdiv float %x, 2.0e+3
%t3 = fmul fast float %t1, 6.0e+3
@@ -375,8 +375,8 @@ define float @fdiv_constant_denominator_fmul(float %x) {
define <4 x float> @fdiv_constant_denominator_fmul_vec(<4 x float> %x) {
; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec(
-; CHECK-NEXT: [[TMP1:%.*]] = fmul fast <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
-; CHECK-NEXT: ret <4 x float> [[TMP1]]
+; CHECK-NEXT: [[T3:%.*]] = fmul fast <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <4 x float> [[T3]]
;
%t1 = fdiv <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
%t3 = fmul fast <4 x float> %t1, <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3>
@@ -387,8 +387,8 @@ define <4 x float> @fdiv_constant_denominator_fmul_vec(<4 x float> %x) {
define <4 x float> @fdiv_constant_denominator_fmul_vec_constexpr(<4 x float> %x) {
; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec_constexpr(
-; CHECK-NEXT: [[TMP1:%.*]] = fmul fast <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
-; CHECK-NEXT: ret <4 x float> [[TMP1]]
+; CHECK-NEXT: [[T3:%.*]] = fmul fast <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <4 x float> [[T3]]
;
%constExprMul = bitcast i128 trunc (i160 bitcast (<5 x float> <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3, float undef> to i160) to i128) to <4 x float>
%t1 = fdiv <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
@@ -416,21 +416,21 @@ define float @fdiv_constant_denominator_fmul_denorm(float %x) {
define float @fdiv_constant_denominator_fmul_denorm_try_harder(float %x) {
; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder(
-; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float [[X:%.*]], 0x47E8000000000000
-; CHECK-NEXT: ret float [[TMP1]]
+; CHECK-NEXT: [[T3:%.*]] = fdiv fast float [[X:%.*]], 0x47E8000000000000
+; CHECK-NEXT: ret float [[T3]]
;
%t1 = fdiv float %x, 3.0
%t3 = fmul fast float %t1, 0x3810000000000000
ret float %t3
}
-; FIXME: We have 2 divisions instead of the 1 we started with.
+; Negative test: we should not have 2 divisions instead of the 1 we started with.
define float @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(float %x) {
; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(
; CHECK-NEXT: [[T1:%.*]] = fdiv float [[X:%.*]], 3.000000e+00
-; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float [[X]], 0x47E8000000000000
-; CHECK-NEXT: [[R:%.*]] = fadd float [[T1]], [[TMP1]]
+; CHECK-NEXT: [[T3:%.*]] = fmul fast float [[T1]], 0x3810000000000000
+; CHECK-NEXT: [[R:%.*]] = fadd float [[T1]], [[T3]]
; CHECK-NEXT: ret float [[R]]
;
%t1 = fdiv float %x, 3.0e+0
OpenPOWER on IntegriCloud