xref: /llvm-project/llvm/test/CodeGen/ARM/usat.ll (revision 4d28d3f93bfee3cecbeb234d1ce306250e12e912)
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=armv6-eabi %s -o -   | FileCheck %s --check-prefix=V6
4; RUN: llc -mtriple=armv6t2-eabi %s -o - | FileCheck %s --check-prefix=V6T2
5
6; Check for several conditions that should result in USAT.
7; For example, the base test is equivalent to
8; x < 0 ? 0 : (x > k ? k : x) in C. All patterns that bound x
9; to the interval [0, k] where k + 1 is a power of 2 can be
10; transformed into USAT. At the end there are some tests
11; checking that conditionals are not transformed if they don't
12; match the right pattern.
13
14;
15; Base tests with different bit widths
16;
17
18; x < 0 ? 0 : (x > k ? k : x)
19; 32-bit base test
20define i32 @unsigned_sat_base_32bit(i32 %x) #0 {
21; V4T-LABEL: unsigned_sat_base_32bit:
22; V4T:       @ %bb.0: @ %entry
23; V4T-NEXT:    ldr r1, .LCPI0_0
24; V4T-NEXT:    cmp r0, r1
25; V4T-NEXT:    movlt r1, r0
26; V4T-NEXT:    bic r0, r1, r1, asr #31
27; V4T-NEXT:    bx lr
28; V4T-NEXT:    .p2align 2
29; V4T-NEXT:  @ %bb.1:
30; V4T-NEXT:  .LCPI0_0:
31; V4T-NEXT:    .long 8388607 @ 0x7fffff
32;
33; V6-LABEL: unsigned_sat_base_32bit:
34; V6:       @ %bb.0: @ %entry
35; V6-NEXT:    usat r0, #23, r0
36; V6-NEXT:    bx lr
37;
38; V6T2-LABEL: unsigned_sat_base_32bit:
39; V6T2:       @ %bb.0: @ %entry
40; V6T2-NEXT:    usat r0, #23, r0
41; V6T2-NEXT:    bx lr
42entry:
43  %0 = icmp slt i32 %x, 8388607
44  %saturateUp = select i1 %0, i32 %x, i32 8388607
45  %1 = icmp sgt i32 %saturateUp, 0
46  %saturateLow = select i1 %1, i32 %saturateUp, i32 0
47  ret i32 %saturateLow
48}
49
50; x < 0 ? 0 : (x > k ? k : x)
51; 16-bit base test
52define i16 @unsigned_sat_base_16bit(i16 %x) #0 {
53; V4T-LABEL: unsigned_sat_base_16bit:
54; V4T:       @ %bb.0: @ %entry
55; V4T-NEXT:    mov r2, #255
56; V4T-NEXT:    lsl r1, r0, #16
57; V4T-NEXT:    orr r2, r2, #1792
58; V4T-NEXT:    asr r1, r1, #16
59; V4T-NEXT:    cmp r1, r2
60; V4T-NEXT:    movge r0, r2
61; V4T-NEXT:    lsl r1, r0, #16
62; V4T-NEXT:    asr r1, r1, #16
63; V4T-NEXT:    cmp r1, #0
64; V4T-NEXT:    movle r0, #0
65; V4T-NEXT:    bx lr
66;
67; V6-LABEL: unsigned_sat_base_16bit:
68; V6:       @ %bb.0: @ %entry
69; V6-NEXT:    mov r2, #255
70; V6-NEXT:    sxth r1, r0
71; V6-NEXT:    orr r2, r2, #1792
72; V6-NEXT:    cmp r1, r2
73; V6-NEXT:    movge r0, r2
74; V6-NEXT:    sxth r1, r0
75; V6-NEXT:    cmp r1, #0
76; V6-NEXT:    movle r0, #0
77; V6-NEXT:    bx lr
78;
79; V6T2-LABEL: unsigned_sat_base_16bit:
80; V6T2:       @ %bb.0: @ %entry
81; V6T2-NEXT:    sxth r1, r0
82; V6T2-NEXT:    movw r2, #2047
83; V6T2-NEXT:    cmp r1, r2
84; V6T2-NEXT:    movge r0, r2
85; V6T2-NEXT:    sxth r1, r0
86; V6T2-NEXT:    cmp r1, #0
87; V6T2-NEXT:    movle r0, #0
88; V6T2-NEXT:    bx lr
89entry:
90  %0 = icmp slt i16 %x, 2047
91  %saturateUp = select i1 %0, i16 %x, i16 2047
92  %1 = icmp sgt i16 %saturateUp, 0
93  %saturateLow = select i1 %1, i16 %saturateUp, i16 0
94  ret i16 %saturateLow
95}
96
97; x < 0 ? 0 : (x > k ? k : x)
98; 8-bit base test
99define i8 @unsigned_sat_base_8bit(i8 %x) #0 {
100; V4T-LABEL: unsigned_sat_base_8bit:
101; V4T:       @ %bb.0: @ %entry
102; V4T-NEXT:    lsl r1, r0, #24
103; V4T-NEXT:    asr r1, r1, #24
104; V4T-NEXT:    cmp r1, #31
105; V4T-NEXT:    movge r0, #31
106; V4T-NEXT:    lsl r1, r0, #24
107; V4T-NEXT:    asr r1, r1, #24
108; V4T-NEXT:    cmp r1, #0
109; V4T-NEXT:    movle r0, #0
110; V4T-NEXT:    bx lr
111;
112; V6-LABEL: unsigned_sat_base_8bit:
113; V6:       @ %bb.0: @ %entry
114; V6-NEXT:    sxtb r1, r0
115; V6-NEXT:    cmp r1, #31
116; V6-NEXT:    movge r0, #31
117; V6-NEXT:    sxtb r1, r0
118; V6-NEXT:    cmp r1, #0
119; V6-NEXT:    movle r0, #0
120; V6-NEXT:    bx lr
121;
122; V6T2-LABEL: unsigned_sat_base_8bit:
123; V6T2:       @ %bb.0: @ %entry
124; V6T2-NEXT:    sxtb r1, r0
125; V6T2-NEXT:    cmp r1, #31
126; V6T2-NEXT:    movge r0, #31
127; V6T2-NEXT:    sxtb r1, r0
128; V6T2-NEXT:    cmp r1, #0
129; V6T2-NEXT:    movle r0, #0
130; V6T2-NEXT:    bx lr
131entry:
132  %0 = icmp slt i8 %x, 31
133  %saturateUp = select i1 %0, i8 %x, i8 31
134  %1 = icmp sgt i8 %saturateUp, 0
135  %saturateLow = select i1 %1, i8 %saturateUp, i8 0
136  ret i8 %saturateLow
137}
138
139;
140; Tests where the conditionals that check for upper and lower bounds,
141; or the < and > operators, are arranged in different ways. Only some
142; of the possible combinations that lead to USAT are tested.
143;
144; x < 0 ? 0 : (x < k ? x : k)
145define i32 @unsigned_sat_lower_upper_1(i32 %x) #0 {
146; V4T-LABEL: unsigned_sat_lower_upper_1:
147; V4T:       @ %bb.0: @ %entry
148; V4T-NEXT:    ldr r1, .LCPI3_0
149; V4T-NEXT:    cmp r0, r1
150; V4T-NEXT:    movlt r1, r0
151; V4T-NEXT:    bic r0, r1, r1, asr #31
152; V4T-NEXT:    bx lr
153; V4T-NEXT:    .p2align 2
154; V4T-NEXT:  @ %bb.1:
155; V4T-NEXT:  .LCPI3_0:
156; V4T-NEXT:    .long 8388607 @ 0x7fffff
157;
158; V6-LABEL: unsigned_sat_lower_upper_1:
159; V6:       @ %bb.0: @ %entry
160; V6-NEXT:    usat r0, #23, r0
161; V6-NEXT:    bx lr
162;
163; V6T2-LABEL: unsigned_sat_lower_upper_1:
164; V6T2:       @ %bb.0: @ %entry
165; V6T2-NEXT:    usat r0, #23, r0
166; V6T2-NEXT:    bx lr
167entry:
168  %cmpUp = icmp slt i32 %x, 8388607
169  %saturateUp = select i1 %cmpUp, i32 %x, i32 8388607
170  %0 = icmp sgt i32 %saturateUp, 0
171  %saturateLow = select i1 %0, i32 %saturateUp, i32 0
172  ret i32 %saturateLow
173}
174
175; x > 0 ? (x > k ? k : x) : 0
176define i32 @unsigned_sat_lower_upper_2(i32 %x) #0 {
177; V4T-LABEL: unsigned_sat_lower_upper_2:
178; V4T:       @ %bb.0: @ %entry
179; V4T-NEXT:    ldr r1, .LCPI4_0
180; V4T-NEXT:    cmp r0, r1
181; V4T-NEXT:    movlt r1, r0
182; V4T-NEXT:    bic r0, r1, r1, asr #31
183; V4T-NEXT:    bx lr
184; V4T-NEXT:    .p2align 2
185; V4T-NEXT:  @ %bb.1:
186; V4T-NEXT:  .LCPI4_0:
187; V4T-NEXT:    .long 8388607 @ 0x7fffff
188;
189; V6-LABEL: unsigned_sat_lower_upper_2:
190; V6:       @ %bb.0: @ %entry
191; V6-NEXT:    usat r0, #23, r0
192; V6-NEXT:    bx lr
193;
194; V6T2-LABEL: unsigned_sat_lower_upper_2:
195; V6T2:       @ %bb.0: @ %entry
196; V6T2-NEXT:    usat r0, #23, r0
197; V6T2-NEXT:    bx lr
198entry:
199  %0 = icmp slt i32 %x, 8388607
200  %saturateUp = select i1 %0, i32 %x, i32 8388607
201  %1 = icmp sgt i32 %saturateUp, 0
202  %saturateLow = select i1 %1, i32 %saturateUp, i32 0
203  ret i32 %saturateLow
204}
205
206; x < k ? (x < 0 ? 0 : x) : k
207define i32 @unsigned_sat_upper_lower_1(i32 %x) #0 {
208; V4T-LABEL: unsigned_sat_upper_lower_1:
209; V4T:       @ %bb.0: @ %entry
210; V4T-NEXT:    bic r1, r0, r0, asr #31
211; V4T-NEXT:    ldr r0, .LCPI5_0
212; V4T-NEXT:    cmp r1, r0
213; V4T-NEXT:    movlt r0, r1
214; V4T-NEXT:    bx lr
215; V4T-NEXT:    .p2align 2
216; V4T-NEXT:  @ %bb.1:
217; V4T-NEXT:  .LCPI5_0:
218; V4T-NEXT:    .long 8388607 @ 0x7fffff
219;
220; V6-LABEL: unsigned_sat_upper_lower_1:
221; V6:       @ %bb.0: @ %entry
222; V6-NEXT:    usat r0, #23, r0
223; V6-NEXT:    bx lr
224;
225; V6T2-LABEL: unsigned_sat_upper_lower_1:
226; V6T2:       @ %bb.0: @ %entry
227; V6T2-NEXT:    usat r0, #23, r0
228; V6T2-NEXT:    bx lr
229entry:
230  %0 = icmp sgt i32 %x, 0
231  %saturateLow = select i1 %0, i32 %x, i32 0
232  %1 = icmp slt i32 %saturateLow, 8388607
233  %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
234  ret i32 %saturateUp
235}
236
237; x > k ? k : (x < 0 ? 0 : x)
238define i32 @unsigned_sat_upper_lower_2(i32 %x) #0 {
239; V4T-LABEL: unsigned_sat_upper_lower_2:
240; V4T:       @ %bb.0: @ %entry
241; V4T-NEXT:    bic r1, r0, r0, asr #31
242; V4T-NEXT:    ldr r0, .LCPI6_0
243; V4T-NEXT:    cmp r1, r0
244; V4T-NEXT:    movlt r0, r1
245; V4T-NEXT:    bx lr
246; V4T-NEXT:    .p2align 2
247; V4T-NEXT:  @ %bb.1:
248; V4T-NEXT:  .LCPI6_0:
249; V4T-NEXT:    .long 8388607 @ 0x7fffff
250;
251; V6-LABEL: unsigned_sat_upper_lower_2:
252; V6:       @ %bb.0: @ %entry
253; V6-NEXT:    usat r0, #23, r0
254; V6-NEXT:    bx lr
255;
256; V6T2-LABEL: unsigned_sat_upper_lower_2:
257; V6T2:       @ %bb.0: @ %entry
258; V6T2-NEXT:    usat r0, #23, r0
259; V6T2-NEXT:    bx lr
260entry:
261  %0 = icmp sgt i32 %x, 0
262  %saturateLow = select i1 %0, i32 %x, i32 0
263  %1 = icmp slt i32 %saturateLow, 8388607
264  %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
265  ret i32 %saturateUp
266}
267
268; k < x ? k : (x > 0 ? x : 0)
269define i32 @unsigned_sat_upper_lower_3(i32 %x) #0 {
270; V4T-LABEL: unsigned_sat_upper_lower_3:
271; V4T:       @ %bb.0: @ %entry
272; V4T-NEXT:    bic r1, r0, r0, asr #31
273; V4T-NEXT:    ldr r0, .LCPI7_0
274; V4T-NEXT:    cmp r1, r0
275; V4T-NEXT:    movlt r0, r1
276; V4T-NEXT:    bx lr
277; V4T-NEXT:    .p2align 2
278; V4T-NEXT:  @ %bb.1:
279; V4T-NEXT:  .LCPI7_0:
280; V4T-NEXT:    .long 8388607 @ 0x7fffff
281;
282; V6-LABEL: unsigned_sat_upper_lower_3:
283; V6:       @ %bb.0: @ %entry
284; V6-NEXT:    usat r0, #23, r0
285; V6-NEXT:    bx lr
286;
287; V6T2-LABEL: unsigned_sat_upper_lower_3:
288; V6T2:       @ %bb.0: @ %entry
289; V6T2-NEXT:    usat r0, #23, r0
290; V6T2-NEXT:    bx lr
291entry:
292  %cmpLow = icmp sgt i32 %x, 0
293  %saturateLow = select i1 %cmpLow, i32 %x, i32 0
294  %0 = icmp slt i32 %saturateLow, 8388607
295  %saturateUp = select i1 %0, i32 %saturateLow, i32 8388607
296  ret i32 %saturateUp
297}
298
299;
300; The following tests check for patterns that should not transform
301; into USAT but are similar enough that could confuse the selector.
302;
303; x > k ? k : (x > 0 ? 0 : x)
304; First condition upper-saturates, second doesn't lower-saturate.
305define i32 @no_unsigned_sat_missing_lower(i32 %x) #0 {
306; V4T-LABEL: no_unsigned_sat_missing_lower:
307; V4T:       @ %bb.0: @ %entry
308; V4T-NEXT:    ldr r1, .LCPI8_0
309; V4T-NEXT:    cmp r0, #8388608
310; V4T-NEXT:    andlt r1, r0, r0, asr #31
311; V4T-NEXT:    mov r0, r1
312; V4T-NEXT:    bx lr
313; V4T-NEXT:    .p2align 2
314; V4T-NEXT:  @ %bb.1:
315; V4T-NEXT:  .LCPI8_0:
316; V4T-NEXT:    .long 8388607 @ 0x7fffff
317;
318; V6-LABEL: no_unsigned_sat_missing_lower:
319; V6:       @ %bb.0: @ %entry
320; V6-NEXT:    ldr r1, .LCPI8_0
321; V6-NEXT:    cmp r0, #8388608
322; V6-NEXT:    andlt r1, r0, r0, asr #31
323; V6-NEXT:    mov r0, r1
324; V6-NEXT:    bx lr
325; V6-NEXT:    .p2align 2
326; V6-NEXT:  @ %bb.1:
327; V6-NEXT:  .LCPI8_0:
328; V6-NEXT:    .long 8388607 @ 0x7fffff
329;
330; V6T2-LABEL: no_unsigned_sat_missing_lower:
331; V6T2:       @ %bb.0: @ %entry
332; V6T2-NEXT:    and r1, r0, r0, asr #31
333; V6T2-NEXT:    cmp r0, #8388608
334; V6T2-NEXT:    movwge r1, #65535
335; V6T2-NEXT:    movtge r1, #127
336; V6T2-NEXT:    mov r0, r1
337; V6T2-NEXT:    bx lr
338entry:
339  %cmpUp = icmp sgt i32 %x, 8388607
340  %0 = icmp slt i32 %x, 0
341  %saturateLow = select i1 %0, i32 %x, i32 0
342  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
343  ret i32 %saturateUp
344}
345
346; x < k ? k : (x < 0 ? 0 : x)
347; Second condition lower-saturates, first doesn't upper-saturate.
348define i32 @no_unsigned_sat_missing_upper(i32 %x) #0 {
349; V4T-LABEL: no_unsigned_sat_missing_upper:
350; V4T:       @ %bb.0: @ %entry
351; V4T-NEXT:    ldr r1, .LCPI9_0
352; V4T-NEXT:    cmp r0, r1
353; V4T-NEXT:    bicge r1, r0, r0, asr #31
354; V4T-NEXT:    mov r0, r1
355; V4T-NEXT:    bx lr
356; V4T-NEXT:    .p2align 2
357; V4T-NEXT:  @ %bb.1:
358; V4T-NEXT:  .LCPI9_0:
359; V4T-NEXT:    .long 8388607 @ 0x7fffff
360;
361; V6-LABEL: no_unsigned_sat_missing_upper:
362; V6:       @ %bb.0: @ %entry
363; V6-NEXT:    ldr r1, .LCPI9_0
364; V6-NEXT:    cmp r0, r1
365; V6-NEXT:    bicge r1, r0, r0, asr #31
366; V6-NEXT:    mov r0, r1
367; V6-NEXT:    bx lr
368; V6-NEXT:    .p2align 2
369; V6-NEXT:  @ %bb.1:
370; V6-NEXT:  .LCPI9_0:
371; V6-NEXT:    .long 8388607 @ 0x7fffff
372;
373; V6T2-LABEL: no_unsigned_sat_missing_upper:
374; V6T2:       @ %bb.0: @ %entry
375; V6T2-NEXT:    movw r2, #65535
376; V6T2-NEXT:    bic r1, r0, r0, asr #31
377; V6T2-NEXT:    movt r2, #127
378; V6T2-NEXT:    cmp r0, r2
379; V6T2-NEXT:    movwlt r1, #65535
380; V6T2-NEXT:    movtlt r1, #127
381; V6T2-NEXT:    mov r0, r1
382; V6T2-NEXT:    bx lr
383entry:
384  %cmpUp = icmp slt i32 %x, 8388607
385  %0 = icmp sgt i32 %x, 0
386  %saturateLow = select i1 %0, i32 %x, i32 0
387  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
388  ret i32 %saturateUp
389}
390
391; Lower constant is different in the select and in the compare
392define i32 @no_unsigned_sat_incorrect_constant(i32 %x) #0 {
393; V4T-LABEL: no_unsigned_sat_incorrect_constant:
394; V4T:       @ %bb.0: @ %entry
395; V4T-NEXT:    orr r1, r0, r0, asr #31
396; V4T-NEXT:    ldr r0, .LCPI10_0
397; V4T-NEXT:    cmp r1, r0
398; V4T-NEXT:    movlt r0, r1
399; V4T-NEXT:    bx lr
400; V4T-NEXT:    .p2align 2
401; V4T-NEXT:  @ %bb.1:
402; V4T-NEXT:  .LCPI10_0:
403; V4T-NEXT:    .long 8388607 @ 0x7fffff
404;
405; V6-LABEL: no_unsigned_sat_incorrect_constant:
406; V6:       @ %bb.0: @ %entry
407; V6-NEXT:    orr r1, r0, r0, asr #31
408; V6-NEXT:    ldr r0, .LCPI10_0
409; V6-NEXT:    cmp r1, r0
410; V6-NEXT:    movlt r0, r1
411; V6-NEXT:    bx lr
412; V6-NEXT:    .p2align 2
413; V6-NEXT:  @ %bb.1:
414; V6-NEXT:  .LCPI10_0:
415; V6-NEXT:    .long 8388607 @ 0x7fffff
416;
417; V6T2-LABEL: no_unsigned_sat_incorrect_constant:
418; V6T2:       @ %bb.0: @ %entry
419; V6T2-NEXT:    orr r1, r0, r0, asr #31
420; V6T2-NEXT:    movw r0, #65535
421; V6T2-NEXT:    movt r0, #127
422; V6T2-NEXT:    cmp r1, r0
423; V6T2-NEXT:    movlt r0, r1
424; V6T2-NEXT:    bx lr
425entry:
426  %cmpLow.inv = icmp sgt i32 %x, -1
427  %saturateLow = select i1 %cmpLow.inv, i32 %x, i32 -1
428  %0 = icmp slt i32 %saturateLow, 8388607
429  %saturateUp = select i1 %0, i32 %saturateLow, i32 8388607
430  ret i32 %saturateUp
431}
432
433; The interval is [0, k] but k+1 is not a power of 2
434define i32 @no_unsigned_sat_incorrect_constant2(i32 %x) #0 {
435; V4T-LABEL: no_unsigned_sat_incorrect_constant2:
436; V4T:       @ %bb.0: @ %entry
437; V4T-NEXT:    bic r1, r0, r0, asr #31
438; V4T-NEXT:    mov r0, #1
439; V4T-NEXT:    orr r0, r0, #8388608
440; V4T-NEXT:    cmp r1, #8388608
441; V4T-NEXT:    movle r0, r1
442; V4T-NEXT:    bx lr
443;
444; V6-LABEL: no_unsigned_sat_incorrect_constant2:
445; V6:       @ %bb.0: @ %entry
446; V6-NEXT:    bic r1, r0, r0, asr #31
447; V6-NEXT:    mov r0, #1
448; V6-NEXT:    orr r0, r0, #8388608
449; V6-NEXT:    cmp r1, #8388608
450; V6-NEXT:    movle r0, r1
451; V6-NEXT:    bx lr
452;
453; V6T2-LABEL: no_unsigned_sat_incorrect_constant2:
454; V6T2:       @ %bb.0: @ %entry
455; V6T2-NEXT:    bic r1, r0, r0, asr #31
456; V6T2-NEXT:    movw r0, #1
457; V6T2-NEXT:    movt r0, #128
458; V6T2-NEXT:    cmp r1, #8388608
459; V6T2-NEXT:    movle r0, r1
460; V6T2-NEXT:    bx lr
461entry:
462  %0 = icmp sgt i32 %x, 0
463  %saturateLow = select i1 %0, i32 %x, i32 0
464  %1 = icmp slt i32 %saturateLow, 8388609
465  %saturateUp = select i1 %1, i32 %saturateLow, i32 8388609
466  ret i32 %saturateUp
467}
468
469; The interval is not [0, k]
470define i32 @no_unsigned_sat_incorrect_interval(i32 %x) #0 {
471; V4T-LABEL: no_unsigned_sat_incorrect_interval:
472; V4T:       @ %bb.0: @ %entry
473; V4T-NEXT:    ldr r1, .LCPI12_0
474; V4T-NEXT:    cmn r0, #4
475; V4T-NEXT:    mvnle r0, #3
476; V4T-NEXT:    cmp r0, r1
477; V4T-NEXT:    movge r0, r1
478; V4T-NEXT:    bx lr
479; V4T-NEXT:    .p2align 2
480; V4T-NEXT:  @ %bb.1:
481; V4T-NEXT:  .LCPI12_0:
482; V4T-NEXT:    .long 8388607 @ 0x7fffff
483;
484; V6-LABEL: no_unsigned_sat_incorrect_interval:
485; V6:       @ %bb.0: @ %entry
486; V6-NEXT:    ldr r1, .LCPI12_0
487; V6-NEXT:    cmn r0, #4
488; V6-NEXT:    mvnle r0, #3
489; V6-NEXT:    cmp r0, r1
490; V6-NEXT:    movge r0, r1
491; V6-NEXT:    bx lr
492; V6-NEXT:    .p2align 2
493; V6-NEXT:  @ %bb.1:
494; V6-NEXT:  .LCPI12_0:
495; V6-NEXT:    .long 8388607 @ 0x7fffff
496;
497; V6T2-LABEL: no_unsigned_sat_incorrect_interval:
498; V6T2:       @ %bb.0: @ %entry
499; V6T2-NEXT:    cmn r0, #4
500; V6T2-NEXT:    movw r1, #65535
501; V6T2-NEXT:    mvnle r0, #3
502; V6T2-NEXT:    movt r1, #127
503; V6T2-NEXT:    cmp r0, r1
504; V6T2-NEXT:    movge r0, r1
505; V6T2-NEXT:    bx lr
506entry:
507  %0 = icmp sgt i32 %x, -4
508  %saturateLow = select i1 %0, i32 %x, i32 -4
509  %1 = icmp slt i32 %saturateLow, 8388607
510  %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
511  ret i32 %saturateUp
512}
513
514; The returned value (y) is not the same as the tested value (x).
515define i32 @no_unsigned_sat_incorrect_return(i32 %x, i32 %y) #0 {
516; V4T-LABEL: no_unsigned_sat_incorrect_return:
517; V4T:       @ %bb.0: @ %entry
518; V4T-NEXT:    cmp r0, #0
519; V4T-NEXT:    ldr r2, .LCPI13_0
520; V4T-NEXT:    movmi r1, #0
521; V4T-NEXT:    cmp r0, #8388608
522; V4T-NEXT:    movlt r2, r1
523; V4T-NEXT:    mov r0, r2
524; V4T-NEXT:    bx lr
525; V4T-NEXT:    .p2align 2
526; V4T-NEXT:  @ %bb.1:
527; V4T-NEXT:  .LCPI13_0:
528; V4T-NEXT:    .long 8388607 @ 0x7fffff
529;
530; V6-LABEL: no_unsigned_sat_incorrect_return:
531; V6:       @ %bb.0: @ %entry
532; V6-NEXT:    cmp r0, #0
533; V6-NEXT:    ldr r2, .LCPI13_0
534; V6-NEXT:    movmi r1, #0
535; V6-NEXT:    cmp r0, #8388608
536; V6-NEXT:    movlt r2, r1
537; V6-NEXT:    mov r0, r2
538; V6-NEXT:    bx lr
539; V6-NEXT:    .p2align 2
540; V6-NEXT:  @ %bb.1:
541; V6-NEXT:  .LCPI13_0:
542; V6-NEXT:    .long 8388607 @ 0x7fffff
543;
544; V6T2-LABEL: no_unsigned_sat_incorrect_return:
545; V6T2:       @ %bb.0: @ %entry
546; V6T2-NEXT:    cmp r0, #0
547; V6T2-NEXT:    movwmi r1, #0
548; V6T2-NEXT:    cmp r0, #8388608
549; V6T2-NEXT:    movwge r1, #65535
550; V6T2-NEXT:    movtge r1, #127
551; V6T2-NEXT:    mov r0, r1
552; V6T2-NEXT:    bx lr
553entry:
554  %cmpUp = icmp sgt i32 %x, 8388607
555  %cmpLow = icmp slt i32 %x, 0
556  %saturateLow = select i1 %cmpLow, i32 0, i32 %y
557  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
558  ret i32 %saturateUp
559}
560
561; One of the values in a compare (y) is not the same as the rest
562; of the compare and select values (x).
563define i32 @no_unsigned_sat_incorrect_compare(i32 %x, i32 %y) #0 {
564; V4T-LABEL: no_unsigned_sat_incorrect_compare:
565; V4T:       @ %bb.0: @ %entry
566; V4T-NEXT:    cmp r1, #0
567; V4T-NEXT:    mov r2, r0
568; V4T-NEXT:    movmi r2, #0
569; V4T-NEXT:    ldr r1, .LCPI14_0
570; V4T-NEXT:    cmp r0, #8388608
571; V4T-NEXT:    movlt r1, r2
572; V4T-NEXT:    mov r0, r1
573; V4T-NEXT:    bx lr
574; V4T-NEXT:    .p2align 2
575; V4T-NEXT:  @ %bb.1:
576; V4T-NEXT:  .LCPI14_0:
577; V4T-NEXT:    .long 8388607 @ 0x7fffff
578;
579; V6-LABEL: no_unsigned_sat_incorrect_compare:
580; V6:       @ %bb.0: @ %entry
581; V6-NEXT:    cmp r1, #0
582; V6-NEXT:    mov r2, r0
583; V6-NEXT:    movmi r2, #0
584; V6-NEXT:    ldr r1, .LCPI14_0
585; V6-NEXT:    cmp r0, #8388608
586; V6-NEXT:    movlt r1, r2
587; V6-NEXT:    mov r0, r1
588; V6-NEXT:    bx lr
589; V6-NEXT:    .p2align 2
590; V6-NEXT:  @ %bb.1:
591; V6-NEXT:  .LCPI14_0:
592; V6-NEXT:    .long 8388607 @ 0x7fffff
593;
594; V6T2-LABEL: no_unsigned_sat_incorrect_compare:
595; V6T2:       @ %bb.0: @ %entry
596; V6T2-NEXT:    cmp r1, #0
597; V6T2-NEXT:    mov r1, r0
598; V6T2-NEXT:    movwmi r1, #0
599; V6T2-NEXT:    cmp r0, #8388608
600; V6T2-NEXT:    movwge r1, #65535
601; V6T2-NEXT:    movtge r1, #127
602; V6T2-NEXT:    mov r0, r1
603; V6T2-NEXT:    bx lr
604entry:
605  %cmpUp = icmp sgt i32 %x, 8388607
606  %cmpLow = icmp slt i32 %y, 0
607  %saturateLow = select i1 %cmpLow, i32 0, i32 %x
608  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
609  ret i32 %saturateUp
610}
611
612define i32 @mm_unsigned_sat_base_32bit(i32 %x) {
613; V4T-LABEL: mm_unsigned_sat_base_32bit:
614; V4T:       @ %bb.0: @ %entry
615; V4T-NEXT:    ldr r1, .LCPI15_0
616; V4T-NEXT:    cmp r0, r1
617; V4T-NEXT:    movlt r1, r0
618; V4T-NEXT:    bic r0, r1, r1, asr #31
619; V4T-NEXT:    bx lr
620; V4T-NEXT:    .p2align 2
621; V4T-NEXT:  @ %bb.1:
622; V4T-NEXT:  .LCPI15_0:
623; V4T-NEXT:    .long 8388607 @ 0x7fffff
624;
625; V6-LABEL: mm_unsigned_sat_base_32bit:
626; V6:       @ %bb.0: @ %entry
627; V6-NEXT:    usat r0, #23, r0
628; V6-NEXT:    bx lr
629;
630; V6T2-LABEL: mm_unsigned_sat_base_32bit:
631; V6T2:       @ %bb.0: @ %entry
632; V6T2-NEXT:    usat r0, #23, r0
633; V6T2-NEXT:    bx lr
634entry:
635  %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607)
636  %1 = call i32 @llvm.smax.i32(i32 %0, i32 0)
637  ret i32 %1
638}
639
640define i16 @mm_unsigned_sat_base_16bit(i16 %x) {
641; V4T-LABEL: mm_unsigned_sat_base_16bit:
642; V4T:       @ %bb.0: @ %entry
643; V4T-NEXT:    mov r2, #255
644; V4T-NEXT:    lsl r0, r0, #16
645; V4T-NEXT:    orr r2, r2, #1792
646; V4T-NEXT:    asr r1, r0, #16
647; V4T-NEXT:    cmp r1, r2
648; V4T-NEXT:    asrlt r2, r0, #16
649; V4T-NEXT:    bic r0, r2, r2, asr #31
650; V4T-NEXT:    bx lr
651;
652; V6-LABEL: mm_unsigned_sat_base_16bit:
653; V6:       @ %bb.0: @ %entry
654; V6-NEXT:    sxth r0, r0
655; V6-NEXT:    usat r0, #11, r0
656; V6-NEXT:    bx lr
657;
658; V6T2-LABEL: mm_unsigned_sat_base_16bit:
659; V6T2:       @ %bb.0: @ %entry
660; V6T2-NEXT:    sxth r0, r0
661; V6T2-NEXT:    usat r0, #11, r0
662; V6T2-NEXT:    bx lr
663entry:
664  %0 = call i16 @llvm.smin.i16(i16 %x, i16 2047)
665  %1 = call i16 @llvm.smax.i16(i16 %0, i16 0)
666  ret i16 %1
667}
668
669define i8 @mm_unsigned_sat_base_8bit(i8 %x) {
670; V4T-LABEL: mm_unsigned_sat_base_8bit:
671; V4T:       @ %bb.0: @ %entry
672; V4T-NEXT:    lsl r0, r0, #24
673; V4T-NEXT:    mov r2, #31
674; V4T-NEXT:    asr r1, r0, #24
675; V4T-NEXT:    cmp r1, #31
676; V4T-NEXT:    asrlt r2, r0, #24
677; V4T-NEXT:    bic r0, r2, r2, asr #31
678; V4T-NEXT:    bx lr
679;
680; V6-LABEL: mm_unsigned_sat_base_8bit:
681; V6:       @ %bb.0: @ %entry
682; V6-NEXT:    sxtb r0, r0
683; V6-NEXT:    usat r0, #5, r0
684; V6-NEXT:    bx lr
685;
686; V6T2-LABEL: mm_unsigned_sat_base_8bit:
687; V6T2:       @ %bb.0: @ %entry
688; V6T2-NEXT:    sxtb r0, r0
689; V6T2-NEXT:    usat r0, #5, r0
690; V6T2-NEXT:    bx lr
691entry:
692  %0 = call i8 @llvm.smin.i8(i8 %x, i8 31)
693  %1 = call i8 @llvm.smax.i8(i8 %0, i8 0)
694  ret i8 %1
695}
696
697define i32 @mm_unsigned_sat_lower_upper_1(i32 %x) {
698; V4T-LABEL: mm_unsigned_sat_lower_upper_1:
699; V4T:       @ %bb.0: @ %entry
700; V4T-NEXT:    ldr r1, .LCPI18_0
701; V4T-NEXT:    cmp r0, r1
702; V4T-NEXT:    movlt r1, r0
703; V4T-NEXT:    bic r0, r1, r1, asr #31
704; V4T-NEXT:    bx lr
705; V4T-NEXT:    .p2align 2
706; V4T-NEXT:  @ %bb.1:
707; V4T-NEXT:  .LCPI18_0:
708; V4T-NEXT:    .long 8388607 @ 0x7fffff
709;
710; V6-LABEL: mm_unsigned_sat_lower_upper_1:
711; V6:       @ %bb.0: @ %entry
712; V6-NEXT:    usat r0, #23, r0
713; V6-NEXT:    bx lr
714;
715; V6T2-LABEL: mm_unsigned_sat_lower_upper_1:
716; V6T2:       @ %bb.0: @ %entry
717; V6T2-NEXT:    usat r0, #23, r0
718; V6T2-NEXT:    bx lr
719entry:
720  %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607)
721  %1 = call i32 @llvm.smax.i32(i32 %0, i32 0)
722  ret i32 %1
723}
724
725define i32 @mm_unsigned_sat_lower_upper_2(i32 %x) {
726; V4T-LABEL: mm_unsigned_sat_lower_upper_2:
727; V4T:       @ %bb.0: @ %entry
728; V4T-NEXT:    ldr r1, .LCPI19_0
729; V4T-NEXT:    cmp r0, r1
730; V4T-NEXT:    movlt r1, r0
731; V4T-NEXT:    bic r0, r1, r1, asr #31
732; V4T-NEXT:    bx lr
733; V4T-NEXT:    .p2align 2
734; V4T-NEXT:  @ %bb.1:
735; V4T-NEXT:  .LCPI19_0:
736; V4T-NEXT:    .long 8388607 @ 0x7fffff
737;
738; V6-LABEL: mm_unsigned_sat_lower_upper_2:
739; V6:       @ %bb.0: @ %entry
740; V6-NEXT:    usat r0, #23, r0
741; V6-NEXT:    bx lr
742;
743; V6T2-LABEL: mm_unsigned_sat_lower_upper_2:
744; V6T2:       @ %bb.0: @ %entry
745; V6T2-NEXT:    usat r0, #23, r0
746; V6T2-NEXT:    bx lr
747entry:
748  %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607)
749  %1 = call i32 @llvm.smax.i32(i32 %0, i32 0)
750  ret i32 %1
751}
752
753define i32 @mm_unsigned_sat_upper_lower_1(i32 %x) {
754; V4T-LABEL: mm_unsigned_sat_upper_lower_1:
755; V4T:       @ %bb.0: @ %entry
756; V4T-NEXT:    bic r1, r0, r0, asr #31
757; V4T-NEXT:    ldr r0, .LCPI20_0
758; V4T-NEXT:    cmp r1, r0
759; V4T-NEXT:    movlt r0, r1
760; V4T-NEXT:    bx lr
761; V4T-NEXT:    .p2align 2
762; V4T-NEXT:  @ %bb.1:
763; V4T-NEXT:  .LCPI20_0:
764; V4T-NEXT:    .long 8388607 @ 0x7fffff
765;
766; V6-LABEL: mm_unsigned_sat_upper_lower_1:
767; V6:       @ %bb.0: @ %entry
768; V6-NEXT:    usat r0, #23, r0
769; V6-NEXT:    bx lr
770;
771; V6T2-LABEL: mm_unsigned_sat_upper_lower_1:
772; V6T2:       @ %bb.0: @ %entry
773; V6T2-NEXT:    usat r0, #23, r0
774; V6T2-NEXT:    bx lr
775entry:
776  %0 = call i32 @llvm.smax.i32(i32 %x, i32 0)
777  %1 = call i32 @llvm.umin.i32(i32 %0, i32 8388607)
778  ret i32 %1
779}
780
781define i32 @mm_unsigned_sat_upper_lower_2(i32 %x) {
782; V4T-LABEL: mm_unsigned_sat_upper_lower_2:
783; V4T:       @ %bb.0: @ %entry
784; V4T-NEXT:    bic r1, r0, r0, asr #31
785; V4T-NEXT:    ldr r0, .LCPI21_0
786; V4T-NEXT:    cmp r1, r0
787; V4T-NEXT:    movlt r0, r1
788; V4T-NEXT:    bx lr
789; V4T-NEXT:    .p2align 2
790; V4T-NEXT:  @ %bb.1:
791; V4T-NEXT:  .LCPI21_0:
792; V4T-NEXT:    .long 8388607 @ 0x7fffff
793;
794; V6-LABEL: mm_unsigned_sat_upper_lower_2:
795; V6:       @ %bb.0: @ %entry
796; V6-NEXT:    usat r0, #23, r0
797; V6-NEXT:    bx lr
798;
799; V6T2-LABEL: mm_unsigned_sat_upper_lower_2:
800; V6T2:       @ %bb.0: @ %entry
801; V6T2-NEXT:    usat r0, #23, r0
802; V6T2-NEXT:    bx lr
803entry:
804  %0 = call i32 @llvm.smax.i32(i32 %x, i32 0)
805  %1 = call i32 @llvm.umin.i32(i32 %0, i32 8388607)
806  ret i32 %1
807}
808
809define i32 @mm_unsigned_sat_upper_lower_3(i32 %x) {
810; V4T-LABEL: mm_unsigned_sat_upper_lower_3:
811; V4T:       @ %bb.0: @ %entry
812; V4T-NEXT:    bic r1, r0, r0, asr #31
813; V4T-NEXT:    ldr r0, .LCPI22_0
814; V4T-NEXT:    cmp r1, r0
815; V4T-NEXT:    movlt r0, r1
816; V4T-NEXT:    bx lr
817; V4T-NEXT:    .p2align 2
818; V4T-NEXT:  @ %bb.1:
819; V4T-NEXT:  .LCPI22_0:
820; V4T-NEXT:    .long 8388607 @ 0x7fffff
821;
822; V6-LABEL: mm_unsigned_sat_upper_lower_3:
823; V6:       @ %bb.0: @ %entry
824; V6-NEXT:    usat r0, #23, r0
825; V6-NEXT:    bx lr
826;
827; V6T2-LABEL: mm_unsigned_sat_upper_lower_3:
828; V6T2:       @ %bb.0: @ %entry
829; V6T2-NEXT:    usat r0, #23, r0
830; V6T2-NEXT:    bx lr
831entry:
832  %0 = call i32 @llvm.smax.i32(i32 %x, i32 0)
833  %1 = call i32 @llvm.umin.i32(i32 %0, i32 8388607)
834  ret i32 %1
835}
836
837define i32 @mm_no_unsigned_sat_incorrect_constant(i32 %x) {
838; V4T-LABEL: mm_no_unsigned_sat_incorrect_constant:
839; V4T:       @ %bb.0: @ %entry
840; V4T-NEXT:    orr r1, r0, r0, asr #31
841; V4T-NEXT:    ldr r0, .LCPI23_0
842; V4T-NEXT:    cmp r1, r0
843; V4T-NEXT:    movlt r0, r1
844; V4T-NEXT:    bx lr
845; V4T-NEXT:    .p2align 2
846; V4T-NEXT:  @ %bb.1:
847; V4T-NEXT:  .LCPI23_0:
848; V4T-NEXT:    .long 8388607 @ 0x7fffff
849;
850; V6-LABEL: mm_no_unsigned_sat_incorrect_constant:
851; V6:       @ %bb.0: @ %entry
852; V6-NEXT:    orr r1, r0, r0, asr #31
853; V6-NEXT:    ldr r0, .LCPI23_0
854; V6-NEXT:    cmp r1, r0
855; V6-NEXT:    movlt r0, r1
856; V6-NEXT:    bx lr
857; V6-NEXT:    .p2align 2
858; V6-NEXT:  @ %bb.1:
859; V6-NEXT:  .LCPI23_0:
860; V6-NEXT:    .long 8388607 @ 0x7fffff
861;
862; V6T2-LABEL: mm_no_unsigned_sat_incorrect_constant:
863; V6T2:       @ %bb.0: @ %entry
864; V6T2-NEXT:    orr r1, r0, r0, asr #31
865; V6T2-NEXT:    movw r0, #65535
866; V6T2-NEXT:    movt r0, #127
867; V6T2-NEXT:    cmp r1, r0
868; V6T2-NEXT:    movlt r0, r1
869; V6T2-NEXT:    bx lr
870entry:
871  %0 = call i32 @llvm.smax.i32(i32 %x, i32 -1)
872  %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607)
873  ret i32 %1
874}
875
876define i32 @mm_no_unsigned_sat_incorrect_constant2(i32 %x) {
877; V4T-LABEL: mm_no_unsigned_sat_incorrect_constant2:
878; V4T:       @ %bb.0: @ %entry
879; V4T-NEXT:    bic r1, r0, r0, asr #31
880; V4T-NEXT:    mov r0, #1
881; V4T-NEXT:    orr r0, r0, #8388608
882; V4T-NEXT:    cmp r1, #8388608
883; V4T-NEXT:    movle r0, r1
884; V4T-NEXT:    bx lr
885;
886; V6-LABEL: mm_no_unsigned_sat_incorrect_constant2:
887; V6:       @ %bb.0: @ %entry
888; V6-NEXT:    bic r1, r0, r0, asr #31
889; V6-NEXT:    mov r0, #1
890; V6-NEXT:    orr r0, r0, #8388608
891; V6-NEXT:    cmp r1, #8388608
892; V6-NEXT:    movle r0, r1
893; V6-NEXT:    bx lr
894;
895; V6T2-LABEL: mm_no_unsigned_sat_incorrect_constant2:
896; V6T2:       @ %bb.0: @ %entry
897; V6T2-NEXT:    bic r1, r0, r0, asr #31
898; V6T2-NEXT:    movw r0, #1
899; V6T2-NEXT:    movt r0, #128
900; V6T2-NEXT:    cmp r1, #8388608
901; V6T2-NEXT:    movle r0, r1
902; V6T2-NEXT:    bx lr
903entry:
904  %0 = call i32 @llvm.smax.i32(i32 %x, i32 0)
905  %1 = call i32 @llvm.umin.i32(i32 %0, i32 8388609)
906  ret i32 %1
907}
908
909define i32 @mm_no_unsigned_sat_incorrect_interval(i32 %x) {
910; V4T-LABEL: mm_no_unsigned_sat_incorrect_interval:
911; V4T:       @ %bb.0: @ %entry
912; V4T-NEXT:    ldr r1, .LCPI25_0
913; V4T-NEXT:    cmn r0, #4
914; V4T-NEXT:    mvnle r0, #3
915; V4T-NEXT:    cmp r0, r1
916; V4T-NEXT:    movge r0, r1
917; V4T-NEXT:    bx lr
918; V4T-NEXT:    .p2align 2
919; V4T-NEXT:  @ %bb.1:
920; V4T-NEXT:  .LCPI25_0:
921; V4T-NEXT:    .long 8388607 @ 0x7fffff
922;
923; V6-LABEL: mm_no_unsigned_sat_incorrect_interval:
924; V6:       @ %bb.0: @ %entry
925; V6-NEXT:    ldr r1, .LCPI25_0
926; V6-NEXT:    cmn r0, #4
927; V6-NEXT:    mvnle r0, #3
928; V6-NEXT:    cmp r0, r1
929; V6-NEXT:    movge r0, r1
930; V6-NEXT:    bx lr
931; V6-NEXT:    .p2align 2
932; V6-NEXT:  @ %bb.1:
933; V6-NEXT:  .LCPI25_0:
934; V6-NEXT:    .long 8388607 @ 0x7fffff
935;
936; V6T2-LABEL: mm_no_unsigned_sat_incorrect_interval:
937; V6T2:       @ %bb.0: @ %entry
938; V6T2-NEXT:    cmn r0, #4
939; V6T2-NEXT:    movw r1, #65535
940; V6T2-NEXT:    mvnle r0, #3
941; V6T2-NEXT:    movt r1, #127
942; V6T2-NEXT:    cmp r0, r1
943; V6T2-NEXT:    movge r0, r1
944; V6T2-NEXT:    bx lr
945entry:
946  %0 = call i32 @llvm.smax.i32(i32 %x, i32 -4)
947  %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607)
948  ret i32 %1
949}
950
951define i32 @test_umin_smax_usat(i32 %x) {
952; V4T-LABEL: test_umin_smax_usat:
953; V4T:       @ %bb.0: @ %entry
954; V4T-NEXT:    bic r0, r0, r0, asr #31
955; V4T-NEXT:    cmp r0, #255
956; V4T-NEXT:    movge r0, #255
957; V4T-NEXT:    bx lr
958;
959; V6-LABEL: test_umin_smax_usat:
960; V6:       @ %bb.0: @ %entry
961; V6-NEXT:    usat r0, #8, r0
962; V6-NEXT:    bx lr
963;
964; V6T2-LABEL: test_umin_smax_usat:
965; V6T2:       @ %bb.0: @ %entry
966; V6T2-NEXT:    usat r0, #8, r0
967; V6T2-NEXT:    bx lr
968entry:
969  %v1 = tail call i32 @llvm.smax.i32(i32 %x, i32 0)
970  %v2 = tail call i32 @llvm.umin.i32(i32 %v1, i32 255)
971  ret i32 %v2
972}
973
974declare i32 @llvm.smin.i32(i32, i32)
975declare i32 @llvm.smax.i32(i32, i32)
976declare i16 @llvm.smin.i16(i16, i16)
977declare i16 @llvm.smax.i16(i16, i16)
978declare i8 @llvm.smin.i8(i8, i8)
979declare i8 @llvm.smax.i8(i8, i8)
980declare i32 @llvm.umin.i32(i32, i32)
981