Skip to content

Commit e17dded

Browse files
authored
[InstSimplify] Generalize simplifyAndOrOfFCmps (#81027)
This patch generalizes `simplifyAndOrOfFCmps` to simplify patterns like: ``` define i1 @src(float %x, float %y) { %or.cond.i = fcmp ord float %x, 0.000000e+00 %cmp.i.i34 = fcmp olt float %x, %y %cmp.i2.sink.i = and i1 %or.cond.i, %cmp.i.i34 ret i1 %cmp.i2.sink.i } define i1 @tgt(float %x, float %y) { %cmp.i.i34 = fcmp olt float %x, %y ret i1 %cmp.i.i34 } ``` Alive2: https://alive2.llvm.org/ce/z/9rydcx This patch and #80986 will fix the regression introduced by #80941. See also the IR diff dtcxzyw/llvm-opt-benchmark#199 (comment).
1 parent c8ca98a commit e17dded

File tree

3 files changed

+199
-31
lines changed

3 files changed

+199
-31
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,35 +1853,36 @@ static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS,
18531853
return nullptr;
18541854

18551855
FCmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
1856-
if ((PredL == FCmpInst::FCMP_ORD && PredR == FCmpInst::FCMP_ORD && IsAnd) ||
1857-
(PredL == FCmpInst::FCMP_UNO && PredR == FCmpInst::FCMP_UNO && !IsAnd)) {
1858-
// (fcmp ord NNAN, X) & (fcmp ord X, Y) --> fcmp ord X, Y
1859-
// (fcmp ord NNAN, X) & (fcmp ord Y, X) --> fcmp ord Y, X
1860-
// (fcmp ord X, NNAN) & (fcmp ord X, Y) --> fcmp ord X, Y
1861-
// (fcmp ord X, NNAN) & (fcmp ord Y, X) --> fcmp ord Y, X
1862-
// (fcmp uno NNAN, X) | (fcmp uno X, Y) --> fcmp uno X, Y
1863-
// (fcmp uno NNAN, X) | (fcmp uno Y, X) --> fcmp uno Y, X
1864-
// (fcmp uno X, NNAN) | (fcmp uno X, Y) --> fcmp uno X, Y
1865-
// (fcmp uno X, NNAN) | (fcmp uno Y, X) --> fcmp uno Y, X
1856+
if ((PredL == FCmpInst::FCMP_ORD || PredL == FCmpInst::FCMP_UNO) &&
1857+
((FCmpInst::isOrdered(PredR) && IsAnd) ||
1858+
(FCmpInst::isUnordered(PredR) && !IsAnd))) {
1859+
// (fcmp ord X, NNAN) & (fcmp o** X, Y) --> fcmp o** X, Y
1860+
// (fcmp uno X, NNAN) & (fcmp o** X, Y) --> false
1861+
// (fcmp uno X, NNAN) | (fcmp u** X, Y) --> fcmp u** X, Y
1862+
// (fcmp ord X, NNAN) | (fcmp u** X, Y) --> true
18661863
if (((LHS1 == RHS0 || LHS1 == RHS1) &&
18671864
isKnownNeverNaN(LHS0, /*Depth=*/0, Q)) ||
18681865
((LHS0 == RHS0 || LHS0 == RHS1) &&
18691866
isKnownNeverNaN(LHS1, /*Depth=*/0, Q)))
1870-
return RHS;
1871-
1872-
// (fcmp ord X, Y) & (fcmp ord NNAN, X) --> fcmp ord X, Y
1873-
// (fcmp ord Y, X) & (fcmp ord NNAN, X) --> fcmp ord Y, X
1874-
// (fcmp ord X, Y) & (fcmp ord X, NNAN) --> fcmp ord X, Y
1875-
// (fcmp ord Y, X) & (fcmp ord X, NNAN) --> fcmp ord Y, X
1876-
// (fcmp uno X, Y) | (fcmp uno NNAN, X) --> fcmp uno X, Y
1877-
// (fcmp uno Y, X) | (fcmp uno NNAN, X) --> fcmp uno Y, X
1878-
// (fcmp uno X, Y) | (fcmp uno X, NNAN) --> fcmp uno X, Y
1879-
// (fcmp uno Y, X) | (fcmp uno X, NNAN) --> fcmp uno Y, X
1867+
return FCmpInst::isOrdered(PredL) == FCmpInst::isOrdered(PredR)
1868+
? static_cast<Value *>(RHS)
1869+
: ConstantInt::getBool(LHS->getType(), !IsAnd);
1870+
}
1871+
1872+
if ((PredR == FCmpInst::FCMP_ORD || PredR == FCmpInst::FCMP_UNO) &&
1873+
((FCmpInst::isOrdered(PredL) && IsAnd) ||
1874+
(FCmpInst::isUnordered(PredL) && !IsAnd))) {
1875+
// (fcmp o** X, Y) & (fcmp ord X, NNAN) --> fcmp o** X, Y
1876+
// (fcmp o** X, Y) & (fcmp uno X, NNAN) --> false
1877+
// (fcmp u** X, Y) | (fcmp uno X, NNAN) --> fcmp u** X, Y
1878+
// (fcmp u** X, Y) | (fcmp ord X, NNAN) --> true
18801879
if (((RHS1 == LHS0 || RHS1 == LHS1) &&
18811880
isKnownNeverNaN(RHS0, /*Depth=*/0, Q)) ||
18821881
((RHS0 == LHS0 || RHS0 == LHS1) &&
18831882
isKnownNeverNaN(RHS1, /*Depth=*/0, Q)))
1884-
return LHS;
1883+
return FCmpInst::isOrdered(PredL) == FCmpInst::isOrdered(PredR)
1884+
? static_cast<Value *>(LHS)
1885+
: ConstantInt::getBool(LHS->getType(), !IsAnd);
18851886
}
18861887

18871888
return nullptr;

llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,8 +1100,8 @@ define i1 @uge_smallest_normal_or_ord(half %x) #0 {
11001100
; -> nan | pnormal | pinf
11011101
define i1 @uge_smallest_normal_or_uno(half %x) #0 {
11021102
; CHECK-LABEL: @uge_smallest_normal_or_uno(
1103-
; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 771)
1104-
; CHECK-NEXT: ret i1 [[CLASS]]
1103+
; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp uge half [[X:%.*]], 0xH0400
1104+
; CHECK-NEXT: ret i1 [[CMP_SMALLEST_NORMAL]]
11051105
;
11061106
%uno = fcmp uno half %x, 0.0
11071107
%cmp.smallest.normal = fcmp uge half %x, 0xH0400
@@ -1307,8 +1307,8 @@ define i1 @oge_fabs_eq_inf_and_ord(half %x) #0 {
13071307

13081308
define i1 @oge_eq_inf_and_ord(half %x) #0 {
13091309
; CHECK-LABEL: @oge_eq_inf_and_ord(
1310-
; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00
1311-
; CHECK-NEXT: ret i1 [[AND]]
1310+
; CHECK-NEXT: [[OGE_FABS_INF:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00
1311+
; CHECK-NEXT: ret i1 [[OGE_FABS_INF]]
13121312
;
13131313
%oge.fabs.inf = fcmp oge half %x, 0xH7C00
13141314
%ord = fcmp ord half %x, 0xH0000
@@ -1379,8 +1379,8 @@ define i1 @ult_fabs_eq_inf_or_uno(half %x) #0 {
13791379

13801380
define i1 @ult_eq_inf_or_uno(half %x) #0 {
13811381
; CHECK-LABEL: @ult_eq_inf_or_uno(
1382-
; CHECK-NEXT: [[OR:%.*]] = fcmp une half [[X:%.*]], 0xH7C00
1383-
; CHECK-NEXT: ret i1 [[OR]]
1382+
; CHECK-NEXT: [[ULT_FABS_INF:%.*]] = fcmp une half [[X:%.*]], 0xH7C00
1383+
; CHECK-NEXT: ret i1 [[ULT_FABS_INF]]
13841384
;
13851385
%ult.fabs.inf = fcmp ult half %x, 0xH7C00
13861386
%uno = fcmp uno half %x, 0xH0000
@@ -1465,8 +1465,8 @@ define i1 @oeq_neginfinity_or_ord(half %x) #0 {
14651465
; -> ninf
14661466
define i1 @oeq_neginfinity_and_ord(half %x) #0 {
14671467
; CHECK-LABEL: @oeq_neginfinity_and_ord(
1468-
; CHECK-NEXT: [[CLASS:%.*]] = fcmp oeq half [[X:%.*]], 0xHFC00
1469-
; CHECK-NEXT: ret i1 [[CLASS]]
1468+
; CHECK-NEXT: [[OEQ_NEG_INFINITY:%.*]] = fcmp oeq half [[X:%.*]], 0xHFC00
1469+
; CHECK-NEXT: ret i1 [[OEQ_NEG_INFINITY]]
14701470
;
14711471
%oeq.neg.infinity = fcmp oeq half %x, 0xHFC00
14721472
%ord = fcmp ord half %x, 0.0
@@ -1597,8 +1597,8 @@ define i1 @ueq_neginfinity_and_olt_smallest_normal(half %x) #0 {
15971597
; -> nan|ninf
15981598
define i1 @ueq_neginfinity_or_uno(half %x) #0 {
15991599
; CHECK-LABEL: @ueq_neginfinity_or_uno(
1600-
; CHECK-NEXT: [[CLASS:%.*]] = fcmp ueq half [[X:%.*]], 0xHFC00
1601-
; CHECK-NEXT: ret i1 [[CLASS]]
1600+
; CHECK-NEXT: [[UEQ_NEG_INFINITY:%.*]] = fcmp ueq half [[X:%.*]], 0xHFC00
1601+
; CHECK-NEXT: ret i1 [[UEQ_NEG_INFINITY]]
16021602
;
16031603
%ueq.neg.infinity = fcmp ueq half %x, 0xHFC00
16041604
%uno = fcmp uno half %x, 0.0

llvm/test/Transforms/InstSimplify/logic-of-fcmps.ll

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,170 @@ define <2 x i1> @uno8(<2 x double> %x, <2 x double> %y) {
259259
%r = or <2 x i1> %cmp1, %cmp2
260260
ret <2 x i1> %r
261261
}
262+
263+
define i1 @olt_implies_ord(float %x, float %y) {
264+
; CHECK-LABEL: @olt_implies_ord(
265+
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
266+
; CHECK-NEXT: ret i1 [[OLT]]
267+
;
268+
%ord = fcmp ord float %x, 0.000000e+00
269+
%olt = fcmp olt float %x, %y
270+
%ret = and i1 %olt, %ord
271+
ret i1 %ret
272+
}
273+
274+
define i1 @olt_implies_ord_commuted1(float %x, float %y) {
275+
; CHECK-LABEL: @olt_implies_ord_commuted1(
276+
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[Y:%.*]], [[X:%.*]]
277+
; CHECK-NEXT: ret i1 [[OLT]]
278+
;
279+
%ord = fcmp ord float %x, 0.000000e+00
280+
%olt = fcmp olt float %y, %x
281+
%ret = and i1 %olt, %ord
282+
ret i1 %ret
283+
}
284+
285+
define i1 @olt_implies_ord_commuted2(float %x, float %y) {
286+
; CHECK-LABEL: @olt_implies_ord_commuted2(
287+
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
288+
; CHECK-NEXT: ret i1 [[OLT]]
289+
;
290+
%ord = fcmp ord float %x, 0.000000e+00
291+
%olt = fcmp olt float %x, %y
292+
%ret = and i1 %ord, %olt
293+
ret i1 %ret
294+
}
295+
296+
define i1 @olt_implies_ord_commuted3(float %x, float %y) {
297+
; CHECK-LABEL: @olt_implies_ord_commuted3(
298+
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[Y:%.*]], [[X:%.*]]
299+
; CHECK-NEXT: ret i1 [[OLT]]
300+
;
301+
%ord = fcmp ord float %x, 0.000000e+00
302+
%olt = fcmp olt float %y, %x
303+
%ret = and i1 %ord, %olt
304+
ret i1 %ret
305+
}
306+
307+
define <2 x i1> @olt_implies_ord_vec(<2 x float> %x, <2 x float> %y) {
308+
; CHECK-LABEL: @olt_implies_ord_vec(
309+
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt <2 x float> [[X:%.*]], [[Y:%.*]]
310+
; CHECK-NEXT: ret <2 x i1> [[OLT]]
311+
;
312+
%ord = fcmp ord <2 x float> %x, zeroinitializer
313+
%olt = fcmp olt <2 x float> %x, %y
314+
%ret = and <2 x i1> %ord, %olt
315+
ret <2 x i1> %ret
316+
}
317+
318+
define i1 @ord_implies_ord(float %x, float %y) {
319+
; CHECK-LABEL: @ord_implies_ord(
320+
; CHECK-NEXT: [[ORD2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
321+
; CHECK-NEXT: ret i1 [[ORD2]]
322+
;
323+
%ord = fcmp ord float %x, 0.000000e+00
324+
%ord2 = fcmp ord float %x, %y
325+
%ret = and i1 %ord, %ord2
326+
ret i1 %ret
327+
}
328+
329+
define i1 @olt_implies_uno(float %x, float %y) {
330+
; CHECK-LABEL: @olt_implies_uno(
331+
; CHECK-NEXT: ret i1 false
332+
;
333+
%uno = fcmp uno float %x, 0.000000e+00
334+
%olt = fcmp olt float %x, %y
335+
%ret = and i1 %olt, %uno
336+
ret i1 %ret
337+
}
338+
339+
define i1 @ult_implies_uno(float %x, float %y) {
340+
; CHECK-LABEL: @ult_implies_uno(
341+
; CHECK-NEXT: [[ULT:%.*]] = fcmp ult float [[X:%.*]], [[Y:%.*]]
342+
; CHECK-NEXT: ret i1 [[ULT]]
343+
;
344+
%uno = fcmp uno float %x, 0.000000e+00
345+
%ult = fcmp ult float %x, %y
346+
%ret = or i1 %ult, %uno
347+
ret i1 %ret
348+
}
349+
350+
define i1 @uno_implies_uno(float %x, float %y) {
351+
; CHECK-LABEL: @uno_implies_uno(
352+
; CHECK-NEXT: [[UNO2:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
353+
; CHECK-NEXT: ret i1 [[UNO2]]
354+
;
355+
%uno = fcmp uno float %x, 0.000000e+00
356+
%uno2 = fcmp uno float %x, %y
357+
%ret = or i1 %uno, %uno2
358+
ret i1 %ret
359+
}
360+
361+
define i1 @ult_implies_ord(float %x, float %y) {
362+
; CHECK-LABEL: @ult_implies_ord(
363+
; CHECK-NEXT: ret i1 true
364+
;
365+
%ord = fcmp ord float %x, 0.000000e+00
366+
%ult = fcmp ult float %x, %y
367+
%ret = or i1 %ult, %ord
368+
ret i1 %ret
369+
}
370+
371+
; TODO: %cmp1 is false implies %cmp3 is true
372+
define float @test_ord_implies_uno(float %x) {
373+
; CHECK-LABEL: @test_ord_implies_uno(
374+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
375+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[X]], 0.000000e+00
376+
; CHECK-NEXT: [[CMP3:%.*]] = fcmp uno float [[X]], 0.000000e+00
377+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
378+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[SEL]], float 0.000000e+00, float [[X]]
379+
; CHECK-NEXT: ret float [[RET]]
380+
;
381+
%cmp1 = fcmp ord float %x, 0.000000e+00
382+
%cmp2 = fcmp olt float %x, 0.000000e+00
383+
%cmp3 = fcmp uno float %x, 0.000000e+00
384+
%sel = select i1 %cmp1, i1 %cmp2, i1 %cmp3
385+
%ret = select i1 %sel, float 0.000000e+00, float %x
386+
ret float %ret
387+
}
388+
389+
; Negative tests
390+
391+
define i1 @olt_implies_ord_fail(float %x, float %y, float %z) {
392+
; CHECK-LABEL: @olt_implies_ord_fail(
393+
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X:%.*]], [[Z:%.*]]
394+
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[X]], [[Y:%.*]]
395+
; CHECK-NEXT: [[RET:%.*]] = and i1 [[OLT]], [[ORD]]
396+
; CHECK-NEXT: ret i1 [[RET]]
397+
;
398+
%ord = fcmp ord float %x, %z
399+
%olt = fcmp olt float %x, %y
400+
%ret = and i1 %olt, %ord
401+
ret i1 %ret
402+
}
403+
404+
define i1 @ult_implies_uno_and(float %x, float %y) {
405+
; CHECK-LABEL: @ult_implies_uno_and(
406+
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
407+
; CHECK-NEXT: [[ULT:%.*]] = fcmp ult float [[X]], [[Y:%.*]]
408+
; CHECK-NEXT: [[RET:%.*]] = and i1 [[ULT]], [[UNO]]
409+
; CHECK-NEXT: ret i1 [[RET]]
410+
;
411+
%uno = fcmp uno float %x, 0.000000e+00
412+
%ult = fcmp ult float %x, %y
413+
%ret = and i1 %ult, %uno
414+
ret i1 %ret
415+
}
416+
417+
define i1 @olt_implies_olt_fail(float %x, float %y) {
418+
; CHECK-LABEL: @olt_implies_olt_fail(
419+
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
420+
; CHECK-NEXT: [[OLT2:%.*]] = fcmp olt float [[X]], [[Y:%.*]]
421+
; CHECK-NEXT: [[RET:%.*]] = and i1 [[OLT]], [[OLT2]]
422+
; CHECK-NEXT: ret i1 [[RET]]
423+
;
424+
%olt = fcmp olt float %x, 0.000000e+00
425+
%olt2 = fcmp olt float %x, %y
426+
%ret = and i1 %olt, %olt2
427+
ret i1 %ret
428+
}

0 commit comments

Comments
 (0)