diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 22 | ||||
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 20 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/fadd.ll | 32 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/fdiv.ll | 16 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/fmul.ll | 55 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/fsub.ll | 24 | ||||
| -rw-r--r-- | llvm/test/Transforms/Reassociate/fast-basictest.ll | 21 |
7 files changed, 101 insertions, 89 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 328c5021967..9c1c0c93480 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1900,6 +1900,22 @@ static Instruction *foldFNegIntoConstant(Instruction &I) { 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(UnaryOperator &I) { 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(BinaryOperator &I) { if (Instruction *X = foldFNegIntoConstant(I)) return X; + if (Instruction *R = hoistFNegAboveFMulFDiv(I, Builder)) + return R; + Value *X, *Y; Constant *C; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 7939bbf5ca6..9e761c9e538 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -373,16 +373,6 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { 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(BinaryOperator &I) { 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. diff --git a/llvm/test/Transforms/InstCombine/fadd.ll b/llvm/test/Transforms/InstCombine/fadd.ll index 50022db9c52..24a22dc52ff 100644 --- a/llvm/test/Transforms/InstCombine/fadd.ll +++ b/llvm/test/Transforms/InstCombine/fadd.ll @@ -160,15 +160,15 @@ define double @fmul_fneg2_commute(double %x, double %py, double %pz) { 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 %x, float %y, float %pz) { 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 %x, float %py, float %pz) { 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(<2 x float> %x, <2 x float> %y, <2 x fl 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 diff --git a/llvm/test/Transforms/InstCombine/fdiv.ll b/llvm/test/Transforms/InstCombine/fdiv.ll index 468df8dd6a1..777bdca87e6 100644 --- a/llvm/test/Transforms/InstCombine/fdiv.ll +++ b/llvm/test/Transforms/InstCombine/fdiv.ll @@ -501,8 +501,8 @@ define <2 x float> @div_constant_dividend3(<2 x float> %x) { 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, double %y) { 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 %x, double %y) { 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 float> %x, <2 x float> %y) { 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 diff --git a/llvm/test/Transforms/InstCombine/fmul.ll b/llvm/test/Transforms/InstCombine/fmul.ll index 99b67dfa845..d448679804f 100644 --- a/llvm/test/Transforms/InstCombine/fmul.ll +++ b/llvm/test/Transforms/InstCombine/fmul.ll @@ -277,11 +277,11 @@ define float @neg_unary_neg_multi_use(float %x, float %y) { 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 %y) { 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, float %y) { 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 float> %x, <2 x float> %y) { 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(<2 x float> %x, <2 x float> %y) { 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(<2 x float> %x, <2 x float> %y) { 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, float %y) { 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 %x, float %y) { 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]] diff --git a/llvm/test/Transforms/InstCombine/fsub.ll b/llvm/test/Transforms/InstCombine/fsub.ll index a08a2944d62..80582cf2b73 100644 --- a/llvm/test/Transforms/InstCombine/fsub.ll +++ b/llvm/test/Transforms/InstCombine/fsub.ll @@ -454,10 +454,10 @@ define double @fsub_fmul_fneg2(double %x, double %y, double %z) { 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(float %x, float %y, float %z) { 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_extra_use(<2 x float> %x, <2 x float> %y, <2 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 diff --git a/llvm/test/Transforms/Reassociate/fast-basictest.ll b/llvm/test/Transforms/Reassociate/fast-basictest.ll index a01b805a6fa..62b13f41b2b 100644 --- a/llvm/test/Transforms/Reassociate/fast-basictest.ll +++ b/llvm/test/Transforms/Reassociate/fast-basictest.ll @@ -614,12 +614,25 @@ define float @test18_reassoc(float %a, float %b, float %z) { 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 |

