Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ 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; } Index: llvm/test/Transforms/InstCombine/fneg.ll =================================================================== --- llvm/test/Transforms/InstCombine/fneg.ll +++ 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,12 +470,11 @@ 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,