]> granicus.if.org Git - llvm/commitdiff
[InstCombine] fold fsub+fneg with fdiv/fmul between
authorSanjay Patel <spatel@rotateright.com>
Sun, 28 Jul 2019 17:10:06 +0000 (17:10 +0000)
committerSanjay Patel <spatel@rotateright.com>
Sun, 28 Jul 2019 17:10:06 +0000 (17:10 +0000)
The backend already does this via isNegatibleForFree(),
but we may want to alter the fneg IR canonicalizations
that currently exist, so we need to try harder to fold
fneg in IR to avoid regressions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@367194 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineAddSub.cpp
test/Transforms/InstCombine/fsub.ll

index 891370e2c766844c4c2b37ed701ca49aa751197d..9363a5e63e91ea0fa09962c211e965542bc7a7c1 100644 (file)
@@ -1964,6 +1964,21 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) {
   if (match(Op1, m_OneUse(m_FPExt(m_FNeg(m_Value(Y))))))
     return BinaryOperator::CreateFAddFMF(Op0, Builder.CreateFPExt(Y, Ty), &I);
 
+  // Similar to above, but look through fmul/fdiv of the negated value:
+  // Op0 - (-X * Y) --> Op0 + (X * Y)
+  // Op0 - (Y * -X) --> Op0 + (X * Y)
+  if (match(Op1, m_OneUse(m_c_FMul(m_FNeg(m_Value(X)), m_Value(Y))))) {
+    Value *FMul = Builder.CreateFMulFMF(X, Y, &I);
+    return BinaryOperator::CreateFAddFMF(Op0, FMul, &I);
+  }
+  // Op0 - (-X / Y) --> Op0 + (X / Y)
+  // Op0 - (X / -Y) --> Op0 + (X / Y)
+  if (match(Op1, m_OneUse(m_FDiv(m_FNeg(m_Value(X)), m_Value(Y)))) ||
+      match(Op1, m_OneUse(m_FDiv(m_Value(X), m_FNeg(m_Value(Y)))))) {
+    Value *FDiv = Builder.CreateFDivFMF(X, Y, &I);
+    return BinaryOperator::CreateFAddFMF(Op0, FDiv, &I);
+  }
+
   // Handle special cases for FSub with selects feeding the operation
   if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1))
     return replaceInstUsesWith(I, V);
index 57148cf5642be0c382ff84436b1bf3f434a8da61..a08a2944d6231c7e7c1be25cc115f14634d46c1e 100644 (file)
@@ -518,8 +518,8 @@ define float @fsub_fdiv_fneg1_extra_use2(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fsub_fdiv_fneg1_extra_use2(
 ; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
 ; CHECK-NEXT:    call void @use(float [[NEG]])
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[X]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %neg = fsub float -0.000000e+00, %x
@@ -533,8 +533,8 @@ define float @fsub_fdiv_fneg2_extra_use2(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fsub_fdiv_fneg2_extra_use2(
 ; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
 ; CHECK-NEXT:    call void @use(float [[NEG]])
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]
-; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X]]
+; CHECK-NEXT:    [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %neg = fsub float -0.000000e+00, %x
@@ -548,8 +548,8 @@ define <2 x float> @fsub_fmul_fneg1_extra_use2(<2 x float> %x, <2 x float> %y, <
 ; CHECK-LABEL: @fsub_fmul_fneg1_extra_use2(
 ; CHECK-NEXT:    [[NEG:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
 ; CHECK-NEXT:    call void @use_vec(<2 x float> [[NEG]])
-; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[MUL]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
@@ -563,8 +563,8 @@ define float @fsub_fmul_fneg2_extra_use2(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fsub_fmul_fneg2_extra_use2(
 ; CHECK-NEXT:    [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
 ; CHECK-NEXT:    call void @use(float [[NEG]])
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[MUL]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %neg = fsub float -0.000000e+00, %x