[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-bitfield-extract.ll
blob7b792bc71bbe4df8ea6008ba75132c815089d498
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 {
11 ; LLC-LABEL: foo:
12 ; LLC:       // %bb.0:
13 ; LLC-NEXT:    ldr w8, [x0]
14 ; LLC-NEXT:    ubfx w8, w8, #3, #1
15 ; LLC-NEXT:    strb w8, [x1, #4]
16 ; LLC-NEXT:    ret
17 ; OPT-LABEL: @foo(
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
25 ; OPT-NEXT:    ret void
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
34   ret void
37 define i32 @baz(i64 %cav1.coerce) nounwind {
38 ; LLC-LABEL: baz:
39 ; LLC:       // %bb.0:
40 ; LLC-NEXT:    sbfx w0, w0, #0, #4
41 ; LLC-NEXT:    ret
42 ; OPT-LABEL: @baz(
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
51   ret i32 %bf.val.sext
54 define i32 @bar(i64 %cav1.coerce) nounwind {
55 ; LLC-LABEL: bar:
56 ; LLC:       // %bb.0:
57 ; LLC-NEXT:    sbfx w0, w0, #4, #6
58 ; LLC-NEXT:    ret
59 ; OPT-LABEL: @bar(
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
68   ret i32 %tmp1
71 define void @fct1(%struct.Z* nocapture %x, %struct.A* nocapture %y) nounwind optsize ssp {
72 ; LLC-LABEL: fct1:
73 ; LLC:       // %bb.0:
74 ; LLC-NEXT:    ldr x8, [x0]
75 ; LLC-NEXT:    ubfx x8, x8, #3, #1
76 ; LLC-NEXT:    str x8, [x1]
77 ; LLC-NEXT:    ret
78 ; OPT-LABEL: @fct1(
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
85 ; OPT-NEXT:    ret void
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
93   ret void
96 define i64 @fct2(i64 %cav1.coerce) nounwind {
97 ; LLC-LABEL: fct2:
98 ; LLC:       // %bb.0:
99 ; LLC-NEXT:    sbfx x0, x0, #0, #36
100 ; LLC-NEXT:    ret
101 ; OPT-LABEL: @fct2(
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
108   ret i64 %bf.val.sext
111 define i64 @fct3(i64 %cav1.coerce) nounwind {
112 ; LLC-LABEL: fct3:
113 ; LLC:       // %bb.0:
114 ; LLC-NEXT:    sbfx x0, x0, #4, #38
115 ; LLC-NEXT:    ret
116 ; OPT-LABEL: @fct3(
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
123   ret i64 %tmp1
126 define void @fct4(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
127 ; LLC-LABEL: fct4:
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]
132 ; LLC-NEXT:    ret
133 ; OPT-LABEL: @fct4(
134 ; OPT-NEXT:  entry:
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
141 ; OPT-NEXT:    ret void
143 entry:
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
150   ret void
153 define void @fct5(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
154 ; LLC-LABEL: fct5:
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]
159 ; LLC-NEXT:    ret
160 ; OPT-LABEL: @fct5(
161 ; OPT-NEXT:  entry:
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
168 ; OPT-NEXT:    ret void
170 entry:
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
177   ret void
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 {
182 ; LLC-LABEL: fct6:
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]
188 ; LLC-NEXT:    ret
189 ; OPT-LABEL: @fct6(
190 ; OPT-NEXT:  entry:
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
198 ; OPT-NEXT:    ret void
200 entry:
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
209   ret void
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 {
215 ; LLC-LABEL: fct7:
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]
221 ; LLC-NEXT:    ret
222 ; OPT-LABEL: @fct7(
223 ; OPT-NEXT:  entry:
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
231 ; OPT-NEXT:    ret void
233 entry:
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
242   ret void
246 ; Check if we can still catch bfm instruction when we drop some low bits
247 ; (i64 version)
248 define void @fct8(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
249 ; LLC-LABEL: fct8:
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]
255 ; LLC-NEXT:    ret
256 ; OPT-LABEL: @fct8(
257 ; OPT-NEXT:  entry:
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
265 ; OPT-NEXT:    ret void
267 entry:
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
276   ret void
280 ; Check if we can still catch bfm instruction when we drop some high bits
281 ; (i64 version)
282 define void @fct9(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
283 ; LLC-LABEL: fct9:
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]
289 ; LLC-NEXT:    ret
290 ; OPT-LABEL: @fct9(
291 ; OPT-NEXT:  entry:
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
299 ; OPT-NEXT:    ret void
301 entry:
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
310   ret void
313 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
314 ; (i32 version)
315 define void @fct10(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
316 ; LLC-LABEL: fct10:
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]
322 ; LLC-NEXT:    ret
323 ; OPT-LABEL: @fct10(
324 ; OPT-NEXT:  entry:
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
331 ; OPT-NEXT:    ret void
333 entry:
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
341   ret void
344 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
345 ; (i64 version)
346 define void @fct11(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
347 ; LLC-LABEL: fct11:
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]
353 ; LLC-NEXT:    ret
354 ; OPT-LABEL: @fct11(
355 ; OPT-NEXT:  entry:
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
362 ; OPT-NEXT:    ret void
364 entry:
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
372   ret void
375 define zeroext i1 @fct12bis(i32 %tmp2) unnamed_addr nounwind ssp align 2 {
376 ; LLC-LABEL: fct12bis:
377 ; LLC:       // %bb.0:
378 ; LLC-NEXT:    ubfx w0, w0, #11, #1
379 ; LLC-NEXT:    ret
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
387   ret i1 %tobool.i.i
390 ; Check if we can still catch bfm instruction when we drop some high bits
391 ; and some low bits
392 define void @fct12(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
393 ; LLC-LABEL: fct12:
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]
399 ; LLC-NEXT:    ret
400 ; OPT-LABEL: @fct12(
401 ; OPT-NEXT:  entry:
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
410 ; OPT-NEXT:    ret void
412 entry:
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
422   ret void
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]
432 ; LLC-NEXT:    ret
433 ; OPT-LABEL: @fct12_mask(
434 ; OPT-NEXT:  entry:
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
443 ; OPT-NEXT:    ret void
445 entry:
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
455   ret void
458 ; Check if we can still catch bfm instruction when we drop some high bits
459 ; and some low bits
460 ; (i64 version)
461 define void @fct13(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
462 ; LLC-LABEL: fct13:
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]
468 ; LLC-NEXT:    ret
469 ; OPT-LABEL: @fct13(
470 ; OPT-NEXT:  entry:
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
479 ; OPT-NEXT:    ret void
481 entry:
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
491   ret void
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]
501 ; LLC-NEXT:    ret
502 ; OPT-LABEL: @fct13_mask(
503 ; OPT-NEXT:  entry:
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
512 ; OPT-NEXT:    ret void
514 entry:
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
524   ret void
528 ; Check if we can still catch bfm instruction when we drop some high bits
529 ; and some low bits
530 define void @fct14(i32* nocapture %y, i32 %x, i32 %x1) nounwind optsize inlinehint ssp {
531 ; LLC-LABEL: fct14:
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]
539 ; LLC-NEXT:    ret
540 ; OPT-LABEL: @fct14(
541 ; OPT-NEXT:  entry:
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
554 ; OPT-NEXT:    ret void
556 entry:
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
571   ret void
574 ; Check if we can still catch bfm instruction when we drop some high bits
575 ; and some low bits
576 ; (i64 version)
577 define void @fct15(i64* nocapture %y, i64 %x, i64 %x1) nounwind optsize inlinehint ssp {
578 ; LLC-LABEL: fct15:
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]
586 ; LLC-NEXT:    ret
587 ; OPT-LABEL: @fct15(
588 ; OPT-NEXT:  entry:
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
601 ; OPT-NEXT:    ret void
603 entry:
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
618   ret void
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 {
624 ; LLC-LABEL: fct16:
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]
633 ; LLC-NEXT:    ret
634 ; OPT-LABEL: @fct16(
635 ; OPT-NEXT:  entry:
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
644 ; OPT-NEXT:    ret void
646 entry:
647 ; Create the constant
648 ; Do the masking
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
658   ret void
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]
670 ; LLC-NEXT:    ret
671 ; OPT-LABEL: @fct16_mask(
672 ; OPT-NEXT:  entry:
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
681 ; OPT-NEXT:    ret void
683 entry:
684 ; Create the constant
685 ; Do the masking
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
695   ret void
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
701 ; (i64 version)
702 define void @fct17(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
703 ; LLC-LABEL: fct17:
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]
712 ; LLC-NEXT:    ret
713 ; OPT-LABEL: @fct17(
714 ; OPT-NEXT:  entry:
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
723 ; OPT-NEXT:    ret void
725 entry:
726 ; Create the constant
727 ; Do the masking
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
737   ret void
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]
749 ; LLC-NEXT:    ret
750 ; OPT-LABEL: @fct17_mask(
751 ; OPT-NEXT:  entry:
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
760 ; OPT-NEXT:    ret void
762 entry:
763 ; Create the constant
764 ; Do the masking
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
774   ret void
777 define i64 @fct18(i32 %xor72) nounwind ssp {
778 ; LLC-LABEL: fct18:
779 ; LLC:       // %bb.0:
780 ; LLC-NEXT:    // kill: def $w0 killed $w0 def $x0
781 ; LLC-NEXT:    ubfx x0, x0, #9, #8
782 ; LLC-NEXT:    ret
783 ; OPT-LABEL: @fct18(
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
792   ret i64 %result
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  {
800 ; LLC-LABEL: fct19:
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]
808 ; LLC-NEXT:    ret
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
817 ; LLC-NEXT:    ret
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
826 ; LLC-NEXT:    ret
827 ; LLC-NEXT:  .LBB26_6:
828 ; LLC-NEXT:    mov w0, #64
829 ; LLC-NEXT:    ret
830 ; OPT-LABEL: @fct19(
831 ; OPT-NEXT:  entry:
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:%.*]]
837 ; OPT:       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:%.*]]
842 ; OPT:       if.end:
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:%.*]]
847 ; OPT:       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]]
855 ; OPT:       if.end13:
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:%.*]]
860 ; OPT:       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]]
868 ; OPT:       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]]
872 entry:
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
884   br label %return
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
899   br label %return
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
913   br label %return
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 ]
917   ret i32 %retval.0
920 ; Make sure we do not assert if the immediate in and is bigger than i64.
921 ; PR19503.
922 define i80 @fct20(i128 %a, i128 %b) {
923 ; LLC-LABEL: fct20:
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
938 ; LLC-NEXT:    ret
939 ; OPT-LABEL: @fct20(
940 ; OPT-NEXT:  entry:
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:%.*]]
945 ; OPT:       then:
946 ; OPT-NEXT:    [[AND:%.*]] = and i128 [[SHR]], 483673642326615442599424
947 ; OPT-NEXT:    [[CONV2:%.*]] = trunc i128 [[AND]] to i80
948 ; OPT-NEXT:    br label [[END]]
949 ; OPT:       end:
950 ; OPT-NEXT:    [[CONV3:%.*]] = phi i80 [ [[CONV]], [[ENTRY:%.*]] ], [ [[CONV2]], [[THEN]] ]
951 ; OPT-NEXT:    ret i80 [[CONV3]]
953 entry:
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
958 then:
959   %and = and i128 %shr, 483673642326615442599424
960   %conv2 = trunc i128 %and to i80
961   br label %end
962 end:
963   %conv3 = phi i80 [%conv, %entry], [%conv2, %then]
964   ret i80 %conv3
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) {
970 ; LLC-LABEL: fct21:
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]
976 ; LLC-NEXT:    ret
977 ; OPT-LABEL: @fct21(
978 ; OPT-NEXT:  entry:
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]]
985 entry:
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
990   ret i64 %0
993 define i16 @test_ignored_rightbits(i32 %dst, i32 %in) {
994 ; LLC-LABEL: test_ignored_rightbits:
995 ; LLC:       // %bb.0:
996 ; LLC-NEXT:    and w0, w0, #0x7
997 ; LLC-NEXT:    bfi w0, w1, #3, #4
998 ; LLC-NEXT:    bfi w0, w0, #8, #7
999 ; LLC-NEXT:    ret
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
1019   ret i16 %conv19
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
1036 ; LLC-NEXT:    ret
1037 ; OPT-LABEL: @sameOperandBFI(
1038 ; OPT-NEXT:  entry:
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:%.*]]
1042 ; OPT:       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]]
1053 ; OPT:       end:
1054 ; OPT-NEXT:    ret void
1056 entry:
1057   %shr47 = lshr i64 %src, 47
1058   %src2.trunc = trunc i64 %src2 to i32
1059   br i1 undef, label %end, label %if.else
1061 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
1071   br label %end
1073 end:
1074   ret void