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