1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -codegenprepare -mtriple=arm64-apple=ios -S -o - %s | FileCheck --check-prefix=OPT %s
3 ; RUN: llc < %s -mtriple=arm64-eabi | FileCheck --check-prefix=LLC %s
5 %struct.X = type { i8, i8, [2 x i8] }
6 %struct.Y = type { i32, i8 }
7 %struct.Z = type { i8, i8, [2 x i8], i16 }
8 %struct.A = type { i64, i8 }
10 define void @foo(%struct.X* nocapture %x, %struct.Y* nocapture %y) nounwind optsize ssp {
13 ; LLC-NEXT: ldr w8, [x0]
14 ; LLC-NEXT: ubfx w8, w8, #3, #1
15 ; LLC-NEXT: strb w8, [x1, #4]
18 ; OPT-NEXT: [[TMP:%.*]] = bitcast %struct.X* [[X:%.*]] to i32*
19 ; OPT-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 4
20 ; OPT-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_Y:%.*]], %struct.Y* [[Y:%.*]], i64 0, i32 1
21 ; OPT-NEXT: [[BF_CLEAR:%.*]] = lshr i32 [[TMP1]], 3
22 ; OPT-NEXT: [[BF_CLEAR_LOBIT:%.*]] = and i32 [[BF_CLEAR]], 1
23 ; OPT-NEXT: [[FROMBOOL:%.*]] = trunc i32 [[BF_CLEAR_LOBIT]] to i8
24 ; OPT-NEXT: store i8 [[FROMBOOL]], i8* [[B]], align 1
27 %tmp = bitcast %struct.X* %x to i32*
28 %tmp1 = load i32, i32* %tmp, align 4
29 %b = getelementptr inbounds %struct.Y, %struct.Y* %y, i64 0, i32 1
30 %bf.clear = lshr i32 %tmp1, 3
31 %bf.clear.lobit = and i32 %bf.clear, 1
32 %frombool = trunc i32 %bf.clear.lobit to i8
33 store i8 %frombool, i8* %b, align 1
37 define i32 @baz(i64 %cav1.coerce) nounwind {
40 ; LLC-NEXT: sbfx w0, w0, #0, #4
43 ; OPT-NEXT: [[TMP:%.*]] = trunc i64 [[CAV1_COERCE:%.*]] to i32
44 ; OPT-NEXT: [[TMP1:%.*]] = shl i32 [[TMP]], 28
45 ; OPT-NEXT: [[BF_VAL_SEXT:%.*]] = ashr exact i32 [[TMP1]], 28
46 ; OPT-NEXT: ret i32 [[BF_VAL_SEXT]]
48 %tmp = trunc i64 %cav1.coerce to i32
49 %tmp1 = shl i32 %tmp, 28
50 %bf.val.sext = ashr exact i32 %tmp1, 28
54 define i32 @bar(i64 %cav1.coerce) nounwind {
57 ; LLC-NEXT: sbfx w0, w0, #4, #6
60 ; OPT-NEXT: [[TMP:%.*]] = trunc i64 [[CAV1_COERCE:%.*]] to i32
61 ; OPT-NEXT: [[CAV1_SROA_0_1_INSERT:%.*]] = shl i32 [[TMP]], 22
62 ; OPT-NEXT: [[TMP1:%.*]] = ashr i32 [[CAV1_SROA_0_1_INSERT]], 26
63 ; OPT-NEXT: ret i32 [[TMP1]]
65 %tmp = trunc i64 %cav1.coerce to i32
66 %cav1.sroa.0.1.insert = shl i32 %tmp, 22
67 %tmp1 = ashr i32 %cav1.sroa.0.1.insert, 26
71 define void @fct1(%struct.Z* nocapture %x, %struct.A* nocapture %y) nounwind optsize ssp {
74 ; LLC-NEXT: ldr x8, [x0]
75 ; LLC-NEXT: ubfx x8, x8, #3, #1
76 ; LLC-NEXT: str x8, [x1]
79 ; OPT-NEXT: [[TMP:%.*]] = bitcast %struct.Z* [[X:%.*]] to i64*
80 ; OPT-NEXT: [[TMP1:%.*]] = load i64, i64* [[TMP]], align 4
81 ; OPT-NEXT: [[B1:%.*]] = bitcast %struct.A* [[Y:%.*]] to i64*
82 ; OPT-NEXT: [[BF_CLEAR:%.*]] = lshr i64 [[TMP1]], 3
83 ; OPT-NEXT: [[BF_CLEAR_LOBIT:%.*]] = and i64 [[BF_CLEAR]], 1
84 ; OPT-NEXT: store i64 [[BF_CLEAR_LOBIT]], i64* [[B1]], align 8
87 %tmp = bitcast %struct.Z* %x to i64*
88 %tmp1 = load i64, i64* %tmp, align 4
89 %b = getelementptr inbounds %struct.A, %struct.A* %y, i64 0, i32 0
90 %bf.clear = lshr i64 %tmp1, 3
91 %bf.clear.lobit = and i64 %bf.clear, 1
92 store i64 %bf.clear.lobit, i64* %b, align 8
96 define i64 @fct2(i64 %cav1.coerce) nounwind {
99 ; LLC-NEXT: sbfx x0, x0, #0, #36
102 ; OPT-NEXT: [[TMP:%.*]] = shl i64 [[CAV1_COERCE:%.*]], 28
103 ; OPT-NEXT: [[BF_VAL_SEXT:%.*]] = ashr exact i64 [[TMP]], 28
104 ; OPT-NEXT: ret i64 [[BF_VAL_SEXT]]
106 %tmp = shl i64 %cav1.coerce, 28
107 %bf.val.sext = ashr exact i64 %tmp, 28
111 define i64 @fct3(i64 %cav1.coerce) nounwind {
114 ; LLC-NEXT: sbfx x0, x0, #4, #38
117 ; OPT-NEXT: [[CAV1_SROA_0_1_INSERT:%.*]] = shl i64 [[CAV1_COERCE:%.*]], 22
118 ; OPT-NEXT: [[TMP1:%.*]] = ashr i64 [[CAV1_SROA_0_1_INSERT]], 26
119 ; OPT-NEXT: ret i64 [[TMP1]]
121 %cav1.sroa.0.1.insert = shl i64 %cav1.coerce, 22
122 %tmp1 = ashr i64 %cav1.sroa.0.1.insert, 26
126 define void @fct4(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
128 ; LLC: // %bb.0: // %entry
129 ; LLC-NEXT: ldr x8, [x0]
130 ; LLC-NEXT: bfxil x8, x1, #16, #24
131 ; LLC-NEXT: str x8, [x0]
135 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
136 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -16777216
137 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
138 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 16777215
139 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
140 ; OPT-NEXT: store i64 [[OR]], i64* [[Y]], align 8
144 %0 = load i64, i64* %y, align 8
145 %and = and i64 %0, -16777216
146 %shr = lshr i64 %x, 16
147 %and1 = and i64 %shr, 16777215
148 %or = or i64 %and, %and1
149 store i64 %or, i64* %y, align 8
153 define void @fct5(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
155 ; LLC: // %bb.0: // %entry
156 ; LLC-NEXT: ldr w8, [x0]
157 ; LLC-NEXT: bfxil w8, w1, #16, #3
158 ; LLC-NEXT: str w8, [x0]
162 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
163 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
164 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
165 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
166 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
167 ; OPT-NEXT: store i32 [[OR]], i32* [[Y]], align 8
171 %0 = load i32, i32* %y, align 8
172 %and = and i32 %0, -8
173 %shr = lshr i32 %x, 16
174 %and1 = and i32 %shr, 7
175 %or = or i32 %and, %and1
176 store i32 %or, i32* %y, align 8
180 ; Check if we can still catch bfm instruction when we drop some low bits
181 define void @fct6(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
183 ; LLC: // %bb.0: // %entry
184 ; LLC-NEXT: ldr w8, [x0]
185 ; LLC-NEXT: bfxil w8, w1, #16, #3
186 ; LLC-NEXT: lsr w8, w8, #2
187 ; LLC-NEXT: str w8, [x0]
191 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
192 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
193 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
194 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
195 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
196 ; OPT-NEXT: [[SHR1:%.*]] = lshr i32 [[OR]], 2
197 ; OPT-NEXT: store i32 [[SHR1]], i32* [[Y]], align 8
201 ; lsr is an alias of ubfm
202 %0 = load i32, i32* %y, align 8
203 %and = and i32 %0, -8
204 %shr = lshr i32 %x, 16
205 %and1 = and i32 %shr, 7
206 %or = or i32 %and, %and1
207 %shr1 = lshr i32 %or, 2
208 store i32 %shr1, i32* %y, align 8
213 ; Check if we can still catch bfm instruction when we drop some high bits
214 define void @fct7(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
216 ; LLC: // %bb.0: // %entry
217 ; LLC-NEXT: ldr w8, [x0]
218 ; LLC-NEXT: bfxil w8, w1, #16, #3
219 ; LLC-NEXT: lsl w8, w8, #2
220 ; LLC-NEXT: str w8, [x0]
224 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
225 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
226 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
227 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
228 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
229 ; OPT-NEXT: [[SHL:%.*]] = shl i32 [[OR]], 2
230 ; OPT-NEXT: store i32 [[SHL]], i32* [[Y]], align 8
234 ; lsl is an alias of ubfm
235 %0 = load i32, i32* %y, align 8
236 %and = and i32 %0, -8
237 %shr = lshr i32 %x, 16
238 %and1 = and i32 %shr, 7
239 %or = or i32 %and, %and1
240 %shl = shl i32 %or, 2
241 store i32 %shl, i32* %y, align 8
246 ; Check if we can still catch bfm instruction when we drop some low bits
248 define void @fct8(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
250 ; LLC: // %bb.0: // %entry
251 ; LLC-NEXT: ldr x8, [x0]
252 ; LLC-NEXT: bfxil x8, x1, #16, #3
253 ; LLC-NEXT: lsr x8, x8, #2
254 ; LLC-NEXT: str x8, [x0]
258 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
259 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
260 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
261 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
262 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
263 ; OPT-NEXT: [[SHR1:%.*]] = lshr i64 [[OR]], 2
264 ; OPT-NEXT: store i64 [[SHR1]], i64* [[Y]], align 8
268 ; lsr is an alias of ubfm
269 %0 = load i64, i64* %y, align 8
270 %and = and i64 %0, -8
271 %shr = lshr i64 %x, 16
272 %and1 = and i64 %shr, 7
273 %or = or i64 %and, %and1
274 %shr1 = lshr i64 %or, 2
275 store i64 %shr1, i64* %y, align 8
280 ; Check if we can still catch bfm instruction when we drop some high bits
282 define void @fct9(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
284 ; LLC: // %bb.0: // %entry
285 ; LLC-NEXT: ldr x8, [x0]
286 ; LLC-NEXT: bfxil x8, x1, #16, #3
287 ; LLC-NEXT: lsl x8, x8, #2
288 ; LLC-NEXT: str x8, [x0]
292 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
293 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
294 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
295 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
296 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
297 ; OPT-NEXT: [[SHL:%.*]] = shl i64 [[OR]], 2
298 ; OPT-NEXT: store i64 [[SHL]], i64* [[Y]], align 8
302 ; lsr is an alias of ubfm
303 %0 = load i64, i64* %y, align 8
304 %and = and i64 %0, -8
305 %shr = lshr i64 %x, 16
306 %and1 = and i64 %shr, 7
307 %or = or i64 %and, %and1
308 %shl = shl i64 %or, 2
309 store i64 %shl, i64* %y, align 8
313 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
315 define void @fct10(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
317 ; LLC: // %bb.0: // %entry
318 ; LLC-NEXT: ldr w8, [x0]
319 ; LLC-NEXT: bfxil w8, w1, #0, #3
320 ; LLC-NEXT: lsl w8, w8, #2
321 ; LLC-NEXT: str w8, [x0]
325 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
326 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
327 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[X:%.*]], 7
328 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
329 ; OPT-NEXT: [[SHL:%.*]] = shl i32 [[OR]], 2
330 ; OPT-NEXT: store i32 [[SHL]], i32* [[Y]], align 8
334 ; lsl is an alias of ubfm
335 %0 = load i32, i32* %y, align 8
336 %and = and i32 %0, -8
337 %and1 = and i32 %x, 7
338 %or = or i32 %and, %and1
339 %shl = shl i32 %or, 2
340 store i32 %shl, i32* %y, align 8
344 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
346 define void @fct11(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
348 ; LLC: // %bb.0: // %entry
349 ; LLC-NEXT: ldr x8, [x0]
350 ; LLC-NEXT: bfxil x8, x1, #0, #3
351 ; LLC-NEXT: lsl x8, x8, #2
352 ; LLC-NEXT: str x8, [x0]
356 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
357 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
358 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[X:%.*]], 7
359 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
360 ; OPT-NEXT: [[SHL:%.*]] = shl i64 [[OR]], 2
361 ; OPT-NEXT: store i64 [[SHL]], i64* [[Y]], align 8
365 ; lsl is an alias of ubfm
366 %0 = load i64, i64* %y, align 8
367 %and = and i64 %0, -8
368 %and1 = and i64 %x, 7
369 %or = or i64 %and, %and1
370 %shl = shl i64 %or, 2
371 store i64 %shl, i64* %y, align 8
375 define zeroext i1 @fct12bis(i32 %tmp2) unnamed_addr nounwind ssp align 2 {
376 ; LLC-LABEL: fct12bis:
378 ; LLC-NEXT: ubfx w0, w0, #11, #1
380 ; OPT-LABEL: @fct12bis(
381 ; OPT-NEXT: [[AND_I_I:%.*]] = and i32 [[TMP2:%.*]], 2048
382 ; OPT-NEXT: [[TOBOOL_I_I:%.*]] = icmp ne i32 [[AND_I_I]], 0
383 ; OPT-NEXT: ret i1 [[TOBOOL_I_I]]
385 %and.i.i = and i32 %tmp2, 2048
386 %tobool.i.i = icmp ne i32 %and.i.i, 0
390 ; Check if we can still catch bfm instruction when we drop some high bits
392 define void @fct12(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
394 ; LLC: // %bb.0: // %entry
395 ; LLC-NEXT: ldr w8, [x0]
396 ; LLC-NEXT: bfxil w8, w1, #16, #3
397 ; LLC-NEXT: ubfx w8, w8, #2, #28
398 ; LLC-NEXT: str w8, [x0]
402 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
403 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
404 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
405 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
406 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
407 ; OPT-NEXT: [[SHL:%.*]] = shl i32 [[OR]], 2
408 ; OPT-NEXT: [[SHR2:%.*]] = lshr i32 [[SHL]], 4
409 ; OPT-NEXT: store i32 [[SHR2]], i32* [[Y]], align 8
413 ; lsr is an alias of ubfm
414 %0 = load i32, i32* %y, align 8
415 %and = and i32 %0, -8
416 %shr = lshr i32 %x, 16
417 %and1 = and i32 %shr, 7
418 %or = or i32 %and, %and1
419 %shl = shl i32 %or, 2
420 %shr2 = lshr i32 %shl, 4
421 store i32 %shr2, i32* %y, align 8
424 define void @fct12_mask(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
425 ; LLC-LABEL: fct12_mask:
426 ; LLC: // %bb.0: // %entry
427 ; LLC-NEXT: ldr w8, [x0]
428 ; LLC-NEXT: and w8, w8, #0x3ffffff8
429 ; LLC-NEXT: bfxil w8, w1, #16, #3
430 ; LLC-NEXT: lsr w8, w8, #2
431 ; LLC-NEXT: str w8, [x0]
433 ; OPT-LABEL: @fct12_mask(
435 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
436 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
437 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
438 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
439 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
440 ; OPT-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], 2
441 ; OPT-NEXT: [[MASK:%.*]] = and i32 [[LSHR]], 268435455
442 ; OPT-NEXT: store i32 [[MASK]], i32* [[Y]], align 8
446 ; lsr is an alias of ubfm
447 %0 = load i32, i32* %y, align 8
448 %and = and i32 %0, -8
449 %shr = lshr i32 %x, 16
450 %and1 = and i32 %shr, 7
451 %or = or i32 %and, %and1
452 %lshr = lshr i32 %or, 2
453 %mask = and i32 %lshr, 268435455
454 store i32 %mask, i32* %y, align 8
458 ; Check if we can still catch bfm instruction when we drop some high bits
461 define void @fct13(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
463 ; LLC: // %bb.0: // %entry
464 ; LLC-NEXT: ldr x8, [x0]
465 ; LLC-NEXT: bfxil x8, x1, #16, #3
466 ; LLC-NEXT: ubfx x8, x8, #2, #60
467 ; LLC-NEXT: str x8, [x0]
471 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
472 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
473 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
474 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
475 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
476 ; OPT-NEXT: [[SHL:%.*]] = shl i64 [[OR]], 2
477 ; OPT-NEXT: [[SHR2:%.*]] = lshr i64 [[SHL]], 4
478 ; OPT-NEXT: store i64 [[SHR2]], i64* [[Y]], align 8
482 ; lsr is an alias of ubfm
483 %0 = load i64, i64* %y, align 8
484 %and = and i64 %0, -8
485 %shr = lshr i64 %x, 16
486 %and1 = and i64 %shr, 7
487 %or = or i64 %and, %and1
488 %shl = shl i64 %or, 2
489 %shr2 = lshr i64 %shl, 4
490 store i64 %shr2, i64* %y, align 8
493 define void @fct13_mask(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
494 ; LLC-LABEL: fct13_mask:
495 ; LLC: // %bb.0: // %entry
496 ; LLC-NEXT: ldr x8, [x0]
497 ; LLC-NEXT: and x8, x8, #0x3ffffffffffffff8
498 ; LLC-NEXT: bfxil x8, x1, #16, #3
499 ; LLC-NEXT: lsr x8, x8, #2
500 ; LLC-NEXT: str x8, [x0]
502 ; OPT-LABEL: @fct13_mask(
504 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
505 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
506 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
507 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
508 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
509 ; OPT-NEXT: [[LSHR:%.*]] = lshr i64 [[OR]], 2
510 ; OPT-NEXT: [[MASK:%.*]] = and i64 [[LSHR]], 1152921504606846975
511 ; OPT-NEXT: store i64 [[MASK]], i64* [[Y]], align 8
515 ; lsr is an alias of ubfm
516 %0 = load i64, i64* %y, align 8
517 %and = and i64 %0, -8
518 %shr = lshr i64 %x, 16
519 %and1 = and i64 %shr, 7
520 %or = or i64 %and, %and1
521 %lshr = lshr i64 %or, 2
522 %mask = and i64 %lshr, 1152921504606846975
523 store i64 %mask, i64* %y, align 8
528 ; Check if we can still catch bfm instruction when we drop some high bits
530 define void @fct14(i32* nocapture %y, i32 %x, i32 %x1) nounwind optsize inlinehint ssp {
532 ; LLC: // %bb.0: // %entry
533 ; LLC-NEXT: ldr w8, [x0]
534 ; LLC-NEXT: bfxil w8, w1, #16, #8
535 ; LLC-NEXT: lsr w8, w8, #4
536 ; LLC-NEXT: bfxil w8, w2, #5, #3
537 ; LLC-NEXT: lsl w8, w8, #2
538 ; LLC-NEXT: str w8, [x0]
542 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
543 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -256
544 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
545 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 255
546 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
547 ; OPT-NEXT: [[SHL:%.*]] = lshr i32 [[OR]], 4
548 ; OPT-NEXT: [[AND2:%.*]] = and i32 [[SHL]], -8
549 ; OPT-NEXT: [[SHR1:%.*]] = lshr i32 [[X1:%.*]], 5
550 ; OPT-NEXT: [[AND3:%.*]] = and i32 [[SHR1]], 7
551 ; OPT-NEXT: [[OR1:%.*]] = or i32 [[AND2]], [[AND3]]
552 ; OPT-NEXT: [[SHL1:%.*]] = shl i32 [[OR1]], 2
553 ; OPT-NEXT: store i32 [[SHL1]], i32* [[Y]], align 8
557 ; lsr is an alias of ubfm
558 ; lsl is an alias of ubfm
559 %0 = load i32, i32* %y, align 8
560 %and = and i32 %0, -256
561 %shr = lshr i32 %x, 16
562 %and1 = and i32 %shr, 255
563 %or = or i32 %and, %and1
564 %shl = lshr i32 %or, 4
565 %and2 = and i32 %shl, -8
566 %shr1 = lshr i32 %x1, 5
567 %and3 = and i32 %shr1, 7
568 %or1 = or i32 %and2, %and3
569 %shl1 = shl i32 %or1, 2
570 store i32 %shl1, i32* %y, align 8
574 ; Check if we can still catch bfm instruction when we drop some high bits
577 define void @fct15(i64* nocapture %y, i64 %x, i64 %x1) nounwind optsize inlinehint ssp {
579 ; LLC: // %bb.0: // %entry
580 ; LLC-NEXT: ldr x8, [x0]
581 ; LLC-NEXT: bfxil x8, x1, #16, #8
582 ; LLC-NEXT: lsr x8, x8, #4
583 ; LLC-NEXT: bfxil x8, x2, #5, #3
584 ; LLC-NEXT: lsl x8, x8, #2
585 ; LLC-NEXT: str x8, [x0]
589 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
590 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -256
591 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
592 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 255
593 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
594 ; OPT-NEXT: [[SHL:%.*]] = lshr i64 [[OR]], 4
595 ; OPT-NEXT: [[AND2:%.*]] = and i64 [[SHL]], -8
596 ; OPT-NEXT: [[SHR1:%.*]] = lshr i64 [[X1:%.*]], 5
597 ; OPT-NEXT: [[AND3:%.*]] = and i64 [[SHR1]], 7
598 ; OPT-NEXT: [[OR1:%.*]] = or i64 [[AND2]], [[AND3]]
599 ; OPT-NEXT: [[SHL1:%.*]] = shl i64 [[OR1]], 2
600 ; OPT-NEXT: store i64 [[SHL1]], i64* [[Y]], align 8
604 ; lsr is an alias of ubfm
605 ; lsl is an alias of ubfm
606 %0 = load i64, i64* %y, align 8
607 %and = and i64 %0, -256
608 %shr = lshr i64 %x, 16
609 %and1 = and i64 %shr, 255
610 %or = or i64 %and, %and1
611 %shl = lshr i64 %or, 4
612 %and2 = and i64 %shl, -8
613 %shr1 = lshr i64 %x1, 5
614 %and3 = and i64 %shr1, 7
615 %or1 = or i64 %and2, %and3
616 %shl1 = shl i64 %or1, 2
617 store i64 %shl1, i64* %y, align 8
621 ; Check if we can still catch bfm instruction when we drop some high bits
622 ; and some low bits and a masking operation has to be kept
623 define void @fct16(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
625 ; LLC: // %bb.0: // %entry
626 ; LLC-NEXT: ldr w8, [x0]
627 ; LLC-NEXT: mov w9, #33120
628 ; LLC-NEXT: movk w9, #26, lsl #16
629 ; LLC-NEXT: and w8, w8, w9
630 ; LLC-NEXT: bfxil w8, w1, #16, #3
631 ; LLC-NEXT: ubfx w8, w8, #2, #28
632 ; LLC-NEXT: str w8, [x0]
636 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
637 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], 1737056
638 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
639 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
640 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
641 ; OPT-NEXT: [[SHL:%.*]] = shl i32 [[OR]], 2
642 ; OPT-NEXT: [[SHR2:%.*]] = lshr i32 [[SHL]], 4
643 ; OPT-NEXT: store i32 [[SHR2]], i32* [[Y]], align 8
647 ; Create the constant
649 ; lsr is an alias of ubfm
650 %0 = load i32, i32* %y, align 8
651 %and = and i32 %0, 1737056
652 %shr = lshr i32 %x, 16
653 %and1 = and i32 %shr, 7
654 %or = or i32 %and, %and1
655 %shl = shl i32 %or, 2
656 %shr2 = lshr i32 %shl, 4
657 store i32 %shr2, i32* %y, align 8
660 define void @fct16_mask(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
661 ; LLC-LABEL: fct16_mask:
662 ; LLC: // %bb.0: // %entry
663 ; LLC-NEXT: ldr w8, [x0]
664 ; LLC-NEXT: mov w9, #33120
665 ; LLC-NEXT: movk w9, #26, lsl #16
666 ; LLC-NEXT: and w8, w8, w9
667 ; LLC-NEXT: bfxil w8, w1, #16, #3
668 ; LLC-NEXT: lsr w8, w8, #2
669 ; LLC-NEXT: str w8, [x0]
671 ; OPT-LABEL: @fct16_mask(
673 ; OPT-NEXT: [[TMP0:%.*]] = load i32, i32* [[Y:%.*]], align 8
674 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], 1737056
675 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
676 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
677 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
678 ; OPT-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], 2
679 ; OPT-NEXT: [[MASK:%.*]] = and i32 [[LSHR]], 268435455
680 ; OPT-NEXT: store i32 [[MASK]], i32* [[Y]], align 8
684 ; Create the constant
686 ; lsr is an alias of ubfm
687 %0 = load i32, i32* %y, align 8
688 %and = and i32 %0, 1737056
689 %shr = lshr i32 %x, 16
690 %and1 = and i32 %shr, 7
691 %or = or i32 %and, %and1
692 %lshr = lshr i32 %or, 2
693 %mask = and i32 %lshr, 268435455
694 store i32 %mask, i32* %y, align 8
699 ; Check if we can still catch bfm instruction when we drop some high bits
700 ; and some low bits and a masking operation has to be kept
702 define void @fct17(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
704 ; LLC: // %bb.0: // %entry
705 ; LLC-NEXT: ldr x8, [x0]
706 ; LLC-NEXT: mov w9, #33120
707 ; LLC-NEXT: movk w9, #26, lsl #16
708 ; LLC-NEXT: and x8, x8, x9
709 ; LLC-NEXT: bfxil x8, x1, #16, #3
710 ; LLC-NEXT: ubfx x8, x8, #2, #60
711 ; LLC-NEXT: str x8, [x0]
715 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
716 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], 1737056
717 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
718 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
719 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
720 ; OPT-NEXT: [[SHL:%.*]] = shl i64 [[OR]], 2
721 ; OPT-NEXT: [[SHR2:%.*]] = lshr i64 [[SHL]], 4
722 ; OPT-NEXT: store i64 [[SHR2]], i64* [[Y]], align 8
726 ; Create the constant
728 ; lsr is an alias of ubfm
729 %0 = load i64, i64* %y, align 8
730 %and = and i64 %0, 1737056
731 %shr = lshr i64 %x, 16
732 %and1 = and i64 %shr, 7
733 %or = or i64 %and, %and1
734 %shl = shl i64 %or, 2
735 %shr2 = lshr i64 %shl, 4
736 store i64 %shr2, i64* %y, align 8
739 define void @fct17_mask(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
740 ; LLC-LABEL: fct17_mask:
741 ; LLC: // %bb.0: // %entry
742 ; LLC-NEXT: ldr x8, [x0]
743 ; LLC-NEXT: mov w9, #33120
744 ; LLC-NEXT: movk w9, #26, lsl #16
745 ; LLC-NEXT: and x8, x8, x9
746 ; LLC-NEXT: bfxil x8, x1, #16, #3
747 ; LLC-NEXT: lsr x8, x8, #2
748 ; LLC-NEXT: str x8, [x0]
750 ; OPT-LABEL: @fct17_mask(
752 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[Y:%.*]], align 8
753 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], 1737056
754 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
755 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
756 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
757 ; OPT-NEXT: [[LSHR:%.*]] = lshr i64 [[OR]], 2
758 ; OPT-NEXT: [[MASK:%.*]] = and i64 [[LSHR]], 1152921504606846975
759 ; OPT-NEXT: store i64 [[MASK]], i64* [[Y]], align 8
763 ; Create the constant
765 ; lsr is an alias of ubfm
766 %0 = load i64, i64* %y, align 8
767 %and = and i64 %0, 1737056
768 %shr = lshr i64 %x, 16
769 %and1 = and i64 %shr, 7
770 %or = or i64 %and, %and1
771 %lshr = lshr i64 %or, 2
772 %mask = and i64 %lshr, 1152921504606846975
773 store i64 %mask, i64* %y, align 8
777 define i64 @fct18(i32 %xor72) nounwind ssp {
780 ; LLC-NEXT: // kill: def $w0 killed $w0 def $x0
781 ; LLC-NEXT: ubfx x0, x0, #9, #8
784 ; OPT-NEXT: [[SHR81:%.*]] = lshr i32 [[XOR72:%.*]], 9
785 ; OPT-NEXT: [[CONV82:%.*]] = zext i32 [[SHR81]] to i64
786 ; OPT-NEXT: [[RESULT:%.*]] = and i64 [[CONV82]], 255
787 ; OPT-NEXT: ret i64 [[RESULT]]
789 %shr81 = lshr i32 %xor72, 9
790 %conv82 = zext i32 %shr81 to i64
791 %result = and i64 %conv82, 255
795 ; Using the access to the global array to keep the instruction and control flow.
796 @first_ones = external global [65536 x i8]
798 ; Function Attrs: nounwind readonly ssp
799 define i32 @fct19(i64 %arg1) nounwind readonly ssp {
801 ; LLC: // %bb.0: // %entry
802 ; LLC-NEXT: lsr x8, x0, #48
803 ; LLC-NEXT: cbz x8, .LBB26_2
804 ; LLC-NEXT: // %bb.1: // %if.then
805 ; LLC-NEXT: adrp x9, first_ones
806 ; LLC-NEXT: add x9, x9, :lo12:first_ones
807 ; LLC-NEXT: ldrb w0, [x9, x8]
809 ; LLC-NEXT: .LBB26_2: // %if.end
810 ; LLC-NEXT: ubfx x8, x0, #32, #16
811 ; LLC-NEXT: cbz w8, .LBB26_4
812 ; LLC-NEXT: // %bb.3: // %if.then7
813 ; LLC-NEXT: adrp x9, first_ones
814 ; LLC-NEXT: add x9, x9, :lo12:first_ones
815 ; LLC-NEXT: ldrb w8, [x9, x8]
816 ; LLC-NEXT: add w0, w8, #16 // =16
818 ; LLC-NEXT: .LBB26_4: // %if.end13
819 ; LLC-NEXT: ubfx x8, x0, #16, #16
820 ; LLC-NEXT: cbz w8, .LBB26_6
821 ; LLC-NEXT: // %bb.5: // %if.then17
822 ; LLC-NEXT: adrp x9, first_ones
823 ; LLC-NEXT: add x9, x9, :lo12:first_ones
824 ; LLC-NEXT: ldrb w8, [x9, x8]
825 ; LLC-NEXT: add w0, w8, #32 // =32
827 ; LLC-NEXT: .LBB26_6:
828 ; LLC-NEXT: mov w0, #64
832 ; OPT-NEXT: [[X_SROA_1_0_EXTRACT_SHIFT:%.*]] = lshr i64 [[ARG1:%.*]], 16
833 ; OPT-NEXT: [[X_SROA_1_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[X_SROA_1_0_EXTRACT_SHIFT]] to i16
834 ; OPT-NEXT: [[X_SROA_5_0_EXTRACT_SHIFT:%.*]] = lshr i64 [[ARG1]], 48
835 ; OPT-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X_SROA_5_0_EXTRACT_SHIFT]], 0
836 ; OPT-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
838 ; OPT-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 [[X_SROA_5_0_EXTRACT_SHIFT]]
839 ; OPT-NEXT: [[TMP0:%.*]] = load i8, i8* [[ARRAYIDX3]], align 1
840 ; OPT-NEXT: [[CONV:%.*]] = zext i8 [[TMP0]] to i32
841 ; OPT-NEXT: br label [[RETURN:%.*]]
843 ; OPT-NEXT: [[TMP1:%.*]] = lshr i64 [[ARG1]], 32
844 ; OPT-NEXT: [[X_SROA_3_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[TMP1]] to i16
845 ; OPT-NEXT: [[TOBOOL6:%.*]] = icmp eq i16 [[X_SROA_3_0_EXTRACT_TRUNC]], 0
846 ; OPT-NEXT: br i1 [[TOBOOL6]], label [[IF_END13:%.*]], label [[IF_THEN7:%.*]]
848 ; OPT-NEXT: [[TMP2:%.*]] = lshr i64 [[ARG1]], 32
849 ; OPT-NEXT: [[IDXPROM10:%.*]] = and i64 [[TMP2]], 65535
850 ; OPT-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 [[IDXPROM10]]
851 ; OPT-NEXT: [[TMP3:%.*]] = load i8, i8* [[ARRAYIDX11]], align 1
852 ; OPT-NEXT: [[CONV12:%.*]] = zext i8 [[TMP3]] to i32
853 ; OPT-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV12]], 16
854 ; OPT-NEXT: br label [[RETURN]]
856 ; OPT-NEXT: [[TMP4:%.*]] = lshr i64 [[ARG1]], 16
857 ; OPT-NEXT: [[TMP5:%.*]] = trunc i64 [[TMP4]] to i16
858 ; OPT-NEXT: [[TOBOOL16:%.*]] = icmp eq i16 [[TMP5]], 0
859 ; OPT-NEXT: br i1 [[TOBOOL16]], label [[RETURN]], label [[IF_THEN17:%.*]]
861 ; OPT-NEXT: [[TMP6:%.*]] = lshr i64 [[ARG1]], 16
862 ; OPT-NEXT: [[IDXPROM20:%.*]] = and i64 [[TMP6]], 65535
863 ; OPT-NEXT: [[ARRAYIDX21:%.*]] = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 [[IDXPROM20]]
864 ; OPT-NEXT: [[TMP7:%.*]] = load i8, i8* [[ARRAYIDX21]], align 1
865 ; OPT-NEXT: [[CONV22:%.*]] = zext i8 [[TMP7]] to i32
866 ; OPT-NEXT: [[ADD23:%.*]] = add nsw i32 [[CONV22]], 32
867 ; OPT-NEXT: br label [[RETURN]]
869 ; OPT-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CONV]], [[IF_THEN]] ], [ [[ADD]], [[IF_THEN7]] ], [ [[ADD23]], [[IF_THEN17]] ], [ 64, [[IF_END13]] ]
870 ; OPT-NEXT: ret i32 [[RETVAL_0]]
873 %x.sroa.1.0.extract.shift = lshr i64 %arg1, 16
874 %x.sroa.1.0.extract.trunc = trunc i64 %x.sroa.1.0.extract.shift to i16
875 %x.sroa.3.0.extract.shift = lshr i64 %arg1, 32
876 %x.sroa.5.0.extract.shift = lshr i64 %arg1, 48
877 %tobool = icmp eq i64 %x.sroa.5.0.extract.shift, 0
878 br i1 %tobool, label %if.end, label %if.then
880 if.then: ; preds = %entry
881 %arrayidx3 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %x.sroa.5.0.extract.shift
882 %0 = load i8, i8* %arrayidx3, align 1
883 %conv = zext i8 %0 to i32
886 if.end: ; preds = %entry
887 %x.sroa.3.0.extract.trunc = trunc i64 %x.sroa.3.0.extract.shift to i16
888 %tobool6 = icmp eq i16 %x.sroa.3.0.extract.trunc, 0
889 br i1 %tobool6, label %if.end13, label %if.then7
891 if.then7: ; preds = %if.end
892 ; "and" should be combined to "ubfm" while "ubfm" should be removed by cse.
893 ; So neither of them should be in the assemble code.
894 %idxprom10 = and i64 %x.sroa.3.0.extract.shift, 65535
895 %arrayidx11 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %idxprom10
896 %1 = load i8, i8* %arrayidx11, align 1
897 %conv12 = zext i8 %1 to i32
898 %add = add nsw i32 %conv12, 16
901 if.end13: ; preds = %if.end
902 %tobool16 = icmp eq i16 %x.sroa.1.0.extract.trunc, 0
903 br i1 %tobool16, label %return, label %if.then17
905 if.then17: ; preds = %if.end13
906 ; "and" should be combined to "ubfm" while "ubfm" should be removed by cse.
907 ; So neither of them should be in the assemble code.
908 %idxprom20 = and i64 %x.sroa.1.0.extract.shift, 65535
909 %arrayidx21 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %idxprom20
910 %2 = load i8, i8* %arrayidx21, align 1
911 %conv22 = zext i8 %2 to i32
912 %add23 = add nsw i32 %conv22, 32
915 return: ; preds = %if.end13, %if.then17, %if.then7, %if.then
916 %retval.0 = phi i32 [ %conv, %if.then ], [ %add, %if.then7 ], [ %add23, %if.then17 ], [ 64, %if.end13 ]
920 ; Make sure we do not assert if the immediate in and is bigger than i64.
922 define i80 @fct20(i128 %a, i128 %b) {
924 ; LLC: // %bb.0: // %entry
925 ; LLC-NEXT: mov x12, #11776
926 ; LLC-NEXT: movk x12, #25856, lsl #16
927 ; LLC-NEXT: movk x12, #11077, lsl #32
928 ; LLC-NEXT: extr x8, x1, x0, #18
929 ; LLC-NEXT: lsr x9, x1, #18
930 ; LLC-NEXT: orr x10, x2, x3
931 ; LLC-NEXT: mov w11, #26220
932 ; LLC-NEXT: movk x12, #45, lsl #48
933 ; LLC-NEXT: and x11, x9, x11
934 ; LLC-NEXT: and x12, x8, x12
935 ; LLC-NEXT: cmp x10, #0 // =0
936 ; LLC-NEXT: csel x0, x12, x8, eq
937 ; LLC-NEXT: csel x1, x11, x9, eq
941 ; OPT-NEXT: [[SHR:%.*]] = lshr i128 [[A:%.*]], 18
942 ; OPT-NEXT: [[CONV:%.*]] = trunc i128 [[SHR]] to i80
943 ; OPT-NEXT: [[TOBOOL:%.*]] = icmp eq i128 [[B:%.*]], 0
944 ; OPT-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[END:%.*]]
946 ; OPT-NEXT: [[AND:%.*]] = and i128 [[SHR]], 483673642326615442599424
947 ; OPT-NEXT: [[CONV2:%.*]] = trunc i128 [[AND]] to i80
948 ; OPT-NEXT: br label [[END]]
950 ; OPT-NEXT: [[CONV3:%.*]] = phi i80 [ [[CONV]], [[ENTRY:%.*]] ], [ [[CONV2]], [[THEN]] ]
951 ; OPT-NEXT: ret i80 [[CONV3]]
954 %shr = lshr i128 %a, 18
955 %conv = trunc i128 %shr to i80
956 %tobool = icmp eq i128 %b, 0
957 br i1 %tobool, label %then, label %end
959 %and = and i128 %shr, 483673642326615442599424
960 %conv2 = trunc i128 %and to i80
963 %conv3 = phi i80 [%conv, %entry], [%conv2, %then]
967 ; Check if we can still catch UBFX when "AND" is used by SHL.
968 @arr = external global [8 x [64 x i64]]
969 define i64 @fct21(i64 %x) {
971 ; LLC: // %bb.0: // %entry
972 ; LLC-NEXT: adrp x9, arr
973 ; LLC-NEXT: ubfx x8, x0, #4, #4
974 ; LLC-NEXT: add x9, x9, :lo12:arr
975 ; LLC-NEXT: ldr x0, [x9, x8, lsl #3]
979 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 4
980 ; OPT-NEXT: [[AND:%.*]] = and i64 [[SHR]], 15
981 ; OPT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x [64 x i64]], [8 x [64 x i64]]* @arr, i64 0, i64 0, i64 [[AND]]
982 ; OPT-NEXT: [[TMP0:%.*]] = load i64, i64* [[ARRAYIDX]], align 8
983 ; OPT-NEXT: ret i64 [[TMP0]]
986 %shr = lshr i64 %x, 4
987 %and = and i64 %shr, 15
988 %arrayidx = getelementptr inbounds [8 x [64 x i64]], [8 x [64 x i64]]* @arr, i64 0, i64 0, i64 %and
989 %0 = load i64, i64* %arrayidx, align 8
993 define i16 @test_ignored_rightbits(i32 %dst, i32 %in) {
994 ; LLC-LABEL: test_ignored_rightbits:
996 ; LLC-NEXT: and w0, w0, #0x7
997 ; LLC-NEXT: bfi w0, w1, #3, #4
998 ; LLC-NEXT: bfi w0, w0, #8, #7
1000 ; OPT-LABEL: @test_ignored_rightbits(
1001 ; OPT-NEXT: [[POSITIONED_FIELD:%.*]] = shl i32 [[IN:%.*]], 3
1002 ; OPT-NEXT: [[POSITIONED_MASKED_FIELD:%.*]] = and i32 [[POSITIONED_FIELD]], 120
1003 ; OPT-NEXT: [[MASKED_DST:%.*]] = and i32 [[DST:%.*]], 7
1004 ; OPT-NEXT: [[INSERTION:%.*]] = or i32 [[MASKED_DST]], [[POSITIONED_MASKED_FIELD]]
1005 ; OPT-NEXT: [[SHL16:%.*]] = shl i32 [[INSERTION]], 8
1006 ; OPT-NEXT: [[OR18:%.*]] = or i32 [[SHL16]], [[INSERTION]]
1007 ; OPT-NEXT: [[CONV19:%.*]] = trunc i32 [[OR18]] to i16
1008 ; OPT-NEXT: ret i16 [[CONV19]]
1010 %positioned_field = shl i32 %in, 3
1011 %positioned_masked_field = and i32 %positioned_field, 120
1012 %masked_dst = and i32 %dst, 7
1013 %insertion = or i32 %masked_dst, %positioned_masked_field
1015 %shl16 = shl i32 %insertion, 8
1016 %or18 = or i32 %shl16, %insertion
1017 %conv19 = trunc i32 %or18 to i16
1022 ; The following test excercises the case where we have a BFI
1023 ; instruction with the same input in both operands. We need to
1024 ; track the useful bits through both operands.
1025 define void @sameOperandBFI(i64 %src, i64 %src2, i16 *%ptr) {
1026 ; LLC-LABEL: sameOperandBFI:
1027 ; LLC: // %bb.0: // %entry
1028 ; LLC-NEXT: cbnz wzr, .LBB30_2
1029 ; LLC-NEXT: // %bb.1: // %if.else
1030 ; LLC-NEXT: lsr x8, x0, #47
1031 ; LLC-NEXT: and w9, w1, #0x3
1032 ; LLC-NEXT: bfi w9, w8, #2, #2
1033 ; LLC-NEXT: bfi w9, w9, #4, #4
1034 ; LLC-NEXT: strh w9, [x2]
1035 ; LLC-NEXT: .LBB30_2: // %end
1037 ; OPT-LABEL: @sameOperandBFI(
1039 ; OPT-NEXT: [[SHR47:%.*]] = lshr i64 [[SRC:%.*]], 47
1040 ; OPT-NEXT: [[SRC2_TRUNC:%.*]] = trunc i64 [[SRC2:%.*]] to i32
1041 ; OPT-NEXT: br i1 undef, label [[END:%.*]], label [[IF_ELSE:%.*]]
1043 ; OPT-NEXT: [[AND3:%.*]] = and i32 [[SRC2_TRUNC]], 3
1044 ; OPT-NEXT: [[SHL2:%.*]] = shl nuw nsw i64 [[SHR47]], 2
1045 ; OPT-NEXT: [[SHL2_TRUNC:%.*]] = trunc i64 [[SHL2]] to i32
1046 ; OPT-NEXT: [[AND12:%.*]] = and i32 [[SHL2_TRUNC]], 12
1047 ; OPT-NEXT: [[BFISOURCE:%.*]] = or i32 [[AND3]], [[AND12]]
1048 ; OPT-NEXT: [[BFIRHS:%.*]] = shl nuw nsw i32 [[BFISOURCE]], 4
1049 ; OPT-NEXT: [[BFI:%.*]] = or i32 [[BFIRHS]], [[BFISOURCE]]
1050 ; OPT-NEXT: [[BFITRUNC:%.*]] = trunc i32 [[BFI]] to i16
1051 ; OPT-NEXT: store i16 [[BFITRUNC]], i16* [[PTR:%.*]], align 4
1052 ; OPT-NEXT: br label [[END]]
1054 ; OPT-NEXT: ret void
1057 %shr47 = lshr i64 %src, 47
1058 %src2.trunc = trunc i64 %src2 to i32
1059 br i1 undef, label %end, label %if.else
1062 %and3 = and i32 %src2.trunc, 3
1063 %shl2 = shl nuw nsw i64 %shr47, 2
1064 %shl2.trunc = trunc i64 %shl2 to i32
1065 %and12 = and i32 %shl2.trunc, 12
1066 %BFISource = or i32 %and3, %and12 ; ...00000ABCD
1067 %BFIRHS = shl nuw nsw i32 %BFISource, 4 ; ...0ABCD0000
1068 %BFI = or i32 %BFIRHS, %BFISource ; ...0ABCDABCD
1069 %BFItrunc = trunc i32 %BFI to i16
1070 store i16 %BFItrunc, i16* %ptr, align 4