[InstCombine] fold reassociative fadd with negated operand
authorSanjay Patel <spatel@rotateright.com>
Thu, 11 Aug 2022 15:40:54 +0000 (11:40 -0400)
committerSanjay Patel <spatel@rotateright.com>
Thu, 11 Aug 2022 15:43:36 +0000 (11:43 -0400)
We manage to iteratively achieve this result with no extra
uses, and the reassociate pass can also do this, but this
pattern falls through the cracks in the example from
issue #57053.

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
llvm/test/Transforms/InstCombine/fadd.ll

index 13a0386..528c74a 100644 (file)
@@ -1665,6 +1665,11 @@ Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) {
         return BinaryOperator::CreateFMulFMF(X, NewMulC, &I);
     }
 
+    // (-X - Y) + (X + Z) --> Z - Y
+    if (match(&I, m_c_FAdd(m_FSub(m_FNeg(m_Value(X)), m_Value(Y)),
+                           m_c_FAdd(m_Deferred(X), m_Value(Z)))))
+      return BinaryOperator::CreateFSubFMF(Z, Y, &I);
+
     if (Value *V = FAddCombine(Builder).simplify(&I))
       return replaceInstUsesWith(I, V);
   }
index 275cecd..32ecd8c 100644 (file)
@@ -534,9 +534,7 @@ define float @fadd_fneg_reass_commute0(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fadd_fneg_reass_commute0(
 ; CHECK-NEXT:    [[N:%.*]] = fneg reassoc nsz float [[X:%.*]]
 ; CHECK-NEXT:    call void @use(float [[N]])
-; CHECK-NEXT:    [[S:%.*]] = fsub reassoc nsz float [[N]], [[Y:%.*]]
-; CHECK-NEXT:    [[A:%.*]] = fadd reassoc nsz float [[X]], [[Z:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[S]], [[A]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %n = fneg reassoc nsz float %x
@@ -553,8 +551,7 @@ define float @fadd_fneg_reass_commute1(float %x, float %y, float %z) {
 ; CHECK-NEXT:    call void @use(float [[N]])
 ; CHECK-NEXT:    [[S:%.*]] = fsub float [[N]], [[Y:%.*]]
 ; CHECK-NEXT:    call void @use(float [[S]])
-; CHECK-NEXT:    [[A:%.*]] = fadd float [[X]], [[Z:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[A]], [[S]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[Y]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %n = fneg float %x
@@ -574,7 +571,7 @@ define float @fadd_fneg_reass_commute2(float %x, float %y, float %z) {
 ; CHECK-NEXT:    call void @use(float [[S]])
 ; CHECK-NEXT:    [[A:%.*]] = fadd float [[Z:%.*]], [[X]]
 ; CHECK-NEXT:    call void @use(float [[A]])
-; CHECK-NEXT:    [[R:%.*]] = fadd fast float [[S]], [[A]]
+; CHECK-NEXT:    [[R:%.*]] = fsub fast float [[Z]], [[Y]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %n = fneg float %x
@@ -591,9 +588,7 @@ define <2 x float> @fadd_fneg_reass_commute3(<2 x float> %x, <2 x float> %y, <2
 ; CHECK-LABEL: @fadd_fneg_reass_commute3(
 ; CHECK-NEXT:    [[N:%.*]] = fneg reassoc nsz <2 x float> [[X:%.*]]
 ; CHECK-NEXT:    call void @use_vec(<2 x float> [[N]])
-; CHECK-NEXT:    [[S:%.*]] = fsub reassoc nsz <2 x float> [[N]], [[Y:%.*]]
-; CHECK-NEXT:    [[A:%.*]] = fadd reassoc nsz <2 x float> [[Z:%.*]], [[X]]
-; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz <2 x float> [[A]], [[S]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz <2 x float> [[Z:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %n = fneg reassoc nsz <2 x float> %x
@@ -604,6 +599,8 @@ define <2 x float> @fadd_fneg_reass_commute3(<2 x float> %x, <2 x float> %y, <2
   ret <2 x float> %r
 }
 
+; negative test - need reassoc (+ nsz)
+
 define float @fadd_fneg_commute0(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fadd_fneg_commute0(
 ; CHECK-NEXT:    [[N:%.*]] = fneg float [[X:%.*]]