[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / Transforms / InstCombine / canonicalize-clamp-like-pattern-between-negative-and-positive-thresholds.ll
blob7daac62d55fd091e7ac4694854d282a2a36d0d40
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
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.)
19 ;-------------------------------------------------------------------------------
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.
26 define 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 slt i32 [[X]], 128
30 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
31 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
32 ; CHECK-NEXT:    ret i32 [[R]]
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
41 define 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 slt i32 [[X]], 128
45 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
46 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
47 ; CHECK-NEXT:    ret i32 [[R]]
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
57 define 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 slt i32 [[X]], 128
61 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
62 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
63 ; CHECK-NEXT:    ret i32 [[R]]
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
72 define 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 slt i32 [[X]], 128
76 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
77 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
78 ; CHECK-NEXT:    ret i32 [[R]]
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
88 define 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 slt i32 [[X]], 128
92 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
93 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
94 ; CHECK-NEXT:    ret i32 [[R]]
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
103 define 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 slt i32 [[X]], 128
107 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
108 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
109 ; CHECK-NEXT:    ret i32 [[R]]
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
119 define 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 slt i32 [[X]], 128
123 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
124 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
125 ; CHECK-NEXT:    ret i32 [[R]]
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
134 define 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 slt i32 [[X]], 128
138 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
139 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
140 ; CHECK-NEXT:    ret i32 [[R]]
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
150 ;-------------------------------------------------------------------------------
152 ; So Ct0 can not be s> 128, or s< -16
154 define 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]]
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
170 define 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]]
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
187 ;-------------------------------------------------------------------------------
189 declare void @use32(i32)
190 declare void @use1(i1)
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.
195 ; This one is ok.
196 define 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 slt i32 [[X]], 128
202 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
203 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
204 ; CHECK-NEXT:    ret i32 [[R]]
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
214 define 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]]
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
233 ; This one is ok.
234 define 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 slt i32 [[X]], 128
240 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]]
241 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]]
242 ; CHECK-NEXT:    ret i32 [[R]]
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
253 define 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]]
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
272 define 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]]
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
292 define 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]]
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
312 define 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]]
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
333 define 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]]
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
355 define 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]]
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
378 define 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]]
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
403 ;-------------------------------------------------------------------------------
405 ; Vectors
407 define <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 slt <2 x i32> [[X]], <i32 128, i32 128>
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> [[TMP3]], <2 x i32> [[REPLACEMENT_HIGH:%.*]]
413 ; CHECK-NEXT:    ret <2 x i32> [[R]]
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
422 define <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 slt <2 x i32> [[X]], <i32 128, i32 256>
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> [[TMP3]], <2 x i32> [[REPLACEMENT_HIGH:%.*]]
428 ; CHECK-NEXT:    ret <2 x i32> [[R]]
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
438 ; Non-canonical predicates
440 declare void @use2xi1(<2 x i1>)
442 declare void @use(<2 x i1>)
443 define <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]]
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
462 define <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 slt <2 x i32> [[X]], <i32 128, i32 2147483647>
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> [[TMP3]], <2 x i32> [[REPLACEMENT_HIGH:%.*]]
470 ; CHECK-NEXT:    ret <2 x i32> [[R]]
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