Skip to content

Commit a8072a0

Browse files
authored
[InstCombine] Eliminate icmp+zext pairs over phis more aggressively (#121767)
When folding icmp over phi, add a special case for `icmp eq (zext(bool), 0)`, which is known to fold to `!bool` and thus won't increase the instruction count. This helps convert more phis to i1, esp. in loops. This is based on existing logic we have to support this for icmp of ucmp/scmp.
1 parent 5656cbc commit a8072a0

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,12 +1822,29 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN,
18221822
continue;
18231823
}
18241824

1825-
// If the only use of phi is comparing it with a constant then we can
1826-
// put this comparison in the incoming BB directly after a ucmp/scmp call
1827-
// because we know that it will simplify to a single icmp.
1828-
const APInt *Ignored;
1829-
if (isa<CmpIntrinsic>(InVal) && InVal->hasOneUser() &&
1830-
match(&I, m_ICmp(m_Specific(PN), m_APInt(Ignored)))) {
1825+
// Handle some cases that can't be fully simplified, but where we know that
1826+
// the two instructions will fold into one.
1827+
auto WillFold = [&]() {
1828+
if (!InVal->hasOneUser())
1829+
return false;
1830+
1831+
// icmp of ucmp/scmp with constant will fold to icmp.
1832+
const APInt *Ignored;
1833+
if (isa<CmpIntrinsic>(InVal) &&
1834+
match(&I, m_ICmp(m_Specific(PN), m_APInt(Ignored))))
1835+
return true;
1836+
1837+
// icmp eq zext(bool), 0 will fold to !bool.
1838+
if (isa<ZExtInst>(InVal) &&
1839+
cast<ZExtInst>(InVal)->getSrcTy()->isIntOrIntVectorTy(1) &&
1840+
match(&I,
1841+
m_SpecificICmp(ICmpInst::ICMP_EQ, m_Specific(PN), m_Zero())))
1842+
return true;
1843+
1844+
return false;
1845+
};
1846+
1847+
if (WillFold()) {
18311848
OpsToMoveUseToIncomingBB.push_back(i);
18321849
NewPhiValues.push_back(nullptr);
18331850
continue;

llvm/test/Transforms/InstCombine/phi.ll

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2828,13 +2828,13 @@ define i1 @test_zext_icmp_eq_0(i1 %a, i1 %b, i32 %c) {
28282828
; CHECK-NEXT: entry:
28292829
; CHECK-NEXT: br i1 [[A:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
28302830
; CHECK: if:
2831-
; CHECK-NEXT: [[B_EXT:%.*]] = zext i1 [[B:%.*]] to i32
2831+
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[B:%.*]], true
28322832
; CHECK-NEXT: br label [[JOIN:%.*]]
28332833
; CHECK: else:
2834+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[C:%.*]], 0
28342835
; CHECK-NEXT: br label [[JOIN]]
28352836
; CHECK: join:
2836-
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[B_EXT]], [[IF]] ], [ [[C:%.*]], [[ELSE]] ]
2837-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[PHI]], 0
2837+
; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ [[TMP0]], [[IF]] ], [ [[TMP1]], [[ELSE]] ]
28382838
; CHECK-NEXT: ret i1 [[CMP]]
28392839
;
28402840
entry:
@@ -2916,10 +2916,9 @@ define i1 @test_zext_icmp_eq_0_loop(i1 %c, i1 %b) {
29162916
; CHECK-NEXT: entry:
29172917
; CHECK-NEXT: br label [[LOOP:%.*]]
29182918
; CHECK: loop:
2919-
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[EXT:%.*]], [[LOOP]] ]
2920-
; CHECK-NEXT: [[X:%.*]] = icmp eq i32 [[PHI]], 0
2919+
; CHECK-NEXT: [[X:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
29212920
; CHECK-NEXT: [[Y:%.*]] = and i1 [[X]], [[B:%.*]]
2922-
; CHECK-NEXT: [[EXT]] = zext i1 [[Y]] to i32
2921+
; CHECK-NEXT: [[TMP0]] = xor i1 [[Y]], true
29232922
; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP]], label [[EXIT:%.*]]
29242923
; CHECK: exit:
29252924
; CHECK-NEXT: ret i1 [[X]]

0 commit comments

Comments
 (0)