1; RUN: llc -mtriple=armv4t-eabi %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=V4T
2; RUN: llc -mtriple=armv6t2-eabi %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=V6T2
3
4; Check for several conditions that should result in SSAT.
5; For example, the base test is equivalent to
6; x < -k ? -k : (x > k ? k : x) in C. All patterns that bound x
7; to the interval [-k, k] where k is a power of 2 can be
8; transformed into SSAT. At the end there are some tests
9; checking that conditionals are not transformed if they don't
10; match the right pattern.
11
12;
13; Base tests with different bit widths
14;
15
16; x < -k ? -k : (x > k ? k : x)
17; 32-bit base test
18define i32 @sat_base_32bit(i32 %x) #0 {
19; CHECK-LABEL: sat_base_32bit:
20; V6T2: ssat r0, #24, r0
21; V4T-NOT: ssat
22entry:
23  %cmpLow = icmp slt i32 %x, -8388608
24  %cmpUp = icmp sgt i32 %x, 8388607
25  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %x
26  %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %saturateUp
27  ret i32 %saturateLow
28}
29
30; x < -k ? -k : (x > k ? k : x)
31; 16-bit base test
32define i16 @sat_base_16bit(i16 %x) #0 {
33; CHECK-LABEL: sat_base_16bit:
34; V6T2: ssat r0, #12, r0
35; V4T-NOT: ssat
36entry:
37  %cmpLow = icmp slt i16 %x, -2048
38  %cmpUp = icmp sgt i16 %x, 2047
39  %saturateUp = select i1 %cmpUp, i16 2047, i16 %x
40  %saturateLow = select i1 %cmpLow, i16 -2048, i16 %saturateUp
41  ret i16 %saturateLow
42}
43
44; x < -k ? -k : (x > k ? k : x)
45; 8-bit base test
46define i8 @sat_base_8bit(i8 %x) #0 {
47; CHECK-LABEL: sat_base_8bit:
48; V6T2: ssat r0, #6, r0
49; V4T-NOT: ssat
50entry:
51  %cmpLow = icmp slt i8 %x, -32
52  %cmpUp = icmp sgt i8 %x, 31
53  %saturateUp = select i1 %cmpUp, i8 31, i8 %x
54  %saturateLow = select i1 %cmpLow, i8 -32, i8 %saturateUp
55  ret i8 %saturateLow
56}
57
58;
59; Tests where the conditionals that check for upper and lower bounds,
60; or the < and > operators, are arranged in different ways. Only some
61; of the possible combinations that lead to SSAT are tested.
62;
63
64; x < -k ? -k : (x < k ? x : k)
65define i32 @sat_lower_upper_1(i32 %x) #0 {
66; CHECK-LABEL: sat_lower_upper_1:
67; V6T2: ssat r0, #24, r0
68; V4T-NOT: ssat
69entry:
70  %cmpLow = icmp slt i32 %x, -8388608
71  %cmpUp = icmp slt i32 %x, 8388607
72  %saturateUp = select i1 %cmpUp, i32 %x, i32 8388607
73  %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %saturateUp
74  ret i32 %saturateLow
75}
76
77; x > -k ? (x > k ? k : x) : -k
78define i32 @sat_lower_upper_2(i32 %x) #0 {
79; CHECK-LABEL: sat_lower_upper_2:
80; V6T2: ssat    r0, #24, r0
81; V4T-NOT: ssat
82entry:
83  %cmpLow = icmp sgt i32 %x, -8388608
84  %cmpUp = icmp sgt i32 %x, 8388607
85  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %x
86  %saturateLow = select i1 %cmpLow, i32 %saturateUp, i32 -8388608
87  ret i32 %saturateLow
88}
89
90; x < k ? (x < -k ? -k : x) : k
91define i32 @sat_upper_lower_1(i32 %x) #0 {
92; CHECK-LABEL: sat_upper_lower_1:
93; V6T2: ssat    r0, #24, r0
94; V4T-NOT: ssat
95entry:
96  %cmpUp = icmp slt i32 %x, 8388607
97  %cmpLow = icmp slt i32 %x, -8388608
98  %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
99  %saturateUp = select i1 %cmpUp, i32 %saturateLow, i32 8388607
100  ret i32 %saturateUp
101}
102
103; x > k ? k : (x < -k ? -k : x)
104define i32 @sat_upper_lower_2(i32 %x) #0 {
105; CHECK-LABEL: sat_upper_lower_2:
106; V6T2: ssat    r0, #24, r0
107; V4T-NOT: ssat
108entry:
109  %cmpUp = icmp sgt i32 %x, 8388607
110  %cmpLow = icmp slt i32 %x, -8388608
111  %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
112  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
113  ret i32 %saturateUp
114}
115
116; k < x ? k : (x > -k ? x : -k)
117define i32 @sat_upper_lower_3(i32 %x) #0 {
118; CHECK-LABEL: sat_upper_lower_3:
119; V6T2: ssat    r0, #24, r0
120; V4T-NOT: ssat
121entry:
122  %cmpUp = icmp slt i32 8388607, %x
123  %cmpLow = icmp sgt i32 %x, -8388608
124  %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608
125  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
126  ret i32 %saturateUp
127}
128
129;
130; Miscellanea
131;
132
133; Check that >= and <= work the same as > and <
134; k <= x ? k : (x >= -k ? x : -k)
135define i32 @sat_le_ge(i32 %x) #0 {
136; CHECK-LABEL: sat_le_ge:
137; V6T2: ssat    r0, #24, r0
138; V4T-NOT: ssat
139entry:
140  %cmpUp = icmp sle i32 8388607, %x
141  %cmpLow = icmp sge i32 %x, -8388608
142  %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608
143  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
144  ret i32 %saturateUp
145}
146
147;
148; The following tests check for patterns that should not transform
149; into SSAT but are similar enough that could confuse the selector.
150;
151
152; x > k ? k : (x > -k ? -k : x)
153; First condition upper-saturates, second doesn't lower-saturate.
154define i32 @no_sat_missing_lower(i32 %x) #0 {
155; CHECK-LABEL: no_sat_missing_lower
156; CHECK-NOT: ssat
157entry:
158  %cmpUp = icmp sgt i32 %x, 8388607
159  %cmpLow = icmp sgt i32 %x, -8388608
160  %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
161  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
162  ret i32 %saturateUp
163}
164
165; x < k ? k : (x < -k ? -k : x)
166; Second condition lower-saturates, first doesn't upper-saturate.
167define i32 @no_sat_missing_upper(i32 %x) #0 {
168; CHECK-LABEL: no_sat_missing_upper:
169; CHECK-NOT: ssat
170entry:
171  %cmpUp = icmp slt i32 %x, 8388607
172  %cmpLow = icmp slt i32 %x, -8388608
173  %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
174  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
175  ret i32 %saturateUp
176}
177
178; Lower constant is different in the select and in the compare
179define i32 @no_sat_incorrect_constant(i32 %x) #0 {
180; CHECK-LABEL: no_sat_incorrect_constant:
181; CHECK-NOT: ssat
182entry:
183  %cmpUp = icmp sgt i32 %x, 8388607
184  %cmpLow = icmp slt i32 %x, -8388608
185  %saturateLow = select i1 %cmpLow, i32 -8388607, i32 %x
186  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
187  ret i32 %saturateUp
188}
189
190; The interval is not [k, ~k]
191define i32 @no_sat_incorrect_interval(i32 %x) #0 {
192; CHECK-LABEL: no_sat_incorrect_interval:
193; CHECK-NOT: ssat
194entry:
195  %cmpUp = icmp sgt i32 %x, 8388607
196  %cmpLow = icmp slt i32 %x, -19088744
197  %saturateLow = select i1 %cmpLow, i32 -19088744, i32 %x
198  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
199  ret i32 %saturateUp
200}
201
202; The returned value (y) is not the same as the tested value (x).
203define i32 @no_sat_incorrect_return(i32 %x, i32 %y) #0 {
204; CHECK-LABEL: no_sat_incorrect_return:
205; CHECK-NOT: ssat
206entry:
207  %cmpUp = icmp sgt i32 %x, 8388607
208  %cmpLow = icmp slt i32 %x, -8388608
209  %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %y
210  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
211  ret i32 %saturateUp
212}
213
214; One of the values in a compare (y) is not the same as the rest
215; of the compare and select values (x).
216define i32 @no_sat_incorrect_compare(i32 %x, i32 %y) #0 {
217; CHECK-LABEL: no_sat_incorrect_compare:
218; CHECK-NOT: ssat
219entry:
220  %cmpUp = icmp sgt i32 %x, 8388607
221  %cmpLow = icmp slt i32 %y, -8388608
222  %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
223  %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
224  ret i32 %saturateUp
225}
226