1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -instcombine < %s | FileCheck %s
3
4declare void @use(i8)
5declare void @use.i1(i1)
6declare i8 @llvm.umin.i8(i8, i8)
7
8define i1 @icmp_select_const(i8 %x, i8 %y) {
9; CHECK-LABEL: @icmp_select_const(
10; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
11; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], 0
12; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
13; CHECK-NEXT:    ret i1 [[CMP2]]
14;
15  %cmp1 = icmp eq i8 %x, 0
16  %sel = select i1 %cmp1, i8 0, i8 %y
17  %cmp2 = icmp eq i8 %sel, 0
18  ret i1 %cmp2
19}
20
21define i1 @icmp_select_var(i8 %x, i8 %y, i8 %z) {
22; CHECK-LABEL: @icmp_select_var(
23; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
24; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[Z:%.*]]
25; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
26; CHECK-NEXT:    ret i1 [[CMP2]]
27;
28  %cmp1 = icmp eq i8 %x, 0
29  %sel = select i1 %cmp1, i8 %z, i8 %y
30  %cmp2 = icmp eq i8 %sel, %z
31  ret i1 %cmp2
32}
33
34define i1 @icmp_select_var_commuted(i8 %x, i8 %y, i8 %_z) {
35; CHECK-LABEL: @icmp_select_var_commuted(
36; CHECK-NEXT:    [[Z:%.*]] = udiv i8 42, [[_Z:%.*]]
37; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
38; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Z]], [[Y:%.*]]
39; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
40; CHECK-NEXT:    ret i1 [[CMP2]]
41;
42  %z = udiv i8 42, %_z ; thwart complexity-based canonicalization
43  %cmp1 = icmp eq i8 %x, 0
44  %sel = select i1 %cmp1, i8 %z, i8 %y
45  %cmp2 = icmp eq i8 %z, %sel
46  ret i1 %cmp2
47}
48
49define i1 @icmp_select_var_select(i8 %x, i8 %y, i1 %c) {
50; CHECK-LABEL: @icmp_select_var_select(
51; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
52; CHECK-NEXT:    [[CMP212:%.*]] = icmp eq i8 [[X]], [[Y:%.*]]
53; CHECK-NEXT:    [[NOT_C:%.*]] = xor i1 [[C:%.*]], true
54; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[CMP1]], i1 true, i1 [[NOT_C]]
55; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[CMP212]]
56; CHECK-NEXT:    ret i1 [[CMP2]]
57;
58  %z = select i1 %c, i8 %x, i8 %y
59  %cmp1 = icmp eq i8 %x, 0
60  %sel = select i1 %cmp1, i8 %z, i8 %y
61  %cmp2 = icmp eq i8 %z, %sel
62  ret i1 %cmp2
63}
64
65define i1 @icmp_select_var_both_fold(i8 %x, i8 %y, i8 %_z) {
66; CHECK-LABEL: @icmp_select_var_both_fold(
67; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
68; CHECK-NEXT:    ret i1 [[CMP1]]
69;
70  %z = or i8 %_z, 1
71  %cmp1 = icmp eq i8 %x, 0
72  %sel = select i1 %cmp1, i8 %z, i8 2
73  %cmp2 = icmp eq i8 %sel, %z
74  ret i1 %cmp2
75}
76
77define i1 @icmp_select_var_extra_use(i8 %x, i8 %y, i8 %z) {
78; CHECK-LABEL: @icmp_select_var_extra_use(
79; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
80; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Z:%.*]], i8 [[Y:%.*]]
81; CHECK-NEXT:    call void @use(i8 [[SEL]])
82; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[Z]]
83; CHECK-NEXT:    ret i1 [[CMP2]]
84;
85  %cmp1 = icmp eq i8 %x, 0
86  %sel = select i1 %cmp1, i8 %z, i8 %y
87  call void @use(i8 %sel)
88  %cmp2 = icmp eq i8 %sel, %z
89  ret i1 %cmp2
90}
91
92define i1 @icmp_select_var_both_fold_extra_use(i8 %x, i8 %y, i8 %_z) {
93; CHECK-LABEL: @icmp_select_var_both_fold_extra_use(
94; CHECK-NEXT:    [[Z:%.*]] = or i8 [[_Z:%.*]], 1
95; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
96; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Z]], i8 2
97; CHECK-NEXT:    call void @use(i8 [[SEL]])
98; CHECK-NEXT:    ret i1 [[CMP1]]
99;
100  %z = or i8 %_z, 1
101  %cmp1 = icmp eq i8 %x, 0
102  %sel = select i1 %cmp1, i8 %z, i8 2
103  call void @use(i8 %sel)
104  %cmp2 = icmp eq i8 %sel, %z
105  ret i1 %cmp2
106}
107
108define i1 @icmp_select_var_pred_ne(i8 %x, i8 %y, i8 %z) {
109; CHECK-LABEL: @icmp_select_var_pred_ne(
110; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
111; CHECK-NEXT:    [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[Z:%.*]]
112; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
113; CHECK-NEXT:    ret i1 [[CMP2]]
114;
115  %cmp1 = icmp eq i8 %x, 0
116  %sel = select i1 %cmp1, i8 %z, i8 %y
117  %cmp2 = icmp ne i8 %sel, %z
118  ret i1 %cmp2
119}
120
121define i1 @icmp_select_var_pred_ult(i8 %x, i8 %y, i8 %z) {
122; CHECK-LABEL: @icmp_select_var_pred_ult(
123; CHECK-NEXT:    [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2
124; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
125; CHECK-NEXT:    [[CMP21:%.*]] = icmp ugt i8 [[Z1]], [[Y:%.*]]
126; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
127; CHECK-NEXT:    ret i1 [[CMP2]]
128;
129  %z1 = add nuw i8 %z, 2
130  %cmp1 = icmp eq i8 %x, 0
131  %sel = select i1 %cmp1, i8 %z, i8 %y
132  %cmp2 = icmp ult i8 %sel, %z1
133  ret i1 %cmp2
134}
135
136define i1 @icmp_select_var_pred_uge(i8 %x, i8 %y, i8 %z) {
137; CHECK-LABEL: @icmp_select_var_pred_uge(
138; CHECK-NEXT:    [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2
139; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
140; CHECK-NEXT:    [[CMP21:%.*]] = icmp ule i8 [[Z1]], [[Y:%.*]]
141; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
142; CHECK-NEXT:    ret i1 [[CMP2]]
143;
144  %z1 = add nuw i8 %z, 2
145  %cmp1 = icmp eq i8 %x, 0
146  %sel = select i1 %cmp1, i8 %z, i8 %y
147  %cmp2 = icmp uge i8 %sel, %z1
148  ret i1 %cmp2
149}
150
151define i1 @icmp_select_var_pred_uge_commuted(i8 %x, i8 %y, i8 %z) {
152; CHECK-LABEL: @icmp_select_var_pred_uge_commuted(
153; CHECK-NEXT:    [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2
154; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
155; CHECK-NEXT:    [[CMP21:%.*]] = icmp uge i8 [[Z1]], [[Y:%.*]]
156; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
157; CHECK-NEXT:    ret i1 [[CMP2]]
158;
159  %z1 = add nuw i8 %z, 2
160  %cmp1 = icmp eq i8 %x, 0
161  %sel = select i1 %cmp1, i8 %z, i8 %y
162  %cmp2 = icmp uge i8 %z1, %sel
163  ret i1 %cmp2
164}
165
166define i1 @icmp_select_implied_cond(i8 %x, i8 %y) {
167; CHECK-LABEL: @icmp_select_implied_cond(
168; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
169; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]]
170; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
171; CHECK-NEXT:    ret i1 [[CMP2]]
172;
173  %cmp1 = icmp eq i8 %x, 0
174  %sel = select i1 %cmp1, i8 0, i8 %y
175  %cmp2 = icmp eq i8 %sel, %x
176  ret i1 %cmp2
177}
178
179define i1 @icmp_select_implied_cond_ne(i8 %x, i8 %y) {
180; CHECK-LABEL: @icmp_select_implied_cond_ne(
181; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
182; CHECK-NEXT:    [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[X]]
183; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
184; CHECK-NEXT:    ret i1 [[CMP2]]
185;
186  %cmp1 = icmp eq i8 %x, 0
187  %sel = select i1 %cmp1, i8 0, i8 %y
188  %cmp2 = icmp ne i8 %sel, %x
189  ret i1 %cmp2
190}
191
192define i1 @icmp_select_implied_cond_swapped_select(i8 %x, i8 %y) {
193; CHECK-LABEL: @icmp_select_implied_cond_swapped_select(
194; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
195; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], 0
196; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
197; CHECK-NEXT:    ret i1 [[CMP2]]
198;
199  %cmp1 = icmp eq i8 %x, 0
200  %sel = select i1 %cmp1, i8 %y, i8 0
201  %cmp2 = icmp eq i8 %sel, %x
202  ret i1 %cmp2
203}
204
205define i1 @icmp_select_implied_cond_swapped_select_with_inv_cond(i8 %x, i8 %y) {
206; CHECK-LABEL: @icmp_select_implied_cond_swapped_select_with_inv_cond(
207; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
208; CHECK-NEXT:    call void @use.i1(i1 [[CMP1]])
209; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]]
210; CHECK-NEXT:    [[NOT_CMP1:%.*]] = xor i1 [[CMP1]], true
211; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[NOT_CMP1]], i1 true, i1 [[CMP21]]
212; CHECK-NEXT:    ret i1 [[CMP2]]
213;
214  %cmp1 = icmp ne i8 %x, 0
215  call void @use.i1(i1 %cmp1)
216  %sel = select i1 %cmp1, i8 %y, i8 0
217  %cmp2 = icmp eq i8 %sel, %x
218  ret i1 %cmp2
219}
220
221define i1 @icmp_select_implied_cond_relational(i8 %x, i8 %y) {
222; CHECK-LABEL: @icmp_select_implied_cond_relational(
223; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10
224; CHECK-NEXT:    [[CMP21:%.*]] = icmp ult i8 [[Y:%.*]], [[X]]
225; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
226; CHECK-NEXT:    ret i1 [[CMP2]]
227;
228  %cmp1 = icmp ugt i8 %x, 10
229  %sel = select i1 %cmp1, i8 10, i8 %y
230  %cmp2 = icmp ult i8 %sel, %x
231  ret i1 %cmp2
232}
233
234define i1 @icmp_select_implied_cond_relational_off_by_one(i8 %x, i8 %y) {
235; CHECK-LABEL: @icmp_select_implied_cond_relational_off_by_one(
236; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10
237; CHECK-NEXT:    call void @use.i1(i1 [[CMP1]])
238; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i8 11, i8 [[Y:%.*]]
239; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 [[SEL]], [[X]]
240; CHECK-NEXT:    ret i1 [[CMP2]]
241;
242  %cmp1 = icmp ugt i8 %x, 10
243  call void @use.i1(i1 %cmp1)
244  %sel = select i1 %cmp1, i8 11, i8 %y
245  %cmp2 = icmp ult i8 %sel, %x
246  ret i1 %cmp2
247}
248
249define i1 @umin_seq_comparison(i8 %x, i8 %y) {
250; CHECK-LABEL: @umin_seq_comparison(
251; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
252; CHECK-NEXT:    [[CMP21:%.*]] = icmp ule i8 [[X]], [[Y:%.*]]
253; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
254; CHECK-NEXT:    ret i1 [[CMP2]]
255;
256  %min = call i8 @llvm.umin.i8(i8 %x, i8 %y)
257  %cmp1 = icmp eq i8 %x, 0
258  %sel = select i1 %cmp1, i8 0, i8 %min
259  %cmp2 = icmp eq i8 %sel, %x
260  ret i1 %cmp2
261}
262