1 ; RUN: llc -mtriple=thumbv8m.main -mcpu=cortex-m33 %s -arm-disable-cgp=false -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
2 ; RUN: llc -mtriple=thumbv7em %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-DSP
3 ; RUN: llc -mtriple=thumbv8 %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -arm-enable-scalar-dsp-imms=true -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-DSP-IMM
5 ; CHECK-COMMON-LABEL: test_ult_254_inc_imm:
6 ; CHECK-DSP: adds r0, #1
7 ; CHECK-DSP-NEXT: uxtb r1, r0
8 ; CHECK-DSP-NEXT: movs r0, #47
9 ; CHECK-DSP-NEXT: cmp r1, #254
10 ; CHECK-DSP-NEXT: it lo
11 ; CHECK-DSP-NEXT: movlo r0, #35
13 ; CHECK-DSP-IMM: movs r1, #1
14 ; CHECK-DSP-IMM-NEXT: uadd8 r1, r0, r1
15 ; CHECK-DSP-IMM-NEXT: movs r0, #47
16 ; CHECK-DSP-IMM-NEXT: cmp r1, #254
17 ; CHECK-DSP-IMM-NEXT: it lo
18 ; CHECK-DSP-IMM-NEXT: movlo r0, #35
19 define i32 @test_ult_254_inc_imm(i8 zeroext %x) {
22 %cmp = icmp ult i8 %add, 254
23 %res = select i1 %cmp, i32 35, i32 47
27 ; CHECK-COMMON-LABEL: test_slt_254_inc_imm
30 define i32 @test_slt_254_inc_imm(i8 signext %x) {
33 %cmp = icmp slt i8 %add, 254
34 %res = select i1 %cmp, i32 35, i32 47
38 ; CHECK-COMMON-LABEL: test_ult_254_inc_var:
39 ; CHECK-NODSP: add r0, r1
40 ; CHECK-NODSP-NEXT: uxtb r1, r0
41 ; CHECK-NODSP-NEXT: movs r0, #47
42 ; CHECK-NODSP-NEXT: cmp r1, #254
43 ; CHECK-NODSP-NEXT: it lo
44 ; CHECK-NODSP-NEXT: movlo r0, #35
46 ; CHECK-DSP: uadd8 r1, r0, r1
47 ; CHECK-DSP-NEXT: movs r0, #47
48 ; CHECK-DSP-NEXT: cmp r1, #254
49 ; CHECK-DSP-NEXT: it lo
50 ; CHECK-DSP-NEXT: movlo r0, #35
51 define i32 @test_ult_254_inc_var(i8 zeroext %x, i8 zeroext %y) {
54 %cmp = icmp ult i8 %add, 254
55 %res = select i1 %cmp, i32 35, i32 47
59 ; CHECK-COMMON-LABEL: test_sle_254_inc_var
63 define i32 @test_sle_254_inc_var(i8 %x, i8 %y) {
66 %cmp = icmp sle i8 %add, 254
67 %res = select i1 %cmp, i32 35, i32 47
71 ; CHECK-COMMON-LABEL: test_ugt_1_dec_imm:
72 ; CHECK-COMMON: subs r1, r0, #1
73 ; CHECK-COMMON-NEXT: movs r0, #47
74 ; CHECK-COMMON-NEXT: cmp r1, #1
75 ; CHECK-COMMON-NEXT: it hi
76 ; CHECK-COMMON-NEXT: movhi r0, #35
77 define i32 @test_ugt_1_dec_imm(i8 zeroext %x) {
80 %cmp = icmp ugt i8 %add, 1
81 %res = select i1 %cmp, i32 35, i32 47
85 ; CHECK-COMMON-LABEL: test_sgt_1_dec_imm
89 define i32 @test_sgt_1_dec_imm(i8 %x) {
92 %cmp = icmp sgt i8 %add, 1
93 %res = select i1 %cmp, i32 35, i32 47
97 ; CHECK-COMMON-LABEL: test_ugt_1_dec_var:
98 ; CHECK-NODSP: subs r0, r0, r1
99 ; CHECK-NODSP-NEXT: uxtb r1, r0
100 ; CHECK-NODSP-NEXT: movs r0, #47
101 ; CHECK-NODSP-NEXT: cmp r1, #1
102 ; CHECK-NODSP-NEXT: it hi
103 ; CHECK-NODSP-NEXT: movhi r0, #35
105 ; CHECK-DSP: usub8 r1, r0, r1
106 ; CHECK-DSP-NEXT: movs r0, #47
107 ; CHECK-DSP-NEXT: cmp r1, #1
108 ; CHECK-DSP-NEXT: it hi
109 ; CHECK-DSP-NEXT: movhi r0, #35
110 define i32 @test_ugt_1_dec_var(i8 zeroext %x, i8 zeroext %y) {
113 %cmp = icmp ugt i8 %sub, 1
114 %res = select i1 %cmp, i32 35, i32 47
118 ; CHECK-COMMON-LABEL: test_sge_1_dec_var
122 define i32 @test_sge_1_dec_var(i8 %x, i8 %y) {
125 %cmp = icmp sge i8 %sub, 1
126 %res = select i1 %cmp, i32 35, i32 47
130 ; CHECK-COMMON-LABEL: dsp_imm1:
131 ; CHECK-DSP: eors r1, r0
132 ; CHECK-DSP-NEXT: and r0, r0, #7
133 ; CHECK-DSP-NEXT: subs r0, r0, r1
134 ; CHECK-DSP-NEXT: adds r0, #1
135 ; CHECK-DSP-NEXT: uxtb r1, r0
136 ; CHECK-DSP-NEXT: movs r0, #47
137 ; CHECK-DSP-NEXT: cmp r1, #254
138 ; CHECK-DSP-NEXT: it lo
139 ; CHECK-DSP-NEXT: movlo r0, #35
141 ; CHECK-DSP-IMM: eors r1, r0
142 ; CHECK-DSP-IMM-NEXT: and r0, r0, #7
143 ; CHECK-DSP-IMM-NEXT: usub8 r0, r0, r1
144 ; CHECK-DSP-IMM-NEXT: movs r1, #1
145 ; CHECK-DSP-IMM-NEXT: uadd8 r1, r0, r1
146 ; CHECK-DSP-IMM-NEXT: movs r0, #47
147 ; CHECK-DSP-IMM-NEXT: cmp r1, #254
148 ; CHECK-DSP-IMM-NEXT: it lo
149 ; CHECK-DSP-IMM-NEXT: movlo r0, #35
150 define i32 @dsp_imm1(i8 zeroext %x, i8 zeroext %y) {
154 %sub = sub i8 %and, %xor
155 %add = add i8 %sub, 1
156 %cmp = icmp ult i8 %add, 254
157 %res = select i1 %cmp, i32 35, i32 47
161 ; CHECK-COMMON-LABEL: dsp_var:
162 ; CHECK-COMMON: eors r1, r0
163 ; CHECK-COMMON: and r2, r0, #7
164 ; CHECK-NODSP: subs r1, r2, r1
165 ; CHECK-NODSP: add.w r0, r1, r0, lsl #1
166 ; CHECK-NODSP: uxtb r1, r0
167 ; CHECK-DSP: usub8 r1, r2, r1
168 ; CHECK-DSP: lsls r0, r0, #1
169 ; CHECK-DSP: uadd8 r1, r1, r0
171 ; CHECK-COMMON: movs r0, #47
172 ; CHECK-COMMON: cmp r1, #254
173 ; CHECK-COMMON: it lo
174 ; CHECK-COMMON: movlo r0, #35
175 define i32 @dsp_var(i8 zeroext %x, i8 zeroext %y) {
178 %sub = sub i8 %and, %xor
179 %mul = shl nuw i8 %x, 1
180 %add = add i8 %sub, %mul
181 %cmp = icmp ult i8 %add, 254
182 %res = select i1 %cmp, i32 35, i32 47
186 ; CHECK-COMMON-LABEL: store_dsp_res
189 define void @store_dsp_res(i8* %in, i8* %out, i8 %compare) {
190 %first = getelementptr inbounds i8, i8* %in, i32 0
191 %second = getelementptr inbounds i8, i8* %in, i32 1
192 %ld0 = load i8, i8* %first
193 %ld1 = load i8, i8* %second
194 %xor = xor i8 %ld0, -1
195 %cmp = icmp ult i8 %compare, %ld1
196 %select = select i1 %cmp, i8 %compare, i8 %xor
197 %sub = sub i8 %ld0, %select
198 store i8 %sub, i8* %out, align 1
202 ; CHECK-COMMON-LABEL: ugt_1_dec_imm:
203 ; CHECK-COMMON: subs r1, r0, #1
204 ; CHECK-COMMON-NEXT: movs r0, #47
205 ; CHECK-COMMON-NEXT: cmp r1, #1
206 ; CHECK-COMMON-NEXT: it hi
207 ; CHECK-COMMON-NEXT: movhi r0, #35
208 define i32 @ugt_1_dec_imm(i8 zeroext %x) {
211 %cmp = icmp ugt i8 %add, 1
212 %res = select i1 %cmp, i32 35, i32 47
216 ; CHECK-COMMON-LABEL: ugt_1_dec_var:
217 ; CHECK-NODSP: subs r0, r0, r1
218 ; CHECK-NODSP-NEXT: uxtb r1, r0
219 ; CHECK-NODSP-NEXT: movs r0, #47
220 ; CHECK-NODSP-NEXT: cmp r1, #1
221 ; CHECK-NODSP-NEXT: it hi
222 ; CHECK-NODSP-NEXT: movhi r0, #35
224 ; CHECK-DSP: usub8 r1, r0, r1
225 ; CHECK-DSP-NEXT: movs r0, #47
226 ; CHECK-DSP-NEXT: cmp r1, #1
227 ; CHECK-DSP-NEXT: it hi
228 ; CHECK-DSP-NEXT: movhi r0, #35
229 define i32 @ugt_1_dec_var(i8 zeroext %x, i8 zeroext %y) {
232 %cmp = icmp ugt i8 %sub, 1
233 %res = select i1 %cmp, i32 35, i32 47
237 ; CHECK-COMMON-LABEL: icmp_eq_minus_one
238 ; CHECK-COMMON: cmp {{r[0-9]+}}, #255
239 define i32 @icmp_eq_minus_one(i8* %ptr) {
240 %load = load i8, i8* %ptr, align 1
241 %conv = zext i8 %load to i32
242 %cmp = icmp eq i8 %load, -1
243 %ret = select i1 %cmp, i32 %conv, i32 -1
247 ; CHECK-COMMON-LABEL: icmp_not
248 ; CHECK-COMMON: movw r2, #65535
249 ; CHECK-COMMON: eors r2, r0
250 ; CHECK-COMMON: movs r0, #32
251 ; CHECK-COMMON: cmp r2, r1
252 define i32 @icmp_not(i16 zeroext %arg0, i16 zeroext %arg1) {
253 %not = xor i16 %arg0, -1
254 %cmp = icmp eq i16 %not, %arg1
255 %res = select i1 %cmp, i32 16, i32 32
259 ; CHECK-COMMON-LABEL: icmp_i1
261 define i32 @icmp_i1(i1* %arg0, i1 zeroext %arg1, i32 %a, i32 %b) {
263 %load = load i1, i1* %arg0
264 %not = xor i1 %load, 1
265 %cmp = icmp eq i1 %arg1, %not
266 %res = select i1 %cmp, i32 %a, i32 %b
270 ; CHECK-COMMON-LABEL: icmp_i7
273 define i32 @icmp_i7(i7* %arg0, i7 zeroext %arg1, i32 %a, i32 %b) {
275 %load = load i7, i7* %arg0
276 %add = add nuw i7 %load, 1
277 %cmp = icmp ult i7 %arg1, %add
278 %res = select i1 %cmp, i32 %a, i32 %b
282 ; CHECK-COMMON-LABEL: icmp_i15
283 ; CHECK-COMMON: movw [[MINUS_ONE:r[0-9]+]], #32767
284 define i32 @icmp_i15(i15 zeroext %arg0, i15 zeroext %arg1) {
285 %xor = xor i15 %arg0, -1
286 %cmp = icmp eq i15 %xor, %arg1
287 %res = select i1 %cmp, i32 21, i32 42
291 ; CHECK-COMMON-LABEL: icmp_minus_imm
292 ; CHECK-NODSP: subs [[SUB:r[0-9]+]],
293 ; CHECK-NODSP: uxtb [[UXT:r[0-9]+]],
294 ; CHECK-NODSP: cmp [[UXT]], #251
296 ; CHECK-DSP: subs [[SUB:r[0-9]+]],
297 ; CHECK-DSP: uxtb [[UXT:r[0-9]+]],
298 ; CHECK-DSP: cmp [[UXT]], #251
300 ; CHECK-DSP-IMM: ldrb [[A:r[0-9]+]],
301 ; CHECK-DSP-IMM: movs [[MINUS_7:r[0-9]+]], #249
302 ; CHECK-DSP-IMM: uadd8 [[RES:r[0-9]+]], [[A]], [[MINUS_7]]
303 ; CHECK-DSP-IMM: cmp [[RES]], #251
304 define i32 @icmp_minus_imm(i8* %a) {
306 %0 = load i8, i8* %a, align 1
307 %add.i = add i8 %0, -7
308 %cmp = icmp ugt i8 %add.i, -5
309 %conv1 = zext i1 %cmp to i32
313 ; CHECK-COMMON-LABEL: mul_with_neg_imm
314 ; CHECK-COMMON-NOT: uxtb
315 ; CHECK-COMMON: and [[BIT0:r[0-9]+]], r0, #1
316 ; CHECK-COMMON: add.w [[MUL32:r[0-9]+]], [[BIT0]], [[BIT0]], lsl #5
317 ; CHECK-COMMON: cmp.w r0, [[MUL32]], lsl #2
318 define void @mul_with_neg_imm(i32, i32* %b) {
320 %1 = trunc i32 %0 to i8
322 %conv.i = mul nuw i8 %2, -124
323 %tobool = icmp eq i8 %conv.i, 0
324 br i1 %tobool, label %if.end, label %if.then
327 store i32 0, i32* %b, align 4