[InstCombine] fold fsub+fneg with fdiv/fmul between

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
This commit is contained in:
Sanjay Patel
2019-07-28 17:10:06 +00:00
parent 2bfd03119c
commit f40aeae387
2 changed files with 23 additions and 8 deletions
@@ -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);
+8 -8
View 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