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:    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
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:    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
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:    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
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:    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
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:    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
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:    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
201;
202; V6T2-LABEL: sat_upper_lower_1:
203; V6T2:       @ %bb.0: @ %entry
204; V6T2-NEXT:    ssat r0, #24, r0
205; V6T2-NEXT:    bx lr
206entry:
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
212}
213
214; x > k ? k : (x < -k ? -k : x)
215define 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
230;
231; V6T2-LABEL: sat_upper_lower_2:
232; V6T2:       @ %bb.0: @ %entry
233; V6T2-NEXT:    ssat r0, #24, r0
234; V6T2-NEXT:    bx lr
235entry:
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
241}
242
243; k < x ? k : (x > -k ? x : -k)
244define 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
259;
260; V6T2-LABEL: sat_upper_lower_3:
261; V6T2:       @ %bb.0: @ %entry
262; V6T2-NEXT:    ssat r0, #24, r0
263; V6T2-NEXT:    bx lr
264entry:
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
270}
271
272;
273; Miscellanea
274;
275
276; Check that >= and <= work the same as > and <
277; k <= x ? k : (x >= -k ? x : -k)
278define 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
293;
294; V6T2-LABEL: sat_le_ge:
295; V6T2:       @ %bb.0: @ %entry
296; V6T2-NEXT:    ssat r0, #24, r0
297; V6T2-NEXT:    bx lr
298entry:
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
304}
305
306;
307; The following tests check for patterns that should not transform
308; into SSAT but are similar enough that could confuse the selector.
309;
310
311; x > k ? k : (x > -k ? -k : x)
312; First condition upper-saturates, second doesn't lower-saturate.
313define 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
329;
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
341entry:
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
347}
348
349; x < k ? k : (x < -k ? -k : x)
350; Second condition lower-saturates, first doesn't upper-saturate.
351define 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
367;
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
381entry:
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
387}
388
389; Lower constant is different in the select and in the compare
390define 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
407;
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
420entry:
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
426}
427
428; The interval is not [k, ~k]
429define 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
445;
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
457entry:
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
463}
464
465; The returned value (y) is not the same as the tested value (x).
466define 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
482;
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
493entry:
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
499}
500
501; One of the values in a compare (y) is not the same as the rest
502; of the compare and select values (x).
503define 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
519;
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
531entry:
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
537}
538
539define void @extended(i32 %xx, i16 signext %y, i8* 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
553;
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
565entry:
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, i8* %z, align 1
575  ret void
576}
577
578
579define 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
594;
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
615}
616
617define 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
630;
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
651}
652