Skip to content

Commit e7c94ef

Browse files
committed
[ValueTracking] determine sign of 0.0 from select when matching min/max FP
In PR39475: https://bugs.llvm.org/show_bug.cgi?id=39475 ..we may fail to recognize/simplify fabs() in some cases because we do not canonicalize fcmp with a -0.0 operand. Adding that canonicalization can cause regressions on min/max FP tests, so that's this patch: for the purpose of determining whether something is min/max, let the value returned by the select determine how we treat a 0.0 operand in the fcmp. This patch doesn't actually change the -0.0 to +0.0. It just changes the analysis, so we don't fail to recognize equivalent min/max patterns that only differ in the signbit of 0.0. Differential Revision: https://reviews.llvm.org/D54001 llvm-svn: 346097
1 parent d96bdd2 commit e7c94ef

File tree

3 files changed

+89
-54
lines changed

3 files changed

+89
-54
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4760,6 +4760,27 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
47604760
Value *TrueVal, Value *FalseVal,
47614761
Value *&LHS, Value *&RHS,
47624762
unsigned Depth) {
4763+
if (CmpInst::isFPPredicate(Pred)) {
4764+
// IEEE-754 ignores the sign of 0.0 in comparisons. So if the select has one
4765+
// 0.0 operand, set the compare's 0.0 operands to that same value for the
4766+
// purpose of identifying min/max. Disregard vector constants with undefined
4767+
// elements because those can not be back-propagated for analysis.
4768+
Value *OutputZeroVal = nullptr;
4769+
if (match(TrueVal, m_AnyZeroFP()) && !match(FalseVal, m_AnyZeroFP()) &&
4770+
!cast<Constant>(TrueVal)->containsUndefElement())
4771+
OutputZeroVal = TrueVal;
4772+
else if (match(FalseVal, m_AnyZeroFP()) && !match(TrueVal, m_AnyZeroFP()) &&
4773+
!cast<Constant>(FalseVal)->containsUndefElement())
4774+
OutputZeroVal = FalseVal;
4775+
4776+
if (OutputZeroVal) {
4777+
if (match(CmpLHS, m_AnyZeroFP()))
4778+
CmpLHS = OutputZeroVal;
4779+
if (match(CmpRHS, m_AnyZeroFP()))
4780+
CmpRHS = OutputZeroVal;
4781+
}
4782+
}
4783+
47634784
LHS = CmpLHS;
47644785
RHS = CmpRHS;
47654786

llvm/test/Transforms/InstCombine/minmax-fp.ll

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -57,49 +57,44 @@ define double @t5(float %a) {
5757
ret double %3
5858
}
5959

60-
; TODO:
61-
; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = −0)."
60+
; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = -0)."
6261
; So the compare constant may be treated as +0.0, and we sink the fpext.
6362

6463
define double @t6(float %a) {
6564
; CHECK-LABEL: @t6(
66-
; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float [[A:%.*]], -0.000000e+00
67-
; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[A]] to double
68-
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double 0.000000e+00
69-
; CHECK-NEXT: ret double [[TMP3]]
65+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], 0.000000e+00
66+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float [[A]]
67+
; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double
68+
; CHECK-NEXT: ret double [[TMP2]]
7069
;
7170
%1 = fcmp ult float %a, -0.0
7271
%2 = fpext float %a to double
7372
%3 = select i1 %1, double %2, double 0.0
7473
ret double %3
7574
}
7675

77-
; TODO:
78-
; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = −0)."
76+
; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = -0)."
7977
; So the compare constant may be treated as -0.0, and we sink the fpext.
8078

8179
define double @t7(float %a) {
8280
; CHECK-LABEL: @t7(
83-
; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float [[A:%.*]], 0.000000e+00
84-
; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[A]] to double
85-
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double -0.000000e+00
86-
; CHECK-NEXT: ret double [[TMP3]]
81+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], -0.000000e+00
82+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float -0.000000e+00, float [[A]]
83+
; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double
84+
; CHECK-NEXT: ret double [[TMP2]]
8785
;
8886
%1 = fcmp ult float %a, 0.0
8987
%2 = fpext float %a to double
9088
%3 = select i1 %1, double %2, double -0.0
9189
ret double %3
9290
}
9391

94-
; TODO:
9592
; min(min(x, 0.0), 0.0) --> min(x, 0.0)
9693

9794
define float @fmin_fmin_zero_mismatch(float %x) {
9895
; CHECK-LABEL: @fmin_fmin_zero_mismatch(
99-
; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[X:%.*]], -0.000000e+00
100-
; CHECK-NEXT: [[MIN1:%.*]] = select i1 [[CMP1]], float [[X]], float 0.000000e+00
101-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[MIN1]], 0.000000e+00
102-
; CHECK-NEXT: [[MIN2:%.*]] = select i1 [[CMP2]], float [[MIN1]], float 0.000000e+00
96+
; CHECK-NEXT: [[TMP1:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
97+
; CHECK-NEXT: [[MIN2:%.*]] = select i1 [[TMP1]], float [[X]], float 0.000000e+00
10398
; CHECK-NEXT: ret float [[MIN2]]
10499
;
105100
%cmp1 = fcmp olt float %x, -0.0
@@ -109,16 +104,13 @@ define float @fmin_fmin_zero_mismatch(float %x) {
109104
ret float %min2
110105
}
111106

112-
; TODO:
113107
; max(max(x, -0.0), -0.0) --> max(x, -0.0)
114108

115109
define float @fmax_fmax_zero_mismatch(float %x) {
116110
; CHECK-LABEL: @fmax_fmax_zero_mismatch(
117-
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00
118-
; CHECK-NEXT: [[MAX1:%.*]] = select i1 [[CMP1]], float [[X]], float -0.000000e+00
119-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[MAX1]], 0.000000e+00
120-
; CHECK-NEXT: [[MAX2:%.*]] = select i1 [[CMP2]], float -0.000000e+00, float [[MAX1]]
121-
; CHECK-NEXT: ret float [[MAX2]]
111+
; CHECK-NEXT: [[TMP1:%.*]] = fcmp ogt float [[X:%.*]], -0.000000e+00
112+
; CHECK-NEXT: [[MAX11:%.*]] = select i1 [[TMP1]], float [[X]], float -0.000000e+00
113+
; CHECK-NEXT: ret float [[MAX11]]
122114
;
123115
%cmp1 = fcmp ogt float %x, 0.0
124116
%max1 = select i1 %cmp1, float %x, float -0.0

llvm/unittests/Analysis/ValueTrackingTest.cpp

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero1) {
156156
" %A = select i1 %1, float 0.0, float %a\n"
157157
" ret float %A\n"
158158
"}\n");
159-
// FIXME: The sign of zero doesn't matter in fcmp.
160-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
159+
// The sign of zero doesn't matter in fcmp.
160+
expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true});
161161
}
162162

163163
TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero2) {
@@ -167,8 +167,8 @@ TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero2) {
167167
" %A = select i1 %1, float 0.0, float %a\n"
168168
" ret float %A\n"
169169
"}\n");
170-
// FIXME: The sign of zero doesn't matter in fcmp.
171-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
170+
// The sign of zero doesn't matter in fcmp.
171+
expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
172172
}
173173

174174
TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero3) {
@@ -178,8 +178,8 @@ TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero3) {
178178
" %A = select i1 %1, float -0.0, float %a\n"
179179
" ret float %A\n"
180180
"}\n");
181-
// FIXME: The sign of zero doesn't matter in fcmp.
182-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
181+
// The sign of zero doesn't matter in fcmp.
182+
expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true});
183183
}
184184

185185
TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero4) {
@@ -189,8 +189,8 @@ TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero4) {
189189
" %A = select i1 %1, float -0.0, float %a\n"
190190
" ret float %A\n"
191191
"}\n");
192-
// FIXME: The sign of zero doesn't matter in fcmp.
193-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
192+
// The sign of zero doesn't matter in fcmp.
193+
expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
194194
}
195195

196196
TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero5) {
@@ -200,8 +200,8 @@ TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero5) {
200200
" %A = select i1 %1, float %a, float 0.0\n"
201201
" ret float %A\n"
202202
"}\n");
203-
// FIXME: The sign of zero doesn't matter in fcmp.
204-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
203+
// The sign of zero doesn't matter in fcmp.
204+
expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false});
205205
}
206206

207207
TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero6) {
@@ -211,8 +211,8 @@ TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero6) {
211211
" %A = select i1 %1, float %a, float 0.0\n"
212212
" ret float %A\n"
213213
"}\n");
214-
// FIXME: The sign of zero doesn't matter in fcmp.
215-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
214+
// The sign of zero doesn't matter in fcmp.
215+
expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
216216
}
217217

218218
TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero7) {
@@ -222,8 +222,8 @@ TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero7) {
222222
" %A = select i1 %1, float %a, float -0.0\n"
223223
" ret float %A\n"
224224
"}\n");
225-
// FIXME: The sign of zero doesn't matter in fcmp.
226-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
225+
// The sign of zero doesn't matter in fcmp.
226+
expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false});
227227
}
228228

229229
TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero8) {
@@ -233,8 +233,8 @@ TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero8) {
233233
" %A = select i1 %1, float %a, float -0.0\n"
234234
" ret float %A\n"
235235
"}\n");
236-
// FIXME: The sign of zero doesn't matter in fcmp.
237-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
236+
// The sign of zero doesn't matter in fcmp.
237+
expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
238238
}
239239

240240
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero1) {
@@ -244,8 +244,8 @@ TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero1) {
244244
" %A = select i1 %1, float 0.0, float %a\n"
245245
" ret float %A\n"
246246
"}\n");
247-
// FIXME: The sign of zero doesn't matter in fcmp.
248-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
247+
// The sign of zero doesn't matter in fcmp.
248+
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true});
249249
}
250250

251251
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero2) {
@@ -255,8 +255,8 @@ TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero2) {
255255
" %A = select i1 %1, float 0.0, float %a\n"
256256
" ret float %A\n"
257257
"}\n");
258-
// FIXME: The sign of zero doesn't matter in fcmp.
259-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
258+
// The sign of zero doesn't matter in fcmp.
259+
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
260260
}
261261

262262
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero3) {
@@ -266,8 +266,8 @@ TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero3) {
266266
" %A = select i1 %1, float -0.0, float %a\n"
267267
" ret float %A\n"
268268
"}\n");
269-
// FIXME: The sign of zero doesn't matter in fcmp.
270-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
269+
// The sign of zero doesn't matter in fcmp.
270+
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true});
271271
}
272272

273273
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero4) {
@@ -277,8 +277,8 @@ TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero4) {
277277
" %A = select i1 %1, float -0.0, float %a\n"
278278
" ret float %A\n"
279279
"}\n");
280-
// FIXME: The sign of zero doesn't matter in fcmp.
281-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
280+
// The sign of zero doesn't matter in fcmp.
281+
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
282282
}
283283

284284
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero5) {
@@ -288,8 +288,8 @@ TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero5) {
288288
" %A = select i1 %1, float %a, float 0.0\n"
289289
" ret float %A\n"
290290
"}\n");
291-
// FIXME: The sign of zero doesn't matter in fcmp.
292-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
291+
// The sign of zero doesn't matter in fcmp.
292+
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
293293
}
294294

295295
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero6) {
@@ -299,8 +299,8 @@ TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero6) {
299299
" %A = select i1 %1, float %a, float 0.0\n"
300300
" ret float %A\n"
301301
"}\n");
302-
// FIXME: The sign of zero doesn't matter in fcmp.
303-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
302+
// The sign of zero doesn't matter in fcmp.
303+
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
304304
}
305305

306306
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero7) {
@@ -310,8 +310,8 @@ TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero7) {
310310
" %A = select i1 %1, float %a, float -0.0\n"
311311
" ret float %A\n"
312312
"}\n");
313-
// FIXME: The sign of zero doesn't matter in fcmp.
314-
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
313+
// The sign of zero doesn't matter in fcmp.
314+
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
315315
}
316316

317317
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero8) {
@@ -321,7 +321,29 @@ TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero8) {
321321
" %A = select i1 %1, float %a, float -0.0\n"
322322
" ret float %A\n"
323323
"}\n");
324-
// FIXME: The sign of zero doesn't matter in fcmp.
324+
// The sign of zero doesn't matter in fcmp.
325+
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
326+
}
327+
328+
TEST_F(MatchSelectPatternTest, FMinMismatchConstantZeroVecUndef) {
329+
parseAssembly(
330+
"define <2 x float> @test(<2 x float> %a) {\n"
331+
" %1 = fcmp ogt <2 x float> %a, <float -0.0, float -0.0>\n"
332+
" %A = select <2 x i1> %1, <2 x float> <float undef, float 0.0>, <2 x float> %a\n"
333+
" ret <2 x float> %A\n"
334+
"}\n");
335+
// An undef in a vector constant can not be back-propagated for this analysis.
336+
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
337+
}
338+
339+
TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZeroVecUndef) {
340+
parseAssembly(
341+
"define <2 x float> @test(<2 x float> %a) {\n"
342+
" %1 = fcmp ogt <2 x float> %a, zeroinitializer\n"
343+
" %A = select <2 x i1> %1, <2 x float> %a, <2 x float> <float -0.0, float undef>\n"
344+
" ret <2 x float> %A\n"
345+
"}\n");
346+
// An undef in a vector constant can not be back-propagated for this analysis.
325347
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
326348
}
327349

0 commit comments

Comments
 (0)