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
4
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.
12
13;
14; Base tests with different bit widths
15;
16
17; x < -k ? -k : (x > k ? k : x)
18; 32-bit base test
19define 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
34;
35; V6T2-LABEL: sat_base_32bit:
36; V6T2:       @ %bb.0: @ %entry
37; V6T2-NEXT:    ssat r0, #24, r0
38; V6T2-NEXT:    bx lr
39entry:
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
45}
46
47; x < -k ? -k : (x > k ? k : x)
48; 16-bit base test
49define 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
68;
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
81entry:
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
87}
88
89; x < -k ? -k : (x > k ? k : x)
90; 8-bit base test
91define 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
103;
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
113entry:
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
119}
120
121;
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.
125;
126
127; x < -k ? -k : (x < k ? x : k)
128define 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
143;
144; V6T2-LABEL: sat_lower_upper_1:
145; V6T2:       @ %bb.0: @ %entry
146; V6T2-NEXT:    ssat r0, #24, r0
147; V6T2-NEXT:    bx lr
148entry:
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
154}
155
156; x > -k ? (x > k ? k : x) : -k
157define 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
172;
173; V6T2-LABEL: sat_lower_upper_2:
174; V6T2:       @ %bb.0: @ %entry
175; V6T2-NEXT:    ssat r0, #24, r0
176; V6T2-NEXT:    bx lr
177entry:
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
183}
184
185; x < k ? (x < -k ? -k : x) : k
186define 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
202;
203; V6T2-LABEL: sat_upper_lower_1:
204; V6T2:       @ %bb.0: @ %entry
205; V6T2-NEXT:    ssat r0, #24, r0
206; V6T2-NEXT:    bx lr
207entry:
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
213}
214
215; x > k ? k : (x < -k ? -k : x)
216define 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
232;
233; V6T2-LABEL: sat_upper_lower_2:
234; V6T2:       @ %bb.0: @ %entry
235; V6T2-NEXT:    ssat r0, #24, r0
236; V6T2-NEXT:    bx lr
237entry:
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
243}
244
245; k < x ? k : (x > -k ? x : -k)
246define 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
262;
263; V6T2-LABEL: sat_upper_lower_3:
264; V6T2:       @ %bb.0: @ %entry
265; V6T2-NEXT:    ssat r0, #24, r0
266; V6T2-NEXT:    bx lr
267entry:
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
273}
274
275;
276; Miscellanea
277;
278
279; Check that >= and <= work the same as > and <
280; k <= x ? k : (x >= -k ? x : -k)
281define 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
297;
298; V6T2-LABEL: sat_le_ge:
299; V6T2:       @ %bb.0: @ %entry
300; V6T2-NEXT:    ssat r0, #24, r0
301; V6T2-NEXT:    bx lr
302entry:
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
308}
309
310;
311; The following tests check for patterns that should not transform
312; into SSAT but are similar enough that could confuse the selector.
313;
314
315; x > k ? k : (x > -k ? -k : x)
316; First condition upper-saturates, second doesn't lower-saturate.
317define 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
333;
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
345entry:
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
351}
352
353; x < k ? k : (x < -k ? -k : x)
354; Second condition lower-saturates, first doesn't upper-saturate.
355define 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
371;
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
385entry:
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
391}
392
393; Lower constant is different in the select and in the compare
394define 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
411;
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
424entry:
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
430}
431
432; The interval is not [k, ~k]
433define 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
450;
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
463entry:
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
469}
470
471; The returned value (y) is not the same as the tested value (x).
472define 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
488;
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
499entry:
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
505}
506
507; One of the values in a compare (y) is not the same as the rest
508; of the compare and select values (x).
509define 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
525;
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
537entry:
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
543}
544
545define 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
559;
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
571entry:
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
582}
583
584
585define 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
600;
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
621}
622
623define 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
636;
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
657}
658