[llvm] r327404 - [InstCombine] fix fmul reassociation to avoid creating an extra fdiv

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 13 07:46:33 PDT 2018


Author: spatel
Date: Tue Mar 13 07:46:32 2018
New Revision: 327404

URL: http://llvm.org/viewvc/llvm-project?rev=327404&view=rev
Log:
[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().

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/trunk/test/Transforms/InstCombine/fmul.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=327404&r1=327403&r2=327404&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Tue Mar 13 07:46:32 2018
@@ -557,14 +557,28 @@ Instruction *InstCombiner::visitFMul(Bin
 
   // 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 &&

Modified: llvm/trunk/test/Transforms/InstCombine/fmul.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fmul.ll?rev=327404&r1=327403&r2=327404&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fmul.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fmul.ll Tue Mar 13 07:46:32 2018
@@ -336,8 +336,8 @@ define float @log2half_commute(float %x1
 
 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_fm
 
 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_
 
 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_denomi
 
 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_
 
 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




More information about the llvm-commits mailing list