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) {
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: tst.w r1, #16843009
203 ; V7M-NEXT: movne r0, #0
205 ; V7M-NEXT: .LBB1_3: @ %D
206 ; V7M-NEXT: movs r0, #1
211 ; V7A-NEXT: movw r2, #257
212 ; V7A-NEXT: tst r0, #1
213 ; V7A-NEXT: movt r2, #257
214 ; V7A-NEXT: and r1, r1, r2
215 ; V7A-NEXT: beq .LBB1_3
216 ; V7A-NEXT: @ %bb.1: @ %A
217 ; V7A-NEXT: cmp r1, #0
218 ; V7A-NEXT: moveq r0, #0
220 ; V7A-NEXT: .LBB1_2: @ %D
221 ; V7A-NEXT: mov r0, #1
223 ; V7A-NEXT: .LBB1_3: @ %B
224 ; V7A-NEXT: mov r0, #0
225 ; V7A-NEXT: cmp r1, #0
226 ; V7A-NEXT: moveq r0, #1
230 ; V7A-T: @ %bb.0: @ %E
231 ; V7A-T-NEXT: lsls r0, r0, #31
232 ; V7A-T-NEXT: beq .LBB1_2
233 ; V7A-T-NEXT: @ %bb.1: @ %A
234 ; V7A-T-NEXT: tst.w r1, #16843009
236 ; V7A-T-NEXT: moveq r0, #0
237 ; V7A-T-NEXT: bxeq lr
238 ; V7A-T-NEXT: b .LBB1_3
239 ; V7A-T-NEXT: .LBB1_2: @ %B
240 ; V7A-T-NEXT: tst.w r1, #16843009
242 ; V7A-T-NEXT: movne r0, #0
243 ; V7A-T-NEXT: bxne lr
244 ; V7A-T-NEXT: .LBB1_3: @ %D
245 ; V7A-T-NEXT: movs r0, #1
250 ; V6M-NEXT: ldr r2, .LCPI1_0
251 ; V6M-NEXT: ands r2, r1
252 ; V6M-NEXT: lsls r0, r0, #31
253 ; V6M-NEXT: beq .LBB1_3
254 ; V6M-NEXT: @ %bb.1: @ %A
255 ; V6M-NEXT: cmp r2, #0
256 ; V6M-NEXT: bne .LBB1_5
258 ; V6M-NEXT: movs r0, #0
260 ; V6M-NEXT: .LBB1_3: @ %B
261 ; V6M-NEXT: cmp r2, #0
262 ; V6M-NEXT: beq .LBB1_5
264 ; V6M-NEXT: movs r0, #0
266 ; V6M-NEXT: .LBB1_5: @ %D
267 ; V6M-NEXT: movs r0, #1
269 ; V6M-NEXT: .p2align 2
271 ; V6M-NEXT: .LCPI1_0:
272 ; V6M-NEXT: .long 16843009 @ 0x1010101
274 %a = and i32 %v, 16843009
275 br i1 %c0, label %A, label %B
278 %c1 = icmp eq i32 %a, 0
279 br i1 %c1, label %C, label %D
282 %c2 = icmp eq i32 %a, 0
283 br i1 %c2, label %D, label %C
292 %x = phi i32 [0, %C], [1, %D]
296 ; Test with a mask that can be encoded both with T32 and A32 instruction sets.
297 define i32 @f1(i1 %c0, i32 %v) {
300 ; V7M-NEXT: lsls r0, r0, #31
301 ; V7M-NEXT: beq .LBB2_2
302 ; V7M-NEXT: @ %bb.1: @ %A
303 ; V7M-NEXT: tst.w r1, #100663296
305 ; V7M-NEXT: moveq r0, #0
307 ; V7M-NEXT: b .LBB2_3
308 ; V7M-NEXT: .LBB2_2: @ %B
309 ; V7M-NEXT: tst.w r1, #100663296
311 ; V7M-NEXT: movne r0, #0
313 ; V7M-NEXT: .LBB2_3: @ %D
314 ; V7M-NEXT: movs r0, #1
319 ; V7A-NEXT: tst r0, #1
320 ; V7A-NEXT: beq .LBB2_3
321 ; V7A-NEXT: @ %bb.1: @ %A
322 ; V7A-NEXT: tst r1, #100663296
323 ; V7A-NEXT: moveq r0, #0
325 ; V7A-NEXT: .LBB2_2: @ %D
326 ; V7A-NEXT: mov r0, #1
328 ; V7A-NEXT: .LBB2_3: @ %B
329 ; V7A-NEXT: mov r0, #0
330 ; V7A-NEXT: tst r1, #100663296
331 ; V7A-NEXT: moveq r0, #1
335 ; V7A-T: @ %bb.0: @ %E
336 ; V7A-T-NEXT: lsls r0, r0, #31
337 ; V7A-T-NEXT: beq .LBB2_2
338 ; V7A-T-NEXT: @ %bb.1: @ %A
339 ; V7A-T-NEXT: tst.w r1, #100663296
341 ; V7A-T-NEXT: moveq r0, #0
342 ; V7A-T-NEXT: bxeq lr
343 ; V7A-T-NEXT: b .LBB2_3
344 ; V7A-T-NEXT: .LBB2_2: @ %B
345 ; V7A-T-NEXT: tst.w r1, #100663296
347 ; V7A-T-NEXT: movne r0, #0
348 ; V7A-T-NEXT: bxne lr
349 ; V7A-T-NEXT: .LBB2_3: @ %D
350 ; V7A-T-NEXT: movs r0, #1
355 ; V6M-NEXT: movs r2, #3
356 ; V6M-NEXT: lsls r2, r2, #25
357 ; V6M-NEXT: ands r2, r1
358 ; V6M-NEXT: lsls r0, r0, #31
359 ; V6M-NEXT: beq .LBB2_3
360 ; V6M-NEXT: @ %bb.1: @ %A
361 ; V6M-NEXT: cmp r2, #0
362 ; V6M-NEXT: bne .LBB2_5
364 ; V6M-NEXT: movs r0, #0
366 ; V6M-NEXT: .LBB2_3: @ %B
367 ; V6M-NEXT: cmp r2, #0
368 ; V6M-NEXT: beq .LBB2_5
370 ; V6M-NEXT: movs r0, #0
372 ; V6M-NEXT: .LBB2_5: @ %D
373 ; V6M-NEXT: movs r0, #1
376 %a = and i32 %v, 100663296
377 br i1 %c0, label %A, label %B
380 %c1 = icmp eq i32 %a, 0
381 br i1 %c1, label %C, label %D
384 %c2 = icmp eq i32 %a, 0
385 br i1 %c2, label %D, label %C
394 %x = phi i32 [0, %C], [1, %D]