[llvm] r367447 - [InstCombine] canonicalize fneg before fmul/fdiv

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 31 09:53:22 PDT 2019


Author: spatel
Date: Wed Jul 31 09:53:22 2019
New Revision: 367447

URL: http://llvm.org/viewvc/llvm-project?rev=367447&view=rev
Log:
[InstCombine] canonicalize fneg before fmul/fdiv

Reverse the canonicalization of fneg relative to fmul/fdiv. That makes it
easier to implement the transforms (and possibly other fneg transforms) in
1 place because we can always start the pattern match from fneg (either the
legacy binop or the new unop).

There's a secondary practical benefit seen in PR21914 and PR42681:
https://bugs.llvm.org/show_bug.cgi?id=21914
https://bugs.llvm.org/show_bug.cgi?id=42681
...hoisting fneg rather than sinking seems to play nicer with LICM in IR
(although this change may expose analysis holes in the other direction).

1. The instcombine test changes show the expected neutral IR diffs from
   reversing the order.

2. The reassociation tests show that we were missing an optimization
   opportunity to fold away fneg-of-fneg. My reading of IEEE-754 says
   that all of these transforms are allowed (regardless of binop/unop
   fneg version) because:

   "For all other operations [besides copy/abs/negate/copysign], this
   standard does not specify the sign bit of a NaN result."
   In all of these transforms, we always have some other binop
   (fadd/fsub/fmul/fdiv), so we are free to flip the sign bit of a
   potential intermediate NaN operand.
   (If that interpretation is wrong, then we must already have a bug in
   the existing transforms?)

3. The clang tests shouldn't exist as-is, but that's effectively a
   revert of rL367149 (the test broke with an extension of the
   pre-existing fneg canonicalization in rL367146).

Differential Revision: https://reviews.llvm.org/D65399

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/trunk/test/Transforms/InstCombine/fadd.ll
    llvm/trunk/test/Transforms/InstCombine/fdiv.ll
    llvm/trunk/test/Transforms/InstCombine/fmul.ll
    llvm/trunk/test/Transforms/InstCombine/fsub.ll
    llvm/trunk/test/Transforms/Reassociate/fast-basictest.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp?rev=367447&r1=367446&r2=367447&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp Wed Jul 31 09:53:22 2019
@@ -1900,6 +1900,22 @@ static Instruction *foldFNegIntoConstant
   return nullptr;
 }
 
+static Instruction *hoistFNegAboveFMulFDiv(Instruction &I,
+                                           InstCombiner::BuilderTy &Builder) {
+  Value *FNeg;
+  if (!match(&I, m_FNeg(m_Value(FNeg))))
+    return nullptr;
+
+  Value *X, *Y;
+  if (match(FNeg, m_OneUse(m_FMul(m_Value(X), m_Value(Y)))))
+    return BinaryOperator::CreateFMulFMF(Builder.CreateFNegFMF(X, &I), Y, &I);
+
+  if (match(FNeg, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))))
+    return BinaryOperator::CreateFDivFMF(Builder.CreateFNegFMF(X, &I), Y, &I);
+
+  return nullptr;
+}
+
 Instruction *InstCombiner::visitFNeg(UnaryOperator &I) {
   Value *Op = I.getOperand(0);
 
@@ -1917,6 +1933,9 @@ Instruction *InstCombiner::visitFNeg(Una
       match(Op, m_OneUse(m_FSub(m_Value(X), m_Value(Y)))))
     return BinaryOperator::CreateFSubFMF(Y, X, &I);
 
+  if (Instruction *R = hoistFNegAboveFMulFDiv(I, Builder))
+    return R;
+
   return nullptr;
 }
 
@@ -1938,6 +1957,9 @@ Instruction *InstCombiner::visitFSub(Bin
   if (Instruction *X = foldFNegIntoConstant(I))
     return X;
 
+  if (Instruction *R = hoistFNegAboveFMulFDiv(I, Builder))
+    return R;
+
   Value *X, *Y;
   Constant *C;
 

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=367447&r1=367446&r2=367447&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Wed Jul 31 09:53:22 2019
@@ -373,16 +373,6 @@ Instruction *InstCombiner::visitFMul(Bin
   if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_Constant(C)))
     return BinaryOperator::CreateFMulFMF(X, ConstantExpr::getFNeg(C), &I);
 
-  // Sink negation: -X * Y --> -(X * Y)
-  // But don't transform constant expressions because there's an inverse fold.
-  if (match(Op0, m_OneUse(m_FNeg(m_Value(X)))) && !isa<ConstantExpr>(Op0))
-    return BinaryOperator::CreateFNegFMF(Builder.CreateFMulFMF(X, Op1, &I), &I);
-
-  // Sink negation: Y * -X --> -(X * Y)
-  // But don't transform constant expressions because there's an inverse fold.
-  if (match(Op1, m_OneUse(m_FNeg(m_Value(X)))) && !isa<ConstantExpr>(Op1))
-    return BinaryOperator::CreateFNegFMF(Builder.CreateFMulFMF(X, Op0, &I), &I);
-
   // fabs(X) * fabs(X) -> X * X
   if (Op0 == Op1 && match(Op0, m_Intrinsic<Intrinsic::fabs>(m_Value(X))))
     return BinaryOperator::CreateFMulFMF(X, X, &I);
@@ -1234,16 +1224,6 @@ Instruction *InstCombiner::visitFDiv(Bin
     return &I;
   }
 
-  // Sink negation: -X / Y --> -(X / Y)
-  // But don't transform constant expressions because there's an inverse fold.
-  if (match(Op0, m_OneUse(m_FNeg(m_Value(X)))) && !isa<ConstantExpr>(Op0))
-    return BinaryOperator::CreateFNegFMF(Builder.CreateFDivFMF(X, Op1, &I), &I);
-
-  // Sink negation: Y / -X --> -(Y / X)
-  // But don't transform constant expressions because there's an inverse fold.
-  if (match(Op1, m_OneUse(m_FNeg(m_Value(X)))) && !isa<ConstantExpr>(Op1))
-    return BinaryOperator::CreateFNegFMF(Builder.CreateFDivFMF(Op0, X, &I), &I);
-
   // X / (X * Y) --> 1.0 / Y
   // Reassociate to (X / X -> 1.0) is legal when NaNs are not allowed.
   // We can ignore the possibility that X is infinity because INF/INF is NaN.

Modified: llvm/trunk/test/Transforms/InstCombine/fadd.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fadd.ll?rev=367447&r1=367446&r2=367447&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fadd.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fadd.ll Wed Jul 31 09:53:22 2019
@@ -160,15 +160,15 @@ define double @fmul_fneg2_commute(double
   ret double %r
 }
 
-; Z + (-X / Y) --> Z - (X / Y)
+; Z + (-X / Y) - extra use means we can't transform to fsub without an extra instruction
 
 define float @fdiv_fneg1_extra_use(float %x, float %y, float %pz) {
 ; CHECK-LABEL: @fdiv_fneg1_extra_use(
 ; CHECK-NEXT:    [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[DIV:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
 ; CHECK-NEXT:    call void @use(float [[DIV]])
-; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z]], [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = fadd float [[Z]], [[DIV]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %z = frem float 42.0, %pz ; thwart complexity-based canonicalization
@@ -179,16 +179,16 @@ define float @fdiv_fneg1_extra_use(float
   ret float %r
 }
 
-; Z + (Y / -X) --> Z - (Y / X)
+; Z + (Y / -X) - extra use means we can't transform to fsub without an extra instruction
 
 define float @fdiv_fneg2_extra_use(float %x, float %py, float %pz) {
 ; CHECK-LABEL: @fdiv_fneg2_extra_use(
 ; CHECK-NEXT:    [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
 ; CHECK-NEXT:    [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[Y]], [[X:%.*]]
-; CHECK-NEXT:    [[DIV:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[Y]], [[NEG]]
 ; CHECK-NEXT:    call void @use(float [[DIV]])
-; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z]], [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = fadd float [[Z]], [[DIV]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %y = frem float -42.0, %py ; thwart complexity-based canonicalization
@@ -200,15 +200,15 @@ define float @fdiv_fneg2_extra_use(float
   ret float %r
 }
 
-; Z + (-X * Y) --> Z - (X * Y)
+; Z + (-X * Y) - extra use means we can't transform to fsub without an extra instruction
 
 define <2 x float> @fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %pz) {
 ; CHECK-LABEL: @fmul_fneg1_extra_use(
 ; CHECK-NEXT:    [[Z:%.*]] = frem <2 x float> <float 4.200000e+01, float -1.000000e+00>, [[PZ:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[NEG]], [[Y:%.*]]
 ; CHECK-NEXT:    call void @use_vec(<2 x float> [[MUL]])
-; CHECK-NEXT:    [[R:%.*]] = fsub <2 x float> [[Z]], [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[Z]], [[MUL]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %z = frem <2 x float> <float 42.0, float -1.0>, %pz ; thwart complexity-based canonicalization
@@ -219,16 +219,16 @@ define <2 x float> @fmul_fneg1_extra_use
   ret <2 x float> %r
 }
 
-; Z + (Y * -X) --> Z - (Y * X)
+; Z + (Y * -X) - extra use means we can't transform to fsub without an extra instruction
 
 define float @fmul_fneg2_extra_use(float %x, float %py, float %pz) {
 ; CHECK-LABEL: @fmul_fneg2_extra_use(
 ; CHECK-NEXT:    [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
 ; CHECK-NEXT:    [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[Y]], [[X:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[Y]], [[NEG]]
 ; CHECK-NEXT:    call void @use(float [[MUL]])
-; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z]], [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = fadd float [[Z]], [[MUL]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %y = frem float -42.0, %py ; thwart complexity-based canonicalization

Modified: llvm/trunk/test/Transforms/InstCombine/fdiv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fdiv.ll?rev=367447&r1=367446&r2=367447&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fdiv.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fdiv.ll Wed Jul 31 09:53:22 2019
@@ -501,8 +501,8 @@ define <2 x float> @div_constant_dividen
 
 define double @fdiv_fneg1(double %x, double %y) {
 ; CHECK-LABEL: @fdiv_fneg1(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[DIV:%.*]] = fsub double -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub double -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
   %neg = fsub double -0.0, %x
@@ -512,8 +512,8 @@ define double @fdiv_fneg1(double %x, dou
 
 define double @fdiv_unary_fneg1(double %x, double %y) {
 ; CHECK-LABEL: @fdiv_unary_fneg1(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[DIV:%.*]] = fsub double -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fneg double [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]]
 ; CHECK-NEXT:    ret double [[DIV]]
 ;
   %neg = fneg double %x
@@ -523,8 +523,8 @@ define double @fdiv_unary_fneg1(double %
 
 define <2 x float> @fdiv_fneg2(<2 x float> %x, <2 x float> %y) {
 ; CHECK-LABEL: @fdiv_fneg2(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv <2 x float> [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[DIV:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
 ; CHECK-NEXT:    ret <2 x float> [[DIV]]
 ;
   %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
@@ -534,8 +534,8 @@ define <2 x float> @fdiv_fneg2(<2 x floa
 
 define <2 x float> @fdiv_unary_fneg2(<2 x float> %x, <2 x float> %y) {
 ; CHECK-LABEL: @fdiv_unary_fneg2(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv <2 x float> [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[DIV:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]]
 ; CHECK-NEXT:    ret <2 x float> [[DIV]]
 ;
   %neg = fneg <2 x float> %x

Modified: llvm/trunk/test/Transforms/InstCombine/fmul.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fmul.ll?rev=367447&r1=367446&r2=367447&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fmul.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fmul.ll Wed Jul 31 09:53:22 2019
@@ -277,11 +277,11 @@ define float @neg_unary_neg_multi_use(fl
   ret float %mul
 }
 
-; (-0.0 - X) * Y => -0.0 - (X * Y)
-define float @neg_sink(float %x, float %y) {
-; CHECK-LABEL: @neg_sink(
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+; (-0.0 - X) * Y
+define float @neg_mul(float %x, float %y) {
+; CHECK-LABEL: @neg_mul(
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB]], [[Y:%.*]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %sub = fsub float -0.0, %x
@@ -289,10 +289,10 @@ define float @neg_sink(float %x, float %
   ret float %mul
 }
 
-define float @unary_neg_sink(float %x, float %y) {
-; CHECK-LABEL: @unary_neg_sink(
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+define float @unary_neg_mul(float %x, float %y) {
+; CHECK-LABEL: @unary_neg_mul(
+; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NEG]], [[Y:%.*]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %neg = fneg float %x
@@ -300,10 +300,10 @@ define float @unary_neg_sink(float %x, f
   ret float %mul
 }
 
-define <2 x float> @neg_sink_vec(<2 x float> %x, <2 x float> %y) {
-; CHECK-LABEL: @neg_sink_vec(
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
+define <2 x float> @neg_mul_vec(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @neg_mul_vec(
+; CHECK-NEXT:    [[SUB:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[SUB]], [[Y:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[MUL]]
 ;
   %sub = fsub <2 x float> <float -0.0, float -0.0>, %x
@@ -311,11 +311,10 @@ define <2 x float> @neg_sink_vec(<2 x fl
   ret <2 x float> %mul
 }
 
-; FIXME: Should generate a unary FNeg.
-define <2 x float> @unary_neg_sink_vec(<2 x float> %x, <2 x float> %y) {
-; CHECK-LABEL: @unary_neg_sink_vec(
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
+define <2 x float> @unary_neg_mul_vec(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @unary_neg_mul_vec(
+; CHECK-NEXT:    [[SUB:%.*]] = fneg <2 x float> [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[SUB]], [[Y:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[MUL]]
 ;
   %sub = fneg <2 x float> %x
@@ -323,10 +322,10 @@ define <2 x float> @unary_neg_sink_vec(<
   ret <2 x float> %mul
 }
 
-define <2 x float> @neg_sink_vec_undef(<2 x float> %x, <2 x float> %y) {
-; CHECK-LABEL: @neg_sink_vec_undef(
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
+define <2 x float> @neg_mul_vec_undef(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @neg_mul_vec_undef(
+; CHECK-NEXT:    [[SUB:%.*]] = fsub <2 x float> <float undef, float -0.000000e+00>, [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[SUB]], [[Y:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[MUL]]
 ;
   %sub = fsub <2 x float> <float undef, float -0.0>, %x
@@ -334,11 +333,11 @@ define <2 x float> @neg_sink_vec_undef(<
   ret <2 x float> %mul
 }
 
-; (0.0 - X) * Y => 0.0 - (X * Y)
+; (0.0 - X) * Y
 define float @neg_sink_nsz(float %x, float %y) {
 ; CHECK-LABEL: @neg_sink_nsz(
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[SUB1:%.*]] = fsub nsz float -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB1]], [[Y:%.*]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %sub1 = fsub nsz float 0.0, %x
@@ -346,8 +345,6 @@ define float @neg_sink_nsz(float %x, flo
   ret float %mul
 }
 
-; "(-0.0 - X) * Y => -0.0 - (X * Y)" is disabled if expression "-0.0 - X"
-; has multiple uses.
 define float @neg_sink_multi_use(float %x, float %y) {
 ; CHECK-LABEL: @neg_sink_multi_use(
 ; CHECK-NEXT:    [[SUB1:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
@@ -361,8 +358,8 @@ define float @neg_sink_multi_use(float %
   ret float %mul2
 }
 
-define float @unary_neg_sink_multi_use(float %x, float %y) {
-; CHECK-LABEL: @unary_neg_sink_multi_use(
+define float @unary_neg_mul_multi_use(float %x, float %y) {
+; CHECK-LABEL: @unary_neg_mul_multi_use(
 ; CHECK-NEXT:    [[SUB1:%.*]] = fneg float [[X:%.*]]
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB1]], [[Y:%.*]]
 ; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[MUL]], [[SUB1]]

Modified: llvm/trunk/test/Transforms/InstCombine/fsub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fsub.ll?rev=367447&r1=367446&r2=367447&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fsub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fsub.ll Wed Jul 31 09:53:22 2019
@@ -454,10 +454,10 @@ define double @fsub_fmul_fneg2(double %x
 
 define float @fsub_fdiv_fneg1_extra_use(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fsub_fdiv_fneg1_extra_use(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[DIV:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
 ; CHECK-NEXT:    call void @use(float [[DIV]])
-; CHECK-NEXT:    [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %neg = fsub float -0.000000e+00, %x
@@ -469,10 +469,10 @@ define float @fsub_fdiv_fneg1_extra_use(
 
 define float @fsub_fdiv_fneg2_extra_use(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fsub_fdiv_fneg2_extra_use(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[DIV:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]
 ; CHECK-NEXT:    call void @use(float [[DIV]])
-; CHECK-NEXT:    [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %neg = fsub float -0.000000e+00, %x
@@ -486,10 +486,10 @@ declare void @use_vec(<2 x float>)
 
 define <2 x float> @fsub_fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
 ; CHECK-LABEL: @fsub_fmul_fneg1_extra_use(
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[NEG]], [[Y:%.*]]
 ; CHECK-NEXT:    call void @use_vec(<2 x float> [[MUL]])
-; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[MUL]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
@@ -501,10 +501,10 @@ define <2 x float> @fsub_fmul_fneg1_extr
 
 define float @fsub_fmul_fneg2_extra_use(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fsub_fmul_fneg2_extra_use(
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
+; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NEG]], [[Y:%.*]]
 ; CHECK-NEXT:    call void @use(float [[MUL]])
-; CHECK-NEXT:    [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[MUL]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %neg = fsub float -0.000000e+00, %x

Modified: llvm/trunk/test/Transforms/Reassociate/fast-basictest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-basictest.ll?rev=367447&r1=367446&r2=367447&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Reassociate/fast-basictest.ll (original)
+++ llvm/trunk/test/Transforms/Reassociate/fast-basictest.ll Wed Jul 31 09:53:22 2019
@@ -614,12 +614,25 @@ define float @test18_reassoc(float %a, f
   ret float %f
 }
 
-; It is not safe to reassociate unary fneg without nnan.
+; fneg of fneg is an identity operation, so no FMF are needed to remove those instructions.
+
+define float @test18_unary_fneg_no_FMF(float %a, float %b, float %z) {
+; CHECK-LABEL: @test18_unary_fneg_no_FMF(
+; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[Z:%.*]], 4.000000e+01
+; CHECK-NEXT:    [[F:%.*]] = fmul float [[TMP1]], [[A:%.*]]
+; CHECK-NEXT:    ret float [[F]]
+;
+  %d = fmul float %z, 4.000000e+01
+  %c = fneg float %d
+  %e = fmul float %a, %c
+  %f = fneg float %e
+  ret float %f
+}
+
 define float @test18_reassoc_unary_fneg(float %a, float %b, float %z) {
 ; CHECK-LABEL: @test18_reassoc_unary_fneg(
-; CHECK-NEXT:    [[C:%.*]] = fmul reassoc float [[Z:%.*]], -4.000000e+01
-; CHECK-NEXT:    [[E:%.*]] = fmul reassoc float [[C]], [[A:%.*]]
-; CHECK-NEXT:    [[F:%.*]] = fneg reassoc float [[E]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[Z:%.*]], 4.000000e+01
+; CHECK-NEXT:    [[F:%.*]] = fmul reassoc float [[TMP1]], [[A:%.*]]
 ; CHECK-NEXT:    ret float [[F]]
 ;
   %d = fmul reassoc float %z, 4.000000e+01




More information about the llvm-commits mailing list