1 ; RUN: llc < %s -march=arm64 | FileCheck %s
2 %struct.X = type { i8, i8, [2 x i8] }
3 %struct.Y = type { i32, i8 }
4 %struct.Z = type { i8, i8, [2 x i8], i16 }
5 %struct.A = type { i64, i8 }
7 define void @foo(%struct.X* nocapture %x, %struct.Y* nocapture %y) nounwind optsize ssp {
13 %tmp = bitcast %struct.X* %x to i32*
14 %tmp1 = load i32* %tmp, align 4
15 %b = getelementptr inbounds %struct.Y* %y, i64 0, i32 1
16 %bf.clear = lshr i32 %tmp1, 3
17 %bf.clear.lobit = and i32 %bf.clear, 1
18 %frombool = trunc i32 %bf.clear.lobit to i8
19 store i8 %frombool, i8* %b, align 1
23 define i32 @baz(i64 %cav1.coerce) nounwind {
25 ; CHECK: sbfm w0, w0, #0, #3
26 %tmp = trunc i64 %cav1.coerce to i32
27 %tmp1 = shl i32 %tmp, 28
28 %bf.val.sext = ashr exact i32 %tmp1, 28
32 define i32 @bar(i64 %cav1.coerce) nounwind {
34 ; CHECK: sbfm w0, w0, #4, #9
35 %tmp = trunc i64 %cav1.coerce to i32
36 %cav1.sroa.0.1.insert = shl i32 %tmp, 22
37 %tmp1 = ashr i32 %cav1.sroa.0.1.insert, 26
41 define void @fct1(%struct.Z* nocapture %x, %struct.A* nocapture %y) nounwind optsize ssp {
47 %tmp = bitcast %struct.Z* %x to i64*
48 %tmp1 = load i64* %tmp, align 4
49 %b = getelementptr inbounds %struct.A* %y, i64 0, i32 0
50 %bf.clear = lshr i64 %tmp1, 3
51 %bf.clear.lobit = and i64 %bf.clear, 1
52 store i64 %bf.clear.lobit, i64* %b, align 8
56 define i64 @fct2(i64 %cav1.coerce) nounwind {
58 ; CHECK: sbfm x0, x0, #0, #35
59 %tmp = shl i64 %cav1.coerce, 28
60 %bf.val.sext = ashr exact i64 %tmp, 28
64 define i64 @fct3(i64 %cav1.coerce) nounwind {
66 ; CHECK: sbfm x0, x0, #4, #41
67 %cav1.sroa.0.1.insert = shl i64 %cav1.coerce, 22
68 %tmp1 = ashr i64 %cav1.sroa.0.1.insert, 26
72 define void @fct4(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
75 ; CHECK: ldr [[REG1:x[0-9]+]],
76 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #39
77 ; CHECK-NEXT: str [[REG1]],
79 %0 = load i64* %y, align 8
80 %and = and i64 %0, -16777216
81 %shr = lshr i64 %x, 16
82 %and1 = and i64 %shr, 16777215
83 %or = or i64 %and, %and1
84 store i64 %or, i64* %y, align 8
88 define void @fct5(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
91 ; CHECK: ldr [[REG1:w[0-9]+]],
92 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #18
93 ; CHECK-NEXT: str [[REG1]],
95 %0 = load i32* %y, align 8
97 %shr = lshr i32 %x, 16
98 %and1 = and i32 %shr, 7
99 %or = or i32 %and, %and1
100 store i32 %or, i32* %y, align 8
104 ; Check if we can still catch bfm instruction when we drop some low bits
105 define void @fct6(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
108 ; CHECK: ldr [[REG1:w[0-9]+]],
109 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #18
110 ; lsr is an alias of ubfm
111 ; CHECK-NEXT: lsr [[REG2:w[0-9]+]], [[REG1]], #2
112 ; CHECK-NEXT: str [[REG2]],
114 %0 = load i32* %y, align 8
115 %and = and i32 %0, -8
116 %shr = lshr i32 %x, 16
117 %and1 = and i32 %shr, 7
118 %or = or i32 %and, %and1
119 %shr1 = lshr i32 %or, 2
120 store i32 %shr1, i32* %y, align 8
125 ; Check if we can still catch bfm instruction when we drop some high bits
126 define void @fct7(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
129 ; CHECK: ldr [[REG1:w[0-9]+]],
130 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #18
131 ; lsl is an alias of ubfm
132 ; CHECK-NEXT: lsl [[REG2:w[0-9]+]], [[REG1]], #2
133 ; CHECK-NEXT: str [[REG2]],
135 %0 = load i32* %y, align 8
136 %and = and i32 %0, -8
137 %shr = lshr i32 %x, 16
138 %and1 = and i32 %shr, 7
139 %or = or i32 %and, %and1
140 %shl = shl i32 %or, 2
141 store i32 %shl, i32* %y, align 8
146 ; Check if we can still catch bfm instruction when we drop some low bits
148 define void @fct8(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
151 ; CHECK: ldr [[REG1:x[0-9]+]],
152 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #18
153 ; lsr is an alias of ubfm
154 ; CHECK-NEXT: lsr [[REG2:x[0-9]+]], [[REG1]], #2
155 ; CHECK-NEXT: str [[REG2]],
157 %0 = load i64* %y, align 8
158 %and = and i64 %0, -8
159 %shr = lshr i64 %x, 16
160 %and1 = and i64 %shr, 7
161 %or = or i64 %and, %and1
162 %shr1 = lshr i64 %or, 2
163 store i64 %shr1, i64* %y, align 8
168 ; Check if we can still catch bfm instruction when we drop some high bits
170 define void @fct9(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
173 ; CHECK: ldr [[REG1:x[0-9]+]],
174 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #18
175 ; lsr is an alias of ubfm
176 ; CHECK-NEXT: lsl [[REG2:x[0-9]+]], [[REG1]], #2
177 ; CHECK-NEXT: str [[REG2]],
179 %0 = load i64* %y, align 8
180 %and = and i64 %0, -8
181 %shr = lshr i64 %x, 16
182 %and1 = and i64 %shr, 7
183 %or = or i64 %and, %and1
184 %shl = shl i64 %or, 2
185 store i64 %shl, i64* %y, align 8
189 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
191 define void @fct10(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
193 ; CHECK-LABEL: fct10:
194 ; CHECK: ldr [[REG1:w[0-9]+]],
195 ; CHECK-NEXT: bfm [[REG1]], w1, #0, #2
196 ; lsl is an alias of ubfm
197 ; CHECK-NEXT: lsl [[REG2:w[0-9]+]], [[REG1]], #2
198 ; CHECK-NEXT: str [[REG2]],
200 %0 = load i32* %y, align 8
201 %and = and i32 %0, -8
202 %and1 = and i32 %x, 7
203 %or = or i32 %and, %and1
204 %shl = shl i32 %or, 2
205 store i32 %shl, i32* %y, align 8
209 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
211 define void @fct11(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
213 ; CHECK-LABEL: fct11:
214 ; CHECK: ldr [[REG1:x[0-9]+]],
215 ; CHECK-NEXT: bfm [[REG1]], x1, #0, #2
216 ; lsl is an alias of ubfm
217 ; CHECK-NEXT: lsl [[REG2:x[0-9]+]], [[REG1]], #2
218 ; CHECK-NEXT: str [[REG2]],
220 %0 = load i64* %y, align 8
221 %and = and i64 %0, -8
222 %and1 = and i64 %x, 7
223 %or = or i64 %and, %and1
224 %shl = shl i64 %or, 2
225 store i64 %shl, i64* %y, align 8
229 define zeroext i1 @fct12bis(i32 %tmp2) unnamed_addr nounwind ssp align 2 {
230 ; CHECK-LABEL: fct12bis:
232 ; CHECK: ubfm w0, w0, #11, #11
233 %and.i.i = and i32 %tmp2, 2048
234 %tobool.i.i = icmp ne i32 %and.i.i, 0
238 ; Check if we can still catch bfm instruction when we drop some high bits
240 define void @fct12(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
242 ; CHECK-LABEL: fct12:
243 ; CHECK: ldr [[REG1:w[0-9]+]],
244 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #18
245 ; lsr is an alias of ubfm
246 ; CHECK-NEXT: ubfm [[REG2:w[0-9]+]], [[REG1]], #2, #29
247 ; CHECK-NEXT: str [[REG2]],
249 %0 = load i32* %y, align 8
250 %and = and i32 %0, -8
251 %shr = lshr i32 %x, 16
252 %and1 = and i32 %shr, 7
253 %or = or i32 %and, %and1
254 %shl = shl i32 %or, 2
255 %shr2 = lshr i32 %shl, 4
256 store i32 %shr2, i32* %y, align 8
260 ; Check if we can still catch bfm instruction when we drop some high bits
263 define void @fct13(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
265 ; CHECK-LABEL: fct13:
266 ; CHECK: ldr [[REG1:x[0-9]+]],
267 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #18
268 ; lsr is an alias of ubfm
269 ; CHECK-NEXT: ubfm [[REG2:x[0-9]+]], [[REG1]], #2, #61
270 ; CHECK-NEXT: str [[REG2]],
272 %0 = load i64* %y, align 8
273 %and = and i64 %0, -8
274 %shr = lshr i64 %x, 16
275 %and1 = and i64 %shr, 7
276 %or = or i64 %and, %and1
277 %shl = shl i64 %or, 2
278 %shr2 = lshr i64 %shl, 4
279 store i64 %shr2, i64* %y, align 8
284 ; Check if we can still catch bfm instruction when we drop some high bits
286 define void @fct14(i32* nocapture %y, i32 %x, i32 %x1) nounwind optsize inlinehint ssp {
288 ; CHECK-LABEL: fct14:
289 ; CHECK: ldr [[REG1:w[0-9]+]],
290 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #23
291 ; lsr is an alias of ubfm
292 ; CHECK-NEXT: lsr [[REG2:w[0-9]+]], [[REG1]], #4
293 ; CHECK-NEXT: bfm [[REG2]], w2, #5, #7
294 ; lsl is an alias of ubfm
295 ; CHECK-NEXT: lsl [[REG3:w[0-9]+]], [[REG2]], #2
296 ; CHECK-NEXT: str [[REG3]],
298 %0 = load i32* %y, align 8
299 %and = and i32 %0, -256
300 %shr = lshr i32 %x, 16
301 %and1 = and i32 %shr, 255
302 %or = or i32 %and, %and1
303 %shl = lshr i32 %or, 4
304 %and2 = and i32 %shl, -8
305 %shr1 = lshr i32 %x1, 5
306 %and3 = and i32 %shr1, 7
307 %or1 = or i32 %and2, %and3
308 %shl1 = shl i32 %or1, 2
309 store i32 %shl1, i32* %y, align 8
313 ; Check if we can still catch bfm instruction when we drop some high bits
316 define void @fct15(i64* nocapture %y, i64 %x, i64 %x1) nounwind optsize inlinehint ssp {
318 ; CHECK-LABEL: fct15:
319 ; CHECK: ldr [[REG1:x[0-9]+]],
320 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #23
321 ; lsr is an alias of ubfm
322 ; CHECK-NEXT: lsr [[REG2:x[0-9]+]], [[REG1]], #4
323 ; CHECK-NEXT: bfm [[REG2]], x2, #5, #7
324 ; lsl is an alias of ubfm
325 ; CHECK-NEXT: lsl [[REG3:x[0-9]+]], [[REG2]], #2
326 ; CHECK-NEXT: str [[REG3]],
328 %0 = load i64* %y, align 8
329 %and = and i64 %0, -256
330 %shr = lshr i64 %x, 16
331 %and1 = and i64 %shr, 255
332 %or = or i64 %and, %and1
333 %shl = lshr i64 %or, 4
334 %and2 = and i64 %shl, -8
335 %shr1 = lshr i64 %x1, 5
336 %and3 = and i64 %shr1, 7
337 %or1 = or i64 %and2, %and3
338 %shl1 = shl i64 %or1, 2
339 store i64 %shl1, i64* %y, align 8
343 ; Check if we can still catch bfm instruction when we drop some high bits
344 ; and some low bits and a masking operation has to be kept
345 define void @fct16(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
347 ; CHECK-LABEL: fct16:
348 ; CHECK: ldr [[REG1:w[0-9]+]],
349 ; Create the constant
350 ; CHECK: movz [[REGCST:w[0-9]+]], #26, lsl #16
351 ; CHECK: movk [[REGCST]], #33120
353 ; CHECK: and [[REG2:w[0-9]+]], [[REG1]], [[REGCST]]
354 ; CHECK-NEXT: bfm [[REG2]], w1, #16, #18
355 ; lsr is an alias of ubfm
356 ; CHECK-NEXT: ubfm [[REG3:w[0-9]+]], [[REG2]], #2, #29
357 ; CHECK-NEXT: str [[REG3]],
359 %0 = load i32* %y, align 8
360 %and = and i32 %0, 1737056
361 %shr = lshr i32 %x, 16
362 %and1 = and i32 %shr, 7
363 %or = or i32 %and, %and1
364 %shl = shl i32 %or, 2
365 %shr2 = lshr i32 %shl, 4
366 store i32 %shr2, i32* %y, align 8
371 ; Check if we can still catch bfm instruction when we drop some high bits
372 ; and some low bits and a masking operation has to be kept
374 define void @fct17(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
376 ; CHECK-LABEL: fct17:
377 ; CHECK: ldr [[REG1:x[0-9]+]],
378 ; Create the constant
379 ; CHECK: movz [[REGCST:x[0-9]+]], #26, lsl #16
380 ; CHECK: movk [[REGCST]], #33120
382 ; CHECK: and [[REG2:x[0-9]+]], [[REG1]], [[REGCST]]
383 ; CHECK-NEXT: bfm [[REG2]], x1, #16, #18
384 ; lsr is an alias of ubfm
385 ; CHECK-NEXT: ubfm [[REG3:x[0-9]+]], [[REG2]], #2, #61
386 ; CHECK-NEXT: str [[REG3]],
388 %0 = load i64* %y, align 8
389 %and = and i64 %0, 1737056
390 %shr = lshr i64 %x, 16
391 %and1 = and i64 %shr, 7
392 %or = or i64 %and, %and1
393 %shl = shl i64 %or, 2
394 %shr2 = lshr i64 %shl, 4
395 store i64 %shr2, i64* %y, align 8
399 define i64 @fct18(i32 %xor72) nounwind ssp {
400 ; CHECK-LABEL: fct18:
401 ; CHECK: ubfm x0, x0, #9, #16
402 %shr81 = lshr i32 %xor72, 9
403 %conv82 = zext i32 %shr81 to i64
404 %result = and i64 %conv82, 255