Index: llvm/include/llvm/IR/FPEnv.h =================================================================== --- llvm/include/llvm/IR/FPEnv.h +++ llvm/include/llvm/IR/FPEnv.h @@ -58,5 +58,11 @@ inline bool isDefaultFPEnvironment(fp::ExceptionBehavior EB, RoundingMode RM) { return EB == fp::ebIgnore && RM == RoundingMode::NearestTiesToEven; } + +/// Returns true if the rounding mode RM may be QRM at compile time or +/// at run time. +inline bool RoundingModeMayBe(RoundingMode RM, RoundingMode QRM) { + return RM == QRM || RM == RoundingMode::Dynamic; +} } #endif Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -4902,17 +4902,22 @@ if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; - if (!isDefaultFPEnvironment(ExBehavior, Rounding)) - return nullptr; - // fadd X, -0 ==> X - if (match(Op1, m_NegZeroFP())) - return Op0; + if (isDefaultFPEnvironment(ExBehavior, Rounding) || + (!RoundingModeMayBe(Rounding, RoundingMode::TowardNegative) && + (ExBehavior != fp::ebStrict || FMF.noNaNs()))) + if (match(Op1, m_NegZeroFP())) + return Op0; // fadd X, 0 ==> X, when we know X is not -0 - if (match(Op1, m_PosZeroFP()) && - (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) - return Op0; + if (isDefaultFPEnvironment(ExBehavior, Rounding) || + (ExBehavior != fp::ebStrict || FMF.noNaNs())) + if (match(Op1, m_PosZeroFP()) && + (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) + return Op0; + + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) + return nullptr; // With nnan: -X + X --> 0.0 (and commuted variant) // We don't have to explicitly exclude infinities (ninf): INF + -INF == NaN. Index: llvm/test/Transforms/InstSimplify/strictfp-fadd.ll =================================================================== --- llvm/test/Transforms/InstSimplify/strictfp-fadd.ll +++ llvm/test/Transforms/InstSimplify/strictfp-fadd.ll @@ -27,8 +27,7 @@ define float @fadd_x_n0_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fadd_x_n0_ebmaytrap( -; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0:[0-9]+]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float [[A:%.*]] ; %ret = call float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 ret float %ret @@ -36,8 +35,7 @@ define <2 x float> @fadd_vec_x_n0_ebmaytrap(<2 x float> %a) #0 { ; CHECK-LABEL: @fadd_vec_x_n0_ebmaytrap( -; CHECK-NEXT: [[RET:%.*]] = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> , metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[RET]] +; CHECK-NEXT: ret <2 x float> [[A:%.*]] ; %ret = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float>, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 ret <2 x float> %ret @@ -45,7 +43,7 @@ define float @fadd_x_n0_ebstrict(float %a) #0 { ; CHECK-LABEL: @fadd_x_n0_ebstrict( -; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0:[0-9]+]] ; CHECK-NEXT: ret float [[RET]] ; %ret = call float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 @@ -101,8 +99,7 @@ ; Test one of the remaining rounding modes and the rest will be fine. define float @fadd_x_n0_towardzero(float %a) #0 { ; CHECK-LABEL: @fadd_x_n0_towardzero( -; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.towardzero", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[RET]] +; CHECK-NEXT: ret float [[A:%.*]] ; %ret = call float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0 ret float %ret @@ -112,8 +109,7 @@ ; Test one of the remaining rounding modes and the rest will be fine. define <2 x float> @fadd_vec_x_n0_towardzero(<2 x float> %a) #0 { ; CHECK-LABEL: @fadd_vec_x_n0_towardzero( -; CHECK-NEXT: [[RET:%.*]] = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> , metadata !"round.towardzero", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[RET]] +; CHECK-NEXT: ret <2 x float> [[A:%.*]] ; %ret = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float>, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0 ret <2 x float> %ret @@ -122,7 +118,7 @@ define float @fadd_nnan_x_n0_ebstrict(float %a) #0 { ; CHECK-LABEL: @fadd_nnan_x_n0_ebstrict( ; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fadd.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.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %ret @@ -131,7 +127,7 @@ define <2 x float> @fadd_vec_nnan_x_n0_ebstrict(<2 x float> %a) #0 { ; CHECK-LABEL: @fadd_vec_nnan_x_n0_ebstrict( ; CHECK-NEXT: [[RET:%.*]] = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> , metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[RET]] +; CHECK-NEXT: ret <2 x float> [[A]] ; %ret = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float>, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret <2 x float> %ret @@ -215,8 +211,7 @@ define float @fold_fadd_nsz_x_0_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fold_fadd_nsz_x_0_ebmaytrap( -; CHECK-NEXT: [[ADD:%.*]] = call nsz float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[ADD]] +; CHECK-NEXT: ret float [[A:%.*]] ; %add = call nsz float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 ret float %add @@ -224,8 +219,7 @@ define <2 x float> @fold_fadd_vec_nsz_x_0_ebmaytrap(<2 x float> %a) #0 { ; CHECK-LABEL: @fold_fadd_vec_nsz_x_0_ebmaytrap( -; CHECK-NEXT: [[ADD:%.*]] = call nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> zeroinitializer, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[ADD]] +; CHECK-NEXT: ret <2 x float> [[A:%.*]] ; %add = call nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float> zeroinitializer, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 ret <2 x float> %add @@ -252,7 +246,7 @@ define float @fold_fadd_nsz_nnan_x_0_ebstrict(float %a) #0 { ; CHECK-LABEL: @fold_fadd_nsz_nnan_x_0_ebstrict( ; CHECK-NEXT: [[ADD:%.*]] = call nnan nsz float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[ADD]] +; CHECK-NEXT: ret float [[A]] ; %add = call nsz nnan float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %add @@ -261,7 +255,7 @@ define <2 x float> @fold_fadd_vec_nsz_nnan_x_0_ebstrict(<2 x float> %a) #0 { ; CHECK-LABEL: @fold_fadd_vec_nsz_nnan_x_0_ebstrict( ; CHECK-NEXT: [[ADD:%.*]] = call nnan nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> zeroinitializer, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[ADD]] +; CHECK-NEXT: ret <2 x float> [[A]] ; %add = call nsz nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float> zeroinitializer, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret <2 x float> %add