1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=thumbv7m-eabi %s -o - | FileCheck %s --check-prefix V7M
3 ; RUN: llc -mtriple=armv7a-eabi %s -o - | FileCheck %s --check-prefix V7A
4 ; RUN: llc -mtriple=thumbv7a-eabi %s -o - | FileCheck %s --check-prefix V7A-T
5 ; RUN: llc -mtriple=armv6m-eabi %s -o - | FileCheck %s --check-prefix V6M
7 target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
9 ; Test sink of `and` instructions to fold in to `tst`, `lsls`, do cmov-bfi combine, etc.
10 define void @f(i32 %v, ptr noalias %outp) {
12 ; V7M: @ %bb.0: @ %entry
13 ; V7M-NEXT: movs r2, #0
14 ; V7M-NEXT: str r2, [r1]
15 ; V7M-NEXT: lsls r2, r0, #31
16 ; V7M-NEXT: bne .LBB0_3
17 ; V7M-NEXT: @ %bb.1: @ %if.then
18 ; V7M-NEXT: tst.w r0, #14
19 ; V7M-NEXT: beq .LBB0_6
21 ; V7M-NEXT: lsls r2, r0, #30
22 ; V7M-NEXT: mov.w r3, #33024
23 ; V7M-NEXT: and.w r2, r3, r2, asr #31
24 ; V7M-NEXT: lsrs r0, r0, #2
25 ; V7M-NEXT: bfi r2, r0, #7, #1
26 ; V7M-NEXT: bfi r2, r0, #14, #1
28 ; V7M-NEXT: .LBB0_3: @ %if.else
29 ; V7M-NEXT: tst.w r0, #14
33 ; V7M-NEXT: lsls r2, r0, #30
34 ; V7M-NEXT: mov.w r3, #8256
35 ; V7M-NEXT: and.w r2, r3, r2, asr #31
36 ; V7M-NEXT: lsrs r0, r0, #2
37 ; V7M-NEXT: bfi r2, r0, #5, #1
38 ; V7M-NEXT: bfi r2, r0, #12, #1
39 ; V7M-NEXT: .LBB0_5: @ %if.end
40 ; V7M-NEXT: str r2, [r1]
41 ; V7M-NEXT: .LBB0_6: @ %exit
45 ; V7A: @ %bb.0: @ %entry
46 ; V7A-NEXT: mov r2, #0
47 ; V7A-NEXT: tst r0, #1
48 ; V7A-NEXT: str r2, [r1]
49 ; V7A-NEXT: bne .LBB0_3
50 ; V7A-NEXT: @ %bb.1: @ %if.then
51 ; V7A-NEXT: tst r0, #14
52 ; V7A-NEXT: beq .LBB0_6
54 ; V7A-NEXT: lsl r2, r0, #30
55 ; V7A-NEXT: mov r3, #33024
56 ; V7A-NEXT: and r2, r3, r2, asr #31
57 ; V7A-NEXT: lsr r0, r0, #2
58 ; V7A-NEXT: bfi r2, r0, #7, #1
59 ; V7A-NEXT: bfi r2, r0, #14, #1
61 ; V7A-NEXT: .LBB0_3: @ %if.else
62 ; V7A-NEXT: tst r0, #14
65 ; V7A-NEXT: lsl r2, r0, #30
66 ; V7A-NEXT: mov r3, #8256
67 ; V7A-NEXT: and r2, r3, r2, asr #31
68 ; V7A-NEXT: lsr r0, r0, #2
69 ; V7A-NEXT: bfi r2, r0, #5, #1
70 ; V7A-NEXT: bfi r2, r0, #12, #1
71 ; V7A-NEXT: .LBB0_5: @ %if.end
72 ; V7A-NEXT: str r2, [r1]
73 ; V7A-NEXT: .LBB0_6: @ %exit
77 ; V7A-T: @ %bb.0: @ %entry
78 ; V7A-T-NEXT: movs r2, #0
79 ; V7A-T-NEXT: str r2, [r1]
80 ; V7A-T-NEXT: lsls r2, r0, #31
81 ; V7A-T-NEXT: bne .LBB0_3
82 ; V7A-T-NEXT: @ %bb.1: @ %if.then
83 ; V7A-T-NEXT: tst.w r0, #14
84 ; V7A-T-NEXT: beq .LBB0_6
85 ; V7A-T-NEXT: @ %bb.2:
86 ; V7A-T-NEXT: lsls r2, r0, #30
87 ; V7A-T-NEXT: mov.w r3, #33024
88 ; V7A-T-NEXT: and.w r2, r3, r2, asr #31
89 ; V7A-T-NEXT: lsrs r0, r0, #2
90 ; V7A-T-NEXT: bfi r2, r0, #7, #1
91 ; V7A-T-NEXT: bfi r2, r0, #14, #1
92 ; V7A-T-NEXT: b .LBB0_5
93 ; V7A-T-NEXT: .LBB0_3: @ %if.else
94 ; V7A-T-NEXT: tst.w r0, #14
97 ; V7A-T-NEXT: .LBB0_4:
98 ; V7A-T-NEXT: lsls r2, r0, #30
99 ; V7A-T-NEXT: mov.w r3, #8256
100 ; V7A-T-NEXT: and.w r2, r3, r2, asr #31
101 ; V7A-T-NEXT: lsrs r0, r0, #2
102 ; V7A-T-NEXT: bfi r2, r0, #5, #1
103 ; V7A-T-NEXT: bfi r2, r0, #12, #1
104 ; V7A-T-NEXT: .LBB0_5: @ %if.end
105 ; V7A-T-NEXT: str r2, [r1]
106 ; V7A-T-NEXT: .LBB0_6: @ %exit
110 ; V6M: @ %bb.0: @ %entry
111 ; V6M-NEXT: .save {r4, lr}
112 ; V6M-NEXT: push {r4, lr}
113 ; V6M-NEXT: movs r2, #0
114 ; V6M-NEXT: str r2, [r1]
115 ; V6M-NEXT: movs r3, #14
116 ; V6M-NEXT: ands r3, r0
117 ; V6M-NEXT: movs r4, #4
118 ; V6M-NEXT: ands r4, r0
119 ; V6M-NEXT: movs r2, #2
120 ; V6M-NEXT: ands r2, r0
121 ; V6M-NEXT: lsls r0, r0, #31
122 ; V6M-NEXT: bne .LBB0_5
123 ; V6M-NEXT: @ %bb.1: @ %if.then
124 ; V6M-NEXT: movs r0, #129
125 ; V6M-NEXT: cmp r2, #0
126 ; V6M-NEXT: beq .LBB0_3
128 ; V6M-NEXT: lsls r2, r0, #8
129 ; V6M-NEXT: .LBB0_3: @ %if.then
130 ; V6M-NEXT: cmp r4, #0
131 ; V6M-NEXT: beq .LBB0_10
132 ; V6M-NEXT: @ %bb.4: @ %if.then
133 ; V6M-NEXT: lsls r0, r0, #7
134 ; V6M-NEXT: b .LBB0_9
135 ; V6M-NEXT: .LBB0_5: @ %if.else
136 ; V6M-NEXT: movs r0, #129
137 ; V6M-NEXT: cmp r2, #0
138 ; V6M-NEXT: beq .LBB0_7
140 ; V6M-NEXT: lsls r2, r0, #6
141 ; V6M-NEXT: .LBB0_7: @ %if.else
142 ; V6M-NEXT: cmp r4, #0
143 ; V6M-NEXT: beq .LBB0_10
144 ; V6M-NEXT: @ %bb.8: @ %if.else
145 ; V6M-NEXT: lsls r0, r0, #5
146 ; V6M-NEXT: .LBB0_9: @ %if.else
147 ; V6M-NEXT: adds r2, r2, r0
148 ; V6M-NEXT: .LBB0_10: @ %if.else
149 ; V6M-NEXT: cmp r3, #0
150 ; V6M-NEXT: beq .LBB0_12
151 ; V6M-NEXT: @ %bb.11: @ %if.end
152 ; V6M-NEXT: str r2, [r1]
153 ; V6M-NEXT: .LBB0_12: @ %exit
154 ; V6M-NEXT: pop {r4, pc}
156 store i32 0, ptr %outp, align 4
158 %cmp = icmp eq i32 %and, 0
159 %and1 = and i32 %v, 2
160 %tobool.not = icmp eq i32 %and1, 0
161 %and2 = and i32 %v, 4
162 %tobool1.not = icmp eq i32 %and2, 0
163 %and3 = and i32 %v, 14
164 %tobool2.not = icmp eq i32 %and3, 0
165 br i1 %cmp, label %if.then, label %if.else
168 %select = select i1 %tobool.not, i32 0, i32 33024
169 %or = or i32 %select, 16512
170 %spec.select = select i1 %tobool1.not, i32 %select, i32 %or
171 br i1 %tobool2.not, label %exit, label %if.end
174 %select1 = select i1 %tobool.not, i32 0, i32 8256
175 %or1 = or i32 %select1, 4128
176 %spec.select1 = select i1 %tobool1.not, i32 %select1, i32 %or1
177 br i1 %tobool2.not, label %exit, label %if.end
180 %spec.select.sink = phi i32 [ %spec.select, %if.then ], [ %spec.select1, %if.else ]
181 store i32 %spec.select.sink, ptr %outp, align 4
188 ; Test with a mask that can be encoded with T32 instruction set, but not with A32.
189 define i32 @f0(i1 %c0, i32 %v, ptr %p) {
192 ; V7M-NEXT: lsls r0, r0, #31
193 ; V7M-NEXT: beq .LBB1_2
194 ; V7M-NEXT: @ %bb.1: @ %A
195 ; V7M-NEXT: tst.w r1, #16843009
197 ; V7M-NEXT: moveq r0, #0
199 ; V7M-NEXT: b .LBB1_3
200 ; V7M-NEXT: .LBB1_2: @ %B
201 ; V7M-NEXT: movs r0, #1
202 ; V7M-NEXT: tst.w r1, #16843009
203 ; V7M-NEXT: str r0, [r2]
205 ; V7M-NEXT: movne r0, #0
207 ; V7M-NEXT: .LBB1_3: @ %D
208 ; V7M-NEXT: movs r0, #1
213 ; V7A-NEXT: movw r3, #257
214 ; V7A-NEXT: tst r0, #1
215 ; V7A-NEXT: movt r3, #257
216 ; V7A-NEXT: and r1, r1, r3
217 ; V7A-NEXT: beq .LBB1_3
218 ; V7A-NEXT: @ %bb.1: @ %A
219 ; V7A-NEXT: cmp r1, #0
220 ; V7A-NEXT: moveq r0, #0
222 ; V7A-NEXT: .LBB1_2: @ %D
223 ; V7A-NEXT: mov r0, #1
225 ; V7A-NEXT: .LBB1_3: @ %B
226 ; V7A-NEXT: mov r0, #1
227 ; V7A-NEXT: cmp r1, #0
228 ; V7A-NEXT: str r0, [r2]
229 ; V7A-NEXT: mov r0, #0
230 ; V7A-NEXT: moveq r0, #1
234 ; V7A-T: @ %bb.0: @ %E
235 ; V7A-T-NEXT: lsls r0, r0, #31
236 ; V7A-T-NEXT: beq .LBB1_2
237 ; V7A-T-NEXT: @ %bb.1: @ %A
238 ; V7A-T-NEXT: tst.w r1, #16843009
240 ; V7A-T-NEXT: moveq r0, #0
241 ; V7A-T-NEXT: bxeq lr
242 ; V7A-T-NEXT: b .LBB1_3
243 ; V7A-T-NEXT: .LBB1_2: @ %B
244 ; V7A-T-NEXT: movs r0, #1
245 ; V7A-T-NEXT: tst.w r1, #16843009
246 ; V7A-T-NEXT: str r0, [r2]
248 ; V7A-T-NEXT: movne r0, #0
249 ; V7A-T-NEXT: bxne lr
250 ; V7A-T-NEXT: .LBB1_3: @ %D
251 ; V7A-T-NEXT: movs r0, #1
256 ; V6M-NEXT: ldr r3, .LCPI1_0
257 ; V6M-NEXT: ands r3, r1
258 ; V6M-NEXT: lsls r0, r0, #31
259 ; V6M-NEXT: beq .LBB1_3
260 ; V6M-NEXT: @ %bb.1: @ %A
261 ; V6M-NEXT: cmp r3, #0
262 ; V6M-NEXT: bne .LBB1_5
264 ; V6M-NEXT: movs r0, #0
266 ; V6M-NEXT: .LBB1_3: @ %B
267 ; V6M-NEXT: movs r0, #1
268 ; V6M-NEXT: str r0, [r2]
269 ; V6M-NEXT: cmp r3, #0
270 ; V6M-NEXT: beq .LBB1_5
272 ; V6M-NEXT: movs r0, #0
274 ; V6M-NEXT: .LBB1_5: @ %D
275 ; V6M-NEXT: movs r0, #1
277 ; V6M-NEXT: .p2align 2
279 ; V6M-NEXT: .LCPI1_0:
280 ; V6M-NEXT: .long 16843009 @ 0x1010101
282 %a = and i32 %v, 16843009
283 br i1 %c0, label %A, label %B
286 %c1 = icmp eq i32 %a, 0
287 br i1 %c1, label %C, label %D
290 %c2 = icmp eq i32 %a, 0
291 store i32 1, ptr %p, align 4
292 br i1 %c2, label %D, label %C
301 %x = phi i32 [0, %C], [1, %D]
305 ; Test with a mask that can be encoded both with T32 and A32 instruction sets.
306 define i32 @f1(i1 %c0, i32 %v, ptr %p) {
309 ; V7M-NEXT: lsls r0, r0, #31
310 ; V7M-NEXT: beq .LBB2_2
311 ; V7M-NEXT: @ %bb.1: @ %A
312 ; V7M-NEXT: tst.w r1, #100663296
314 ; V7M-NEXT: moveq r0, #0
316 ; V7M-NEXT: b .LBB2_3
317 ; V7M-NEXT: .LBB2_2: @ %B
318 ; V7M-NEXT: movs r0, #1
319 ; V7M-NEXT: tst.w r1, #100663296
320 ; V7M-NEXT: str r0, [r2]
322 ; V7M-NEXT: movne r0, #0
324 ; V7M-NEXT: .LBB2_3: @ %D
325 ; V7M-NEXT: movs r0, #1
330 ; V7A-NEXT: tst r0, #1
331 ; V7A-NEXT: beq .LBB2_3
332 ; V7A-NEXT: @ %bb.1: @ %A
333 ; V7A-NEXT: tst r1, #100663296
334 ; V7A-NEXT: moveq r0, #0
336 ; V7A-NEXT: .LBB2_2: @ %D
337 ; V7A-NEXT: mov r0, #1
339 ; V7A-NEXT: .LBB2_3: @ %B
340 ; V7A-NEXT: mov r0, #1
341 ; V7A-NEXT: tst r1, #100663296
342 ; V7A-NEXT: str r0, [r2]
343 ; V7A-NEXT: mov r0, #0
344 ; V7A-NEXT: moveq r0, #1
348 ; V7A-T: @ %bb.0: @ %E
349 ; V7A-T-NEXT: lsls r0, r0, #31
350 ; V7A-T-NEXT: beq .LBB2_2
351 ; V7A-T-NEXT: @ %bb.1: @ %A
352 ; V7A-T-NEXT: tst.w r1, #100663296
354 ; V7A-T-NEXT: moveq r0, #0
355 ; V7A-T-NEXT: bxeq lr
356 ; V7A-T-NEXT: b .LBB2_3
357 ; V7A-T-NEXT: .LBB2_2: @ %B
358 ; V7A-T-NEXT: movs r0, #1
359 ; V7A-T-NEXT: tst.w r1, #100663296
360 ; V7A-T-NEXT: str r0, [r2]
362 ; V7A-T-NEXT: movne r0, #0
363 ; V7A-T-NEXT: bxne lr
364 ; V7A-T-NEXT: .LBB2_3: @ %D
365 ; V7A-T-NEXT: movs r0, #1
370 ; V6M-NEXT: movs r3, #3
371 ; V6M-NEXT: lsls r3, r3, #25
372 ; V6M-NEXT: ands r3, r1
373 ; V6M-NEXT: lsls r0, r0, #31
374 ; V6M-NEXT: beq .LBB2_3
375 ; V6M-NEXT: @ %bb.1: @ %A
376 ; V6M-NEXT: cmp r3, #0
377 ; V6M-NEXT: bne .LBB2_5
379 ; V6M-NEXT: movs r0, #0
381 ; V6M-NEXT: .LBB2_3: @ %B
382 ; V6M-NEXT: movs r0, #1
383 ; V6M-NEXT: str r0, [r2]
384 ; V6M-NEXT: cmp r3, #0
385 ; V6M-NEXT: beq .LBB2_5
387 ; V6M-NEXT: movs r0, #0
389 ; V6M-NEXT: .LBB2_5: @ %D
390 ; V6M-NEXT: movs r0, #1
393 %a = and i32 %v, 100663296
394 br i1 %c0, label %A, label %B
397 %c1 = icmp eq i32 %a, 0
398 br i1 %c1, label %C, label %D
401 %c2 = icmp eq i32 %a, 0
402 store i32 1, ptr %p, align 4
403 br i1 %c2, label %D, label %C
412 %x = phi i32 [0, %C], [1, %D]