1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; Given a pattern like:
5;   %old_cmp1 = icmp slt i32 %x, C2
6;   %old_replacement = select i1 %old_cmp1, i32 %target_low, i32 %target_high
7;   %old_x_offseted = add i32 %x, C1
8;   %old_cmp0 = icmp ult i32 %old_x_offseted, C0
9;   %r = select i1 %old_cmp0, i32 %x, i32 %old_replacement
10; it can be rewriten as more canonical pattern:
11;   %new_cmp1 = icmp slt i32 %x, -C1
12;   %new_cmp2 = icmp sge i32 %x, C0-C1
13;   %new_clamped_low = select i1 %new_cmp1, i32 %target_low, i32 %x
14;   %r = select i1 %new_cmp2, i32 %target_high, i32 %new_clamped_low
15; Iff -C1 s<= C2 s<= C0-C1
16; Also, ULT predicate can also be UGE; or UGT iff C0 != -1 (+invert result)
17; Also, SLT predicate can also be SGE; or SGT iff C2 != INT_MAX (+invert res.)
18
19;-------------------------------------------------------------------------------
20
21; Basic pattern. There is no 'and', so lower threshold is 0 (inclusive).
22; The upper threshold is 127 (inclusive).
23; There are 2 icmp's so for scalars there are 4 possible combinations.
24; The constant in %t0 has to be between the thresholds, i.e 128 <= Ct0 <= 0.
25
26define i32 @t0_ult_slt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) {
27; CHECK-LABEL: @t0_ult_slt_128(
28; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
29; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
30; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
31; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
32; CHECK-NEXT:    ret i32 [[R]]
33;
34  %t0 = icmp slt i32 %x, 128
35  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
36  %t2 = add i32 %x, 16
37  %t3 = icmp ult i32 %t2, 144
38  %r = select i1 %t3, i32 %x, i32 %t1
39  ret i32 %r
40}
41define i32 @t1_ult_slt_0(i32 %x, i32 %replacement_low, i32 %replacement_high) {
42; CHECK-LABEL: @t1_ult_slt_0(
43; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
44; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
45; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
46; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
47; CHECK-NEXT:    ret i32 [[R]]
48;
49  %t0 = icmp slt i32 %x, -16
50  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
51  %t2 = add i32 %x, 16
52  %t3 = icmp ult i32 %t2, 144
53  %r = select i1 %t3, i32 %x, i32 %t1
54  ret i32 %r
55}
56
57define i32 @t2_ult_sgt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) {
58; CHECK-LABEL: @t2_ult_sgt_128(
59; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
60; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
61; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
62; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
63; CHECK-NEXT:    ret i32 [[R]]
64;
65  %t0 = icmp sgt i32 %x, 127
66  %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low
67  %t2 = add i32 %x, 16
68  %t3 = icmp ult i32 %t2, 144
69  %r = select i1 %t3, i32 %x, i32 %t1
70  ret i32 %r
71}
72define i32 @t3_ult_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) {
73; CHECK-LABEL: @t3_ult_sgt_neg1(
74; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
75; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
76; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
77; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
78; CHECK-NEXT:    ret i32 [[R]]
79;
80  %t0 = icmp sgt i32 %x, -17
81  %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low
82  %t2 = add i32 %x, 16
83  %t3 = icmp ult i32 %t2, 144
84  %r = select i1 %t3, i32 %x, i32 %t1
85  ret i32 %r
86}
87
88define i32 @t4_ugt_slt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) {
89; CHECK-LABEL: @t4_ugt_slt_128(
90; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
91; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
92; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
93; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
94; CHECK-NEXT:    ret i32 [[R]]
95;
96  %t0 = icmp slt i32 %x, 128
97  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
98  %t2 = add i32 %x, 16
99  %t3 = icmp ugt i32 %t2, 143
100  %r = select i1 %t3, i32 %t1, i32 %x
101  ret i32 %r
102}
103define i32 @t5_ugt_slt_0(i32 %x, i32 %replacement_low, i32 %replacement_high) {
104; CHECK-LABEL: @t5_ugt_slt_0(
105; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
106; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
107; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
108; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
109; CHECK-NEXT:    ret i32 [[R]]
110;
111  %t0 = icmp slt i32 %x, -16
112  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
113  %t2 = add i32 %x, 16
114  %t3 = icmp ugt i32 %t2, 143
115  %r = select i1 %t3, i32 %t1, i32 %x
116  ret i32 %r
117}
118
119define i32 @t6_ugt_sgt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) {
120; CHECK-LABEL: @t6_ugt_sgt_128(
121; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
122; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
123; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
124; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
125; CHECK-NEXT:    ret i32 [[R]]
126;
127  %t0 = icmp sgt i32 %x, 127
128  %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low
129  %t2 = add i32 %x, 16
130  %t3 = icmp ugt i32 %t2, 143
131  %r = select i1 %t3, i32 %t1, i32 %x
132  ret i32 %r
133}
134define i32 @t7_ugt_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) {
135; CHECK-LABEL: @t7_ugt_sgt_neg1(
136; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
137; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
138; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
139; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
140; CHECK-NEXT:    ret i32 [[R]]
141;
142  %t0 = icmp sgt i32 %x, -17
143  %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low
144  %t2 = add i32 %x, 16
145  %t3 = icmp ugt i32 %t2, 143
146  %r = select i1 %t3, i32 %t1, i32 %x
147  ret i32 %r
148}
149
150;-------------------------------------------------------------------------------
151
152; So Ct0 can not be s> 128, or s< -16
153
154define i32 @n8_ult_slt_129(i32 %x, i32 %replacement_low, i32 %replacement_high) {
155; CHECK-LABEL: @n8_ult_slt_129(
156; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 129
157; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
158; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
159; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
160; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
161; CHECK-NEXT:    ret i32 [[R]]
162;
163  %t0 = icmp slt i32 %x, 129
164  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
165  %t2 = add i32 %x, 16
166  %t3 = icmp ult i32 %t2, 144
167  %r = select i1 %t3, i32 %x, i32 %t1
168  ret i32 %r
169}
170define i32 @n9_ult_slt_neg17(i32 %x, i32 %replacement_low, i32 %replacement_high) {
171; CHECK-LABEL: @n9_ult_slt_neg17(
172; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], -17
173; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
174; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
175; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
176; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
177; CHECK-NEXT:    ret i32 [[R]]
178;
179  %t0 = icmp slt i32 %x, -17
180  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
181  %t2 = add i32 %x, 16
182  %t3 = icmp ult i32 %t2, 144
183  %r = select i1 %t3, i32 %x, i32 %t1
184  ret i32 %r
185}
186
187;-------------------------------------------------------------------------------
188
189declare void @use32(i32)
190declare void @use1(i1)
191
192; One-use restrictions: here the entire pattern needs to be one-use.
193; FIXME: if %t0 could be reused then it's less restrictive.
194
195; This one is ok.
196define i32 @t10_oneuse0(i32 %x, i32 %replacement_low, i32 %replacement_high) {
197; CHECK-LABEL: @t10_oneuse0(
198; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
199; CHECK-NEXT:    call void @use1(i1 [[T0]])
200; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X]], -16
201; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
202; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
203; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
204; CHECK-NEXT:    ret i32 [[R]]
205;
206  %t0 = icmp slt i32 %x, 64
207  call void @use1(i1 %t0)
208  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
209  %t2 = add i32 %x, 16
210  %t3 = icmp ult i32 %t2, 144
211  %r = select i1 %t3, i32 %x, i32 %t1
212  ret i32 %r
213}
214define i32 @n11_oneuse1(i32 %x, i32 %replacement_low, i32 %replacement_high) {
215; CHECK-LABEL: @n11_oneuse1(
216; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
217; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
218; CHECK-NEXT:    call void @use32(i32 [[T1]])
219; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
220; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
221; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
222; CHECK-NEXT:    ret i32 [[R]]
223;
224  %t0 = icmp slt i32 %x, 64
225  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
226  call void @use32(i32 %t1)
227  %t2 = add i32 %x, 16
228  %t3 = icmp ult i32 %t2, 144
229  %r = select i1 %t3, i32 %x, i32 %t1
230  ret i32 %r
231}
232
233; This one is ok.
234define i32 @t12_oneuse2(i32 %x, i32 %replacement_low, i32 %replacement_high) {
235; CHECK-LABEL: @t12_oneuse2(
236; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X:%.*]], 16
237; CHECK-NEXT:    call void @use32(i32 [[T2]])
238; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X]], -16
239; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
240; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
241; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
242; CHECK-NEXT:    ret i32 [[R]]
243;
244  %t0 = icmp slt i32 %x, 64
245  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
246  %t2 = add i32 %x, 16
247  call void @use32(i32 %t2)
248  %t3 = icmp ult i32 %t2, 144
249  %r = select i1 %t3, i32 %x, i32 %t1
250  ret i32 %r
251}
252
253define i32 @n13_oneuse3(i32 %x, i32 %replacement_low, i32 %replacement_high) {
254; CHECK-LABEL: @n13_oneuse3(
255; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
256; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
257; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
258; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
259; CHECK-NEXT:    call void @use1(i1 [[T3]])
260; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
261; CHECK-NEXT:    ret i32 [[R]]
262;
263  %t0 = icmp slt i32 %x, 64
264  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
265  %t2 = add i32 %x, 16
266  %t3 = icmp ult i32 %t2, 144
267  call void @use1(i1 %t3)
268  %r = select i1 %t3, i32 %x, i32 %t1
269  ret i32 %r
270}
271
272define i32 @n14_oneuse4(i32 %x, i32 %replacement_low, i32 %replacement_high) {
273; CHECK-LABEL: @n14_oneuse4(
274; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
275; CHECK-NEXT:    call void @use1(i1 [[T0]])
276; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
277; CHECK-NEXT:    call void @use32(i32 [[T1]])
278; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
279; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
280; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
281; CHECK-NEXT:    ret i32 [[R]]
282;
283  %t0 = icmp slt i32 %x, 64
284  call void @use1(i1 %t0)
285  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
286  call void @use32(i32 %t1)
287  %t2 = add i32 %x, 16
288  %t3 = icmp ult i32 %t2, 144
289  %r = select i1 %t3, i32 %x, i32 %t1
290  ret i32 %r
291}
292define i32 @n15_oneuse5(i32 %x, i32 %replacement_low, i32 %replacement_high) {
293; CHECK-LABEL: @n15_oneuse5(
294; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
295; CHECK-NEXT:    call void @use1(i1 [[T0]])
296; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
297; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
298; CHECK-NEXT:    call void @use32(i32 [[T2]])
299; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
300; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
301; CHECK-NEXT:    ret i32 [[R]]
302;
303  %t0 = icmp slt i32 %x, 64
304  call void @use1(i1 %t0)
305  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
306  %t2 = add i32 %x, 16
307  call void @use32(i32 %t2)
308  %t3 = icmp ult i32 %t2, 144
309  %r = select i1 %t3, i32 %x, i32 %t1
310  ret i32 %r
311}
312define i32 @n16_oneuse6(i32 %x, i32 %replacement_low, i32 %replacement_high) {
313; CHECK-LABEL: @n16_oneuse6(
314; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
315; CHECK-NEXT:    call void @use1(i1 [[T0]])
316; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
317; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
318; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
319; CHECK-NEXT:    call void @use1(i1 [[T3]])
320; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
321; CHECK-NEXT:    ret i32 [[R]]
322;
323  %t0 = icmp slt i32 %x, 64
324  call void @use1(i1 %t0)
325  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
326  %t2 = add i32 %x, 16
327  %t3 = icmp ult i32 %t2, 144
328  call void @use1(i1 %t3)
329  %r = select i1 %t3, i32 %x, i32 %t1
330  ret i32 %r
331}
332
333define i32 @n17_oneuse7(i32 %x, i32 %replacement_low, i32 %replacement_high) {
334; CHECK-LABEL: @n17_oneuse7(
335; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
336; CHECK-NEXT:    call void @use1(i1 [[T0]])
337; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
338; CHECK-NEXT:    call void @use32(i32 [[T1]])
339; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
340; CHECK-NEXT:    call void @use32(i32 [[T2]])
341; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
342; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
343; CHECK-NEXT:    ret i32 [[R]]
344;
345  %t0 = icmp slt i32 %x, 64
346  call void @use1(i1 %t0)
347  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
348  call void @use32(i32 %t1)
349  %t2 = add i32 %x, 16
350  call void @use32(i32 %t2)
351  %t3 = icmp ult i32 %t2, 144
352  %r = select i1 %t3, i32 %x, i32 %t1
353  ret i32 %r
354}
355define i32 @n18_oneuse8(i32 %x, i32 %replacement_low, i32 %replacement_high) {
356; CHECK-LABEL: @n18_oneuse8(
357; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
358; CHECK-NEXT:    call void @use1(i1 [[T0]])
359; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
360; CHECK-NEXT:    call void @use32(i32 [[T1]])
361; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
362; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
363; CHECK-NEXT:    call void @use1(i1 [[T3]])
364; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
365; CHECK-NEXT:    ret i32 [[R]]
366;
367  %t0 = icmp slt i32 %x, 64
368  call void @use1(i1 %t0)
369  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
370  call void @use32(i32 %t1)
371  %t2 = add i32 %x, 16
372  %t3 = icmp ult i32 %t2, 144
373  call void @use1(i1 %t3)
374  %r = select i1 %t3, i32 %x, i32 %t1
375  ret i32 %r
376}
377
378define i32 @n19_oneuse9(i32 %x, i32 %replacement_low, i32 %replacement_high) {
379; CHECK-LABEL: @n19_oneuse9(
380; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
381; CHECK-NEXT:    call void @use1(i1 [[T0]])
382; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
383; CHECK-NEXT:    call void @use32(i32 [[T1]])
384; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
385; CHECK-NEXT:    call void @use32(i32 [[T2]])
386; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
387; CHECK-NEXT:    call void @use1(i1 [[T3]])
388; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
389; CHECK-NEXT:    ret i32 [[R]]
390;
391  %t0 = icmp slt i32 %x, 64
392  call void @use1(i1 %t0)
393  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
394  call void @use32(i32 %t1)
395  %t2 = add i32 %x, 16
396  call void @use32(i32 %t2)
397  %t3 = icmp ult i32 %t2, 144
398  call void @use1(i1 %t3)
399  %r = select i1 %t3, i32 %x, i32 %t1
400  ret i32 %r
401}
402
403;-------------------------------------------------------------------------------
404
405; Vectors
406
407define <2 x i32> @t20_ult_slt_vec_splat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) {
408; CHECK-LABEL: @t20_ult_slt_vec_splat(
409; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 -16, i32 -16>
410; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], <i32 127, i32 127>
411; CHECK-NEXT:    [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]]
412; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]]
413; CHECK-NEXT:    ret <2 x i32> [[R]]
414;
415  %t0 = icmp slt <2 x i32> %x, <i32 128, i32 128>
416  %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high
417  %t2 = add <2 x i32> %x, <i32 16, i32 16>
418  %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 144>
419  %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1
420  ret <2 x i32> %r
421}
422define <2 x i32> @t21_ult_slt_vec_nonsplat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) {
423; CHECK-LABEL: @t21_ult_slt_vec_nonsplat(
424; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 -16, i32 -8>
425; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], <i32 127, i32 255>
426; CHECK-NEXT:    [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]]
427; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]]
428; CHECK-NEXT:    ret <2 x i32> [[R]]
429;
430  %t0 = icmp slt <2 x i32> %x, <i32 128, i32 64>
431  %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high
432  %t2 = add <2 x i32> %x, <i32 16, i32 8>
433  %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 264>
434  %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1
435  ret <2 x i32> %r
436}
437
438; Non-canonical predicates
439
440declare void @use2xi1(<2 x i1>)
441
442declare void @use(<2 x i1>)
443define <2 x i32> @t22_uge_slt(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) {
444; CHECK-LABEL: @t22_uge_slt(
445; CHECK-NEXT:    [[T0:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 128, i32 128>
446; CHECK-NEXT:    [[T1:%.*]] = select <2 x i1> [[T0]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[REPLACEMENT_HIGH:%.*]]
447; CHECK-NEXT:    [[T2:%.*]] = add <2 x i32> [[X]], <i32 16, i32 16>
448; CHECK-NEXT:    [[T3:%.*]] = icmp uge <2 x i32> [[T2]], <i32 144, i32 0>
449; CHECK-NEXT:    call void @use2xi1(<2 x i1> [[T3]])
450; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T3]], <2 x i32> [[T1]], <2 x i32> [[X]]
451; CHECK-NEXT:    ret <2 x i32> [[R]]
452;
453  %t0 = icmp slt <2 x i32> %x, <i32 128, i32 128>
454  %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high
455  %t2 = add <2 x i32> %x, <i32 16, i32 16>
456  %t3 = icmp uge <2 x i32> %t2, <i32 144, i32 0>
457  call void @use2xi1(<2 x i1> %t3)
458  %r = select <2 x i1> %t3, <2 x i32> %t1, <2 x i32> %x
459  ret <2 x i32> %r
460}
461
462define <2 x i32> @t23_ult_sge(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) {
463; CHECK-LABEL: @t23_ult_sge(
464; CHECK-NEXT:    [[T0:%.*]] = icmp sge <2 x i32> [[X:%.*]], <i32 128, i32 -2147483648>
465; CHECK-NEXT:    call void @use2xi1(<2 x i1> [[T0]])
466; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <2 x i32> [[X]], <i32 -16, i32 -2147483648>
467; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], <i32 127, i32 2147483646>
468; CHECK-NEXT:    [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]]
469; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]]
470; CHECK-NEXT:    ret <2 x i32> [[R]]
471;
472  %t0 = icmp sge <2 x i32> %x, <i32 128, i32 -2147483648>
473  call void @use2xi1(<2 x i1> %t0)
474  %t1 = select <2 x i1> %t0, <2 x i32> %replacement_high, <2 x i32> %replacement_low
475  %t2 = add <2 x i32> %x, <i32 16, i32 -2147483648>
476  %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 -1>
477  %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1
478  ret <2 x i32> %r
479}
480