1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=arm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
3 ; RUN: llc -mtriple=thumb-eabi %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-T
4 ; RUN: llc -mtriple=thumb-eabi -mcpu=arm1156t2-s -mattr=+thumb2 %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-T2
6 ; Check for clipping against 0 that should result in bic
8 ; Base tests with different bit widths
12 define i32 @sat0_base_32bit(i32 %x) #0 {
13 ; CHECK-ARM-LABEL: sat0_base_32bit:
14 ; CHECK-ARM: @ %bb.0: @ %entry
15 ; CHECK-ARM-NEXT: bic r0, r0, r0, asr #31
16 ; CHECK-ARM-NEXT: mov pc, lr
18 ; CHECK-T-LABEL: sat0_base_32bit:
19 ; CHECK-T: @ %bb.0: @ %entry
20 ; CHECK-T-NEXT: asrs r1, r0, #31
21 ; CHECK-T-NEXT: bics r0, r1
24 ; CHECK-T2-LABEL: sat0_base_32bit:
25 ; CHECK-T2: @ %bb.0: @ %entry
26 ; CHECK-T2-NEXT: bic.w r0, r0, r0, asr #31
27 ; CHECK-T2-NEXT: bx lr
29 %cmpLow = icmp slt i32 %x, 0
30 %saturateLow = select i1 %cmpLow, i32 0, i32 %x
36 define i16 @sat0_base_16bit(i16 %x) #0 {
37 ; CHECK-ARM-LABEL: sat0_base_16bit:
38 ; CHECK-ARM: @ %bb.0: @ %entry
39 ; CHECK-ARM-NEXT: lsl r1, r0, #16
40 ; CHECK-ARM-NEXT: asr r1, r1, #16
41 ; CHECK-ARM-NEXT: cmp r1, #0
42 ; CHECK-ARM-NEXT: movmi r0, #0
43 ; CHECK-ARM-NEXT: mov pc, lr
45 ; CHECK-T-LABEL: sat0_base_16bit:
46 ; CHECK-T: @ %bb.0: @ %entry
47 ; CHECK-T-NEXT: lsls r1, r0, #16
48 ; CHECK-T-NEXT: asrs r1, r1, #16
49 ; CHECK-T-NEXT: bpl .LBB1_2
50 ; CHECK-T-NEXT: @ %bb.1:
51 ; CHECK-T-NEXT: movs r0, #0
52 ; CHECK-T-NEXT: .LBB1_2: @ %entry
55 ; CHECK-T2-LABEL: sat0_base_16bit:
56 ; CHECK-T2: @ %bb.0: @ %entry
57 ; CHECK-T2-NEXT: sxth r1, r0
58 ; CHECK-T2-NEXT: cmp r1, #0
59 ; CHECK-T2-NEXT: it mi
60 ; CHECK-T2-NEXT: movmi r0, #0
61 ; CHECK-T2-NEXT: bx lr
63 %cmpLow = icmp slt i16 %x, 0
64 %saturateLow = select i1 %cmpLow, i16 0, i16 %x
70 define i8 @sat0_base_8bit(i8 %x) #0 {
71 ; CHECK-ARM-LABEL: sat0_base_8bit:
72 ; CHECK-ARM: @ %bb.0: @ %entry
73 ; CHECK-ARM-NEXT: lsl r1, r0, #24
74 ; CHECK-ARM-NEXT: asr r1, r1, #24
75 ; CHECK-ARM-NEXT: cmp r1, #0
76 ; CHECK-ARM-NEXT: movmi r0, #0
77 ; CHECK-ARM-NEXT: mov pc, lr
79 ; CHECK-T-LABEL: sat0_base_8bit:
80 ; CHECK-T: @ %bb.0: @ %entry
81 ; CHECK-T-NEXT: lsls r1, r0, #24
82 ; CHECK-T-NEXT: asrs r1, r1, #24
83 ; CHECK-T-NEXT: bpl .LBB2_2
84 ; CHECK-T-NEXT: @ %bb.1:
85 ; CHECK-T-NEXT: movs r0, #0
86 ; CHECK-T-NEXT: .LBB2_2: @ %entry
89 ; CHECK-T2-LABEL: sat0_base_8bit:
90 ; CHECK-T2: @ %bb.0: @ %entry
91 ; CHECK-T2-NEXT: sxtb r1, r0
92 ; CHECK-T2-NEXT: cmp r1, #0
93 ; CHECK-T2-NEXT: it mi
94 ; CHECK-T2-NEXT: movmi r0, #0
95 ; CHECK-T2-NEXT: bx lr
97 %cmpLow = icmp slt i8 %x, 0
98 %saturateLow = select i1 %cmpLow, i8 0, i8 %x
102 ; Test where the conditional is formed in a different way
105 define i32 @sat0_lower_1(i32 %x) #0 {
106 ; CHECK-ARM-LABEL: sat0_lower_1:
107 ; CHECK-ARM: @ %bb.0: @ %entry
108 ; CHECK-ARM-NEXT: bic r0, r0, r0, asr #31
109 ; CHECK-ARM-NEXT: mov pc, lr
111 ; CHECK-T-LABEL: sat0_lower_1:
112 ; CHECK-T: @ %bb.0: @ %entry
113 ; CHECK-T-NEXT: asrs r1, r0, #31
114 ; CHECK-T-NEXT: bics r0, r1
115 ; CHECK-T-NEXT: bx lr
117 ; CHECK-T2-LABEL: sat0_lower_1:
118 ; CHECK-T2: @ %bb.0: @ %entry
119 ; CHECK-T2-NEXT: bic.w r0, r0, r0, asr #31
120 ; CHECK-T2-NEXT: bx lr
122 %cmpGt = icmp sgt i32 %x, 0
123 %saturateLow = select i1 %cmpGt, i32 %x, i32 0
128 ; Check for clipping against -1 that should result in orr
130 ; Base tests with different bit widths
135 define i32 @sat1_base_32bit(i32 %x) #0 {
136 ; CHECK-ARM-LABEL: sat1_base_32bit:
137 ; CHECK-ARM: @ %bb.0: @ %entry
138 ; CHECK-ARM-NEXT: orr r0, r0, r0, asr #31
139 ; CHECK-ARM-NEXT: mov pc, lr
141 ; CHECK-T-LABEL: sat1_base_32bit:
142 ; CHECK-T: @ %bb.0: @ %entry
143 ; CHECK-T-NEXT: asrs r1, r0, #31
144 ; CHECK-T-NEXT: orrs r0, r1
145 ; CHECK-T-NEXT: bx lr
147 ; CHECK-T2-LABEL: sat1_base_32bit:
148 ; CHECK-T2: @ %bb.0: @ %entry
149 ; CHECK-T2-NEXT: orr.w r0, r0, r0, asr #31
150 ; CHECK-T2-NEXT: bx lr
152 %cmpLow = icmp slt i32 %x, -1
153 %saturateLow = select i1 %cmpLow, i32 -1, i32 %x
159 define i16 @sat1_base_16bit(i16 %x) #0 {
160 ; CHECK-ARM-LABEL: sat1_base_16bit:
161 ; CHECK-ARM: @ %bb.0: @ %entry
162 ; CHECK-ARM-NEXT: lsl r1, r0, #16
163 ; CHECK-ARM-NEXT: asr r1, r1, #16
164 ; CHECK-ARM-NEXT: cmn r1, #1
165 ; CHECK-ARM-NEXT: mvnlt r0, #0
166 ; CHECK-ARM-NEXT: mov pc, lr
168 ; CHECK-T-LABEL: sat1_base_16bit:
169 ; CHECK-T: @ %bb.0: @ %entry
170 ; CHECK-T-NEXT: movs r1, #0
171 ; CHECK-T-NEXT: mvns r1, r1
172 ; CHECK-T-NEXT: lsls r2, r0, #16
173 ; CHECK-T-NEXT: asrs r2, r2, #16
174 ; CHECK-T-NEXT: cmp r2, r1
175 ; CHECK-T-NEXT: blt .LBB5_2
176 ; CHECK-T-NEXT: @ %bb.1: @ %entry
177 ; CHECK-T-NEXT: movs r1, r0
178 ; CHECK-T-NEXT: .LBB5_2: @ %entry
179 ; CHECK-T-NEXT: movs r0, r1
180 ; CHECK-T-NEXT: bx lr
182 ; CHECK-T2-LABEL: sat1_base_16bit:
183 ; CHECK-T2: @ %bb.0: @ %entry
184 ; CHECK-T2-NEXT: sxth r1, r0
185 ; CHECK-T2-NEXT: cmp.w r1, #-1
186 ; CHECK-T2-NEXT: it lt
187 ; CHECK-T2-NEXT: movlt.w r0, #-1
188 ; CHECK-T2-NEXT: bx lr
190 %cmpLow = icmp slt i16 %x, -1
191 %saturateLow = select i1 %cmpLow, i16 -1, i16 %x
197 define i8 @sat1_base_8bit(i8 %x) #0 {
198 ; CHECK-ARM-LABEL: sat1_base_8bit:
199 ; CHECK-ARM: @ %bb.0: @ %entry
200 ; CHECK-ARM-NEXT: lsl r1, r0, #24
201 ; CHECK-ARM-NEXT: asr r1, r1, #24
202 ; CHECK-ARM-NEXT: cmn r1, #1
203 ; CHECK-ARM-NEXT: mvnlt r0, #0
204 ; CHECK-ARM-NEXT: mov pc, lr
206 ; CHECK-T-LABEL: sat1_base_8bit:
207 ; CHECK-T: @ %bb.0: @ %entry
208 ; CHECK-T-NEXT: movs r1, #0
209 ; CHECK-T-NEXT: mvns r1, r1
210 ; CHECK-T-NEXT: lsls r2, r0, #24
211 ; CHECK-T-NEXT: asrs r2, r2, #24
212 ; CHECK-T-NEXT: cmp r2, r1
213 ; CHECK-T-NEXT: blt .LBB6_2
214 ; CHECK-T-NEXT: @ %bb.1: @ %entry
215 ; CHECK-T-NEXT: movs r1, r0
216 ; CHECK-T-NEXT: .LBB6_2: @ %entry
217 ; CHECK-T-NEXT: movs r0, r1
218 ; CHECK-T-NEXT: bx lr
220 ; CHECK-T2-LABEL: sat1_base_8bit:
221 ; CHECK-T2: @ %bb.0: @ %entry
222 ; CHECK-T2-NEXT: sxtb r1, r0
223 ; CHECK-T2-NEXT: cmp.w r1, #-1
224 ; CHECK-T2-NEXT: it lt
225 ; CHECK-T2-NEXT: movlt.w r0, #-1
226 ; CHECK-T2-NEXT: bx lr
228 %cmpLow = icmp slt i8 %x, -1
229 %saturateLow = select i1 %cmpLow, i8 -1, i8 %x
233 ; Test where the conditional is formed in a different way
236 define i32 @sat1_lower_1(i32 %x) #0 {
237 ; CHECK-ARM-LABEL: sat1_lower_1:
238 ; CHECK-ARM: @ %bb.0: @ %entry
239 ; CHECK-ARM-NEXT: orr r0, r0, r0, asr #31
240 ; CHECK-ARM-NEXT: mov pc, lr
242 ; CHECK-T-LABEL: sat1_lower_1:
243 ; CHECK-T: @ %bb.0: @ %entry
244 ; CHECK-T-NEXT: asrs r1, r0, #31
245 ; CHECK-T-NEXT: orrs r0, r1
246 ; CHECK-T-NEXT: bx lr
248 ; CHECK-T2-LABEL: sat1_lower_1:
249 ; CHECK-T2: @ %bb.0: @ %entry
250 ; CHECK-T2-NEXT: orr.w r0, r0, r0, asr #31
251 ; CHECK-T2-NEXT: bx lr
253 %cmpGt = icmp sgt i32 %x, -1
254 %saturateLow = select i1 %cmpGt, i32 %x, i32 -1
258 ; The following tests for patterns that should not transform into bitops
259 ; but that are similar enough that could confuse the selector.
261 ; x < 0 ? 0 : y where x and y does not properly match
262 define i32 @no_sat0_incorrect_variable(i32 %x, i32 %y) #0 {
263 ; CHECK-ARM-LABEL: no_sat0_incorrect_variable:
264 ; CHECK-ARM: @ %bb.0: @ %entry
265 ; CHECK-ARM-NEXT: cmp r0, #0
266 ; CHECK-ARM-NEXT: movmi r1, #0
267 ; CHECK-ARM-NEXT: mov r0, r1
268 ; CHECK-ARM-NEXT: mov pc, lr
270 ; CHECK-T-LABEL: no_sat0_incorrect_variable:
271 ; CHECK-T: @ %bb.0: @ %entry
272 ; CHECK-T-NEXT: cmp r0, #0
273 ; CHECK-T-NEXT: bpl .LBB8_2
274 ; CHECK-T-NEXT: @ %bb.1:
275 ; CHECK-T-NEXT: movs r1, #0
276 ; CHECK-T-NEXT: .LBB8_2: @ %entry
277 ; CHECK-T-NEXT: movs r0, r1
278 ; CHECK-T-NEXT: bx lr
280 ; CHECK-T2-LABEL: no_sat0_incorrect_variable:
281 ; CHECK-T2: @ %bb.0: @ %entry
282 ; CHECK-T2-NEXT: cmp r0, #0
283 ; CHECK-T2-NEXT: it mi
284 ; CHECK-T2-NEXT: movmi r1, #0
285 ; CHECK-T2-NEXT: mov r0, r1
286 ; CHECK-T2-NEXT: bx lr
288 %cmpLow = icmp slt i32 %x, 0
289 %saturateLow = select i1 %cmpLow, i32 0, i32 %y
294 define i32 @no_sat0_incorrect_constant(i32 %x) {
295 ; CHECK-ARM-LABEL: no_sat0_incorrect_constant:
296 ; CHECK-ARM: @ %bb.0: @ %entry
297 ; CHECK-ARM-NEXT: cmp r0, #0
298 ; CHECK-ARM-NEXT: mvnmi r0, #0
299 ; CHECK-ARM-NEXT: mov pc, lr
301 ; CHECK-T-LABEL: no_sat0_incorrect_constant:
302 ; CHECK-T: @ %bb.0: @ %entry
303 ; CHECK-T-NEXT: cmp r0, #0
304 ; CHECK-T-NEXT: bpl .LBB9_2
305 ; CHECK-T-NEXT: @ %bb.1:
306 ; CHECK-T-NEXT: movs r0, #0
307 ; CHECK-T-NEXT: mvns r0, r0
308 ; CHECK-T-NEXT: .LBB9_2: @ %entry
309 ; CHECK-T-NEXT: bx lr
311 ; CHECK-T2-LABEL: no_sat0_incorrect_constant:
312 ; CHECK-T2: @ %bb.0: @ %entry
313 ; CHECK-T2-NEXT: cmp r0, #0
314 ; CHECK-T2-NEXT: it mi
315 ; CHECK-T2-NEXT: movmi.w r0, #-1
316 ; CHECK-T2-NEXT: bx lr
318 %cmpLow = icmp slt i32 %x, 0
319 %saturateLow = select i1 %cmpLow, i32 -1, i32 %x