Skip to content

Commit f86c930

Browse files
committed
[FPEnv][InstSimplify] Fold constrained X + -0.0 ==> X
Currently the fadd optimizations in InstSimplify don't know how to do this "X + -0.0 ==> X" fold when using the constrained intrinsics. This adds the support. This commit is derived from D106362 with some improvements from D107285. Differential Revision: https://reviews.llvm.org/D111085
1 parent a2796f1 commit f86c930

File tree

3 files changed

+28
-14
lines changed

3 files changed

+28
-14
lines changed

llvm/include/llvm/IR/FPEnv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,11 @@ Optional<StringRef> ExceptionBehaviorToStr(fp::ExceptionBehavior);
5858
inline bool isDefaultFPEnvironment(fp::ExceptionBehavior EB, RoundingMode RM) {
5959
return EB == fp::ebIgnore && RM == RoundingMode::NearestTiesToEven;
6060
}
61+
62+
/// Returns true if the rounding mode RM may be QRM at compile time or
63+
/// at run time.
64+
inline bool canRoundingModeBe(RoundingMode RM, RoundingMode QRM) {
65+
return RM == QRM || RM == RoundingMode::Dynamic;
66+
}
6167
}
6268
#endif

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4935,6 +4935,11 @@ static Constant *simplifyFPOp(ArrayRef<Value *> Ops, FastMathFlags FMF,
49354935
return nullptr;
49364936
}
49374937

4938+
// TODO: Move this out to a header file:
4939+
static inline bool canIgnoreSNaN(fp::ExceptionBehavior EB, FastMathFlags FMF) {
4940+
return (EB == fp::ebIgnore || FMF.noNaNs());
4941+
}
4942+
49384943
/// Given operands for an FAdd, see if we can fold the result. If not, this
49394944
/// returns null.
49404945
static Value *
@@ -4949,13 +4954,20 @@ SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
49494954
if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding))
49504955
return C;
49514956

4957+
// fadd X, -0 ==> X
4958+
// With strict/constrained FP, we have these possible edge cases that do
4959+
// not simplify to Op0:
4960+
// fadd SNaN, -0.0 --> QNaN
4961+
// fadd +0.0, -0.0 --> -0.0 (but only with round toward negative)
4962+
if (canIgnoreSNaN(ExBehavior, FMF) &&
4963+
(!canRoundingModeBe(Rounding, RoundingMode::TowardNegative) ||
4964+
FMF.noSignedZeros()))
4965+
if (match(Op1, m_NegZeroFP()))
4966+
return Op0;
4967+
49524968
if (!isDefaultFPEnvironment(ExBehavior, Rounding))
49534969
return nullptr;
49544970

4955-
// fadd X, -0 ==> X
4956-
if (match(Op1, m_NegZeroFP()))
4957-
return Op0;
4958-
49594971
// fadd X, 0 ==> X, when we know X is not -0
49604972
if (match(Op1, m_PosZeroFP()) &&
49614973
(FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI)))

llvm/test/Transforms/InstSimplify/strictfp-fadd.ll

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,7 @@ define <2 x float> @fadd_vec_x_n0_dynamic(<2 x float> %a) #0 {
101101
; Test one of the remaining rounding modes and the rest will be fine.
102102
define float @fadd_x_n0_towardzero(float %a) #0 {
103103
; CHECK-LABEL: @fadd_x_n0_towardzero(
104-
; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.towardzero", metadata !"fpexcept.ignore") #[[ATTR0]]
105-
; CHECK-NEXT: ret float [[RET]]
104+
; CHECK-NEXT: ret float [[A:%.*]]
106105
;
107106
%ret = call float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0
108107
ret float %ret
@@ -112,26 +111,23 @@ define float @fadd_x_n0_towardzero(float %a) #0 {
112111
; Test one of the remaining rounding modes and the rest will be fine.
113112
define <2 x float> @fadd_vec_x_n0_towardzero(<2 x float> %a) #0 {
114113
; CHECK-LABEL: @fadd_vec_x_n0_towardzero(
115-
; 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]]
116-
; CHECK-NEXT: ret <2 x float> [[RET]]
114+
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
117115
;
118116
%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
119117
ret <2 x float> %ret
120118
}
121119

122120
define float @fadd_nnan_x_n0_ebmaytrap(float %a) #0 {
123121
; CHECK-LABEL: @fadd_nnan_x_n0_ebmaytrap(
124-
; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]]
125-
; CHECK-NEXT: ret float [[RET]]
122+
; CHECK-NEXT: ret float [[A:%.*]]
126123
;
127124
%ret = call nnan float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0
128125
ret float %ret
129126
}
130127

131128
define <2 x float> @fadd_vec_nnan_x_n0_ebmaytrap(<2 x float> %a) #0 {
132129
; CHECK-LABEL: @fadd_vec_nnan_x_n0_ebmaytrap(
133-
; 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]]
134-
; CHECK-NEXT: ret <2 x float> [[RET]]
130+
; CHECK-NEXT: ret <2 x float> [[A:%.*]]
135131
;
136132
%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
137133
ret <2 x float> %ret
@@ -140,7 +136,7 @@ define <2 x float> @fadd_vec_nnan_x_n0_ebmaytrap(<2 x float> %a) #0 {
140136
define float @fadd_nnan_x_n0_ebstrict(float %a) #0 {
141137
; CHECK-LABEL: @fadd_nnan_x_n0_ebstrict(
142138
; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
143-
; CHECK-NEXT: ret float [[RET]]
139+
; CHECK-NEXT: ret float [[A]]
144140
;
145141
%ret = call nnan float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
146142
ret float %ret
@@ -149,7 +145,7 @@ define float @fadd_nnan_x_n0_ebstrict(float %a) #0 {
149145
define <2 x float> @fadd_vec_nnan_x_n0_ebstrict(<2 x float> %a) #0 {
150146
; CHECK-LABEL: @fadd_vec_nnan_x_n0_ebstrict(
151147
; 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]]
152-
; CHECK-NEXT: ret <2 x float> [[RET]]
148+
; CHECK-NEXT: ret <2 x float> [[A]]
153149
;
154150
%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
155151
ret <2 x float> %ret

0 commit comments

Comments
 (0)