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 @@ -5471,9 +5471,6 @@ (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) return Op0; - if (!isDefaultFPEnvironment(ExBehavior, Rounding)) - return nullptr; - if (FMF.noNaNs()) { // With nnan: X + {+/-}Inf --> {+/-}Inf if (match(Op1, m_Inf())) @@ -5486,22 +5483,27 @@ // X = -0.0: ( 0.0 - (-0.0)) + (-0.0) == ( 0.0) + (-0.0) == 0.0 // X = 0.0: (-0.0 - ( 0.0)) + ( 0.0) == (-0.0) + ( 0.0) == 0.0 // X = 0.0: ( 0.0 - ( 0.0)) + ( 0.0) == ( 0.0) + ( 0.0) == 0.0 - if (match(Op0, m_FSub(m_AnyZeroFP(), m_Specific(Op1))) || - match(Op1, m_FSub(m_AnyZeroFP(), m_Specific(Op0)))) - return ConstantFP::getNullValue(Op0->getType()); + // TODO: Constrained intrinsics can have differing rounding modes. + // TODO: This complicates the set of cases. + if (isDefaultFPEnvironment(ExBehavior, Rounding)) + if (match(Op0, m_FSub(m_AnyZeroFP(), m_Specific(Op1))) || + match(Op1, m_FSub(m_AnyZeroFP(), m_Specific(Op0)))) + return ConstantFP::getNullValue(Op0->getType()); - if (match(Op0, m_FNeg(m_Specific(Op1))) || - match(Op1, m_FNeg(m_Specific(Op0)))) - return ConstantFP::getNullValue(Op0->getType()); + if (isDefaultFPEnvironment(ExBehavior, Rounding)) + if (match(Op0, m_FNeg(m_Specific(Op1))) || + match(Op1, m_FNeg(m_Specific(Op0)))) + return ConstantFP::getNullValue(Op0->getType()); } // (X - Y) + Y --> X // Y + (X - Y) --> X Value *X; - if (FMF.noSignedZeros() && FMF.allowReassoc() && - (match(Op0, m_FSub(m_Value(X), m_Specific(Op1))) || - match(Op1, m_FSub(m_Value(X), m_Specific(Op0))))) - return X; + if (isDefaultFPEnvironment(ExBehavior, Rounding)) + if (FMF.noSignedZeros() && FMF.allowReassoc() && + (match(Op0, m_FSub(m_Value(X), m_Specific(Op1))) || + match(Op1, m_FSub(m_Value(X), m_Specific(Op0))))) + return X; return nullptr; } diff --git a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll --- a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll +++ b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll @@ -44,6 +44,78 @@ ret <2 x float> %r } +; fadd Inf, X -> Inf +define double @fadd_nnan_inf_op0_defaultenv(double %x) #0 { +; CHECK-LABEL: @fadd_nnan_inf_op0_defaultenv( +; CHECK-NEXT: ret double 0x7FF0000000000000 +; + %r = call nnan double @llvm.experimental.constrained.fadd.f64(double 0x7ff0000000000000, double %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %r +} + +define double @fadd_nnan_inf_op0_dynamic(double %x) #0 { +; CHECK-LABEL: @fadd_nnan_inf_op0_dynamic( +; CHECK-NEXT: [[R:%.*]] = call nnan double @llvm.experimental.constrained.fadd.f64(double 0x7FF0000000000000, double [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret double [[R]] +; + %r = call nnan double @llvm.experimental.constrained.fadd.f64(double 0x7ff0000000000000, double %x, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + ret double %r +} + +define double @fadd_nnan_inf_op0_maytrap(double %x) #0 { +; CHECK-LABEL: @fadd_nnan_inf_op0_maytrap( +; CHECK-NEXT: [[R:%.*]] = call nnan double @llvm.experimental.constrained.fadd.f64(double 0x7FF0000000000000, double [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] +; CHECK-NEXT: ret double [[R]] +; + %r = call nnan double @llvm.experimental.constrained.fadd.f64(double 0x7ff0000000000000, double %x, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 + ret double %r +} + +define double @fadd_nnan_inf_op0_strict(double %x) #0 { +; CHECK-LABEL: @fadd_nnan_inf_op0_strict( +; CHECK-NEXT: [[R:%.*]] = call nnan double @llvm.experimental.constrained.fadd.f64(double 0x7FF0000000000000, double [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: ret double [[R]] +; + %r = call nnan double @llvm.experimental.constrained.fadd.f64(double 0x7ff0000000000000, double %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret double %r +} + +; fadd X, Inf -> Inf +define double @fadd_nnan_inf_op1_defaultenv(double %x) #0 { +; CHECK-LABEL: @fadd_nnan_inf_op1_defaultenv( +; CHECK-NEXT: ret double 0x7FF0000000000000 +; + %r = call nnan double @llvm.experimental.constrained.fadd.f64(double %x, double 0x7ff0000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %r +} + +define double @fadd_nnan_inf_op1_dynamic(double %x) #0 { +; CHECK-LABEL: @fadd_nnan_inf_op1_dynamic( +; CHECK-NEXT: ret double 0x7FF0000000000000 +; + %r = call nnan double @llvm.experimental.constrained.fadd.f64(double %x, double 0x7ff0000000000000, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + ret double %r +} + +define double @fadd_nnan_inf_op1_maytrap(double %x) #0 { +; CHECK-LABEL: @fadd_nnan_inf_op1_maytrap( +; CHECK-NEXT: ret double 0x7FF0000000000000 +; + %r = call nnan double @llvm.experimental.constrained.fadd.f64(double %x, double 0x7ff0000000000000, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 + ret double %r +} + +define double @fadd_nnan_inf_op1_strict(double %x) #0 { +; CHECK-LABEL: @fadd_nnan_inf_op1_strict( +; CHECK-NEXT: [[R:%.*]] = call nnan double @llvm.experimental.constrained.fadd.f64(double [[X:%.*]], double 0x7FF0000000000000, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: ret double 0x7FF0000000000000 +; + %r = call nnan double @llvm.experimental.constrained.fadd.f64(double %x, double 0x7ff0000000000000, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret double %r +} + + + ; fsub -0.0, (fsub -0.0, X) ==> X define float @fsub_-0_-0_x(float %a) #0 { ; CHECK-LABEL: @fsub_-0_-0_x( @@ -523,6 +595,7 @@ declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) #0 declare <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 +declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) #0 declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata) #0 declare <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0