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(ptr nocapture %x, ptr 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: [[TMP1:%.*]] = load i32, ptr [[X:%.*]], align 4
19 ; OPT-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_Y:%.*]], ptr [[Y:%.*]], i64 0, i32 1
20 ; OPT-NEXT: [[BF_CLEAR:%.*]] = lshr i32 [[TMP1]], 3
21 ; OPT-NEXT: [[BF_CLEAR_LOBIT:%.*]] = and i32 [[BF_CLEAR]], 1
22 ; OPT-NEXT: [[FROMBOOL:%.*]] = trunc i32 [[BF_CLEAR_LOBIT]] to i8
23 ; OPT-NEXT: store i8 [[FROMBOOL]], ptr [[B]], align 1
26 %tmp1 = load i32, ptr %x, align 4
27 %b = getelementptr inbounds %struct.Y, ptr %y, i64 0, i32 1
28 %bf.clear = lshr i32 %tmp1, 3
29 %bf.clear.lobit = and i32 %bf.clear, 1
30 %frombool = trunc i32 %bf.clear.lobit to i8
31 store i8 %frombool, ptr %b, align 1
35 define i32 @baz(i64 %cav1.coerce) nounwind {
38 ; LLC-NEXT: sbfx w0, w0, #0, #4
41 ; OPT-NEXT: [[TMP:%.*]] = trunc i64 [[CAV1_COERCE:%.*]] to i32
42 ; OPT-NEXT: [[TMP1:%.*]] = shl i32 [[TMP]], 28
43 ; OPT-NEXT: [[BF_VAL_SEXT:%.*]] = ashr exact i32 [[TMP1]], 28
44 ; OPT-NEXT: ret i32 [[BF_VAL_SEXT]]
46 %tmp = trunc i64 %cav1.coerce to i32
47 %tmp1 = shl i32 %tmp, 28
48 %bf.val.sext = ashr exact i32 %tmp1, 28
52 define i32 @bar(i64 %cav1.coerce) nounwind {
55 ; LLC-NEXT: sbfx w0, w0, #4, #6
58 ; OPT-NEXT: [[TMP:%.*]] = trunc i64 [[CAV1_COERCE:%.*]] to i32
59 ; OPT-NEXT: [[CAV1_SROA_0_1_INSERT:%.*]] = shl i32 [[TMP]], 22
60 ; OPT-NEXT: [[TMP1:%.*]] = ashr i32 [[CAV1_SROA_0_1_INSERT]], 26
61 ; OPT-NEXT: ret i32 [[TMP1]]
63 %tmp = trunc i64 %cav1.coerce to i32
64 %cav1.sroa.0.1.insert = shl i32 %tmp, 22
65 %tmp1 = ashr i32 %cav1.sroa.0.1.insert, 26
69 define void @fct1(ptr nocapture %x, ptr nocapture %y) nounwind optsize ssp {
72 ; LLC-NEXT: ldr x8, [x0]
73 ; LLC-NEXT: ubfx x8, x8, #3, #1
74 ; LLC-NEXT: str x8, [x1]
77 ; OPT-NEXT: [[TMP1:%.*]] = load i64, ptr [[X:%.*]], align 4
78 ; OPT-NEXT: [[BF_CLEAR:%.*]] = lshr i64 [[TMP1]], 3
79 ; OPT-NEXT: [[BF_CLEAR_LOBIT:%.*]] = and i64 [[BF_CLEAR]], 1
80 ; OPT-NEXT: store i64 [[BF_CLEAR_LOBIT]], ptr [[Y:%.*]], align 8
83 %tmp1 = load i64, ptr %x, align 4
84 %bf.clear = lshr i64 %tmp1, 3
85 %bf.clear.lobit = and i64 %bf.clear, 1
86 store i64 %bf.clear.lobit, ptr %y, align 8
90 define i64 @fct2(i64 %cav1.coerce) nounwind {
93 ; LLC-NEXT: sbfx x0, x0, #0, #36
96 ; OPT-NEXT: [[TMP:%.*]] = shl i64 [[CAV1_COERCE:%.*]], 28
97 ; OPT-NEXT: [[BF_VAL_SEXT:%.*]] = ashr exact i64 [[TMP]], 28
98 ; OPT-NEXT: ret i64 [[BF_VAL_SEXT]]
100 %tmp = shl i64 %cav1.coerce, 28
101 %bf.val.sext = ashr exact i64 %tmp, 28
105 define i64 @fct3(i64 %cav1.coerce) nounwind {
108 ; LLC-NEXT: sbfx x0, x0, #4, #38
111 ; OPT-NEXT: [[CAV1_SROA_0_1_INSERT:%.*]] = shl i64 [[CAV1_COERCE:%.*]], 22
112 ; OPT-NEXT: [[TMP1:%.*]] = ashr i64 [[CAV1_SROA_0_1_INSERT]], 26
113 ; OPT-NEXT: ret i64 [[TMP1]]
115 %cav1.sroa.0.1.insert = shl i64 %cav1.coerce, 22
116 %tmp1 = ashr i64 %cav1.sroa.0.1.insert, 26
120 define void @fct4(ptr nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
122 ; LLC: // %bb.0: // %entry
123 ; LLC-NEXT: ldr x8, [x0]
124 ; LLC-NEXT: bfxil x8, x1, #16, #24
125 ; LLC-NEXT: str x8, [x0]
129 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
130 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -16777216
131 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
132 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 16777215
133 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
134 ; OPT-NEXT: store i64 [[OR]], ptr [[Y]], align 8
138 %0 = load i64, ptr %y, align 8
139 %and = and i64 %0, -16777216
140 %shr = lshr i64 %x, 16
141 %and1 = and i64 %shr, 16777215
142 %or = or i64 %and, %and1
143 store i64 %or, ptr %y, align 8
147 define void @fct5(ptr nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
149 ; LLC: // %bb.0: // %entry
150 ; LLC-NEXT: ldr w8, [x0]
151 ; LLC-NEXT: bfxil w8, w1, #16, #3
152 ; LLC-NEXT: str w8, [x0]
156 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
157 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
158 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
159 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
160 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
161 ; OPT-NEXT: store i32 [[OR]], ptr [[Y]], align 8
165 %0 = load i32, ptr %y, align 8
166 %and = and i32 %0, -8
167 %shr = lshr i32 %x, 16
168 %and1 = and i32 %shr, 7
169 %or = or i32 %and, %and1
170 store i32 %or, ptr %y, align 8
174 ; Check if we can still catch bfm instruction when we drop some low bits
175 define void @fct6(ptr nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
177 ; LLC: // %bb.0: // %entry
178 ; LLC-NEXT: ldr w8, [x0]
179 ; LLC-NEXT: bfxil w8, w1, #16, #3
180 ; LLC-NEXT: lsr w8, w8, #2
181 ; LLC-NEXT: str w8, [x0]
185 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
186 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
187 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
188 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
189 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
190 ; OPT-NEXT: [[SHR1:%.*]] = lshr i32 [[OR]], 2
191 ; OPT-NEXT: store i32 [[SHR1]], ptr [[Y]], align 8
195 ; lsr is an alias of ubfm
196 %0 = load i32, ptr %y, align 8
197 %and = and i32 %0, -8
198 %shr = lshr i32 %x, 16
199 %and1 = and i32 %shr, 7
200 %or = or i32 %and, %and1
201 %shr1 = lshr i32 %or, 2
202 store i32 %shr1, ptr %y, align 8
207 ; Check if we can still catch bfm instruction when we drop some high bits
208 define void @fct7(ptr nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
210 ; LLC: // %bb.0: // %entry
211 ; LLC-NEXT: ldr w8, [x0]
212 ; LLC-NEXT: bfxil w8, w1, #16, #3
213 ; LLC-NEXT: lsl w8, w8, #2
214 ; LLC-NEXT: str w8, [x0]
218 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
219 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
220 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
221 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
222 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
223 ; OPT-NEXT: [[SHL:%.*]] = shl i32 [[OR]], 2
224 ; OPT-NEXT: store i32 [[SHL]], ptr [[Y]], align 8
228 ; lsl is an alias of ubfm
229 %0 = load i32, ptr %y, align 8
230 %and = and i32 %0, -8
231 %shr = lshr i32 %x, 16
232 %and1 = and i32 %shr, 7
233 %or = or i32 %and, %and1
234 %shl = shl i32 %or, 2
235 store i32 %shl, ptr %y, align 8
240 ; Check if we can still catch bfm instruction when we drop some low bits
242 define void @fct8(ptr nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
244 ; LLC: // %bb.0: // %entry
245 ; LLC-NEXT: ldr x8, [x0]
246 ; LLC-NEXT: bfxil x8, x1, #16, #3
247 ; LLC-NEXT: lsr x8, x8, #2
248 ; LLC-NEXT: str x8, [x0]
252 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
253 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
254 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
255 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
256 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
257 ; OPT-NEXT: [[SHR1:%.*]] = lshr i64 [[OR]], 2
258 ; OPT-NEXT: store i64 [[SHR1]], ptr [[Y]], align 8
262 ; lsr is an alias of ubfm
263 %0 = load i64, ptr %y, align 8
264 %and = and i64 %0, -8
265 %shr = lshr i64 %x, 16
266 %and1 = and i64 %shr, 7
267 %or = or i64 %and, %and1
268 %shr1 = lshr i64 %or, 2
269 store i64 %shr1, ptr %y, align 8
274 ; Check if we can still catch bfm instruction when we drop some high bits
276 define void @fct9(ptr nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
278 ; LLC: // %bb.0: // %entry
279 ; LLC-NEXT: ldr x8, [x0]
280 ; LLC-NEXT: bfxil x8, x1, #16, #3
281 ; LLC-NEXT: lsl x8, x8, #2
282 ; LLC-NEXT: str x8, [x0]
286 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
287 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
288 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
289 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
290 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
291 ; OPT-NEXT: [[SHL:%.*]] = shl i64 [[OR]], 2
292 ; OPT-NEXT: store i64 [[SHL]], ptr [[Y]], align 8
296 ; lsr is an alias of ubfm
297 %0 = load i64, ptr %y, align 8
298 %and = and i64 %0, -8
299 %shr = lshr i64 %x, 16
300 %and1 = and i64 %shr, 7
301 %or = or i64 %and, %and1
302 %shl = shl i64 %or, 2
303 store i64 %shl, ptr %y, align 8
307 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
309 define void @fct10(ptr nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
311 ; LLC: // %bb.0: // %entry
312 ; LLC-NEXT: ldr w8, [x0]
313 ; LLC-NEXT: bfxil w8, w1, #0, #3
314 ; LLC-NEXT: lsl w8, w8, #2
315 ; LLC-NEXT: str w8, [x0]
319 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
320 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
321 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[X:%.*]], 7
322 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
323 ; OPT-NEXT: [[SHL:%.*]] = shl i32 [[OR]], 2
324 ; OPT-NEXT: store i32 [[SHL]], ptr [[Y]], align 8
328 ; lsl is an alias of ubfm
329 %0 = load i32, ptr %y, align 8
330 %and = and i32 %0, -8
331 %and1 = and i32 %x, 7
332 %or = or i32 %and, %and1
333 %shl = shl i32 %or, 2
334 store i32 %shl, ptr %y, align 8
338 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
340 define void @fct11(ptr nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
342 ; LLC: // %bb.0: // %entry
343 ; LLC-NEXT: ldr x8, [x0]
344 ; LLC-NEXT: bfxil x8, x1, #0, #3
345 ; LLC-NEXT: lsl x8, x8, #2
346 ; LLC-NEXT: str x8, [x0]
350 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
351 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
352 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[X:%.*]], 7
353 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
354 ; OPT-NEXT: [[SHL:%.*]] = shl i64 [[OR]], 2
355 ; OPT-NEXT: store i64 [[SHL]], ptr [[Y]], align 8
359 ; lsl is an alias of ubfm
360 %0 = load i64, ptr %y, align 8
361 %and = and i64 %0, -8
362 %and1 = and i64 %x, 7
363 %or = or i64 %and, %and1
364 %shl = shl i64 %or, 2
365 store i64 %shl, ptr %y, align 8
369 define zeroext i1 @fct12bis(i32 %tmp2) unnamed_addr nounwind ssp align 2 {
370 ; LLC-LABEL: fct12bis:
372 ; LLC-NEXT: ubfx w0, w0, #11, #1
374 ; OPT-LABEL: @fct12bis(
375 ; OPT-NEXT: [[AND_I_I:%.*]] = and i32 [[TMP2:%.*]], 2048
376 ; OPT-NEXT: [[TOBOOL_I_I:%.*]] = icmp ne i32 [[AND_I_I]], 0
377 ; OPT-NEXT: ret i1 [[TOBOOL_I_I]]
379 %and.i.i = and i32 %tmp2, 2048
380 %tobool.i.i = icmp ne i32 %and.i.i, 0
384 ; Check if we can still catch bfm instruction when we drop some high bits
386 define void @fct12(ptr nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
388 ; LLC: // %bb.0: // %entry
389 ; LLC-NEXT: ldr w8, [x0]
390 ; LLC-NEXT: bfxil w8, w1, #16, #3
391 ; LLC-NEXT: ubfx w8, w8, #2, #28
392 ; LLC-NEXT: str w8, [x0]
396 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
397 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
398 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
399 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
400 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
401 ; OPT-NEXT: [[SHL:%.*]] = shl i32 [[OR]], 2
402 ; OPT-NEXT: [[SHR2:%.*]] = lshr i32 [[SHL]], 4
403 ; OPT-NEXT: store i32 [[SHR2]], ptr [[Y]], align 8
407 ; lsr is an alias of ubfm
408 %0 = load i32, ptr %y, align 8
409 %and = and i32 %0, -8
410 %shr = lshr i32 %x, 16
411 %and1 = and i32 %shr, 7
412 %or = or i32 %and, %and1
413 %shl = shl i32 %or, 2
414 %shr2 = lshr i32 %shl, 4
415 store i32 %shr2, ptr %y, align 8
418 define void @fct12_mask(ptr nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
419 ; LLC-LABEL: fct12_mask:
420 ; LLC: // %bb.0: // %entry
421 ; LLC-NEXT: ldr w8, [x0]
422 ; LLC-NEXT: and w8, w8, #0x3ffffff8
423 ; LLC-NEXT: bfxil w8, w1, #16, #3
424 ; LLC-NEXT: lsr w8, w8, #2
425 ; LLC-NEXT: str w8, [x0]
427 ; OPT-LABEL: @fct12_mask(
429 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
430 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -8
431 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
432 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
433 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
434 ; OPT-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], 2
435 ; OPT-NEXT: [[MASK:%.*]] = and i32 [[LSHR]], 268435455
436 ; OPT-NEXT: store i32 [[MASK]], ptr [[Y]], align 8
440 ; lsr is an alias of ubfm
441 %0 = load i32, ptr %y, align 8
442 %and = and i32 %0, -8
443 %shr = lshr i32 %x, 16
444 %and1 = and i32 %shr, 7
445 %or = or i32 %and, %and1
446 %lshr = lshr i32 %or, 2
447 %mask = and i32 %lshr, 268435455
448 store i32 %mask, ptr %y, align 8
452 ; Check if we can still catch bfm instruction when we drop some high bits
455 define void @fct13(ptr nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
457 ; LLC: // %bb.0: // %entry
458 ; LLC-NEXT: ldr x8, [x0]
459 ; LLC-NEXT: bfxil x8, x1, #16, #3
460 ; LLC-NEXT: ubfx x8, x8, #2, #60
461 ; LLC-NEXT: str x8, [x0]
465 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
466 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
467 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
468 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
469 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
470 ; OPT-NEXT: [[SHL:%.*]] = shl i64 [[OR]], 2
471 ; OPT-NEXT: [[SHR2:%.*]] = lshr i64 [[SHL]], 4
472 ; OPT-NEXT: store i64 [[SHR2]], ptr [[Y]], align 8
476 ; lsr is an alias of ubfm
477 %0 = load i64, ptr %y, align 8
478 %and = and i64 %0, -8
479 %shr = lshr i64 %x, 16
480 %and1 = and i64 %shr, 7
481 %or = or i64 %and, %and1
482 %shl = shl i64 %or, 2
483 %shr2 = lshr i64 %shl, 4
484 store i64 %shr2, ptr %y, align 8
487 define void @fct13_mask(ptr nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
488 ; LLC-LABEL: fct13_mask:
489 ; LLC: // %bb.0: // %entry
490 ; LLC-NEXT: ldr x8, [x0]
491 ; LLC-NEXT: and x8, x8, #0x3ffffffffffffff8
492 ; LLC-NEXT: bfxil x8, x1, #16, #3
493 ; LLC-NEXT: lsr x8, x8, #2
494 ; LLC-NEXT: str x8, [x0]
496 ; OPT-LABEL: @fct13_mask(
498 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
499 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -8
500 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
501 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
502 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
503 ; OPT-NEXT: [[LSHR:%.*]] = lshr i64 [[OR]], 2
504 ; OPT-NEXT: [[MASK:%.*]] = and i64 [[LSHR]], 1152921504606846975
505 ; OPT-NEXT: store i64 [[MASK]], ptr [[Y]], align 8
509 ; lsr is an alias of ubfm
510 %0 = load i64, ptr %y, align 8
511 %and = and i64 %0, -8
512 %shr = lshr i64 %x, 16
513 %and1 = and i64 %shr, 7
514 %or = or i64 %and, %and1
515 %lshr = lshr i64 %or, 2
516 %mask = and i64 %lshr, 1152921504606846975
517 store i64 %mask, ptr %y, align 8
522 ; Check if we can still catch bfm instruction when we drop some high bits
524 define void @fct14(ptr nocapture %y, i32 %x, i32 %x1) nounwind optsize inlinehint ssp {
526 ; LLC: // %bb.0: // %entry
527 ; LLC-NEXT: ldr w8, [x0]
528 ; LLC-NEXT: bfxil w8, w1, #16, #8
529 ; LLC-NEXT: lsr w8, w8, #4
530 ; LLC-NEXT: bfxil w8, w2, #5, #3
531 ; LLC-NEXT: lsl w8, w8, #2
532 ; LLC-NEXT: str w8, [x0]
536 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
537 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], -256
538 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
539 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 255
540 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
541 ; OPT-NEXT: [[SHL:%.*]] = lshr i32 [[OR]], 4
542 ; OPT-NEXT: [[AND2:%.*]] = and i32 [[SHL]], -8
543 ; OPT-NEXT: [[SHR1:%.*]] = lshr i32 [[X1:%.*]], 5
544 ; OPT-NEXT: [[AND3:%.*]] = and i32 [[SHR1]], 7
545 ; OPT-NEXT: [[OR1:%.*]] = or i32 [[AND2]], [[AND3]]
546 ; OPT-NEXT: [[SHL1:%.*]] = shl i32 [[OR1]], 2
547 ; OPT-NEXT: store i32 [[SHL1]], ptr [[Y]], align 8
551 ; lsr is an alias of ubfm
552 ; lsl is an alias of ubfm
553 %0 = load i32, ptr %y, align 8
554 %and = and i32 %0, -256
555 %shr = lshr i32 %x, 16
556 %and1 = and i32 %shr, 255
557 %or = or i32 %and, %and1
558 %shl = lshr i32 %or, 4
559 %and2 = and i32 %shl, -8
560 %shr1 = lshr i32 %x1, 5
561 %and3 = and i32 %shr1, 7
562 %or1 = or i32 %and2, %and3
563 %shl1 = shl i32 %or1, 2
564 store i32 %shl1, ptr %y, align 8
568 ; Check if we can still catch bfm instruction when we drop some high bits
571 define void @fct15(ptr nocapture %y, i64 %x, i64 %x1) nounwind optsize inlinehint ssp {
573 ; LLC: // %bb.0: // %entry
574 ; LLC-NEXT: ldr x8, [x0]
575 ; LLC-NEXT: bfxil x8, x1, #16, #8
576 ; LLC-NEXT: lsr x8, x8, #4
577 ; LLC-NEXT: bfxil x8, x2, #5, #3
578 ; LLC-NEXT: lsl x8, x8, #2
579 ; LLC-NEXT: str x8, [x0]
583 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
584 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], -256
585 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
586 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 255
587 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
588 ; OPT-NEXT: [[SHL:%.*]] = lshr i64 [[OR]], 4
589 ; OPT-NEXT: [[AND2:%.*]] = and i64 [[SHL]], -8
590 ; OPT-NEXT: [[SHR1:%.*]] = lshr i64 [[X1:%.*]], 5
591 ; OPT-NEXT: [[AND3:%.*]] = and i64 [[SHR1]], 7
592 ; OPT-NEXT: [[OR1:%.*]] = or i64 [[AND2]], [[AND3]]
593 ; OPT-NEXT: [[SHL1:%.*]] = shl i64 [[OR1]], 2
594 ; OPT-NEXT: store i64 [[SHL1]], ptr [[Y]], align 8
598 ; lsr is an alias of ubfm
599 ; lsl is an alias of ubfm
600 %0 = load i64, ptr %y, align 8
601 %and = and i64 %0, -256
602 %shr = lshr i64 %x, 16
603 %and1 = and i64 %shr, 255
604 %or = or i64 %and, %and1
605 %shl = lshr i64 %or, 4
606 %and2 = and i64 %shl, -8
607 %shr1 = lshr i64 %x1, 5
608 %and3 = and i64 %shr1, 7
609 %or1 = or i64 %and2, %and3
610 %shl1 = shl i64 %or1, 2
611 store i64 %shl1, ptr %y, align 8
615 ; Check if we can still catch bfm instruction when we drop some high bits
616 ; and some low bits and a masking operation has to be kept
617 define void @fct16(ptr nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
619 ; LLC: // %bb.0: // %entry
620 ; LLC-NEXT: ldr w8, [x0]
621 ; LLC-NEXT: mov w9, #33120
622 ; LLC-NEXT: movk w9, #26, lsl #16
623 ; LLC-NEXT: and w8, w8, w9
624 ; LLC-NEXT: bfxil w8, w1, #16, #3
625 ; LLC-NEXT: ubfx w8, w8, #2, #28
626 ; LLC-NEXT: str w8, [x0]
630 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
631 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], 1737056
632 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
633 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
634 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
635 ; OPT-NEXT: [[SHL:%.*]] = shl i32 [[OR]], 2
636 ; OPT-NEXT: [[SHR2:%.*]] = lshr i32 [[SHL]], 4
637 ; OPT-NEXT: store i32 [[SHR2]], ptr [[Y]], align 8
641 ; Create the constant
643 ; lsr is an alias of ubfm
644 %0 = load i32, ptr %y, align 8
645 %and = and i32 %0, 1737056
646 %shr = lshr i32 %x, 16
647 %and1 = and i32 %shr, 7
648 %or = or i32 %and, %and1
649 %shl = shl i32 %or, 2
650 %shr2 = lshr i32 %shl, 4
651 store i32 %shr2, ptr %y, align 8
654 define void @fct16_mask(ptr nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
655 ; LLC-LABEL: fct16_mask:
656 ; LLC: // %bb.0: // %entry
657 ; LLC-NEXT: ldr w8, [x0]
658 ; LLC-NEXT: mov w9, #33120
659 ; LLC-NEXT: movk w9, #26, lsl #16
660 ; LLC-NEXT: and w8, w8, w9
661 ; LLC-NEXT: bfxil w8, w1, #16, #3
662 ; LLC-NEXT: lsr w8, w8, #2
663 ; LLC-NEXT: str w8, [x0]
665 ; OPT-LABEL: @fct16_mask(
667 ; OPT-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y:%.*]], align 8
668 ; OPT-NEXT: [[AND:%.*]] = and i32 [[TMP0]], 1737056
669 ; OPT-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], 16
670 ; OPT-NEXT: [[AND1:%.*]] = and i32 [[SHR]], 7
671 ; OPT-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND1]]
672 ; OPT-NEXT: [[LSHR:%.*]] = lshr i32 [[OR]], 2
673 ; OPT-NEXT: [[MASK:%.*]] = and i32 [[LSHR]], 268435455
674 ; OPT-NEXT: store i32 [[MASK]], ptr [[Y]], align 8
678 ; Create the constant
680 ; lsr is an alias of ubfm
681 %0 = load i32, ptr %y, align 8
682 %and = and i32 %0, 1737056
683 %shr = lshr i32 %x, 16
684 %and1 = and i32 %shr, 7
685 %or = or i32 %and, %and1
686 %lshr = lshr i32 %or, 2
687 %mask = and i32 %lshr, 268435455
688 store i32 %mask, ptr %y, align 8
693 ; Check if we can still catch bfm instruction when we drop some high bits
694 ; and some low bits and a masking operation has to be kept
696 define void @fct17(ptr nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
698 ; LLC: // %bb.0: // %entry
699 ; LLC-NEXT: ldr x8, [x0]
700 ; LLC-NEXT: mov w9, #33120
701 ; LLC-NEXT: movk w9, #26, lsl #16
702 ; LLC-NEXT: and x8, x8, x9
703 ; LLC-NEXT: bfxil x8, x1, #16, #3
704 ; LLC-NEXT: ubfx x8, x8, #2, #60
705 ; LLC-NEXT: str x8, [x0]
709 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
710 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], 1737056
711 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
712 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
713 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
714 ; OPT-NEXT: [[SHL:%.*]] = shl i64 [[OR]], 2
715 ; OPT-NEXT: [[SHR2:%.*]] = lshr i64 [[SHL]], 4
716 ; OPT-NEXT: store i64 [[SHR2]], ptr [[Y]], align 8
720 ; Create the constant
722 ; lsr is an alias of ubfm
723 %0 = load i64, ptr %y, align 8
724 %and = and i64 %0, 1737056
725 %shr = lshr i64 %x, 16
726 %and1 = and i64 %shr, 7
727 %or = or i64 %and, %and1
728 %shl = shl i64 %or, 2
729 %shr2 = lshr i64 %shl, 4
730 store i64 %shr2, ptr %y, align 8
733 define void @fct17_mask(ptr nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
734 ; LLC-LABEL: fct17_mask:
735 ; LLC: // %bb.0: // %entry
736 ; LLC-NEXT: ldr x8, [x0]
737 ; LLC-NEXT: mov w9, #33120
738 ; LLC-NEXT: movk w9, #26, lsl #16
739 ; LLC-NEXT: and x8, x8, x9
740 ; LLC-NEXT: bfxil x8, x1, #16, #3
741 ; LLC-NEXT: lsr x8, x8, #2
742 ; LLC-NEXT: str x8, [x0]
744 ; OPT-LABEL: @fct17_mask(
746 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[Y:%.*]], align 8
747 ; OPT-NEXT: [[AND:%.*]] = and i64 [[TMP0]], 1737056
748 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 16
749 ; OPT-NEXT: [[AND1:%.*]] = and i64 [[SHR]], 7
750 ; OPT-NEXT: [[OR:%.*]] = or i64 [[AND]], [[AND1]]
751 ; OPT-NEXT: [[LSHR:%.*]] = lshr i64 [[OR]], 2
752 ; OPT-NEXT: [[MASK:%.*]] = and i64 [[LSHR]], 1152921504606846975
753 ; OPT-NEXT: store i64 [[MASK]], ptr [[Y]], align 8
757 ; Create the constant
759 ; lsr is an alias of ubfm
760 %0 = load i64, ptr %y, align 8
761 %and = and i64 %0, 1737056
762 %shr = lshr i64 %x, 16
763 %and1 = and i64 %shr, 7
764 %or = or i64 %and, %and1
765 %lshr = lshr i64 %or, 2
766 %mask = and i64 %lshr, 1152921504606846975
767 store i64 %mask, ptr %y, align 8
771 define i64 @fct18(i32 %xor72) nounwind ssp {
774 ; LLC-NEXT: // kill: def $w0 killed $w0 def $x0
775 ; LLC-NEXT: ubfx x0, x0, #9, #8
778 ; OPT-NEXT: [[SHR81:%.*]] = lshr i32 [[XOR72:%.*]], 9
779 ; OPT-NEXT: [[CONV82:%.*]] = zext i32 [[SHR81]] to i64
780 ; OPT-NEXT: [[RESULT:%.*]] = and i64 [[CONV82]], 255
781 ; OPT-NEXT: ret i64 [[RESULT]]
783 %shr81 = lshr i32 %xor72, 9
784 %conv82 = zext i32 %shr81 to i64
785 %result = and i64 %conv82, 255
789 ; Using the access to the global array to keep the instruction and control flow.
790 @first_ones = external dso_local global [65536 x i8]
792 ; Function Attrs: nounwind readonly ssp
793 define i32 @fct19(i64 %arg1) nounwind readonly ssp {
795 ; LLC: // %bb.0: // %entry
796 ; LLC-NEXT: lsr x8, x0, #48
797 ; LLC-NEXT: cbz x8, .LBB26_2
798 ; LLC-NEXT: // %bb.1: // %if.then
799 ; LLC-NEXT: adrp x9, first_ones
800 ; LLC-NEXT: add x9, x9, :lo12:first_ones
801 ; LLC-NEXT: ldrb w0, [x9, x8]
803 ; LLC-NEXT: .LBB26_2: // %if.end
804 ; LLC-NEXT: ubfx x8, x0, #32, #16
805 ; LLC-NEXT: cbz w8, .LBB26_4
806 ; LLC-NEXT: // %bb.3: // %if.then7
807 ; LLC-NEXT: adrp x9, first_ones
808 ; LLC-NEXT: add x9, x9, :lo12:first_ones
809 ; LLC-NEXT: ldrb w8, [x9, x8]
810 ; LLC-NEXT: add w0, w8, #16
812 ; LLC-NEXT: .LBB26_4: // %if.end13
813 ; LLC-NEXT: ubfx x8, x0, #16, #16
814 ; LLC-NEXT: cbz w8, .LBB26_6
815 ; LLC-NEXT: // %bb.5: // %if.then17
816 ; LLC-NEXT: adrp x9, first_ones
817 ; LLC-NEXT: add x9, x9, :lo12:first_ones
818 ; LLC-NEXT: ldrb w8, [x9, x8]
819 ; LLC-NEXT: add w0, w8, #32
821 ; LLC-NEXT: .LBB26_6:
822 ; LLC-NEXT: mov w0, #64
826 ; OPT-NEXT: [[X_SROA_1_0_EXTRACT_SHIFT:%.*]] = lshr i64 [[ARG1:%.*]], 16
827 ; OPT-NEXT: [[X_SROA_1_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[X_SROA_1_0_EXTRACT_SHIFT]] to i16
828 ; OPT-NEXT: [[X_SROA_5_0_EXTRACT_SHIFT:%.*]] = lshr i64 [[ARG1]], 48
829 ; OPT-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X_SROA_5_0_EXTRACT_SHIFT]], 0
830 ; OPT-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
832 ; OPT-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 [[X_SROA_5_0_EXTRACT_SHIFT]]
833 ; OPT-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX3]], align 1
834 ; OPT-NEXT: [[CONV:%.*]] = zext i8 [[TMP0]] to i32
835 ; OPT-NEXT: br label [[RETURN:%.*]]
837 ; OPT-NEXT: [[TMP1:%.*]] = lshr i64 [[ARG1]], 32
838 ; OPT-NEXT: [[X_SROA_3_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[TMP1]] to i16
839 ; OPT-NEXT: [[TOBOOL6:%.*]] = icmp eq i16 [[X_SROA_3_0_EXTRACT_TRUNC]], 0
840 ; OPT-NEXT: br i1 [[TOBOOL6]], label [[IF_END13:%.*]], label [[IF_THEN7:%.*]]
842 ; OPT-NEXT: [[TMP2:%.*]] = lshr i64 [[ARG1]], 32
843 ; OPT-NEXT: [[IDXPROM10:%.*]] = and i64 [[TMP2]], 65535
844 ; OPT-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 [[IDXPROM10]]
845 ; OPT-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX11]], align 1
846 ; OPT-NEXT: [[CONV12:%.*]] = zext i8 [[TMP3]] to i32
847 ; OPT-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV12]], 16
848 ; OPT-NEXT: br label [[RETURN]]
850 ; OPT-NEXT: [[TMP4:%.*]] = lshr i64 [[ARG1]], 16
851 ; OPT-NEXT: [[TMP5:%.*]] = trunc i64 [[TMP4]] to i16
852 ; OPT-NEXT: [[TOBOOL16:%.*]] = icmp eq i16 [[TMP5]], 0
853 ; OPT-NEXT: br i1 [[TOBOOL16]], label [[RETURN]], label [[IF_THEN17:%.*]]
855 ; OPT-NEXT: [[TMP6:%.*]] = lshr i64 [[ARG1]], 16
856 ; OPT-NEXT: [[IDXPROM20:%.*]] = and i64 [[TMP6]], 65535
857 ; OPT-NEXT: [[ARRAYIDX21:%.*]] = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 [[IDXPROM20]]
858 ; OPT-NEXT: [[TMP7:%.*]] = load i8, ptr [[ARRAYIDX21]], align 1
859 ; OPT-NEXT: [[CONV22:%.*]] = zext i8 [[TMP7]] to i32
860 ; OPT-NEXT: [[ADD23:%.*]] = add nsw i32 [[CONV22]], 32
861 ; OPT-NEXT: br label [[RETURN]]
863 ; OPT-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CONV]], [[IF_THEN]] ], [ [[ADD]], [[IF_THEN7]] ], [ [[ADD23]], [[IF_THEN17]] ], [ 64, [[IF_END13]] ]
864 ; OPT-NEXT: ret i32 [[RETVAL_0]]
867 %x.sroa.1.0.extract.shift = lshr i64 %arg1, 16
868 %x.sroa.1.0.extract.trunc = trunc i64 %x.sroa.1.0.extract.shift to i16
869 %x.sroa.3.0.extract.shift = lshr i64 %arg1, 32
870 %x.sroa.5.0.extract.shift = lshr i64 %arg1, 48
871 %tobool = icmp eq i64 %x.sroa.5.0.extract.shift, 0
872 br i1 %tobool, label %if.end, label %if.then
874 if.then: ; preds = %entry
875 %arrayidx3 = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 %x.sroa.5.0.extract.shift
876 %0 = load i8, ptr %arrayidx3, align 1
877 %conv = zext i8 %0 to i32
880 if.end: ; preds = %entry
881 %x.sroa.3.0.extract.trunc = trunc i64 %x.sroa.3.0.extract.shift to i16
882 %tobool6 = icmp eq i16 %x.sroa.3.0.extract.trunc, 0
883 br i1 %tobool6, label %if.end13, label %if.then7
885 if.then7: ; preds = %if.end
886 ; "and" should be combined to "ubfm" while "ubfm" should be removed by cse.
887 ; So neither of them should be in the assemble code.
888 %idxprom10 = and i64 %x.sroa.3.0.extract.shift, 65535
889 %arrayidx11 = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 %idxprom10
890 %1 = load i8, ptr %arrayidx11, align 1
891 %conv12 = zext i8 %1 to i32
892 %add = add nsw i32 %conv12, 16
895 if.end13: ; preds = %if.end
896 %tobool16 = icmp eq i16 %x.sroa.1.0.extract.trunc, 0
897 br i1 %tobool16, label %return, label %if.then17
899 if.then17: ; preds = %if.end13
900 ; "and" should be combined to "ubfm" while "ubfm" should be removed by cse.
901 ; So neither of them should be in the assemble code.
902 %idxprom20 = and i64 %x.sroa.1.0.extract.shift, 65535
903 %arrayidx21 = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 %idxprom20
904 %2 = load i8, ptr %arrayidx21, align 1
905 %conv22 = zext i8 %2 to i32
906 %add23 = add nsw i32 %conv22, 32
909 return: ; preds = %if.end13, %if.then17, %if.then7, %if.then
910 %retval.0 = phi i32 [ %conv, %if.then ], [ %add, %if.then7 ], [ %add23, %if.then17 ], [ 64, %if.end13 ]
914 ; Make sure we do not assert if the immediate in and is bigger than i64.
916 define i80 @fct20(i128 %a, i128 %b) {
918 ; LLC: // %bb.0: // %entry
919 ; LLC-NEXT: mov x12, #11776 // =0x2e00
920 ; LLC-NEXT: lsr x8, x1, #18
921 ; LLC-NEXT: extr x9, x1, x0, #18
922 ; LLC-NEXT: movk x12, #25856, lsl #16
923 ; LLC-NEXT: orr x10, x2, x3
924 ; LLC-NEXT: mov w11, #26220 // =0x666c
925 ; LLC-NEXT: movk x12, #11077, lsl #32
926 ; LLC-NEXT: and x11, x8, x11
927 ; LLC-NEXT: cmp x10, #0
928 ; LLC-NEXT: movk x12, #45, lsl #48
929 ; LLC-NEXT: csel x1, x11, x8, eq
930 ; LLC-NEXT: and x12, x9, x12
931 ; LLC-NEXT: csel x0, x12, x9, eq
935 ; OPT-NEXT: [[SHR:%.*]] = lshr i128 [[A:%.*]], 18
936 ; OPT-NEXT: [[CONV:%.*]] = trunc i128 [[SHR]] to i80
937 ; OPT-NEXT: [[TOBOOL:%.*]] = icmp eq i128 [[B:%.*]], 0
938 ; OPT-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[END:%.*]]
940 ; OPT-NEXT: [[AND:%.*]] = and i128 [[SHR]], 483673642326615442599424
941 ; OPT-NEXT: [[CONV2:%.*]] = trunc i128 [[AND]] to i80
942 ; OPT-NEXT: br label [[END]]
944 ; OPT-NEXT: [[CONV3:%.*]] = phi i80 [ [[CONV]], [[ENTRY:%.*]] ], [ [[CONV2]], [[THEN]] ]
945 ; OPT-NEXT: ret i80 [[CONV3]]
948 %shr = lshr i128 %a, 18
949 %conv = trunc i128 %shr to i80
950 %tobool = icmp eq i128 %b, 0
951 br i1 %tobool, label %then, label %end
953 %and = and i128 %shr, 483673642326615442599424
954 %conv2 = trunc i128 %and to i80
957 %conv3 = phi i80 [%conv, %entry], [%conv2, %then]
961 ; Check if we can still catch UBFX when "AND" is used by SHL.
962 @arr = external dso_local global [8 x [64 x i64]]
963 define i64 @fct21(i64 %x) {
965 ; LLC: // %bb.0: // %entry
966 ; LLC-NEXT: ubfx x8, x0, #4, #4
967 ; LLC-NEXT: adrp x9, arr
968 ; LLC-NEXT: add x9, x9, :lo12:arr
969 ; LLC-NEXT: ldr x0, [x9, x8, lsl #3]
973 ; OPT-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], 4
974 ; OPT-NEXT: [[AND:%.*]] = and i64 [[SHR]], 15
975 ; OPT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x [64 x i64]], ptr @arr, i64 0, i64 0, i64 [[AND]]
976 ; OPT-NEXT: [[TMP0:%.*]] = load i64, ptr [[ARRAYIDX]], align 8
977 ; OPT-NEXT: ret i64 [[TMP0]]
980 %shr = lshr i64 %x, 4
981 %and = and i64 %shr, 15
982 %arrayidx = getelementptr inbounds [8 x [64 x i64]], ptr @arr, i64 0, i64 0, i64 %and
983 %0 = load i64, ptr %arrayidx, align 8
987 define i16 @test_ignored_rightbits(i32 %dst, i32 %in) {
988 ; LLC-LABEL: test_ignored_rightbits:
990 ; LLC-NEXT: and w8, w0, #0x7
991 ; LLC-NEXT: bfi w8, w1, #3, #4
992 ; LLC-NEXT: orr w0, w8, w8, lsl #8
994 ; OPT-LABEL: @test_ignored_rightbits(
995 ; OPT-NEXT: [[POSITIONED_FIELD:%.*]] = shl i32 [[IN:%.*]], 3
996 ; OPT-NEXT: [[POSITIONED_MASKED_FIELD:%.*]] = and i32 [[POSITIONED_FIELD]], 120
997 ; OPT-NEXT: [[MASKED_DST:%.*]] = and i32 [[DST:%.*]], 7
998 ; OPT-NEXT: [[INSERTION:%.*]] = or i32 [[MASKED_DST]], [[POSITIONED_MASKED_FIELD]]
999 ; OPT-NEXT: [[SHL16:%.*]] = shl i32 [[INSERTION]], 8
1000 ; OPT-NEXT: [[OR18:%.*]] = or i32 [[SHL16]], [[INSERTION]]
1001 ; OPT-NEXT: [[CONV19:%.*]] = trunc i32 [[OR18]] to i16
1002 ; OPT-NEXT: ret i16 [[CONV19]]
1004 %positioned_field = shl i32 %in, 3
1005 %positioned_masked_field = and i32 %positioned_field, 120
1006 %masked_dst = and i32 %dst, 7
1007 %insertion = or i32 %masked_dst, %positioned_masked_field
1009 %shl16 = shl i32 %insertion, 8
1010 %or18 = or i32 %shl16, %insertion
1011 %conv19 = trunc i32 %or18 to i16
1016 ; The following test excercises the case where we have a BFI
1017 ; instruction with the same input in both operands. We need to
1018 ; track the useful bits through both operands.
1019 define void @sameOperandBFI(i64 %src, i64 %src2, ptr %ptr) {
1020 ; LLC-LABEL: sameOperandBFI:
1021 ; LLC: // %bb.0: // %entry
1022 ; LLC-NEXT: cbnz wzr, .LBB30_2
1023 ; LLC-NEXT: // %bb.1: // %if.else
1024 ; LLC-NEXT: lsr x8, x0, #47
1025 ; LLC-NEXT: and w9, w1, #0x3
1026 ; LLC-NEXT: bfi w9, w8, #2, #2
1027 ; LLC-NEXT: orr w8, w9, w9, lsl #4
1028 ; LLC-NEXT: strh w8, [x2]
1029 ; LLC-NEXT: .LBB30_2: // %end
1031 ; OPT-LABEL: @sameOperandBFI(
1033 ; OPT-NEXT: [[SHR47:%.*]] = lshr i64 [[SRC:%.*]], 47
1034 ; OPT-NEXT: [[SRC2_TRUNC:%.*]] = trunc i64 [[SRC2:%.*]] to i32
1035 ; OPT-NEXT: br i1 undef, label [[END:%.*]], label [[IF_ELSE:%.*]]
1037 ; OPT-NEXT: [[AND3:%.*]] = and i32 [[SRC2_TRUNC]], 3
1038 ; OPT-NEXT: [[SHL2:%.*]] = shl nuw nsw i64 [[SHR47]], 2
1039 ; OPT-NEXT: [[SHL2_TRUNC:%.*]] = trunc i64 [[SHL2]] to i32
1040 ; OPT-NEXT: [[AND12:%.*]] = and i32 [[SHL2_TRUNC]], 12
1041 ; OPT-NEXT: [[BFISOURCE:%.*]] = or i32 [[AND3]], [[AND12]]
1042 ; OPT-NEXT: [[BFIRHS:%.*]] = shl nuw nsw i32 [[BFISOURCE]], 4
1043 ; OPT-NEXT: [[BFI:%.*]] = or i32 [[BFIRHS]], [[BFISOURCE]]
1044 ; OPT-NEXT: [[BFITRUNC:%.*]] = trunc i32 [[BFI]] to i16
1045 ; OPT-NEXT: store i16 [[BFITRUNC]], ptr [[PTR:%.*]], align 4
1046 ; OPT-NEXT: br label [[END]]
1048 ; OPT-NEXT: ret void
1051 %shr47 = lshr i64 %src, 47
1052 %src2.trunc = trunc i64 %src2 to i32
1053 br i1 undef, label %end, label %if.else
1056 %and3 = and i32 %src2.trunc, 3
1057 %shl2 = shl nuw nsw i64 %shr47, 2
1058 %shl2.trunc = trunc i64 %shl2 to i32
1059 %and12 = and i32 %shl2.trunc, 12
1060 %BFISource = or i32 %and3, %and12 ; ...00000ABCD
1061 %BFIRHS = shl nuw nsw i32 %BFISource, 4 ; ...0ABCD0000
1062 %BFI = or i32 %BFIRHS, %BFISource ; ...0ABCDABCD
1063 %BFItrunc = trunc i32 %BFI to i16
1064 store i16 %BFItrunc, ptr %ptr, align 4