[NFC][Py Reformat] Reformat python files in llvm
[llvm-project.git] / llvm / test / CodeGen / ARM / ssat.ll
blobed777f2b1882bef05fff467bdce8c3ccd9c8b74a
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:    movge r0, r1
25 ; V4T-NEXT:    mov r1, #1065353216
26 ; V4T-NEXT:    orr r1, r1, #-1073741824
27 ; V4T-NEXT:    cmn r0, #8388608
28 ; V4T-NEXT:    movle 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:    movge r0, r2
58 ; V4T-NEXT:    ldr r2, .LCPI1_0
59 ; V4T-NEXT:    lsl r1, r0, #16
60 ; V4T-NEXT:    asr r1, r1, #16
61 ; V4T-NEXT:    cmn r1, #2048
62 ; V4T-NEXT:    movle 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:    movge r0, r2
75 ; V6T2-NEXT:    movw r2, #63488
76 ; V6T2-NEXT:    sxth r1, r0
77 ; V6T2-NEXT:    movt r2, #65535
78 ; V6T2-NEXT:    cmn r1, #2048
79 ; V6T2-NEXT:    movle 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:    movge r0, r1
134 ; V4T-NEXT:    mov r1, #1065353216
135 ; V4T-NEXT:    orr r1, r1, #-1073741824
136 ; V4T-NEXT:    cmn r0, #8388608
137 ; V4T-NEXT:    movle 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:    movge r0, r1
163 ; V4T-NEXT:    mov r1, #1065353216
164 ; V4T-NEXT:    orr r1, r1, #-1073741824
165 ; V4T-NEXT:    cmn r0, #8388608
166 ; V4T-NEXT:    movle 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:    movle r0, r1
193 ; V4T-NEXT:    ldr r1, .LCPI5_0
194 ; V4T-NEXT:    cmp r0, r1
195 ; V4T-NEXT:    movge r0, r1
196 ; V4T-NEXT:    bx lr
197 ; V4T-NEXT:    .p2align 2
198 ; V4T-NEXT:  @ %bb.1:
199 ; V4T-NEXT:  .LCPI5_0:
200 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
202 ; V6T2-LABEL: sat_upper_lower_1:
203 ; V6T2:       @ %bb.0: @ %entry
204 ; V6T2-NEXT:    ssat r0, #24, r0
205 ; V6T2-NEXT:    bx lr
206 entry:
207   %0 = icmp sgt i32 %x, -8388608
208   %saturateLow = select i1 %0, i32 %x, i32 -8388608
209   %1 = icmp slt i32 %saturateLow, 8388607
210   %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
211   ret i32 %saturateUp
214 ; x > k ? k : (x < -k ? -k : x)
215 define i32 @sat_upper_lower_2(i32 %x) #0 {
216 ; V4T-LABEL: sat_upper_lower_2:
217 ; V4T:       @ %bb.0: @ %entry
218 ; V4T-NEXT:    mov r1, #1065353216
219 ; V4T-NEXT:    cmn r0, #8388608
220 ; V4T-NEXT:    orr r1, r1, #-1073741824
221 ; V4T-NEXT:    movle r0, r1
222 ; V4T-NEXT:    ldr r1, .LCPI6_0
223 ; V4T-NEXT:    cmp r0, r1
224 ; V4T-NEXT:    movge r0, r1
225 ; V4T-NEXT:    bx lr
226 ; V4T-NEXT:    .p2align 2
227 ; V4T-NEXT:  @ %bb.1:
228 ; V4T-NEXT:  .LCPI6_0:
229 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
231 ; V6T2-LABEL: sat_upper_lower_2:
232 ; V6T2:       @ %bb.0: @ %entry
233 ; V6T2-NEXT:    ssat r0, #24, r0
234 ; V6T2-NEXT:    bx lr
235 entry:
236   %0 = icmp sgt i32 %x, -8388608
237   %saturateLow = select i1 %0, i32 %x, i32 -8388608
238   %1 = icmp slt i32 %saturateLow, 8388607
239   %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
240   ret i32 %saturateUp
243 ; k < x ? k : (x > -k ? x : -k)
244 define i32 @sat_upper_lower_3(i32 %x) #0 {
245 ; V4T-LABEL: sat_upper_lower_3:
246 ; V4T:       @ %bb.0: @ %entry
247 ; V4T-NEXT:    mov r1, #1065353216
248 ; V4T-NEXT:    cmn r0, #8388608
249 ; V4T-NEXT:    orr r1, r1, #-1073741824
250 ; V4T-NEXT:    movle r0, r1
251 ; V4T-NEXT:    ldr r1, .LCPI7_0
252 ; V4T-NEXT:    cmp r0, r1
253 ; V4T-NEXT:    movge r0, r1
254 ; V4T-NEXT:    bx lr
255 ; V4T-NEXT:    .p2align 2
256 ; V4T-NEXT:  @ %bb.1:
257 ; V4T-NEXT:  .LCPI7_0:
258 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
260 ; V6T2-LABEL: sat_upper_lower_3:
261 ; V6T2:       @ %bb.0: @ %entry
262 ; V6T2-NEXT:    ssat r0, #24, r0
263 ; V6T2-NEXT:    bx lr
264 entry:
265   %cmpLow = icmp sgt i32 %x, -8388608
266   %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608
267   %0 = icmp slt i32 %saturateLow, 8388607
268   %saturateUp = select i1 %0, i32 %saturateLow, i32 8388607
269   ret i32 %saturateUp
273 ; Miscellanea
276 ; Check that >= and <= work the same as > and <
277 ; k <= x ? k : (x >= -k ? x : -k)
278 define i32 @sat_le_ge(i32 %x) #0 {
279 ; V4T-LABEL: sat_le_ge:
280 ; V4T:       @ %bb.0: @ %entry
281 ; V4T-NEXT:    mov r1, #1065353216
282 ; V4T-NEXT:    cmn r0, #8388608
283 ; V4T-NEXT:    orr r1, r1, #-1073741824
284 ; V4T-NEXT:    movle r0, r1
285 ; V4T-NEXT:    ldr r1, .LCPI8_0
286 ; V4T-NEXT:    cmp r0, r1
287 ; V4T-NEXT:    movge r0, r1
288 ; V4T-NEXT:    bx lr
289 ; V4T-NEXT:    .p2align 2
290 ; V4T-NEXT:  @ %bb.1:
291 ; V4T-NEXT:  .LCPI8_0:
292 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
294 ; V6T2-LABEL: sat_le_ge:
295 ; V6T2:       @ %bb.0: @ %entry
296 ; V6T2-NEXT:    ssat r0, #24, r0
297 ; V6T2-NEXT:    bx lr
298 entry:
299   %0 = icmp sgt i32 %x, -8388608
300   %saturateLow = select i1 %0, i32 %x, i32 -8388608
301   %1 = icmp slt i32 %saturateLow, 8388607
302   %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
303   ret i32 %saturateUp
307 ; The following tests check for patterns that should not transform
308 ; into SSAT but are similar enough that could confuse the selector.
311 ; x > k ? k : (x > -k ? -k : x)
312 ; First condition upper-saturates, second doesn't lower-saturate.
313 define i32 @no_sat_missing_lower(i32 %x) #0 {
314 ; V4T-LABEL: no_sat_missing_lower:
315 ; V4T:       @ %bb.0: @ %entry
316 ; V4T-NEXT:    mov r2, #1065353216
317 ; V4T-NEXT:    cmn r0, #8388608
318 ; V4T-NEXT:    orr r2, r2, #-1073741824
319 ; V4T-NEXT:    ldr r1, .LCPI9_0
320 ; V4T-NEXT:    movlt r2, r0
321 ; V4T-NEXT:    cmp r0, #8388608
322 ; V4T-NEXT:    movlt r1, r2
323 ; V4T-NEXT:    mov r0, r1
324 ; V4T-NEXT:    bx lr
325 ; V4T-NEXT:    .p2align 2
326 ; V4T-NEXT:  @ %bb.1:
327 ; V4T-NEXT:  .LCPI9_0:
328 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
330 ; V6T2-LABEL: no_sat_missing_lower:
331 ; V6T2:       @ %bb.0: @ %entry
332 ; V6T2-NEXT:    movw r1, #0
333 ; V6T2-NEXT:    cmn r0, #8388608
334 ; V6T2-NEXT:    movt r1, #65408
335 ; V6T2-NEXT:    movlt r1, r0
336 ; V6T2-NEXT:    cmp r0, #8388608
337 ; V6T2-NEXT:    movwge r1, #65535
338 ; V6T2-NEXT:    movtge r1, #127
339 ; V6T2-NEXT:    mov r0, r1
340 ; V6T2-NEXT:    bx lr
341 entry:
342   %cmpUp = icmp sgt i32 %x, 8388607
343   %0 = icmp slt i32 %x, -8388608
344   %saturateLow = select i1 %0, i32 %x, i32 -8388608
345   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
346   ret i32 %saturateUp
349 ; x < k ? k : (x < -k ? -k : x)
350 ; Second condition lower-saturates, first doesn't upper-saturate.
351 define i32 @no_sat_missing_upper(i32 %x) #0 {
352 ; V4T-LABEL: no_sat_missing_upper:
353 ; V4T:       @ %bb.0: @ %entry
354 ; V4T-NEXT:    mov r1, #1065353216
355 ; V4T-NEXT:    ldr r2, .LCPI10_0
356 ; V4T-NEXT:    orr r1, r1, #-1073741824
357 ; V4T-NEXT:    cmn r0, #8388608
358 ; V4T-NEXT:    movgt r1, r0
359 ; V4T-NEXT:    cmp r0, r2
360 ; V4T-NEXT:    movlt r1, r2
361 ; V4T-NEXT:    mov r0, r1
362 ; V4T-NEXT:    bx lr
363 ; V4T-NEXT:    .p2align 2
364 ; V4T-NEXT:  @ %bb.1:
365 ; V4T-NEXT:  .LCPI10_0:
366 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
368 ; V6T2-LABEL: no_sat_missing_upper:
369 ; V6T2:       @ %bb.0: @ %entry
370 ; V6T2-NEXT:    movw r1, #0
371 ; V6T2-NEXT:    movw r2, #65535
372 ; V6T2-NEXT:    movt r1, #65408
373 ; V6T2-NEXT:    cmn r0, #8388608
374 ; V6T2-NEXT:    movgt r1, r0
375 ; V6T2-NEXT:    movt r2, #127
376 ; V6T2-NEXT:    cmp r0, r2
377 ; V6T2-NEXT:    movwlt r1, #65535
378 ; V6T2-NEXT:    movtlt r1, #127
379 ; V6T2-NEXT:    mov r0, r1
380 ; V6T2-NEXT:    bx lr
381 entry:
382   %cmpUp = icmp slt i32 %x, 8388607
383   %0 = icmp sgt i32 %x, -8388608
384   %saturateLow = select i1 %0, i32 %x, i32 -8388608
385   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
386   ret i32 %saturateUp
389 ; Lower constant is different in the select and in the compare
390 define i32 @no_sat_incorrect_constant(i32 %x) #0 {
391 ; V4T-LABEL: no_sat_incorrect_constant:
392 ; V4T:       @ %bb.0: @ %entry
393 ; V4T-NEXT:    mov r1, #1065353216
394 ; V4T-NEXT:    cmn r0, #8388608
395 ; V4T-NEXT:    orr r1, r1, #-1073741824
396 ; V4T-NEXT:    mov r2, r0
397 ; V4T-NEXT:    orrlt r2, r1, #1
398 ; V4T-NEXT:    ldr r1, .LCPI11_0
399 ; V4T-NEXT:    cmp r0, #8388608
400 ; V4T-NEXT:    movlt r1, r2
401 ; V4T-NEXT:    mov r0, r1
402 ; V4T-NEXT:    bx lr
403 ; V4T-NEXT:    .p2align 2
404 ; V4T-NEXT:  @ %bb.1:
405 ; V4T-NEXT:  .LCPI11_0:
406 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
408 ; V6T2-LABEL: no_sat_incorrect_constant:
409 ; V6T2:       @ %bb.0: @ %entry
410 ; V6T2-NEXT:    movw r2, #0
411 ; V6T2-NEXT:    cmn r0, #8388608
412 ; V6T2-NEXT:    mov r1, r0
413 ; V6T2-NEXT:    movt r2, #65408
414 ; V6T2-NEXT:    orrlt r1, r2, #1
415 ; V6T2-NEXT:    cmp r0, #8388608
416 ; V6T2-NEXT:    movwge r1, #65535
417 ; V6T2-NEXT:    movtge r1, #127
418 ; V6T2-NEXT:    mov r0, r1
419 ; V6T2-NEXT:    bx lr
420 entry:
421   %cmpUp = icmp sgt i32 %x, 8388607
422   %cmpLow = icmp slt i32 %x, -8388608
423   %saturateLow = select i1 %cmpLow, i32 -8388607, i32 %x
424   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
425   ret i32 %saturateUp
428 ; The interval is not [k, ~k]
429 define i32 @no_sat_incorrect_interval(i32 %x) #0 {
430 ; V4T-LABEL: no_sat_incorrect_interval:
431 ; V4T:       @ %bb.0: @ %entry
432 ; V4T-NEXT:    ldr r1, .LCPI12_0
433 ; V4T-NEXT:    cmp r0, r1
434 ; V4T-NEXT:    movle r0, r1
435 ; V4T-NEXT:    ldr r1, .LCPI12_1
436 ; V4T-NEXT:    cmp r0, r1
437 ; V4T-NEXT:    movge r0, r1
438 ; V4T-NEXT:    bx lr
439 ; V4T-NEXT:    .p2align 2
440 ; V4T-NEXT:  @ %bb.1:
441 ; V4T-NEXT:  .LCPI12_0:
442 ; V4T-NEXT:    .long 4275878552 @ 0xfedcba98
443 ; V4T-NEXT:  .LCPI12_1:
444 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
446 ; V6T2-LABEL: no_sat_incorrect_interval:
447 ; V6T2:       @ %bb.0: @ %entry
448 ; V6T2-NEXT:    movw r1, #47768
449 ; V6T2-NEXT:    movt r1, #65244
450 ; V6T2-NEXT:    cmp r0, r1
451 ; V6T2-NEXT:    movle r0, r1
452 ; V6T2-NEXT:    movw r1, #65535
453 ; V6T2-NEXT:    movt r1, #127
454 ; V6T2-NEXT:    cmp r0, r1
455 ; V6T2-NEXT:    movge r0, r1
456 ; V6T2-NEXT:    bx lr
457 entry:
458   %0 = icmp sgt i32 %x, -19088744
459   %saturateLow = select i1 %0, i32 %x, i32 -19088744
460   %1 = icmp slt i32 %saturateLow, 8388607
461   %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
462   ret i32 %saturateUp
465 ; The returned value (y) is not the same as the tested value (x).
466 define i32 @no_sat_incorrect_return(i32 %x, i32 %y) #0 {
467 ; V4T-LABEL: no_sat_incorrect_return:
468 ; V4T:       @ %bb.0: @ %entry
469 ; V4T-NEXT:    mov r2, #1065353216
470 ; V4T-NEXT:    cmn r0, #8388608
471 ; V4T-NEXT:    orr r2, r2, #-1073741824
472 ; V4T-NEXT:    movge r2, r1
473 ; V4T-NEXT:    ldr r1, .LCPI13_0
474 ; V4T-NEXT:    cmp r0, #8388608
475 ; V4T-NEXT:    movlt r1, r2
476 ; V4T-NEXT:    mov r0, r1
477 ; V4T-NEXT:    bx lr
478 ; V4T-NEXT:    .p2align 2
479 ; V4T-NEXT:  @ %bb.1:
480 ; V4T-NEXT:  .LCPI13_0:
481 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
483 ; V6T2-LABEL: no_sat_incorrect_return:
484 ; V6T2:       @ %bb.0: @ %entry
485 ; V6T2-NEXT:    cmn r0, #8388608
486 ; V6T2-NEXT:    movwlt r1, #0
487 ; V6T2-NEXT:    movtlt r1, #65408
488 ; V6T2-NEXT:    cmp r0, #8388608
489 ; V6T2-NEXT:    movwge r1, #65535
490 ; V6T2-NEXT:    movtge r1, #127
491 ; V6T2-NEXT:    mov r0, r1
492 ; V6T2-NEXT:    bx lr
493 entry:
494   %cmpUp = icmp sgt i32 %x, 8388607
495   %cmpLow = icmp slt i32 %x, -8388608
496   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %y
497   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
498   ret i32 %saturateUp
501 ; One of the values in a compare (y) is not the same as the rest
502 ; of the compare and select values (x).
503 define i32 @no_sat_incorrect_compare(i32 %x, i32 %y) #0 {
504 ; V4T-LABEL: no_sat_incorrect_compare:
505 ; V4T:       @ %bb.0: @ %entry
506 ; V4T-NEXT:    mov r2, #1065353216
507 ; V4T-NEXT:    cmn r1, #8388608
508 ; V4T-NEXT:    orr r2, r2, #-1073741824
509 ; V4T-NEXT:    ldr r1, .LCPI14_0
510 ; V4T-NEXT:    movge r2, r0
511 ; V4T-NEXT:    cmp r0, #8388608
512 ; V4T-NEXT:    movlt r1, r2
513 ; V4T-NEXT:    mov r0, r1
514 ; V4T-NEXT:    bx lr
515 ; V4T-NEXT:    .p2align 2
516 ; V4T-NEXT:  @ %bb.1:
517 ; V4T-NEXT:  .LCPI14_0:
518 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
520 ; V6T2-LABEL: no_sat_incorrect_compare:
521 ; V6T2:       @ %bb.0: @ %entry
522 ; V6T2-NEXT:    cmn r1, #8388608
523 ; V6T2-NEXT:    mov r1, r0
524 ; V6T2-NEXT:    movwlt r1, #0
525 ; V6T2-NEXT:    movtlt r1, #65408
526 ; V6T2-NEXT:    cmp r0, #8388608
527 ; V6T2-NEXT:    movwge r1, #65535
528 ; V6T2-NEXT:    movtge r1, #127
529 ; V6T2-NEXT:    mov r0, r1
530 ; V6T2-NEXT:    bx lr
531 entry:
532   %cmpUp = icmp sgt i32 %x, 8388607
533   %cmpLow = icmp slt i32 %y, -8388608
534   %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
535   %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
536   ret i32 %saturateUp
539 define void @extended(i32 %xx, i16 signext %y, ptr nocapture %z) {
540 ; V4T-LABEL: extended:
541 ; V4T:       @ %bb.0: @ %entry
542 ; V4T-NEXT:    add r0, r1, r0, lsr #16
543 ; V4T-NEXT:    lsl r1, r0, #16
544 ; V4T-NEXT:    asr r1, r1, #16
545 ; V4T-NEXT:    cmp r1, #127
546 ; V4T-NEXT:    movge r0, #127
547 ; V4T-NEXT:    lsl r1, r0, #16
548 ; V4T-NEXT:    asr r1, r1, #16
549 ; V4T-NEXT:    cmn r1, #128
550 ; V4T-NEXT:    mvnle r0, #127
551 ; V4T-NEXT:    strb r0, [r2]
552 ; V4T-NEXT:    bx lr
554 ; V6T2-LABEL: extended:
555 ; V6T2:       @ %bb.0: @ %entry
556 ; V6T2-NEXT:    add r0, r1, r0, lsr #16
557 ; V6T2-NEXT:    sxth r1, r0
558 ; V6T2-NEXT:    cmp r1, #127
559 ; V6T2-NEXT:    movge r0, #127
560 ; V6T2-NEXT:    sxth r1, r0
561 ; V6T2-NEXT:    cmn r1, #128
562 ; V6T2-NEXT:    mvnle r0, #127
563 ; V6T2-NEXT:    strb r0, [r2]
564 ; V6T2-NEXT:    bx lr
565 entry:
566   %0 = lshr i32 %xx, 16
567   %1 = trunc i32 %0 to i16
568   %conv3 = add i16 %1, %y
569   %cmp.i = icmp slt i16 %conv3, 127
570   %cond.i = select i1 %cmp.i, i16 %conv3, i16 127
571   %cmp.i11 = icmp sgt i16 %cond.i, -128
572   %cond.i12 = select i1 %cmp.i11, i16 %cond.i, i16 -128
573   %conv5 = trunc i16 %cond.i12 to i8
574   store i8 %conv5, ptr %z, align 1
575   ret void
579 define i32 @formulated_valid(i32 %a) {
580 ; V4T-LABEL: formulated_valid:
581 ; V4T:       @ %bb.0:
582 ; V4T-NEXT:    lsl r1, r0, #16
583 ; V4T-NEXT:    asr r1, r1, #16
584 ; V4T-NEXT:    cmp r1, #127
585 ; V4T-NEXT:    movge r0, #127
586 ; V4T-NEXT:    lsl r1, r0, #16
587 ; V4T-NEXT:    asr r1, r1, #16
588 ; V4T-NEXT:    cmn r1, #128
589 ; V4T-NEXT:    mov r1, #255
590 ; V4T-NEXT:    mvnle r0, #127
591 ; V4T-NEXT:    orr r1, r1, #65280
592 ; V4T-NEXT:    and r0, r0, r1
593 ; V4T-NEXT:    bx lr
595 ; V6T2-LABEL: formulated_valid:
596 ; V6T2:       @ %bb.0:
597 ; V6T2-NEXT:    sxth r1, r0
598 ; V6T2-NEXT:    cmp r1, #127
599 ; V6T2-NEXT:    movge r0, #127
600 ; V6T2-NEXT:    sxth r1, r0
601 ; V6T2-NEXT:    cmn r1, #128
602 ; V6T2-NEXT:    mvnle r0, #127
603 ; V6T2-NEXT:    uxth r0, r0
604 ; V6T2-NEXT:    bx lr
605   %x1 = trunc i32 %a to i16
606   %x2 = sext i16 %x1 to i32
607   %c1 = icmp slt i32 %x2, 127
608   %s1 = select i1 %c1, i32 %a, i32 127
609   %y1 = trunc i32 %s1 to i16
610   %y2 = sext i16 %y1 to i32
611   %c2 = icmp sgt i32 %y2, -128
612   %s2 = select i1 %c2, i32 %s1, i32 -128
613   %r = and i32 %s2, 65535
614   ret i32 %r
617 define i32 @formulated_invalid(i32 %a) {
618 ; V4T-LABEL: formulated_invalid:
619 ; V4T:       @ %bb.0:
620 ; V4T-NEXT:    lsl r1, r0, #16
621 ; V4T-NEXT:    asr r1, r1, #16
622 ; V4T-NEXT:    cmp r1, #127
623 ; V4T-NEXT:    movge r0, #127
624 ; V4T-NEXT:    lsl r1, r0, #16
625 ; V4T-NEXT:    asr r1, r1, #16
626 ; V4T-NEXT:    cmn r1, #128
627 ; V4T-NEXT:    mvnle r0, #127
628 ; V4T-NEXT:    bic r0, r0, #-16777216
629 ; V4T-NEXT:    bx lr
631 ; V6T2-LABEL: formulated_invalid:
632 ; V6T2:       @ %bb.0:
633 ; V6T2-NEXT:    sxth r1, r0
634 ; V6T2-NEXT:    cmp r1, #127
635 ; V6T2-NEXT:    movge r0, #127
636 ; V6T2-NEXT:    sxth r1, r0
637 ; V6T2-NEXT:    cmn r1, #128
638 ; V6T2-NEXT:    mvnle r0, #127
639 ; V6T2-NEXT:    bic r0, r0, #-16777216
640 ; V6T2-NEXT:    bx lr
641   %x1 = trunc i32 %a to i16
642   %x2 = sext i16 %x1 to i32
643   %c1 = icmp slt i32 %x2, 127
644   %s1 = select i1 %c1, i32 %a, i32 127
645   %y1 = trunc i32 %s1 to i16
646   %y2 = sext i16 %y1 to i32
647   %c2 = icmp sgt i32 %y2, -128
648   %s2 = select i1 %c2, i32 %s1, i32 -128
649   %r = and i32 %s2, 16777215
650   ret i32 %r
654 define i32 @mm_sat_base_32bit(i32 %x) {
655 ; V4T-LABEL: mm_sat_base_32bit:
656 ; V4T:       @ %bb.0: @ %entry
657 ; V4T-NEXT:    ldr r1, .LCPI18_0
658 ; V4T-NEXT:    cmp r0, r1
659 ; V4T-NEXT:    movge r0, r1
660 ; V4T-NEXT:    mov r1, #1065353216
661 ; V4T-NEXT:    orr r1, r1, #-1073741824
662 ; V4T-NEXT:    cmn r0, #8388608
663 ; V4T-NEXT:    movle r0, r1
664 ; V4T-NEXT:    bx lr
665 ; V4T-NEXT:    .p2align 2
666 ; V4T-NEXT:  @ %bb.1:
667 ; V4T-NEXT:  .LCPI18_0:
668 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
670 ; V6T2-LABEL: mm_sat_base_32bit:
671 ; V6T2:       @ %bb.0: @ %entry
672 ; V6T2-NEXT:    ssat r0, #24, r0
673 ; V6T2-NEXT:    bx lr
674 entry:
675   %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607)
676   %1 = call i32 @llvm.smax.i32(i32 %0, i32 -8388608)
677   ret i32 %1
680 define i16 @mm_sat_base_16bit(i16 %x) {
681 ; V4T-LABEL: mm_sat_base_16bit:
682 ; V4T:       @ %bb.0: @ %entry
683 ; V4T-NEXT:    mov r2, #255
684 ; V4T-NEXT:    lsl r0, r0, #16
685 ; V4T-NEXT:    orr r2, r2, #1792
686 ; V4T-NEXT:    asr r1, r0, #16
687 ; V4T-NEXT:    cmp r1, r2
688 ; V4T-NEXT:    asrlt r2, r0, #16
689 ; V4T-NEXT:    ldr r0, .LCPI19_0
690 ; V4T-NEXT:    cmn r2, #2048
691 ; V4T-NEXT:    movgt r0, r2
692 ; V4T-NEXT:    bx lr
693 ; V4T-NEXT:    .p2align 2
694 ; V4T-NEXT:  @ %bb.1:
695 ; V4T-NEXT:  .LCPI19_0:
696 ; V4T-NEXT:    .long 4294965248 @ 0xfffff800
698 ; V6T2-LABEL: mm_sat_base_16bit:
699 ; V6T2:       @ %bb.0: @ %entry
700 ; V6T2-NEXT:    sxth r0, r0
701 ; V6T2-NEXT:    ssat r0, #12, r0
702 ; V6T2-NEXT:    bx lr
703 entry:
704   %0 = call i16 @llvm.smin.i16(i16 %x, i16 2047)
705   %1 = call i16 @llvm.smax.i16(i16 %0, i16 -2048)
706   ret i16 %1
709 define i8 @mm_sat_base_8bit(i8 %x) {
710 ; V4T-LABEL: mm_sat_base_8bit:
711 ; V4T:       @ %bb.0: @ %entry
712 ; V4T-NEXT:    lsl r1, r0, #24
713 ; V4T-NEXT:    mov r0, #31
714 ; V4T-NEXT:    asr r2, r1, #24
715 ; V4T-NEXT:    cmp r2, #31
716 ; V4T-NEXT:    asrlt r0, r1, #24
717 ; V4T-NEXT:    cmn r0, #32
718 ; V4T-NEXT:    mvnle r0, #31
719 ; V4T-NEXT:    bx lr
721 ; V6T2-LABEL: mm_sat_base_8bit:
722 ; V6T2:       @ %bb.0: @ %entry
723 ; V6T2-NEXT:    sxtb r0, r0
724 ; V6T2-NEXT:    ssat r0, #6, r0
725 ; V6T2-NEXT:    bx lr
726 entry:
727   %0 = call i8 @llvm.smin.i8(i8 %x, i8 31)
728   %1 = call i8 @llvm.smax.i8(i8 %0, i8 -32)
729   ret i8 %1
732 define i32 @mm_sat_lower_upper_1(i32 %x) {
733 ; V4T-LABEL: mm_sat_lower_upper_1:
734 ; V4T:       @ %bb.0: @ %entry
735 ; V4T-NEXT:    ldr r1, .LCPI21_0
736 ; V4T-NEXT:    cmp r0, r1
737 ; V4T-NEXT:    movge r0, r1
738 ; V4T-NEXT:    mov r1, #1065353216
739 ; V4T-NEXT:    orr r1, r1, #-1073741824
740 ; V4T-NEXT:    cmn r0, #8388608
741 ; V4T-NEXT:    movle r0, r1
742 ; V4T-NEXT:    bx lr
743 ; V4T-NEXT:    .p2align 2
744 ; V4T-NEXT:  @ %bb.1:
745 ; V4T-NEXT:  .LCPI21_0:
746 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
748 ; V6T2-LABEL: mm_sat_lower_upper_1:
749 ; V6T2:       @ %bb.0: @ %entry
750 ; V6T2-NEXT:    ssat r0, #24, r0
751 ; V6T2-NEXT:    bx lr
752 entry:
753   %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607)
754   %1 = call i32 @llvm.smax.i32(i32 %0, i32 -8388608)
755   ret i32 %1
758 define i32 @mm_sat_lower_upper_2(i32 %x) {
759 ; V4T-LABEL: mm_sat_lower_upper_2:
760 ; V4T:       @ %bb.0: @ %entry
761 ; V4T-NEXT:    ldr r1, .LCPI22_0
762 ; V4T-NEXT:    cmp r0, r1
763 ; V4T-NEXT:    movge r0, r1
764 ; V4T-NEXT:    mov r1, #1065353216
765 ; V4T-NEXT:    orr r1, r1, #-1073741824
766 ; V4T-NEXT:    cmn r0, #8388608
767 ; V4T-NEXT:    movle r0, r1
768 ; V4T-NEXT:    bx lr
769 ; V4T-NEXT:    .p2align 2
770 ; V4T-NEXT:  @ %bb.1:
771 ; V4T-NEXT:  .LCPI22_0:
772 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
774 ; V6T2-LABEL: mm_sat_lower_upper_2:
775 ; V6T2:       @ %bb.0: @ %entry
776 ; V6T2-NEXT:    ssat r0, #24, r0
777 ; V6T2-NEXT:    bx lr
778 entry:
779   %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607)
780   %1 = call i32 @llvm.smax.i32(i32 %0, i32 -8388608)
781   ret i32 %1
784 define i32 @mm_sat_upper_lower_1(i32 %x) {
785 ; V4T-LABEL: mm_sat_upper_lower_1:
786 ; V4T:       @ %bb.0: @ %entry
787 ; V4T-NEXT:    mov r1, #1065353216
788 ; V4T-NEXT:    cmn r0, #8388608
789 ; V4T-NEXT:    orr r1, r1, #-1073741824
790 ; V4T-NEXT:    movle r0, r1
791 ; V4T-NEXT:    ldr r1, .LCPI23_0
792 ; V4T-NEXT:    cmp r0, r1
793 ; V4T-NEXT:    movge r0, r1
794 ; V4T-NEXT:    bx lr
795 ; V4T-NEXT:    .p2align 2
796 ; V4T-NEXT:  @ %bb.1:
797 ; V4T-NEXT:  .LCPI23_0:
798 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
800 ; V6T2-LABEL: mm_sat_upper_lower_1:
801 ; V6T2:       @ %bb.0: @ %entry
802 ; V6T2-NEXT:    ssat r0, #24, r0
803 ; V6T2-NEXT:    bx lr
804 entry:
805   %0 = call i32 @llvm.smax.i32(i32 %x, i32 -8388608)
806   %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607)
807   ret i32 %1
810 define i32 @mm_sat_upper_lower_2(i32 %x) {
811 ; V4T-LABEL: mm_sat_upper_lower_2:
812 ; V4T:       @ %bb.0: @ %entry
813 ; V4T-NEXT:    mov r1, #1065353216
814 ; V4T-NEXT:    cmn r0, #8388608
815 ; V4T-NEXT:    orr r1, r1, #-1073741824
816 ; V4T-NEXT:    movle r0, r1
817 ; V4T-NEXT:    ldr r1, .LCPI24_0
818 ; V4T-NEXT:    cmp r0, r1
819 ; V4T-NEXT:    movge r0, r1
820 ; V4T-NEXT:    bx lr
821 ; V4T-NEXT:    .p2align 2
822 ; V4T-NEXT:  @ %bb.1:
823 ; V4T-NEXT:  .LCPI24_0:
824 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
826 ; V6T2-LABEL: mm_sat_upper_lower_2:
827 ; V6T2:       @ %bb.0: @ %entry
828 ; V6T2-NEXT:    ssat r0, #24, r0
829 ; V6T2-NEXT:    bx lr
830 entry:
831   %0 = call i32 @llvm.smax.i32(i32 %x, i32 -8388608)
832   %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607)
833   ret i32 %1
836 define i32 @mm_sat_upper_lower_3(i32 %x) {
837 ; V4T-LABEL: mm_sat_upper_lower_3:
838 ; V4T:       @ %bb.0: @ %entry
839 ; V4T-NEXT:    mov r1, #1065353216
840 ; V4T-NEXT:    cmn r0, #8388608
841 ; V4T-NEXT:    orr r1, r1, #-1073741824
842 ; V4T-NEXT:    movle r0, r1
843 ; V4T-NEXT:    ldr r1, .LCPI25_0
844 ; V4T-NEXT:    cmp r0, r1
845 ; V4T-NEXT:    movge r0, r1
846 ; V4T-NEXT:    bx lr
847 ; V4T-NEXT:    .p2align 2
848 ; V4T-NEXT:  @ %bb.1:
849 ; V4T-NEXT:  .LCPI25_0:
850 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
852 ; V6T2-LABEL: mm_sat_upper_lower_3:
853 ; V6T2:       @ %bb.0: @ %entry
854 ; V6T2-NEXT:    ssat r0, #24, r0
855 ; V6T2-NEXT:    bx lr
856 entry:
857   %0 = call i32 @llvm.smax.i32(i32 %x, i32 -8388608)
858   %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607)
859   ret i32 %1
862 define i32 @mm_sat_le_ge(i32 %x) {
863 ; V4T-LABEL: mm_sat_le_ge:
864 ; V4T:       @ %bb.0: @ %entry
865 ; V4T-NEXT:    mov r1, #1065353216
866 ; V4T-NEXT:    cmn r0, #8388608
867 ; V4T-NEXT:    orr r1, r1, #-1073741824
868 ; V4T-NEXT:    movle r0, r1
869 ; V4T-NEXT:    ldr r1, .LCPI26_0
870 ; V4T-NEXT:    cmp r0, r1
871 ; V4T-NEXT:    movge r0, r1
872 ; V4T-NEXT:    bx lr
873 ; V4T-NEXT:    .p2align 2
874 ; V4T-NEXT:  @ %bb.1:
875 ; V4T-NEXT:  .LCPI26_0:
876 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
878 ; V6T2-LABEL: mm_sat_le_ge:
879 ; V6T2:       @ %bb.0: @ %entry
880 ; V6T2-NEXT:    ssat r0, #24, r0
881 ; V6T2-NEXT:    bx lr
882 entry:
883   %0 = call i32 @llvm.smax.i32(i32 %x, i32 -8388608)
884   %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607)
885   ret i32 %1
888 define i32 @mm_no_sat_incorrect_interval(i32 %x) {
889 ; V4T-LABEL: mm_no_sat_incorrect_interval:
890 ; V4T:       @ %bb.0: @ %entry
891 ; V4T-NEXT:    ldr r1, .LCPI27_0
892 ; V4T-NEXT:    cmp r0, r1
893 ; V4T-NEXT:    movle r0, r1
894 ; V4T-NEXT:    ldr r1, .LCPI27_1
895 ; V4T-NEXT:    cmp r0, r1
896 ; V4T-NEXT:    movge r0, r1
897 ; V4T-NEXT:    bx lr
898 ; V4T-NEXT:    .p2align 2
899 ; V4T-NEXT:  @ %bb.1:
900 ; V4T-NEXT:  .LCPI27_0:
901 ; V4T-NEXT:    .long 4275878552 @ 0xfedcba98
902 ; V4T-NEXT:  .LCPI27_1:
903 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
905 ; V6T2-LABEL: mm_no_sat_incorrect_interval:
906 ; V6T2:       @ %bb.0: @ %entry
907 ; V6T2-NEXT:    movw r1, #47768
908 ; V6T2-NEXT:    movt r1, #65244
909 ; V6T2-NEXT:    cmp r0, r1
910 ; V6T2-NEXT:    movle r0, r1
911 ; V6T2-NEXT:    movw r1, #65535
912 ; V6T2-NEXT:    movt r1, #127
913 ; V6T2-NEXT:    cmp r0, r1
914 ; V6T2-NEXT:    movge r0, r1
915 ; V6T2-NEXT:    bx lr
916 entry:
917   %0 = call i32 @llvm.smax.i32(i32 %x, i32 -19088744)
918   %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607)
919   ret i32 %1
922 declare i32 @llvm.smin.i32(i32, i32)
923 declare i32 @llvm.smax.i32(i32, i32)
924 declare i16 @llvm.smin.i16(i16, i16)
925 declare i16 @llvm.smax.i16(i16, i16)
926 declare i8 @llvm.smin.i8(i8, i8)
927 declare i8 @llvm.smax.i8(i8, i8)