diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -2132,6 +2132,12 @@ if (match(&I, m_FNeg(m_OneUse(m_FDiv(m_Constant(C), m_Value(X)))))) return BinaryOperator::CreateFDivFMF(ConstantExpr::getFNeg(C), X, &I); + // With NSZ [ counter-example with -0.0: -(-0.0 + 0.0) != 0.0 + -0.0 ]: + // -(X + C) --> -X + -C --> -C - X + if (I.hasNoSignedZeros() && + match(&I, m_FNeg(m_OneUse(m_FAdd(m_Value(X), m_Constant(C)))))) + return BinaryOperator::CreateFSubFMF(ConstantExpr::getFNeg(C), X, &I); + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll --- a/llvm/test/Transforms/InstCombine/fneg.ll +++ b/llvm/test/Transforms/InstCombine/fneg.ll @@ -378,6 +378,8 @@ ret float %sel } +; Negative test + define float @fneg_fadd_constant(float %x) { ; CHECK-LABEL: @fneg_fadd_constant( ; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01 @@ -389,6 +391,8 @@ ret float %r } +; Negative test + define float @fake_nsz_fadd_constant(float %x) { ; CHECK-LABEL: @fake_nsz_fadd_constant( ; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01 @@ -400,12 +404,11 @@ ret float %r } -; TODO: -(X + C) --> -C - X +; -(X + C) --> -C - X define float @fneg_nsz_fadd_constant(float %x) { ; CHECK-LABEL: @fneg_nsz_fadd_constant( -; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01 -; CHECK-NEXT: [[R:%.*]] = fneg nsz float [[A]] +; CHECK-NEXT: [[R:%.*]] = fsub nsz float -4.200000e+01, [[X:%.*]] ; CHECK-NEXT: ret float [[R]] ; %a = fadd float %x, 42.0 @@ -413,12 +416,11 @@ ret float %r } -; TODO: -(X + C) --> -C - X +; -(X + C) --> -C - X define float @fake_fneg_nsz_fadd_constant(float %x) { ; CHECK-LABEL: @fake_fneg_nsz_fadd_constant( -; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01 -; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[A]] +; CHECK-NEXT: [[R:%.*]] = fsub fast float -4.200000e+01, [[X:%.*]] ; CHECK-NEXT: ret float [[R]] ; %a = fadd float %x, 42.0 @@ -426,6 +428,8 @@ ret float %r } +; Negative test + define float @fneg_nsz_fadd_constant_extra_use(float %x) { ; CHECK-LABEL: @fneg_nsz_fadd_constant_extra_use( ; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01 @@ -439,6 +443,8 @@ ret float %r } +; Negative test + define float @fake_fneg_nsz_fadd_constant_extra_use(float %x) { ; CHECK-LABEL: @fake_fneg_nsz_fadd_constant_extra_use( ; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01 @@ -452,12 +458,11 @@ ret float %r } -; TODO: -(X + C) --> -C - X +; -(X + C) --> -C - X define <2 x float> @fneg_nsz_fadd_constant_vec(<2 x float> %x) { ; CHECK-LABEL: @fneg_nsz_fadd_constant_vec( -; CHECK-NEXT: [[A:%.*]] = fadd <2 x float> [[X:%.*]], -; CHECK-NEXT: [[R:%.*]] = fneg reassoc nnan nsz <2 x float> [[A]] +; CHECK-NEXT: [[R:%.*]] = fsub reassoc nnan nsz <2 x float> , [[X:%.*]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %a = fadd <2 x float> %x, @@ -465,15 +470,36 @@ ret <2 x float> %r } -; TODO: -(X + C) --> -C - X +; -(X + C) --> -C - X define <2 x float> @fake_fneg_nsz_fadd_constant_vec(<2 x float> %x) { ; CHECK-LABEL: @fake_fneg_nsz_fadd_constant_vec( -; CHECK-NEXT: [[A:%.*]] = fadd <2 x float> [[X:%.*]], -; CHECK-NEXT: [[R:%.*]] = fsub nsz <2 x float> , [[A]] +; CHECK-NEXT: [[R:%.*]] = fsub nsz <2 x float> , [[X:%.*]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %a = fadd <2 x float> %x, %r = fsub nsz <2 x float> , %a ret <2 x float> %r } + +@g = external global i16, align 1 + +define float @fneg_nsz_fadd_constant_expr(float %x) { +; CHECK-LABEL: @fneg_nsz_fadd_constant_expr( +; CHECK-NEXT: [[R:%.*]] = fsub nsz float fneg (float bitcast (i32 ptrtoint (i16* @g to i32) to float)), [[X:%.*]] +; CHECK-NEXT: ret float [[R]] +; + %a = fadd float %x, bitcast (i32 ptrtoint (i16* @g to i32) to float) + %r = fneg nsz float %a + ret float %r +} + +define float @fake_fneg_nsz_fadd_constant_expr(float %x) { +; CHECK-LABEL: @fake_fneg_nsz_fadd_constant_expr( +; CHECK-NEXT: [[R:%.*]] = fsub nsz float fneg (float bitcast (i32 ptrtoint (i16* @g to i32) to float)), [[X:%.*]] +; CHECK-NEXT: ret float [[R]] +; + %a = fadd float %x, bitcast (i32 ptrtoint (i16* @g to i32) to float) + %r = fsub nsz float -0.0, %a + ret float %r +}