1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=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}
134
135define i32 @t7_ugt_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) {
136; CHECK-LABEL: @t7_ugt_sgt_neg1(
137; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16
138; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
139; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
140; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
141; CHECK-NEXT:    ret i32 [[R]]
142;
143  %t0 = icmp sgt i32 %x, -17
144  %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low
145  %t2 = add i32 %x, 16
146  %t3 = icmp ugt i32 %t2, 143
147  %r = select i1 %t3, i32 %t1, i32 %x
148  ret i32 %r
149}
150
151;-------------------------------------------------------------------------------
152
153; So Ct0 can not be s> 128, or s< -16
154
155define i32 @n8_ult_slt_129(i32 %x, i32 %replacement_low, i32 %replacement_high) {
156; CHECK-LABEL: @n8_ult_slt_129(
157; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 129
158; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
159; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
160; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
161; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
162; CHECK-NEXT:    ret i32 [[R]]
163;
164  %t0 = icmp slt i32 %x, 129
165  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
166  %t2 = add i32 %x, 16
167  %t3 = icmp ult i32 %t2, 144
168  %r = select i1 %t3, i32 %x, i32 %t1
169  ret i32 %r
170}
171
172define i32 @n9_ult_slt_neg17(i32 %x, i32 %replacement_low, i32 %replacement_high) {
173; CHECK-LABEL: @n9_ult_slt_neg17(
174; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], -17
175; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
176; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
177; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
178; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
179; CHECK-NEXT:    ret i32 [[R]]
180;
181  %t0 = icmp slt i32 %x, -17
182  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
183  %t2 = add i32 %x, 16
184  %t3 = icmp ult i32 %t2, 144
185  %r = select i1 %t3, i32 %x, i32 %t1
186  ret i32 %r
187}
188
189; Regression test for PR53252.
190define i32 @n10_ugt_slt(i32 %x, i32 %replacement_low, i32 %replacement_high) {
191; CHECK-LABEL: @n10_ugt_slt(
192; CHECK-NEXT:    [[T2:%.*]] = icmp ugt i32 [[X:%.*]], 128
193; CHECK-NEXT:    [[R:%.*]] = select i1 [[T2]], i32 [[X]], i32 [[REPLACEMENT_HIGH:%.*]]
194; CHECK-NEXT:    ret i32 [[R]]
195;
196  %t0 = icmp slt i32 %x, 0
197  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
198  %t2 = icmp ugt i32 %x, 128
199  %r = select i1 %t2, i32 %x, i32 %t1
200  ret i32 %r
201}
202
203define i32 @n11_uge_slt(i32 %x, i32 %replacement_low, i32 %replacement_high) {
204; CHECK-LABEL: @n11_uge_slt(
205; CHECK-NEXT:    [[T2:%.*]] = icmp ult i32 [[X:%.*]], 129
206; CHECK-NEXT:    [[R:%.*]] = select i1 [[T2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[X]]
207; CHECK-NEXT:    ret i32 [[R]]
208;
209  %t0 = icmp slt i32 %x, 0
210  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
211  %t2 = icmp ult i32 %x, 129
212  %r = select i1 %t2, i32 %t1, i32 %x
213  ret i32 %r
214}
215
216define i32 @n12_ule_slt(i32 %x, i32 %replacement_low, i32 %replacement_high) {
217; CHECK-LABEL: @n12_ule_slt(
218; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], -1
219; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
220; CHECK-NEXT:    [[T2:%.*]] = icmp ugt i32 [[X]], 127
221; CHECK-NEXT:    [[R:%.*]] = select i1 [[T2]], i32 [[T1]], i32 [[X]]
222; CHECK-NEXT:    ret i32 [[R]]
223;
224  %t0 = icmp slt i32 %x, -1
225  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
226  %t2 = icmp ugt i32 %x, 127
227  %r = select i1 %t2, i32 %t1, i32 %x
228  ret i32 %r
229}
230
231;-------------------------------------------------------------------------------
232
233declare void @use32(i32)
234declare void @use1(i1)
235
236; One-use restrictions: here the entire pattern needs to be one-use.
237; FIXME: if %t0 could be reused then it's less restrictive.
238
239; This one is ok.
240define i32 @t10_oneuse0(i32 %x, i32 %replacement_low, i32 %replacement_high) {
241; CHECK-LABEL: @t10_oneuse0(
242; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
243; CHECK-NEXT:    call void @use1(i1 [[T0]])
244; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X]], -16
245; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
246; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
247; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
248; CHECK-NEXT:    ret i32 [[R]]
249;
250  %t0 = icmp slt i32 %x, 64
251  call void @use1(i1 %t0)
252  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
253  %t2 = add i32 %x, 16
254  %t3 = icmp ult i32 %t2, 144
255  %r = select i1 %t3, i32 %x, i32 %t1
256  ret i32 %r
257}
258define i32 @n11_oneuse1(i32 %x, i32 %replacement_low, i32 %replacement_high) {
259; CHECK-LABEL: @n11_oneuse1(
260; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
261; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
262; CHECK-NEXT:    call void @use32(i32 [[T1]])
263; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
264; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
265; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
266; CHECK-NEXT:    ret i32 [[R]]
267;
268  %t0 = icmp slt i32 %x, 64
269  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
270  call void @use32(i32 %t1)
271  %t2 = add i32 %x, 16
272  %t3 = icmp ult i32 %t2, 144
273  %r = select i1 %t3, i32 %x, i32 %t1
274  ret i32 %r
275}
276
277; This one is ok.
278define i32 @t12_oneuse2(i32 %x, i32 %replacement_low, i32 %replacement_high) {
279; CHECK-LABEL: @t12_oneuse2(
280; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X:%.*]], 16
281; CHECK-NEXT:    call void @use32(i32 [[T2]])
282; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X]], -16
283; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], 127
284; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
285; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]]
286; CHECK-NEXT:    ret i32 [[R]]
287;
288  %t0 = icmp slt i32 %x, 64
289  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
290  %t2 = add i32 %x, 16
291  call void @use32(i32 %t2)
292  %t3 = icmp ult i32 %t2, 144
293  %r = select i1 %t3, i32 %x, i32 %t1
294  ret i32 %r
295}
296
297define i32 @n13_oneuse3(i32 %x, i32 %replacement_low, i32 %replacement_high) {
298; CHECK-LABEL: @n13_oneuse3(
299; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
300; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
301; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
302; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
303; CHECK-NEXT:    call void @use1(i1 [[T3]])
304; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
305; CHECK-NEXT:    ret i32 [[R]]
306;
307  %t0 = icmp slt i32 %x, 64
308  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
309  %t2 = add i32 %x, 16
310  %t3 = icmp ult i32 %t2, 144
311  call void @use1(i1 %t3)
312  %r = select i1 %t3, i32 %x, i32 %t1
313  ret i32 %r
314}
315
316define i32 @n14_oneuse4(i32 %x, i32 %replacement_low, i32 %replacement_high) {
317; CHECK-LABEL: @n14_oneuse4(
318; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
319; CHECK-NEXT:    call void @use1(i1 [[T0]])
320; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
321; CHECK-NEXT:    call void @use32(i32 [[T1]])
322; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
323; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
324; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
325; CHECK-NEXT:    ret i32 [[R]]
326;
327  %t0 = icmp slt i32 %x, 64
328  call void @use1(i1 %t0)
329  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
330  call void @use32(i32 %t1)
331  %t2 = add i32 %x, 16
332  %t3 = icmp ult i32 %t2, 144
333  %r = select i1 %t3, i32 %x, i32 %t1
334  ret i32 %r
335}
336define i32 @n15_oneuse5(i32 %x, i32 %replacement_low, i32 %replacement_high) {
337; CHECK-LABEL: @n15_oneuse5(
338; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
339; CHECK-NEXT:    call void @use1(i1 [[T0]])
340; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
341; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
342; CHECK-NEXT:    call void @use32(i32 [[T2]])
343; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
344; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
345; CHECK-NEXT:    ret i32 [[R]]
346;
347  %t0 = icmp slt i32 %x, 64
348  call void @use1(i1 %t0)
349  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
350  %t2 = add i32 %x, 16
351  call void @use32(i32 %t2)
352  %t3 = icmp ult i32 %t2, 144
353  %r = select i1 %t3, i32 %x, i32 %t1
354  ret i32 %r
355}
356define i32 @n16_oneuse6(i32 %x, i32 %replacement_low, i32 %replacement_high) {
357; CHECK-LABEL: @n16_oneuse6(
358; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
359; CHECK-NEXT:    call void @use1(i1 [[T0]])
360; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
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  %t2 = add i32 %x, 16
371  %t3 = icmp ult i32 %t2, 144
372  call void @use1(i1 %t3)
373  %r = select i1 %t3, i32 %x, i32 %t1
374  ret i32 %r
375}
376
377define i32 @n17_oneuse7(i32 %x, i32 %replacement_low, i32 %replacement_high) {
378; CHECK-LABEL: @n17_oneuse7(
379; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
380; CHECK-NEXT:    call void @use1(i1 [[T0]])
381; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
382; CHECK-NEXT:    call void @use32(i32 [[T1]])
383; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
384; CHECK-NEXT:    call void @use32(i32 [[T2]])
385; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
386; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
387; CHECK-NEXT:    ret i32 [[R]]
388;
389  %t0 = icmp slt i32 %x, 64
390  call void @use1(i1 %t0)
391  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
392  call void @use32(i32 %t1)
393  %t2 = add i32 %x, 16
394  call void @use32(i32 %t2)
395  %t3 = icmp ult i32 %t2, 144
396  %r = select i1 %t3, i32 %x, i32 %t1
397  ret i32 %r
398}
399define i32 @n18_oneuse8(i32 %x, i32 %replacement_low, i32 %replacement_high) {
400; CHECK-LABEL: @n18_oneuse8(
401; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
402; CHECK-NEXT:    call void @use1(i1 [[T0]])
403; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
404; CHECK-NEXT:    call void @use32(i32 [[T1]])
405; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
406; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
407; CHECK-NEXT:    call void @use1(i1 [[T3]])
408; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
409; CHECK-NEXT:    ret i32 [[R]]
410;
411  %t0 = icmp slt i32 %x, 64
412  call void @use1(i1 %t0)
413  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
414  call void @use32(i32 %t1)
415  %t2 = add i32 %x, 16
416  %t3 = icmp ult i32 %t2, 144
417  call void @use1(i1 %t3)
418  %r = select i1 %t3, i32 %x, i32 %t1
419  ret i32 %r
420}
421
422define i32 @n19_oneuse9(i32 %x, i32 %replacement_low, i32 %replacement_high) {
423; CHECK-LABEL: @n19_oneuse9(
424; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64
425; CHECK-NEXT:    call void @use1(i1 [[T0]])
426; CHECK-NEXT:    [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]]
427; CHECK-NEXT:    call void @use32(i32 [[T1]])
428; CHECK-NEXT:    [[T2:%.*]] = add i32 [[X]], 16
429; CHECK-NEXT:    call void @use32(i32 [[T2]])
430; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 144
431; CHECK-NEXT:    call void @use1(i1 [[T3]])
432; CHECK-NEXT:    [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]]
433; CHECK-NEXT:    ret i32 [[R]]
434;
435  %t0 = icmp slt i32 %x, 64
436  call void @use1(i1 %t0)
437  %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high
438  call void @use32(i32 %t1)
439  %t2 = add i32 %x, 16
440  call void @use32(i32 %t2)
441  %t3 = icmp ult i32 %t2, 144
442  call void @use1(i1 %t3)
443  %r = select i1 %t3, i32 %x, i32 %t1
444  ret i32 %r
445}
446
447;-------------------------------------------------------------------------------
448
449; Vectors
450
451define <2 x i32> @t20_ult_slt_vec_splat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) {
452; CHECK-LABEL: @t20_ult_slt_vec_splat(
453; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], splat (i32 -16)
454; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], splat (i32 127)
455; CHECK-NEXT:    [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]]
456; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]]
457; CHECK-NEXT:    ret <2 x i32> [[R]]
458;
459  %t0 = icmp slt <2 x i32> %x, <i32 128, i32 128>
460  %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high
461  %t2 = add <2 x i32> %x, <i32 16, i32 16>
462  %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 144>
463  %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1
464  ret <2 x i32> %r
465}
466define <2 x i32> @t21_ult_slt_vec_nonsplat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) {
467; CHECK-LABEL: @t21_ult_slt_vec_nonsplat(
468; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 -16, i32 -8>
469; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], <i32 127, i32 255>
470; CHECK-NEXT:    [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]]
471; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]]
472; CHECK-NEXT:    ret <2 x i32> [[R]]
473;
474  %t0 = icmp slt <2 x i32> %x, <i32 128, i32 64>
475  %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high
476  %t2 = add <2 x i32> %x, <i32 16, i32 8>
477  %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 264>
478  %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1
479  ret <2 x i32> %r
480}
481
482; Non-canonical predicates
483
484declare void @use2xi1(<2 x i1>)
485
486declare void @use(<2 x i1>)
487define <2 x i32> @t22_uge_slt(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) {
488; CHECK-LABEL: @t22_uge_slt(
489; CHECK-NEXT:    [[T0:%.*]] = icmp slt <2 x i32> [[X:%.*]], splat (i32 128)
490; CHECK-NEXT:    [[T1:%.*]] = select <2 x i1> [[T0]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[REPLACEMENT_HIGH:%.*]]
491; CHECK-NEXT:    [[T2:%.*]] = add <2 x i32> [[X]], splat (i32 16)
492; CHECK-NEXT:    [[T3:%.*]] = icmp uge <2 x i32> [[T2]], <i32 144, i32 0>
493; CHECK-NEXT:    call void @use2xi1(<2 x i1> [[T3]])
494; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T3]], <2 x i32> [[T1]], <2 x i32> [[X]]
495; CHECK-NEXT:    ret <2 x i32> [[R]]
496;
497  %t0 = icmp slt <2 x i32> %x, <i32 128, i32 128>
498  %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high
499  %t2 = add <2 x i32> %x, <i32 16, i32 16>
500  %t3 = icmp uge <2 x i32> %t2, <i32 144, i32 0>
501  call void @use2xi1(<2 x i1> %t3)
502  %r = select <2 x i1> %t3, <2 x i32> %t1, <2 x i32> %x
503  ret <2 x i32> %r
504}
505
506define <2 x i32> @t23_ult_sge(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) {
507; CHECK-LABEL: @t23_ult_sge(
508; CHECK-NEXT:    [[T0:%.*]] = icmp sge <2 x i32> [[X:%.*]], <i32 128, i32 -2147483648>
509; CHECK-NEXT:    call void @use2xi1(<2 x i1> [[T0]])
510; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <2 x i32> [[X]], <i32 -16, i32 -2147483648>
511; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], <i32 127, i32 2147483646>
512; CHECK-NEXT:    [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]]
513; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]]
514; CHECK-NEXT:    ret <2 x i32> [[R]]
515;
516  %t0 = icmp sge <2 x i32> %x, <i32 128, i32 -2147483648>
517  call void @use2xi1(<2 x i1> %t0)
518  %t1 = select <2 x i1> %t0, <2 x i32> %replacement_high, <2 x i32> %replacement_low
519  %t2 = add <2 x i32> %x, <i32 16, i32 -2147483648>
520  %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 -1>
521  %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1
522  ret <2 x i32> %r
523}
524