Skip to content

Commit b1a93cf

Browse files
authored
[InstCombine] foldOpIntoPhi should apply to icmp with non-constant operand (#147676)
Alive2: https://alive2.llvm.org/ce/z/4MeCzA Fixes #146263.
1 parent 5458151 commit b1a93cf

File tree

2 files changed

+166
-4
lines changed

2 files changed

+166
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4305,10 +4305,6 @@ Instruction *InstCombinerImpl::foldICmpInstWithConstantNotInt(ICmpInst &I) {
43054305
return nullptr;
43064306

43074307
switch (LHSI->getOpcode()) {
4308-
case Instruction::PHI:
4309-
if (Instruction *NV = foldOpIntoPhi(I, cast<PHINode>(LHSI)))
4310-
return NV;
4311-
break;
43124308
case Instruction::IntToPtr:
43134309
// icmp pred inttoptr(X), null -> icmp pred X, 0
43144310
if (RHSC->isNullValue() &&
@@ -7699,6 +7695,13 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
76997695
if (Instruction *New = foldSignBitTest(I))
77007696
return New;
77017697

7698+
if (auto *PN = dyn_cast<PHINode>(Op0))
7699+
if (Instruction *NV = foldOpIntoPhi(I, PN))
7700+
return NV;
7701+
if (auto *PN = dyn_cast<PHINode>(Op1))
7702+
if (Instruction *NV = foldOpIntoPhi(I, PN))
7703+
return NV;
7704+
77027705
if (Instruction *Res = foldICmpInstWithConstantNotInt(I))
77037706
return Res;
77047707

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3+
4+
define i1 @test(i1 %cond, i64 %left, i64 %right) {
5+
; CHECK-LABEL: define i1 @test(
6+
; CHECK-SAME: i1 [[COND:%.*]], i64 [[LEFT:%.*]], i64 [[RIGHT:%.*]]) {
7+
; CHECK-NEXT: [[START:.*:]]
8+
; CHECK-NEXT: br i1 [[COND]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
9+
; CHECK: [[COND_TRUE]]:
10+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[RIGHT]], [[LEFT]]
11+
; CHECK-NEXT: br i1 [[CMP]], label %[[END:.*]], label %[[COND_FALSE]]
12+
; CHECK: [[COND_FALSE]]:
13+
; CHECK-NEXT: br label %[[END]]
14+
; CHECK: [[END]]:
15+
; CHECK-NEXT: ret i1 false
16+
;
17+
start:
18+
br i1 %cond, label %cond.true, label %cond.false
19+
20+
cond.true:
21+
%cmp = icmp sgt i64 %right, %left
22+
br i1 %cmp, label %end, label %cond.false
23+
24+
cond.false:
25+
%left_or_right = phi i64 [ %left, %start ], [ %right, %cond.true ]
26+
%false = icmp sgt i64 %left_or_right, %left
27+
br label %end
28+
29+
end:
30+
%result = phi i1 [ false, %cond.true ], [ %false, %cond.false ]
31+
ret i1 %result
32+
}
33+
34+
define i1 @test_commuted(i1 %cond, i64 %left, i64 %right) {
35+
; CHECK-LABEL: define i1 @test_commuted(
36+
; CHECK-SAME: i1 [[COND:%.*]], i64 [[LEFT:%.*]], i64 [[RIGHT:%.*]]) {
37+
; CHECK-NEXT: [[START:.*:]]
38+
; CHECK-NEXT: br i1 [[COND]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
39+
; CHECK: [[COND_TRUE]]:
40+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[RIGHT]], [[LEFT]]
41+
; CHECK-NEXT: br i1 [[CMP]], label %[[END:.*]], label %[[COND_FALSE]]
42+
; CHECK: [[COND_FALSE]]:
43+
; CHECK-NEXT: br label %[[END]]
44+
; CHECK: [[END]]:
45+
; CHECK-NEXT: ret i1 false
46+
;
47+
start:
48+
br i1 %cond, label %cond.true, label %cond.false
49+
50+
cond.true:
51+
%cmp = icmp sgt i64 %right, %left
52+
br i1 %cmp, label %end, label %cond.false
53+
54+
cond.false:
55+
%left_or_right = phi i64 [ %left, %start ], [ %right, %cond.true ]
56+
%false = icmp slt i64 %left, %left_or_right
57+
br label %end
58+
59+
end:
60+
%result = phi i1 [ false, %cond.true ], [ %false, %cond.false ]
61+
ret i1 %result
62+
}
63+
64+
define i1 @test_with_wrong_icmp(i1 %cond, i64 %left, i64 %right) {
65+
; CHECK-LABEL: define i1 @test_with_wrong_icmp(
66+
; CHECK-SAME: i1 [[COND:%.*]], i64 [[LEFT:%.*]], i64 [[RIGHT:%.*]]) {
67+
; CHECK-NEXT: [[START:.*]]:
68+
; CHECK-NEXT: br i1 [[COND]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
69+
; CHECK: [[COND_TRUE]]:
70+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[RIGHT]], [[LEFT]]
71+
; CHECK-NEXT: br i1 [[CMP]], label %[[END:.*]], label %[[COND_FALSE]]
72+
; CHECK: [[COND_FALSE]]:
73+
; CHECK-NEXT: [[LEFT_OR_RIGHT:%.*]] = phi i64 [ [[LEFT]], %[[START]] ], [ [[RIGHT]], %[[COND_TRUE]] ]
74+
; CHECK-NEXT: [[FALSE:%.*]] = icmp sge i64 [[LEFT_OR_RIGHT]], [[LEFT]]
75+
; CHECK-NEXT: br label %[[END]]
76+
; CHECK: [[END]]:
77+
; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ false, %[[COND_TRUE]] ], [ [[FALSE]], %[[COND_FALSE]] ]
78+
; CHECK-NEXT: ret i1 [[RESULT]]
79+
;
80+
start:
81+
br i1 %cond, label %cond.true, label %cond.false
82+
83+
cond.true:
84+
%cmp = icmp sgt i64 %right, %left
85+
br i1 %cmp, label %end, label %cond.false
86+
87+
cond.false:
88+
%left_or_right = phi i64 [ %left, %start ], [ %right, %cond.true ]
89+
%false = icmp sge i64 %left_or_right, %left
90+
br label %end
91+
92+
end:
93+
%result = phi i1 [ false, %cond.true ], [ %false, %cond.false ]
94+
ret i1 %result
95+
}
96+
97+
define i1 @test_with_unfoldable_phi(i1 %cond, i64 %left, i64 %right) {
98+
; CHECK-LABEL: define i1 @test_with_unfoldable_phi(
99+
; CHECK-SAME: i1 [[COND:%.*]], i64 [[LEFT:%.*]], i64 [[RIGHT:%.*]]) {
100+
; CHECK-NEXT: [[START:.*]]:
101+
; CHECK-NEXT: br i1 [[COND]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
102+
; CHECK: [[COND_TRUE]]:
103+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[RIGHT]], [[LEFT]]
104+
; CHECK-NEXT: br i1 [[CMP]], label %[[END:.*]], label %[[COND_FALSE]]
105+
; CHECK: [[COND_FALSE]]:
106+
; CHECK-NEXT: [[LEFT_OR_RIGHT:%.*]] = phi i64 [ [[LEFT]], %[[START]] ], [ [[RIGHT]], %[[COND_TRUE]] ]
107+
; CHECK-NEXT: [[FALSE:%.*]] = icmp sgt i64 [[LEFT_OR_RIGHT]], [[LEFT]]
108+
; CHECK-NEXT: br label %[[END]]
109+
; CHECK: [[END]]:
110+
; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ false, %[[COND_TRUE]] ], [ [[FALSE]], %[[COND_FALSE]] ]
111+
; CHECK-NEXT: ret i1 [[RESULT]]
112+
;
113+
start:
114+
br i1 %cond, label %cond.true, label %cond.false
115+
116+
cond.true:
117+
%cmp = icmp slt i64 %right, %left ; slt instead of sgt here
118+
br i1 %cmp, label %end, label %cond.false
119+
120+
cond.false:
121+
%left_or_right = phi i64 [ %left, %start ], [ %right, %cond.true ]
122+
%false = icmp sgt i64 %left_or_right, %left
123+
br label %end
124+
125+
end:
126+
%result = phi i1 [ false, %cond.true ], [ %false, %cond.false ]
127+
ret i1 %result
128+
}
129+
130+
define i1 @test_which_optimizes_to_select(i1 %cond, i64 %left, i64 %right) {
131+
; CHECK-LABEL: define i1 @test_which_optimizes_to_select(
132+
; CHECK-SAME: i1 [[COND:%.*]], i64 [[LEFT:%.*]], i64 [[RIGHT:%.*]]) {
133+
; CHECK-NEXT: [[START:.*:]]
134+
; CHECK-NEXT: br i1 [[COND]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
135+
; CHECK: [[COND_TRUE]]:
136+
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i64 [[RIGHT]], [[LEFT]]
137+
; CHECK-NEXT: br i1 [[CMP_NOT]], label %[[COND_FALSE]], label %[[END:.*]]
138+
; CHECK: [[COND_FALSE]]:
139+
; CHECK-NEXT: br label %[[END]]
140+
; CHECK: [[END]]:
141+
; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ false, %[[COND_TRUE]] ], [ [[COND]], %[[COND_FALSE]] ]
142+
; CHECK-NEXT: ret i1 [[RESULT]]
143+
;
144+
start:
145+
br i1 %cond, label %cond.true, label %cond.false
146+
147+
cond.true:
148+
%cmp = icmp sle i64 %right, %left
149+
br i1 %cmp, label %end, label %cond.false
150+
151+
cond.false:
152+
%left_or_right = phi i64 [ %left, %start ], [ %right, %cond.true ]
153+
%false = icmp sgt i64 %left_or_right, %left
154+
br label %end
155+
156+
end:
157+
%result = phi i1 [ false, %cond.true ], [ %false, %cond.false ]
158+
ret i1 %result
159+
}

0 commit comments

Comments
 (0)