llvm.org GIT mirror llvm / fd7c7dd
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346097 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 10 months ago
3 changed file(s) with 89 addition(s) and 54 deletion(s). Raw diff Collapse all Expand all
47594759 Value *TrueVal, Value *FalseVal,
47604760 Value *&LHS, Value *&RHS,
47614761 unsigned Depth) {
4762 if (CmpInst::isFPPredicate(Pred)) {
4763 // IEEE-754 ignores the sign of 0.0 in comparisons. So if the select has one
4764 // 0.0 operand, set the compare's 0.0 operands to that same value for the
4765 // purpose of identifying min/max. Disregard vector constants with undefined
4766 // elements because those can not be back-propagated for analysis.
4767 Value *OutputZeroVal = nullptr;
4768 if (match(TrueVal, m_AnyZeroFP()) && !match(FalseVal, m_AnyZeroFP()) &&
4769 !cast(TrueVal)->containsUndefElement())
4770 OutputZeroVal = TrueVal;
4771 else if (match(FalseVal, m_AnyZeroFP()) && !match(TrueVal, m_AnyZeroFP()) &&
4772 !cast(FalseVal)->containsUndefElement())
4773 OutputZeroVal = FalseVal;
4774
4775 if (OutputZeroVal) {
4776 if (match(CmpLHS, m_AnyZeroFP()))
4777 CmpLHS = OutputZeroVal;
4778 if (match(CmpRHS, m_AnyZeroFP()))
4779 CmpRHS = OutputZeroVal;
4780 }
4781 }
4782
47624783 LHS = CmpLHS;
47634784 RHS = CmpRHS;
47644785
5656 ret double %3
5757 }
5858
59 ; TODO:
60 ; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = 0)."
59 ; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = -0)."
6160 ; So the compare constant may be treated as +0.0, and we sink the fpext.
6261
6362 define double @t6(float %a) {
6463 ; CHECK-LABEL: @t6(
65 ; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float [[A:%.*]], -0.000000e+00
66 ; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[A]] to double
67 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double 0.000000e+00
68 ; CHECK-NEXT: ret double [[TMP3]]
64 ; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], 0.000000e+00
65 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float [[A]]
66 ; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double
67 ; CHECK-NEXT: ret double [[TMP2]]
6968 ;
7069 %1 = fcmp ult float %a, -0.0
7170 %2 = fpext float %a to double
7372 ret double %3
7473 }
7574
76 ; TODO:
77 ; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = 0)."
75 ; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = -0)."
7876 ; So the compare constant may be treated as -0.0, and we sink the fpext.
7977
8078 define double @t7(float %a) {
8179 ; CHECK-LABEL: @t7(
82 ; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float [[A:%.*]], 0.000000e+00
83 ; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[A]] to double
84 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double -0.000000e+00
85 ; CHECK-NEXT: ret double [[TMP3]]
80 ; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], -0.000000e+00
81 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float -0.000000e+00, float [[A]]
82 ; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double
83 ; CHECK-NEXT: ret double [[TMP2]]
8684 ;
8785 %1 = fcmp ult float %a, 0.0
8886 %2 = fpext float %a to double
9088 ret double %3
9189 }
9290
93 ; TODO:
9491 ; min(min(x, 0.0), 0.0) --> min(x, 0.0)
9592
9693 define float @fmin_fmin_zero_mismatch(float %x) {
9794 ; CHECK-LABEL: @fmin_fmin_zero_mismatch(
98 ; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[X:%.*]], -0.000000e+00
99 ; CHECK-NEXT: [[MIN1:%.*]] = select i1 [[CMP1]], float [[X]], float 0.000000e+00
100 ; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[MIN1]], 0.000000e+00
101 ; CHECK-NEXT: [[MIN2:%.*]] = select i1 [[CMP2]], float [[MIN1]], float 0.000000e+00
95 ; CHECK-NEXT: [[TMP1:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
96 ; CHECK-NEXT: [[MIN2:%.*]] = select i1 [[TMP1]], float [[X]], float 0.000000e+00
10297 ; CHECK-NEXT: ret float [[MIN2]]
10398 ;
10499 %cmp1 = fcmp olt float %x, -0.0
108103 ret float %min2
109104 }
110105
111 ; TODO:
112106 ; max(max(x, -0.0), -0.0) --> max(x, -0.0)
113107
114108 define float @fmax_fmax_zero_mismatch(float %x) {
115109 ; CHECK-LABEL: @fmax_fmax_zero_mismatch(
116 ; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00
117 ; CHECK-NEXT: [[MAX1:%.*]] = select i1 [[CMP1]], float [[X]], float -0.000000e+00
118 ; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[MAX1]], 0.000000e+00
119 ; CHECK-NEXT: [[MAX2:%.*]] = select i1 [[CMP2]], float -0.000000e+00, float [[MAX1]]
120 ; CHECK-NEXT: ret float [[MAX2]]
110 ; CHECK-NEXT: [[TMP1:%.*]] = fcmp ogt float [[X:%.*]], -0.000000e+00
111 ; CHECK-NEXT: [[MAX11:%.*]] = select i1 [[TMP1]], float [[X]], float -0.000000e+00
112 ; CHECK-NEXT: ret float [[MAX11]]
121113 ;
122114 %cmp1 = fcmp ogt float %x, 0.0
123115 %max1 = select i1 %cmp1, float %x, float -0.0
155155 " %A = select i1 %1, float 0.0, float %a\n"
156156 " ret float %A\n"
157157 "}\n");
158 // FIXME: The sign of zero doesn't matter in fcmp.
159 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
158 // The sign of zero doesn't matter in fcmp.
159 expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true});
160160 }
161161
162162 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero2) {
166166 " %A = select i1 %1, float 0.0, float %a\n"
167167 " ret float %A\n"
168168 "}\n");
169 // FIXME: The sign of zero doesn't matter in fcmp.
170 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
169 // The sign of zero doesn't matter in fcmp.
170 expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
171171 }
172172
173173 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero3) {
177177 " %A = select i1 %1, float -0.0, float %a\n"
178178 " ret float %A\n"
179179 "}\n");
180 // FIXME: The sign of zero doesn't matter in fcmp.
181 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
180 // The sign of zero doesn't matter in fcmp.
181 expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true});
182182 }
183183
184184 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero4) {
188188 " %A = select i1 %1, float -0.0, float %a\n"
189189 " ret float %A\n"
190190 "}\n");
191 // FIXME: The sign of zero doesn't matter in fcmp.
192 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
191 // The sign of zero doesn't matter in fcmp.
192 expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
193193 }
194194
195195 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero5) {
199199 " %A = select i1 %1, float %a, float 0.0\n"
200200 " ret float %A\n"
201201 "}\n");
202 // FIXME: The sign of zero doesn't matter in fcmp.
203 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
202 // The sign of zero doesn't matter in fcmp.
203 expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false});
204204 }
205205
206206 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero6) {
210210 " %A = select i1 %1, float %a, float 0.0\n"
211211 " ret float %A\n"
212212 "}\n");
213 // FIXME: The sign of zero doesn't matter in fcmp.
214 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
213 // The sign of zero doesn't matter in fcmp.
214 expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
215215 }
216216
217217 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero7) {
221221 " %A = select i1 %1, float %a, float -0.0\n"
222222 " ret float %A\n"
223223 "}\n");
224 // FIXME: The sign of zero doesn't matter in fcmp.
225 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
224 // The sign of zero doesn't matter in fcmp.
225 expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false});
226226 }
227227
228228 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero8) {
232232 " %A = select i1 %1, float %a, float -0.0\n"
233233 " ret float %A\n"
234234 "}\n");
235 // FIXME: The sign of zero doesn't matter in fcmp.
236 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
235 // The sign of zero doesn't matter in fcmp.
236 expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
237237 }
238238
239239 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero1) {
243243 " %A = select i1 %1, float 0.0, float %a\n"
244244 " ret float %A\n"
245245 "}\n");
246 // FIXME: The sign of zero doesn't matter in fcmp.
247 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
246 // The sign of zero doesn't matter in fcmp.
247 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true});
248248 }
249249
250250 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero2) {
254254 " %A = select i1 %1, float 0.0, float %a\n"
255255 " ret float %A\n"
256256 "}\n");
257 // FIXME: The sign of zero doesn't matter in fcmp.
258 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
257 // The sign of zero doesn't matter in fcmp.
258 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
259259 }
260260
261261 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero3) {
265265 " %A = select i1 %1, float -0.0, float %a\n"
266266 " ret float %A\n"
267267 "}\n");
268 // FIXME: The sign of zero doesn't matter in fcmp.
269 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
268 // The sign of zero doesn't matter in fcmp.
269 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true});
270270 }
271271
272272 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero4) {
276276 " %A = select i1 %1, float -0.0, float %a\n"
277277 " ret float %A\n"
278278 "}\n");
279 // FIXME: The sign of zero doesn't matter in fcmp.
280 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
279 // The sign of zero doesn't matter in fcmp.
280 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
281281 }
282282
283283 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero5) {
287287 " %A = select i1 %1, float %a, float 0.0\n"
288288 " ret float %A\n"
289289 "}\n");
290 // FIXME: The sign of zero doesn't matter in fcmp.
291 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
290 // The sign of zero doesn't matter in fcmp.
291 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
292292 }
293293
294294 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero6) {
298298 " %A = select i1 %1, float %a, float 0.0\n"
299299 " ret float %A\n"
300300 "}\n");
301 // FIXME: The sign of zero doesn't matter in fcmp.
302 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
301 // The sign of zero doesn't matter in fcmp.
302 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
303303 }
304304
305305 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero7) {
309309 " %A = select i1 %1, float %a, float -0.0\n"
310310 " ret float %A\n"
311311 "}\n");
312 // FIXME: The sign of zero doesn't matter in fcmp.
313 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
312 // The sign of zero doesn't matter in fcmp.
313 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
314314 }
315315
316316 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero8) {
320320 " %A = select i1 %1, float %a, float -0.0\n"
321321 " ret float %A\n"
322322 "}\n");
323 // FIXME: The sign of zero doesn't matter in fcmp.
323 // The sign of zero doesn't matter in fcmp.
324 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
325 }
326
327 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZeroVecUndef) {
328 parseAssembly(
329 "define <2 x float> @test(<2 x float> %a) {\n"
330 " %1 = fcmp ogt <2 x float> %a, \n"
331 " %A = select <2 x i1> %1, <2 x float> , <2 x float> %a\n"
332 " ret <2 x float> %A\n"
333 "}\n");
334 // An undef in a vector constant can not be back-propagated for this analysis.
335 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
336 }
337
338 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZeroVecUndef) {
339 parseAssembly(
340 "define <2 x float> @test(<2 x float> %a) {\n"
341 " %1 = fcmp ogt <2 x float> %a, zeroinitializer\n"
342 " %A = select <2 x i1> %1, <2 x float> %a, <2 x float> \n"
343 " ret <2 x float> %A\n"
344 "}\n");
345 // An undef in a vector constant can not be back-propagated for this analysis.
324346 expectPattern({SPF_UNKNOWN, SPNB_NA, false});
325347 }
326348