Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -5027,42 +5027,46 @@ if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; - if (!isDefaultFPEnvironment(ExBehavior, Rounding)) - return nullptr; - // fsub X, +0 ==> X - if (match(Op1, m_PosZeroFP())) - return Op0; + if (canIgnoreSNaN(ExBehavior, FMF)) + if (match(Op1, m_PosZeroFP())) + return Op0; // fsub X, -0 ==> X, when we know X is not -0 - if (match(Op1, m_NegZeroFP()) && - (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) - return Op0; + if (canIgnoreSNaN(ExBehavior, FMF)) + if (match(Op1, m_NegZeroFP()) && + (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) + return Op0; // fsub -0.0, (fsub -0.0, X) ==> X // fsub -0.0, (fneg X) ==> X Value *X; - if (match(Op0, m_NegZeroFP()) && - match(Op1, m_FNeg(m_Value(X)))) - return X; + if (canIgnoreSNaN(ExBehavior, FMF)) + if (match(Op0, m_NegZeroFP()) && + match(Op1, m_FNeg(m_Value(X)))) + return X; // fsub 0.0, (fsub 0.0, X) ==> X if signed zeros are ignored. // fsub 0.0, (fneg X) ==> X if signed zeros are ignored. - if (FMF.noSignedZeros() && match(Op0, m_AnyZeroFP()) && - (match(Op1, m_FSub(m_AnyZeroFP(), m_Value(X))) || - match(Op1, m_FNeg(m_Value(X))))) - return X; + if (canIgnoreSNaN(ExBehavior, FMF)) + if (FMF.noSignedZeros() && match(Op0, m_AnyZeroFP()) && + (match(Op1, m_FSub(m_AnyZeroFP(), m_Value(X))) || + match(Op1, m_FNeg(m_Value(X))))) + return X; // fsub nnan x, x ==> 0.0 - if (FMF.noNaNs() && Op0 == Op1) - return Constant::getNullValue(Op0->getType()); + if (!canRoundingModeBe(Rounding, RoundingMode::TowardNegative) || + FMF.noSignedZeros()) + if (FMF.noNaNs() && Op0 == Op1) + return Constant::getNullValue(Op0->getType()); // Y - (Y - X) --> X // (X + Y) - Y --> X - if (FMF.noSignedZeros() && FMF.allowReassoc() && - (match(Op1, m_FSub(m_Specific(Op0), m_Value(X))) || - match(Op0, m_c_FAdd(m_Specific(Op1), m_Value(X))))) - return X; + if (canIgnoreSNaN(ExBehavior, FMF)) + if (FMF.noSignedZeros() && FMF.allowReassoc() && + (match(Op1, m_FSub(m_Specific(Op0), m_Value(X))) || + match(Op0, m_c_FAdd(m_Specific(Op1), m_Value(X))))) + return X; return nullptr; } Index: llvm/test/Transforms/InstSimplify/strictfp-fsub.ll =================================================================== --- llvm/test/Transforms/InstSimplify/strictfp-fsub.ll +++ llvm/test/Transforms/InstSimplify/strictfp-fsub.ll @@ -27,11 +27,9 @@ ret float %ret } -; TODO: This will fold if we allow non-default floating point environments. define float @fsub_nnan_x_p0_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fsub_nnan_x_p0_ebmaytrap( -; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float [[A:%.*]] ; %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 ret float %ret @@ -47,12 +45,10 @@ ret float %ret } -; TODO: This will fold if we allow non-default floating point environments. -; TODO: The instruction is expected to remain, but the result isn't used. define float @fsub_nnan_x_p0_ebstrict(float %a) #0 { ; CHECK-LABEL: @fsub_nnan_x_p0_ebstrict( ; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float [[A]] ; %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %ret @@ -91,11 +87,9 @@ ret float %sub } -; TODO: This will fold if we allow non-default floating point environments. define float @fold_fsub_nnan_nsz_x_n0_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fold_fsub_nnan_nsz_x_n0_ebmaytrap( -; CHECK-NEXT: [[SUB:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[SUB]] +; CHECK-NEXT: ret float [[A:%.*]] ; %sub = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 ret float %sub @@ -111,12 +105,10 @@ ret float %sub } -; TODO: This will fold if we allow non-default floating point environments. -; TODO: The instruction is expected to remain, but the result isn't used. define float @fold_fsub_nsz_nnan_x_n0_ebstrict(float %a) #0 { ; CHECK-LABEL: @fold_fsub_nsz_nnan_x_n0_ebstrict( ; CHECK-NEXT: [[SUB:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[SUB]] +; CHECK-NEXT: ret float [[A]] ; %sub = call nsz nnan float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %sub @@ -149,12 +141,10 @@ ret float %sub } -; TODO: This will fold if we allow non-default floating point environments. define float @fold_fsub_fabs_nnan_x_n0_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fold_fsub_fabs_nnan_x_n0_ebmaytrap( ; CHECK-NEXT: [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) -; CHECK-NEXT: [[SUB:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[ABSA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[SUB]] +; CHECK-NEXT: ret float [[ABSA]] ; %absa = call float @llvm.fabs.f32(float %a) %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 @@ -173,13 +163,11 @@ ret float %sub } -; TODO: This will fold if we allow non-default floating point environments. -; TODO: The instruction is expected to remain, but the result isn't used. define float @fold_fsub_fabs_nnan_x_n0_ebstrict(float %a) #0 { ; CHECK-LABEL: @fold_fsub_fabs_nnan_x_n0_ebstrict( ; CHECK-NEXT: [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) ; CHECK-NEXT: [[SUB:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[ABSA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[SUB]] +; CHECK-NEXT: ret float [[ABSA]] ; %absa = call float @llvm.fabs.f32(float %a) %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 @@ -223,12 +211,9 @@ ret float %ret } -; TODO: This will fold if we allow non-default floating point environments. define float @fsub_fneg_nnan_n0_fnX_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fsub_fneg_nnan_n0_fnX_ebmaytrap( -; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] -; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float [[A:%.*]] ; %nega = fneg float %a %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 @@ -247,13 +232,11 @@ ret float %ret } -; TODO: This will fold if we allow non-default floating point environments. -; TODO: The instruction is expected to remain, but the result isn't used. define float @fsub_fneg_nnan_n0_fnX_ebstrict(float %a) #0 { ; CHECK-LABEL: @fsub_fneg_nnan_n0_fnX_ebstrict( ; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] ; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float [[A]] ; %nega = fneg float %a %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 @@ -349,12 +332,9 @@ ret float %ret } -; TODO: This will fold if we allow non-default floating point environments. define float @fsub_fneg_nsz_nnan_p0_fnX_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fsub_fneg_nsz_nnan_p0_fnX_ebmaytrap( -; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] -; CHECK-NEXT: [[RET:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float [[A:%.*]] ; %nega = fneg float %a %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 @@ -373,13 +353,11 @@ ret float %ret } -; TODO: This will fold if we allow non-default floating point environments. -; TODO: The instruction is expected to remain, but the result isn't used. define float @fsub_fneg_nnan_nsz_p0_fnX_ebstrict(float %a) #0 { ; CHECK-LABEL: @fsub_fneg_nnan_nsz_p0_fnX_ebstrict( ; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] ; CHECK-NEXT: [[RET:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float [[A]] ; %nega = fneg float %a %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 @@ -482,11 +460,9 @@ ret float %ret } -; TODO: This will fold if we allow non-default floating point environments. define float @fsub_nnan_x_x_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fsub_nnan_x_x_ebmaytrap( -; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float 0.000000e+00 ; %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 ret float %ret @@ -502,12 +478,10 @@ ret float %ret } -; TODO: This will fold if we allow non-default floating point environments. -; TODO: The instruction is expected to remain, but the result isn't used. define float @fsub_nnan_x_x_ebstrict(float %a) #0 { ; CHECK-LABEL: @fsub_nnan_x_x_ebstrict( ; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float 0.000000e+00 ; %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %ret