forked from OSchip/llvm-project
[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. llvm-svn: 367194
This commit is contained in:
parent
2c8098374b
commit
99c57c6daf
|
@ -1964,6 +1964,21 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) {
|
||||||
if (match(Op1, m_OneUse(m_FPExt(m_FNeg(m_Value(Y))))))
|
if (match(Op1, m_OneUse(m_FPExt(m_FNeg(m_Value(Y))))))
|
||||||
return BinaryOperator::CreateFAddFMF(Op0, Builder.CreateFPExt(Y, Ty), &I);
|
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
|
// Handle special cases for FSub with selects feeding the operation
|
||||||
if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1))
|
if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1))
|
||||||
return replaceInstUsesWith(I, V);
|
return replaceInstUsesWith(I, V);
|
||||||
|
|
|
@ -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-LABEL: @fsub_fdiv_fneg1_extra_use2(
|
||||||
; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
|
; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
|
||||||
; CHECK-NEXT: call void @use(float [[NEG]])
|
; CHECK-NEXT: call void @use(float [[NEG]])
|
||||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
|
; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X]], [[Y:%.*]]
|
||||||
; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]
|
; CHECK-NEXT: [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
|
||||||
; CHECK-NEXT: ret float [[R]]
|
; CHECK-NEXT: ret float [[R]]
|
||||||
;
|
;
|
||||||
%neg = fsub float -0.000000e+00, %x
|
%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-LABEL: @fsub_fdiv_fneg2_extra_use2(
|
||||||
; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
|
; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
|
||||||
; CHECK-NEXT: call void @use(float [[NEG]])
|
; CHECK-NEXT: call void @use(float [[NEG]])
|
||||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]
|
; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X]]
|
||||||
; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]
|
; CHECK-NEXT: [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
|
||||||
; CHECK-NEXT: ret float [[R]]
|
; CHECK-NEXT: ret float [[R]]
|
||||||
;
|
;
|
||||||
%neg = fsub float -0.000000e+00, %x
|
%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-LABEL: @fsub_fmul_fneg1_extra_use2(
|
||||||
; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
|
; 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: call void @use_vec(<2 x float> [[NEG]])
|
||||||
; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[NEG]], [[Y:%.*]]
|
; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X]], [[Y:%.*]]
|
||||||
; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[MUL]]
|
; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[TMP1]], [[Z:%.*]]
|
||||||
; CHECK-NEXT: ret <2 x float> [[R]]
|
; CHECK-NEXT: ret <2 x float> [[R]]
|
||||||
;
|
;
|
||||||
%neg = fsub <2 x float> <float -0.0, float -0.0>, %x
|
%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-LABEL: @fsub_fmul_fneg2_extra_use2(
|
||||||
; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
|
; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
|
||||||
; CHECK-NEXT: call void @use(float [[NEG]])
|
; CHECK-NEXT: call void @use(float [[NEG]])
|
||||||
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NEG]], [[Y:%.*]]
|
; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X]], [[Y:%.*]]
|
||||||
; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[MUL]]
|
; CHECK-NEXT: [[R:%.*]] = fadd float [[TMP1]], [[Z:%.*]]
|
||||||
; CHECK-NEXT: ret float [[R]]
|
; CHECK-NEXT: ret float [[R]]
|
||||||
;
|
;
|
||||||
%neg = fsub float -0.000000e+00, %x
|
%neg = fsub float -0.000000e+00, %x
|
||||||
|
|
Loading…
Reference in New Issue