diff --git a/llvm/include/llvm/IR/FPEnv.h b/llvm/include/llvm/IR/FPEnv.h --- a/llvm/include/llvm/IR/FPEnv.h +++ b/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 diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4927,6 +4927,11 @@ return nullptr; } +// TODO: Move this out to a header file: +static inline bool canIgnoreSNaN(fp::ExceptionBehavior EB, FastMathFlags FMF) { + return (EB == fp::ebIgnore || FMF.noNaNs()); +} + /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. static Value * @@ -4941,13 +4946,16 @@ if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; + // fadd X, -0 ==> X + if (canIgnoreSNaN(ExBehavior, FMF) && + (!RoundingModeMayBe(Rounding, RoundingMode::TowardNegative) || + FMF.noSignedZeros())) + if (match(Op1, m_NegZeroFP())) + return Op0; + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) return nullptr; - // fadd X, -0 ==> X - 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))) diff --git a/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll b/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll --- a/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll +++ b/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll @@ -101,8 +101,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 +111,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 @@ -121,8 +119,7 @@ define float @fadd_nnan_x_n0_ebmaytrap(float %a) #0 { ; CHECK-LABEL: @fadd_nnan_x_n0_ebmaytrap( -; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fadd.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.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 ret float %ret @@ -130,8 +127,7 @@ define <2 x float> @fadd_vec_nnan_x_n0_ebmaytrap(<2 x float> %a) #0 { ; CHECK-LABEL: @fadd_vec_nnan_x_n0_ebmaytrap( -; 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.maytrap") #[[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.maytrap") #0 ret <2 x float> %ret @@ -140,7 +136,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 @@ -149,7 +145,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