[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / ARM / ssat.ll
blobfb3c17710b75692c69db5525475962578b4b6a86
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=armv4t-eabi %s -o - | FileCheck %s --check-prefix=V4T
3 ; RUN: llc -mtriple=armv6t2-eabi %s -o - | FileCheck %s --check-prefix=V6T2
5 ; Check for several conditions that should result in SSAT.
6 ; For example, the base test is equivalent to
7 ; x < -k ? -k : (x > k ? k : x) in C. All patterns that bound x
8 ; to the interval [-k, k] where k is a power of 2 can be
9 ; transformed into SSAT. At the end there are some tests
10 ; checking that conditionals are not transformed if they don't
11 ; match the right pattern.
14 ; Base tests with different bit widths
17 ; x < -k ? -k : (x > k ? k : x)
18 ; 32-bit base test
19 define i32 @sat_base_32bit(i32 %x) #0 {
20 ; V4T-LABEL: sat_base_32bit:
21 ; V4T:       @ %bb.0: @ %entry
22 ; V4T-NEXT:    ldr r1, .LCPI0_0
23 ; V4T-NEXT:    cmp r0, r1
24 ; V4T-NEXT:    movlt r1, r0
25 ; V4T-NEXT:    mov r0, #1065353216
26 ; V4T-NEXT:    orr r0, r0, #-1073741824
27 ; V4T-NEXT:    cmn r1, #8388608
28 ; V4T-NEXT:    movgt r0, r1
29 ; V4T-NEXT:    bx lr
30 ; V4T-NEXT:    .p2align 2
31 ; V4T-NEXT:  @ %bb.1:
32 ; V4T-NEXT:  .LCPI0_0:
33 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
35 ; V6T2-LABEL: sat_base_32bit:
36 ; V6T2:       @ %bb.0: @ %entry
37 ; V6T2-NEXT:    ssat r0, #24, r0
38 ; V6T2-NEXT:    bx lr
39 entry:
40   %0 = icmp slt i32 %x, 8388607
41   %saturateUp = select i1 %0, i32 %x, i32 8388607
42   %1 = icmp sgt i32 %saturateUp, -8388608
43   %saturateLow = select i1 %1, i32 %saturateUp, i32 -8388608
44   ret i32 %saturateLow
47 ; x < -k ? -k : (x > k ? k : x)
48 ; 16-bit base test
49 define i16 @sat_base_16bit(i16 %x) #0 {
50 ; V4T-LABEL: sat_base_16bit:
51 ; V4T:       @ %bb.0: @ %entry
52 ; V4T-NEXT:    mov r2, #255
53 ; V4T-NEXT:    lsl r1, r0, #16
54 ; V4T-NEXT:    orr r2, r2, #1792
55 ; V4T-NEXT:    asr r1, r1, #16
56 ; V4T-NEXT:    cmp r1, r2
57 ; V4T-NEXT:    movlt r2, r0
58 ; V4T-NEXT:    lsl r0, r2, #16
59 ; V4T-NEXT:    asr r1, r0, #16
60 ; V4T-NEXT:    ldr r0, .LCPI1_0
61 ; V4T-NEXT:    cmn r1, #2048
62 ; V4T-NEXT:    movgt r0, r2
63 ; V4T-NEXT:    bx lr
64 ; V4T-NEXT:    .p2align 2
65 ; V4T-NEXT:  @ %bb.1:
66 ; V4T-NEXT:  .LCPI1_0:
67 ; V4T-NEXT:    .long 4294965248 @ 0xfffff800
69 ; V6T2-LABEL: sat_base_16bit:
70 ; V6T2:       @ %bb.0: @ %entry
71 ; V6T2-NEXT:    sxth r1, r0
72 ; V6T2-NEXT:    movw r2, #2047
73 ; V6T2-NEXT:    cmp r1, r2
74 ; V6T2-NEXT:    movlt r2, r0
75 ; V6T2-NEXT:    movw r0, #63488
76 ; V6T2-NEXT:    sxth r1, r2
77 ; V6T2-NEXT:    movt r0, #65535
78 ; V6T2-NEXT:    cmn r1, #2048
79 ; V6T2-NEXT:    movgt r0, r2
80 ; V6T2-NEXT:    bx lr
81 entry:
82   %0 = icmp slt i16 %x, 2047
83   %saturateUp = select i1 %0, i16 %x, i16 2047
84   %1 = icmp sgt i16 %saturateUp, -2048
85   %saturateLow = select i1 %1, i16 %saturateUp, i16 -2048
86   ret i16 %saturateLow
89 ; x < -k ? -k : (x > k ? k : x)
90 ; 8-bit base test
91 define i8 @sat_base_8bit(i8 %x) #0 {
92 ; V4T-LABEL: sat_base_8bit:
93 ; V4T:       @ %bb.0: @ %entry
94 ; V4T-NEXT:    lsl r1, r0, #24
95 ; V4T-NEXT:    asr r1, r1, #24
96 ; V4T-NEXT:    cmp r1, #31
97 ; V4T-NEXT:    movge r0, #31
98 ; V4T-NEXT:    lsl r1, r0, #24
99 ; V4T-NEXT:    asr r1, r1, #24
100 ; V4T-NEXT:    cmn r1, #32
101 ; V4T-NEXT:    mvnle r0, #31
102 ; V4T-NEXT:    bx lr
104 ; V6T2-LABEL: sat_base_8bit:
105 ; V6T2:       @ %bb.0: @ %entry
106 ; V6T2-NEXT:    sxtb r1, r0
107 ; V6T2-NEXT:    cmp r1, #31
108 ; V6T2-NEXT:    movge r0, #31
109 ; V6T2-NEXT:    sxtb r1, r0
110 ; V6T2-NEXT:    cmn r1, #32
111 ; V6T2-NEXT:    mvnle r0, #31
112 ; V6T2-NEXT:    bx lr
113 entry:
114   %0 = icmp slt i8 %x, 31
115   %saturateUp = select i1 %0, i8 %x, i8 31
116   %1 = icmp sgt i8 %saturateUp, -32
117   %saturateLow = select i1 %1, i8 %saturateUp, i8 -32
118   ret i8 %saturateLow
122 ; Tests where the conditionals that check for upper and lower bounds,
123 ; or the < and > operators, are arranged in different ways. Only some
124 ; of the possible combinations that lead to SSAT are tested.
127 ; x < -k ? -k : (x < k ? x : k)
128 define i32 @sat_lower_upper_1(i32 %x) #0 {
129 ; V4T-LABEL: sat_lower_upper_1:
130 ; V4T:       @ %bb.0: @ %entry
131 ; V4T-NEXT:    ldr r1, .LCPI3_0
132 ; V4T-NEXT:    cmp r0, r1
133 ; V4T-NEXT:    movlt r1, r0
134 ; V4T-NEXT:    mov r0, #1065353216
135 ; V4T-NEXT:    orr r0, r0, #-1073741824
136 ; V4T-NEXT:    cmn r1, #8388608
137 ; V4T-NEXT:    movgt r0, r1
138 ; V4T-NEXT:    bx lr
139 ; V4T-NEXT:    .p2align 2
140 ; V4T-NEXT:  @ %bb.1:
141 ; V4T-NEXT:  .LCPI3_0:
142 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
144 ; V6T2-LABEL: sat_lower_upper_1:
145 ; V6T2:       @ %bb.0: @ %entry
146 ; V6T2-NEXT:    ssat r0, #24, r0
147 ; V6T2-NEXT:    bx lr
148 entry:
149   %cmpUp = icmp slt i32 %x, 8388607
150   %saturateUp = select i1 %cmpUp, i32 %x, i32 8388607
151   %0 = icmp sgt i32 %saturateUp, -8388608
152   %saturateLow = select i1 %0, i32 %saturateUp, i32 -8388608
153   ret i32 %saturateLow
156 ; x > -k ? (x > k ? k : x) : -k
157 define i32 @sat_lower_upper_2(i32 %x) #0 {
158 ; V4T-LABEL: sat_lower_upper_2:
159 ; V4T:       @ %bb.0: @ %entry
160 ; V4T-NEXT:    ldr r1, .LCPI4_0
161 ; V4T-NEXT:    cmp r0, r1
162 ; V4T-NEXT:    movlt r1, r0
163 ; V4T-NEXT:    mov r0, #1065353216
164 ; V4T-NEXT:    orr r0, r0, #-1073741824
165 ; V4T-NEXT:    cmn r1, #8388608
166 ; V4T-NEXT:    movgt r0, r1
167 ; V4T-NEXT:    bx lr
168 ; V4T-NEXT:    .p2align 2
169 ; V4T-NEXT:  @ %bb.1:
170 ; V4T-NEXT:  .LCPI4_0:
171 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
173 ; V6T2-LABEL: sat_lower_upper_2:
174 ; V6T2:       @ %bb.0: @ %entry
175 ; V6T2-NEXT:    ssat r0, #24, r0
176 ; V6T2-NEXT:    bx lr
177 entry:
178   %0 = icmp slt i32 %x, 8388607
179   %saturateUp = select i1 %0, i32 %x, i32 8388607
180   %1 = icmp sgt i32 %saturateUp, -8388608
181   %saturateLow = select i1 %1, i32 %saturateUp, i32 -8388608
182   ret i32 %saturateLow
185 ; x < k ? (x < -k ? -k : x) : k
186 define i32 @sat_upper_lower_1(i32 %x) #0 {
187 ; V4T-LABEL: sat_upper_lower_1:
188 ; V4T:       @ %bb.0: @ %entry
189 ; V4T-NEXT:    mov r1, #1065353216
190 ; V4T-NEXT:    cmn r0, #8388608
191 ; V4T-NEXT:    orr r1, r1, #-1073741824
192 ; V4T-NEXT:    movgt r1, r0
193 ; V4T-NEXT:    ldr r0, .LCPI5_0
194 ; V4T-NEXT:    cmp r1, r0
195 ; V4T-NEXT:    movge r1, r0
196 ; V4T-NEXT:    mov r0, r1
197 ; V4T-NEXT:    bx lr
198 ; V4T-NEXT:    .p2align 2
199 ; V4T-NEXT:  @ %bb.1:
200 ; V4T-NEXT:  .LCPI5_0:
201 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
203 ; V6T2-LABEL: sat_upper_lower_1:
204 ; V6T2:       @ %bb.0: @ %entry
205 ; V6T2-NEXT:    ssat r0, #24, r0
206 ; V6T2-NEXT:    bx lr
207 entry:
208   %0 = icmp sgt i32 %x, -8388608
209   %saturateLow = select i1 %0, i32 %x, i32 -8388608
210   %1 = icmp slt i32 %saturateLow, 8388607
211   %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
212   ret i32 %saturateUp
215 ; x > k ? k : (x < -k ? -k : x)
216 define i32 @sat_upper_lower_2(i32 %x) #0 {
217 ; V4T-LABEL: sat_upper_lower_2:
218 ; V4T:       @ %bb.0: @ %entry
219 ; V4T-NEXT:    mov r1, #1065353216
220 ; V4T-NEXT:    cmn r0, #8388608
221 ; V4T-NEXT:    orr r1, r1, #-1073741824
222 ; V4T-NEXT:    movgt r1, r0
223 ; V4T-NEXT:    ldr r0, .LCPI6_0
224 ; V4T-NEXT:    cmp r1, r0
225 ; V4T-NEXT:    movge r1, r0
226 ; V4T-NEXT:    mov r0, r1
227 ; V4T-NEXT:    bx lr
228 ; V4T-NEXT:    .p2align 2
229 ; V4T-NEXT:  @ %bb.1:
230 ; V4T-NEXT:  .LCPI6_0:
231 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
233 ; V6T2-LABEL: sat_upper_lower_2:
234 ; V6T2:       @ %bb.0: @ %entry
235 ; V6T2-NEXT:    ssat r0, #24, r0
236 ; V6T2-NEXT:    bx lr
237 entry:
238   %0 = icmp sgt i32 %x, -8388608
239   %saturateLow = select i1 %0, i32 %x, i32 -8388608
240   %1 = icmp slt i32 %saturateLow, 8388607
241   %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
242   ret i32 %saturateUp
245 ; k < x ? k : (x > -k ? x : -k)
246 define i32 @sat_upper_lower_3(i32 %x) #0 {
247 ; V4T-LABEL: sat_upper_lower_3:
248 ; V4T:       @ %bb.0: @ %entry
249 ; V4T-NEXT:    mov r1, #1065353216
250 ; V4T-NEXT:    cmn r0, #8388608
251 ; V4T-NEXT:    orr r1, r1, #-1073741824
252 ; V4T-NEXT:    movgt r1, r0
253 ; V4T-NEXT:    ldr r0, .LCPI7_0
254 ; V4T-NEXT:    cmp r1, r0
255 ; V4T-NEXT:    movge r1, r0
256 ; V4T-NEXT:    mov r0, r1
257 ; V4T-NEXT:    bx lr
258 ; V4T-NEXT:    .p2align 2
259 ; V4T-NEXT:  @ %bb.1:
260 ; V4T-NEXT:  .LCPI7_0:
261 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
263 ; V6T2-LABEL: sat_upper_lower_3:
264 ; V6T2:       @ %bb.0: @ %entry
265 ; V6T2-NEXT:    ssat r0, #24, r0
266 ; V6T2-NEXT:    bx lr
267 entry:
268   %cmpLow = icmp sgt i32 %x, -8388608
269   %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608
270   %0 = icmp slt i32 %saturateLow, 8388607
271   %saturateUp = select i1 %0, i32 %saturateLow, i32 8388607
272   ret i32 %saturateUp
276 ; Miscellanea
279 ; Check that >= and <= work the same as > and <
280 ; k <= x ? k : (x >= -k ? x : -k)
281 define i32 @sat_le_ge(i32 %x) #0 {
282 ; V4T-LABEL: sat_le_ge:
283 ; V4T:       @ %bb.0: @ %entry
284 ; V4T-NEXT:    mov r1, #1065353216
285 ; V4T-NEXT:    cmn r0, #8388608
286 ; V4T-NEXT:    orr r1, r1, #-1073741824
287 ; V4T-NEXT:    movgt r1, r0
288 ; V4T-NEXT:    ldr r0, .LCPI8_0
289 ; V4T-NEXT:    cmp r1, r0
290 ; V4T-NEXT:    movge r1, r0
291 ; V4T-NEXT:    mov r0, r1
292 ; V4T-NEXT:    bx lr
293 ; V4T-NEXT:    .p2align 2
294 ; V4T-NEXT:  @ %bb.1:
295 ; V4T-NEXT:  .LCPI8_0:
296 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
298 ; V6T2-LABEL: sat_le_ge:
299 ; V6T2:       @ %bb.0: @ %entry
300 ; V6T2-NEXT:    ssat r0, #24, r0
301 ; V6T2-NEXT:    bx lr
302 entry:
303   %0 = icmp sgt i32 %x, -8388608
304   %saturateLow = select i1 %0, i32 %x, i32 -8388608
305   %1 = icmp slt i32 %saturateLow, 8388607
306   %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
307   ret i32 %saturateUp
311 ; The following tests check for patterns that should not transform
312 ; into SSAT but are similar enough that could confuse the selector.
315 ; x > k ? k : (x > -k ? -k : x)
316 ; First condition upper-saturates, second doesn't lower-saturate.
317 define i32 @no_sat_missing_lower(i32 %x) #0 {
318 ; V4T-LABEL: no_sat_missing_lower:
319 ; V4T:       @ %bb.0: @ %entry
320 ; V4T-NEXT:    mov r2, #1065353216
321 ; V4T-NEXT:    cmn r0, #8388608
322 ; V4T-NEXT:    orr r2, r2, #-1073741824
323 ; V4T-NEXT:    ldr r1, .LCPI9_0
324 ; V4T-NEXT:    movlt r2, r0
325 ; V4T-NEXT:    cmp r0, #8388608
326 ; V4T-NEXT:    movlt r1, r2
327 ; V4T-NEXT:    mov r0, r1
328 ; V4T-NEXT:    bx lr
329 ; V4T-NEXT:    .p2align 2
330 ; V4T-NEXT:  @ %bb.1:
331 ; V4T-NEXT:  .LCPI9_0:
332 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
334 ; V6T2-LABEL: no_sat_missing_lower:
335 ; V6T2:       @ %bb.0: @ %entry
336 ; V6T2-NEXT:    movw r1, #0
337 ; V6T2-NEXT:    cmn r0, #8388608
338 ; V6T2-NEXT:    movt r1, #65408
339 ; V6T2-NEXT:    movlt r1, r0
340 ; V6T2-NEXT:    cmp r0, #8388608
341 ; V6T2-NEXT:    movwge r1, #65535
342 ; V6T2-NEXT:    movtge r1, #127
343 ; V6T2-NEXT:    mov r0, r1
344 ; V6T2-NEXT:    bx lr
345 entry:
346   %cmpUp = icmp sgt i32 %x, 8388607
347   %0 = icmp slt i32 %x, -8388608
348   %saturateLow = select i1 %0, i32 %x, i32 -8388608
349   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
350   ret i32 %saturateUp
353 ; x < k ? k : (x < -k ? -k : x)
354 ; Second condition lower-saturates, first doesn't upper-saturate.
355 define i32 @no_sat_missing_upper(i32 %x) #0 {
356 ; V4T-LABEL: no_sat_missing_upper:
357 ; V4T:       @ %bb.0: @ %entry
358 ; V4T-NEXT:    mov r1, #1065353216
359 ; V4T-NEXT:    ldr r2, .LCPI10_0
360 ; V4T-NEXT:    orr r1, r1, #-1073741824
361 ; V4T-NEXT:    cmn r0, #8388608
362 ; V4T-NEXT:    movgt r1, r0
363 ; V4T-NEXT:    cmp r0, r2
364 ; V4T-NEXT:    movlt r1, r2
365 ; V4T-NEXT:    mov r0, r1
366 ; V4T-NEXT:    bx lr
367 ; V4T-NEXT:    .p2align 2
368 ; V4T-NEXT:  @ %bb.1:
369 ; V4T-NEXT:  .LCPI10_0:
370 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
372 ; V6T2-LABEL: no_sat_missing_upper:
373 ; V6T2:       @ %bb.0: @ %entry
374 ; V6T2-NEXT:    movw r1, #0
375 ; V6T2-NEXT:    movw r2, #65535
376 ; V6T2-NEXT:    movt r1, #65408
377 ; V6T2-NEXT:    cmn r0, #8388608
378 ; V6T2-NEXT:    movgt r1, r0
379 ; V6T2-NEXT:    movt r2, #127
380 ; V6T2-NEXT:    cmp r0, r2
381 ; V6T2-NEXT:    movwlt r1, #65535
382 ; V6T2-NEXT:    movtlt r1, #127
383 ; V6T2-NEXT:    mov r0, r1
384 ; V6T2-NEXT:    bx lr
385 entry:
386   %cmpUp = icmp slt i32 %x, 8388607
387   %0 = icmp sgt i32 %x, -8388608
388   %saturateLow = select i1 %0, i32 %x, i32 -8388608
389   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
390   ret i32 %saturateUp
393 ; Lower constant is different in the select and in the compare
394 define i32 @no_sat_incorrect_constant(i32 %x) #0 {
395 ; V4T-LABEL: no_sat_incorrect_constant:
396 ; V4T:       @ %bb.0: @ %entry
397 ; V4T-NEXT:    mov r2, #1065353216
398 ; V4T-NEXT:    cmn r0, #8388608
399 ; V4T-NEXT:    orr r2, r2, #-1073741824
400 ; V4T-NEXT:    mov r1, r0
401 ; V4T-NEXT:    orrlt r1, r2, #1
402 ; V4T-NEXT:    ldr r2, .LCPI11_0
403 ; V4T-NEXT:    cmp r0, #8388608
404 ; V4T-NEXT:    movge r1, r2
405 ; V4T-NEXT:    mov r0, r1
406 ; V4T-NEXT:    bx lr
407 ; V4T-NEXT:    .p2align 2
408 ; V4T-NEXT:  @ %bb.1:
409 ; V4T-NEXT:  .LCPI11_0:
410 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
412 ; V6T2-LABEL: no_sat_incorrect_constant:
413 ; V6T2:       @ %bb.0: @ %entry
414 ; V6T2-NEXT:    movw r2, #0
415 ; V6T2-NEXT:    cmn r0, #8388608
416 ; V6T2-NEXT:    mov r1, r0
417 ; V6T2-NEXT:    movt r2, #65408
418 ; V6T2-NEXT:    orrlt r1, r2, #1
419 ; V6T2-NEXT:    cmp r0, #8388608
420 ; V6T2-NEXT:    movwge r1, #65535
421 ; V6T2-NEXT:    movtge r1, #127
422 ; V6T2-NEXT:    mov r0, r1
423 ; V6T2-NEXT:    bx lr
424 entry:
425   %cmpUp = icmp sgt i32 %x, 8388607
426   %cmpLow = icmp slt i32 %x, -8388608
427   %saturateLow = select i1 %cmpLow, i32 -8388607, i32 %x
428   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
429   ret i32 %saturateUp
432 ; The interval is not [k, ~k]
433 define i32 @no_sat_incorrect_interval(i32 %x) #0 {
434 ; V4T-LABEL: no_sat_incorrect_interval:
435 ; V4T:       @ %bb.0: @ %entry
436 ; V4T-NEXT:    ldr r1, .LCPI12_0
437 ; V4T-NEXT:    cmp r0, r1
438 ; V4T-NEXT:    movgt r1, r0
439 ; V4T-NEXT:    ldr r0, .LCPI12_1
440 ; V4T-NEXT:    cmp r1, r0
441 ; V4T-NEXT:    movge r1, r0
442 ; V4T-NEXT:    mov r0, r1
443 ; V4T-NEXT:    bx lr
444 ; V4T-NEXT:    .p2align 2
445 ; V4T-NEXT:  @ %bb.1:
446 ; V4T-NEXT:  .LCPI12_0:
447 ; V4T-NEXT:    .long 4275878552 @ 0xfedcba98
448 ; V4T-NEXT:  .LCPI12_1:
449 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
451 ; V6T2-LABEL: no_sat_incorrect_interval:
452 ; V6T2:       @ %bb.0: @ %entry
453 ; V6T2-NEXT:    movw r1, #47768
454 ; V6T2-NEXT:    movt r1, #65244
455 ; V6T2-NEXT:    cmp r0, r1
456 ; V6T2-NEXT:    movgt r1, r0
457 ; V6T2-NEXT:    movw r0, #65535
458 ; V6T2-NEXT:    movt r0, #127
459 ; V6T2-NEXT:    cmp r1, r0
460 ; V6T2-NEXT:    movge r1, r0
461 ; V6T2-NEXT:    mov r0, r1
462 ; V6T2-NEXT:    bx lr
463 entry:
464   %0 = icmp sgt i32 %x, -19088744
465   %saturateLow = select i1 %0, i32 %x, i32 -19088744
466   %1 = icmp slt i32 %saturateLow, 8388607
467   %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
468   ret i32 %saturateUp
471 ; The returned value (y) is not the same as the tested value (x).
472 define i32 @no_sat_incorrect_return(i32 %x, i32 %y) #0 {
473 ; V4T-LABEL: no_sat_incorrect_return:
474 ; V4T:       @ %bb.0: @ %entry
475 ; V4T-NEXT:    mov r2, #1065353216
476 ; V4T-NEXT:    cmn r0, #8388608
477 ; V4T-NEXT:    orr r2, r2, #-1073741824
478 ; V4T-NEXT:    movge r2, r1
479 ; V4T-NEXT:    ldr r1, .LCPI13_0
480 ; V4T-NEXT:    cmp r0, #8388608
481 ; V4T-NEXT:    movlt r1, r2
482 ; V4T-NEXT:    mov r0, r1
483 ; V4T-NEXT:    bx lr
484 ; V4T-NEXT:    .p2align 2
485 ; V4T-NEXT:  @ %bb.1:
486 ; V4T-NEXT:  .LCPI13_0:
487 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
489 ; V6T2-LABEL: no_sat_incorrect_return:
490 ; V6T2:       @ %bb.0: @ %entry
491 ; V6T2-NEXT:    cmn r0, #8388608
492 ; V6T2-NEXT:    movwlt r1, #0
493 ; V6T2-NEXT:    movtlt r1, #65408
494 ; V6T2-NEXT:    cmp r0, #8388608
495 ; V6T2-NEXT:    movwge r1, #65535
496 ; V6T2-NEXT:    movtge r1, #127
497 ; V6T2-NEXT:    mov r0, r1
498 ; V6T2-NEXT:    bx lr
499 entry:
500   %cmpUp = icmp sgt i32 %x, 8388607
501   %cmpLow = icmp slt i32 %x, -8388608
502   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %y
503   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
504   ret i32 %saturateUp
507 ; One of the values in a compare (y) is not the same as the rest
508 ; of the compare and select values (x).
509 define i32 @no_sat_incorrect_compare(i32 %x, i32 %y) #0 {
510 ; V4T-LABEL: no_sat_incorrect_compare:
511 ; V4T:       @ %bb.0: @ %entry
512 ; V4T-NEXT:    mov r2, #1065353216
513 ; V4T-NEXT:    cmn r1, #8388608
514 ; V4T-NEXT:    orr r2, r2, #-1073741824
515 ; V4T-NEXT:    ldr r1, .LCPI14_0
516 ; V4T-NEXT:    movge r2, r0
517 ; V4T-NEXT:    cmp r0, #8388608
518 ; V4T-NEXT:    movlt r1, r2
519 ; V4T-NEXT:    mov r0, r1
520 ; V4T-NEXT:    bx lr
521 ; V4T-NEXT:    .p2align 2
522 ; V4T-NEXT:  @ %bb.1:
523 ; V4T-NEXT:  .LCPI14_0:
524 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
526 ; V6T2-LABEL: no_sat_incorrect_compare:
527 ; V6T2:       @ %bb.0: @ %entry
528 ; V6T2-NEXT:    cmn r1, #8388608
529 ; V6T2-NEXT:    mov r1, r0
530 ; V6T2-NEXT:    movwlt r1, #0
531 ; V6T2-NEXT:    movtlt r1, #65408
532 ; V6T2-NEXT:    cmp r0, #8388608
533 ; V6T2-NEXT:    movwge r1, #65535
534 ; V6T2-NEXT:    movtge r1, #127
535 ; V6T2-NEXT:    mov r0, r1
536 ; V6T2-NEXT:    bx lr
537 entry:
538   %cmpUp = icmp sgt i32 %x, 8388607
539   %cmpLow = icmp slt i32 %y, -8388608
540   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
541   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
542   ret i32 %saturateUp
545 define void @extended(i32 %xx, i16 signext %y, i8* nocapture %z) {
546 ; V4T-LABEL: extended:
547 ; V4T:       @ %bb.0: @ %entry
548 ; V4T-NEXT:    add r0, r1, r0, lsr #16
549 ; V4T-NEXT:    lsl r1, r0, #16
550 ; V4T-NEXT:    asr r1, r1, #16
551 ; V4T-NEXT:    cmp r1, #127
552 ; V4T-NEXT:    movge r0, #127
553 ; V4T-NEXT:    lsl r1, r0, #16
554 ; V4T-NEXT:    asr r1, r1, #16
555 ; V4T-NEXT:    cmn r1, #128
556 ; V4T-NEXT:    mvnle r0, #127
557 ; V4T-NEXT:    strb r0, [r2]
558 ; V4T-NEXT:    bx lr
560 ; V6T2-LABEL: extended:
561 ; V6T2:       @ %bb.0: @ %entry
562 ; V6T2-NEXT:    add r0, r1, r0, lsr #16
563 ; V6T2-NEXT:    sxth r1, r0
564 ; V6T2-NEXT:    cmp r1, #127
565 ; V6T2-NEXT:    movge r0, #127
566 ; V6T2-NEXT:    sxth r1, r0
567 ; V6T2-NEXT:    cmn r1, #128
568 ; V6T2-NEXT:    mvnle r0, #127
569 ; V6T2-NEXT:    strb r0, [r2]
570 ; V6T2-NEXT:    bx lr
571 entry:
572   %0 = lshr i32 %xx, 16
573   %1 = trunc i32 %0 to i16
574   %conv3 = add i16 %1, %y
575   %cmp.i = icmp slt i16 %conv3, 127
576   %cond.i = select i1 %cmp.i, i16 %conv3, i16 127
577   %cmp.i11 = icmp sgt i16 %cond.i, -128
578   %cond.i12 = select i1 %cmp.i11, i16 %cond.i, i16 -128
579   %conv5 = trunc i16 %cond.i12 to i8
580   store i8 %conv5, i8* %z, align 1
581   ret void
585 define i32 @formulated_valid(i32 %a) {
586 ; V4T-LABEL: formulated_valid:
587 ; V4T:       @ %bb.0:
588 ; V4T-NEXT:    lsl r1, r0, #16
589 ; V4T-NEXT:    asr r1, r1, #16
590 ; V4T-NEXT:    cmp r1, #127
591 ; V4T-NEXT:    movge r0, #127
592 ; V4T-NEXT:    lsl r1, r0, #16
593 ; V4T-NEXT:    asr r1, r1, #16
594 ; V4T-NEXT:    cmn r1, #128
595 ; V4T-NEXT:    mov r1, #255
596 ; V4T-NEXT:    mvnle r0, #127
597 ; V4T-NEXT:    orr r1, r1, #65280
598 ; V4T-NEXT:    and r0, r0, r1
599 ; V4T-NEXT:    bx lr
601 ; V6T2-LABEL: formulated_valid:
602 ; V6T2:       @ %bb.0:
603 ; V6T2-NEXT:    sxth r1, r0
604 ; V6T2-NEXT:    cmp r1, #127
605 ; V6T2-NEXT:    movge r0, #127
606 ; V6T2-NEXT:    sxth r1, r0
607 ; V6T2-NEXT:    cmn r1, #128
608 ; V6T2-NEXT:    mvnle r0, #127
609 ; V6T2-NEXT:    uxth r0, r0
610 ; V6T2-NEXT:    bx lr
611   %x1 = trunc i32 %a to i16
612   %x2 = sext i16 %x1 to i32
613   %c1 = icmp slt i32 %x2, 127
614   %s1 = select i1 %c1, i32 %a, i32 127
615   %y1 = trunc i32 %s1 to i16
616   %y2 = sext i16 %y1 to i32
617   %c2 = icmp sgt i32 %y2, -128
618   %s2 = select i1 %c2, i32 %s1, i32 -128
619   %r = and i32 %s2, 65535
620   ret i32 %r
623 define i32 @formulated_invalid(i32 %a) {
624 ; V4T-LABEL: formulated_invalid:
625 ; V4T:       @ %bb.0:
626 ; V4T-NEXT:    lsl r1, r0, #16
627 ; V4T-NEXT:    asr r1, r1, #16
628 ; V4T-NEXT:    cmp r1, #127
629 ; V4T-NEXT:    movge r0, #127
630 ; V4T-NEXT:    lsl r1, r0, #16
631 ; V4T-NEXT:    asr r1, r1, #16
632 ; V4T-NEXT:    cmn r1, #128
633 ; V4T-NEXT:    mvnle r0, #127
634 ; V4T-NEXT:    bic r0, r0, #-16777216
635 ; V4T-NEXT:    bx lr
637 ; V6T2-LABEL: formulated_invalid:
638 ; V6T2:       @ %bb.0:
639 ; V6T2-NEXT:    sxth r1, r0
640 ; V6T2-NEXT:    cmp r1, #127
641 ; V6T2-NEXT:    movge r0, #127
642 ; V6T2-NEXT:    sxth r1, r0
643 ; V6T2-NEXT:    cmn r1, #128
644 ; V6T2-NEXT:    mvnle r0, #127
645 ; V6T2-NEXT:    bic r0, r0, #-16777216
646 ; V6T2-NEXT:    bx lr
647   %x1 = trunc i32 %a to i16
648   %x2 = sext i16 %x1 to i32
649   %c1 = icmp slt i32 %x2, 127
650   %s1 = select i1 %c1, i32 %a, i32 127
651   %y1 = trunc i32 %s1 to i16
652   %y2 = sext i16 %y1 to i32
653   %c2 = icmp sgt i32 %y2, -128
654   %s2 = select i1 %c2, i32 %s1, i32 -128
655   %r = and i32 %s2, 16777215
656   ret i32 %r