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 *
if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding))
return C;
+ // fadd X, -0 ==> X
+ // With strict/constrained FP, we have these possible edge cases that do
+ // not simplify to Op0:
+ // fadd SNaN, -0.0 --> QNaN
+ // fadd +0.0, -0.0 --> -0.0 (but only with round toward negative)
+ if (canIgnoreSNaN(ExBehavior, FMF) &&
+ (!canRoundingModeBe(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)))
; 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
; 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> <float -0.000000e+00, float -0.000000e+00>, 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><float -0.0, float -0.0>, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0
ret <2 x float> %ret
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
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> <float -0.000000e+00, float -0.000000e+00>, 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><float -0.0, float -0.0>, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0
ret <2 x float> %ret
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
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> <float -0.000000e+00, float -0.000000e+00>, 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><float -0.0, float -0.0>, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
ret <2 x float> %ret