From 0ade2abdb01f4a16b1f08d1a78d664b9e9d5f3b5 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 22 Jan 2020 09:29:19 -0500 Subject: [PATCH] [InstCombine] fneg(X + C) --> -C - X This is 1 of the potential folds uncovered by extending D72521. We don't seem to do this in the backend either (unless I'm not seeing some target-specific transform). icc and gcc (appears to be target-specific) do this transform. Differential Revision: https://reviews.llvm.org/D73057 --- .../Transforms/InstCombine/InstCombineAddSub.cpp | 6 +++ llvm/test/Transforms/InstCombine/fneg.ll | 50 ++++++++++++++++------ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 6eaae8f..d707dbf 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -2132,6 +2132,12 @@ static Instruction *foldFNegIntoConstant(Instruction &I) { 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 index fde5577..01949e8 100644 --- a/llvm/test/Transforms/InstCombine/fneg.ll +++ b/llvm/test/Transforms/InstCombine/fneg.ll @@ -378,6 +378,8 @@ define float @fneg_fneg_sel_extra_use3(float %x, float %y, i1 %cond) { 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 @@ define float @fneg_fadd_constant(float %x) { 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 @@ define float @fake_nsz_fadd_constant(float %x) { 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 @@ define float @fneg_nsz_fadd_constant(float %x) { 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 @@ define float @fake_fneg_nsz_fadd_constant(float %x) { 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 @@ define float @fneg_nsz_fadd_constant_extra_use(float %x) { 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 @@ define float @fake_fneg_nsz_fadd_constant_extra_use(float %x) { 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 @@ define <2 x float> @fneg_nsz_fadd_constant_vec(<2 x float> %x) { 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 +} -- 2.7.4