ARM64: add more scalar patterns for usqadd & suqadd.
[oota-llvm.git] / test / CodeGen / ARM64 / bitfield-extract.ll
1 ; RUN: llc < %s -march=arm64 | FileCheck %s
2 %struct.X = type { i8, i8, [2 x i8] }
3 %struct.Y = type { i32, i8 }
4 %struct.Z = type { i8, i8, [2 x i8], i16 }
5 %struct.A = type { i64, i8 }
6
7 define void @foo(%struct.X* nocapture %x, %struct.Y* nocapture %y) nounwind optsize ssp {
8 ; CHECK-LABEL: foo:
9 ; CHECK: ubfm
10 ; CHECK-NOT: and
11 ; CHECK: ret
12
13   %tmp = bitcast %struct.X* %x to i32*
14   %tmp1 = load i32* %tmp, align 4
15   %b = getelementptr inbounds %struct.Y* %y, i64 0, i32 1
16   %bf.clear = lshr i32 %tmp1, 3
17   %bf.clear.lobit = and i32 %bf.clear, 1
18   %frombool = trunc i32 %bf.clear.lobit to i8
19   store i8 %frombool, i8* %b, align 1
20   ret void
21 }
22
23 define i32 @baz(i64 %cav1.coerce) nounwind {
24 ; CHECK-LABEL: baz:
25 ; CHECK: sbfm  w0, w0, #0, #3
26   %tmp = trunc i64 %cav1.coerce to i32
27   %tmp1 = shl i32 %tmp, 28
28   %bf.val.sext = ashr exact i32 %tmp1, 28
29   ret i32 %bf.val.sext
30 }
31
32 define i32 @bar(i64 %cav1.coerce) nounwind {
33 ; CHECK-LABEL: bar:
34 ; CHECK: sbfm  w0, w0, #4, #9
35   %tmp = trunc i64 %cav1.coerce to i32
36   %cav1.sroa.0.1.insert = shl i32 %tmp, 22
37   %tmp1 = ashr i32 %cav1.sroa.0.1.insert, 26
38   ret i32 %tmp1
39 }
40
41 define void @fct1(%struct.Z* nocapture %x, %struct.A* nocapture %y) nounwind optsize ssp {
42 ; CHECK-LABEL: fct1:
43 ; CHECK: ubfm
44 ; CHECK-NOT: and
45 ; CHECK: ret
46
47   %tmp = bitcast %struct.Z* %x to i64*
48   %tmp1 = load i64* %tmp, align 4
49   %b = getelementptr inbounds %struct.A* %y, i64 0, i32 0
50   %bf.clear = lshr i64 %tmp1, 3
51   %bf.clear.lobit = and i64 %bf.clear, 1
52   store i64 %bf.clear.lobit, i64* %b, align 8
53   ret void
54 }
55
56 define i64 @fct2(i64 %cav1.coerce) nounwind {
57 ; CHECK-LABEL: fct2:
58 ; CHECK: sbfm  x0, x0, #0, #35
59   %tmp = shl i64 %cav1.coerce, 28
60   %bf.val.sext = ashr exact i64 %tmp, 28
61   ret i64 %bf.val.sext
62 }
63
64 define i64 @fct3(i64 %cav1.coerce) nounwind {
65 ; CHECK-LABEL: fct3:
66 ; CHECK: sbfm  x0, x0, #4, #41
67   %cav1.sroa.0.1.insert = shl i64 %cav1.coerce, 22
68   %tmp1 = ashr i64 %cav1.sroa.0.1.insert, 26
69   ret i64 %tmp1
70 }
71
72 define void @fct4(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
73 entry:
74 ; CHECK-LABEL: fct4:
75 ; CHECK: ldr [[REG1:x[0-9]+]],
76 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #39
77 ; CHECK-NEXT: str [[REG1]],
78 ; CHECK-NEXT: ret
79   %0 = load i64* %y, align 8
80   %and = and i64 %0, -16777216
81   %shr = lshr i64 %x, 16
82   %and1 = and i64 %shr, 16777215
83   %or = or i64 %and, %and1
84   store i64 %or, i64* %y, align 8
85   ret void
86 }
87
88 define void @fct5(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
89 entry:
90 ; CHECK-LABEL: fct5:
91 ; CHECK: ldr [[REG1:w[0-9]+]],
92 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #18
93 ; CHECK-NEXT: str [[REG1]],
94 ; CHECK-NEXT: ret
95   %0 = load i32* %y, align 8
96   %and = and i32 %0, -8
97   %shr = lshr i32 %x, 16
98   %and1 = and i32 %shr, 7
99   %or = or i32 %and, %and1
100   store i32 %or, i32* %y, align 8
101   ret void
102 }
103
104 ; Check if we can still catch bfm instruction when we drop some low bits
105 define void @fct6(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
106 entry:
107 ; CHECK-LABEL: fct6:
108 ; CHECK: ldr [[REG1:w[0-9]+]],
109 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #18
110 ; lsr is an alias of ubfm
111 ; CHECK-NEXT: lsr [[REG2:w[0-9]+]], [[REG1]], #2
112 ; CHECK-NEXT: str [[REG2]],
113 ; CHECK-NEXT: ret
114   %0 = load i32* %y, align 8
115   %and = and i32 %0, -8
116   %shr = lshr i32 %x, 16
117   %and1 = and i32 %shr, 7
118   %or = or i32 %and, %and1
119   %shr1 = lshr i32 %or, 2
120   store i32 %shr1, i32* %y, align 8
121   ret void
122 }
123
124
125 ; Check if we can still catch bfm instruction when we drop some high bits
126 define void @fct7(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
127 entry:
128 ; CHECK-LABEL: fct7:
129 ; CHECK: ldr [[REG1:w[0-9]+]],
130 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #18
131 ; lsl is an alias of ubfm
132 ; CHECK-NEXT: lsl [[REG2:w[0-9]+]], [[REG1]], #2
133 ; CHECK-NEXT: str [[REG2]],
134 ; CHECK-NEXT: ret
135   %0 = load i32* %y, align 8
136   %and = and i32 %0, -8
137   %shr = lshr i32 %x, 16
138   %and1 = and i32 %shr, 7
139   %or = or i32 %and, %and1
140   %shl = shl i32 %or, 2
141   store i32 %shl, i32* %y, align 8
142   ret void
143 }
144
145
146 ; Check if we can still catch bfm instruction when we drop some low bits
147 ; (i64 version)
148 define void @fct8(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
149 entry:
150 ; CHECK-LABEL: fct8:
151 ; CHECK: ldr [[REG1:x[0-9]+]],
152 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #18
153 ; lsr is an alias of ubfm
154 ; CHECK-NEXT: lsr [[REG2:x[0-9]+]], [[REG1]], #2
155 ; CHECK-NEXT: str [[REG2]],
156 ; CHECK-NEXT: ret
157   %0 = load i64* %y, align 8
158   %and = and i64 %0, -8
159   %shr = lshr i64 %x, 16
160   %and1 = and i64 %shr, 7
161   %or = or i64 %and, %and1
162   %shr1 = lshr i64 %or, 2
163   store i64 %shr1, i64* %y, align 8
164   ret void
165 }
166
167
168 ; Check if we can still catch bfm instruction when we drop some high bits
169 ; (i64 version)
170 define void @fct9(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
171 entry:
172 ; CHECK-LABEL: fct9:
173 ; CHECK: ldr [[REG1:x[0-9]+]],
174 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #18
175 ; lsr is an alias of ubfm
176 ; CHECK-NEXT: lsl [[REG2:x[0-9]+]], [[REG1]], #2
177 ; CHECK-NEXT: str [[REG2]],
178 ; CHECK-NEXT: ret
179   %0 = load i64* %y, align 8
180   %and = and i64 %0, -8
181   %shr = lshr i64 %x, 16
182   %and1 = and i64 %shr, 7
183   %or = or i64 %and, %and1
184   %shl = shl i64 %or, 2
185   store i64 %shl, i64* %y, align 8
186   ret void
187 }
188
189 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
190 ; (i32 version)
191 define void @fct10(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
192 entry:
193 ; CHECK-LABEL: fct10:
194 ; CHECK: ldr [[REG1:w[0-9]+]],
195 ; CHECK-NEXT: bfm [[REG1]], w1, #0, #2
196 ; lsl is an alias of ubfm
197 ; CHECK-NEXT: lsl [[REG2:w[0-9]+]], [[REG1]], #2
198 ; CHECK-NEXT: str [[REG2]],
199 ; CHECK-NEXT: ret
200   %0 = load i32* %y, align 8
201   %and = and i32 %0, -8
202   %and1 = and i32 %x, 7
203   %or = or i32 %and, %and1
204   %shl = shl i32 %or, 2
205   store i32 %shl, i32* %y, align 8
206   ret void
207 }
208
209 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr)
210 ; (i64 version)
211 define void @fct11(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
212 entry:
213 ; CHECK-LABEL: fct11:
214 ; CHECK: ldr [[REG1:x[0-9]+]],
215 ; CHECK-NEXT: bfm [[REG1]], x1, #0, #2
216 ; lsl is an alias of ubfm
217 ; CHECK-NEXT: lsl [[REG2:x[0-9]+]], [[REG1]], #2
218 ; CHECK-NEXT: str [[REG2]],
219 ; CHECK-NEXT: ret
220   %0 = load i64* %y, align 8
221   %and = and i64 %0, -8
222   %and1 = and i64 %x, 7
223   %or = or i64 %and, %and1
224   %shl = shl i64 %or, 2
225   store i64 %shl, i64* %y, align 8
226   ret void
227 }
228
229 define zeroext i1 @fct12bis(i32 %tmp2) unnamed_addr nounwind ssp align 2 {
230 ; CHECK-LABEL: fct12bis:
231 ; CHECK-NOT: and
232 ; CHECK: ubfm w0, w0, #11, #11
233   %and.i.i = and i32 %tmp2, 2048
234   %tobool.i.i = icmp ne i32 %and.i.i, 0
235   ret i1 %tobool.i.i
236 }
237
238 ; Check if we can still catch bfm instruction when we drop some high bits
239 ; and some low bits
240 define void @fct12(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
241 entry:
242 ; CHECK-LABEL: fct12:
243 ; CHECK: ldr [[REG1:w[0-9]+]],
244 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #18
245 ; lsr is an alias of ubfm
246 ; CHECK-NEXT: ubfm [[REG2:w[0-9]+]], [[REG1]], #2, #29
247 ; CHECK-NEXT: str [[REG2]],
248 ; CHECK-NEXT: ret
249   %0 = load i32* %y, align 8
250   %and = and i32 %0, -8
251   %shr = lshr i32 %x, 16
252   %and1 = and i32 %shr, 7
253   %or = or i32 %and, %and1
254   %shl = shl i32 %or, 2
255   %shr2 = lshr i32 %shl, 4
256   store i32 %shr2, i32* %y, align 8
257   ret void
258 }
259
260 ; Check if we can still catch bfm instruction when we drop some high bits
261 ; and some low bits
262 ; (i64 version)
263 define void @fct13(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
264 entry:
265 ; CHECK-LABEL: fct13:
266 ; CHECK: ldr [[REG1:x[0-9]+]],
267 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #18
268 ; lsr is an alias of ubfm
269 ; CHECK-NEXT: ubfm [[REG2:x[0-9]+]], [[REG1]], #2, #61
270 ; CHECK-NEXT: str [[REG2]],
271 ; CHECK-NEXT: ret
272   %0 = load i64* %y, align 8
273   %and = and i64 %0, -8
274   %shr = lshr i64 %x, 16
275   %and1 = and i64 %shr, 7
276   %or = or i64 %and, %and1
277   %shl = shl i64 %or, 2
278   %shr2 = lshr i64 %shl, 4
279   store i64 %shr2, i64* %y, align 8
280   ret void
281 }
282
283
284 ; Check if we can still catch bfm instruction when we drop some high bits
285 ; and some low bits
286 define void @fct14(i32* nocapture %y, i32 %x, i32 %x1) nounwind optsize inlinehint ssp {
287 entry:
288 ; CHECK-LABEL: fct14:
289 ; CHECK: ldr [[REG1:w[0-9]+]],
290 ; CHECK-NEXT: bfm [[REG1]], w1, #16, #23
291 ; lsr is an alias of ubfm
292 ; CHECK-NEXT: lsr [[REG2:w[0-9]+]], [[REG1]], #4
293 ; CHECK-NEXT: bfm [[REG2]], w2, #5, #7
294 ; lsl is an alias of ubfm
295 ; CHECK-NEXT: lsl [[REG3:w[0-9]+]], [[REG2]], #2
296 ; CHECK-NEXT: str [[REG3]],
297 ; CHECK-NEXT: ret
298   %0 = load i32* %y, align 8
299   %and = and i32 %0, -256
300   %shr = lshr i32 %x, 16
301   %and1 = and i32 %shr, 255
302   %or = or i32 %and, %and1
303   %shl = lshr i32 %or, 4
304   %and2 = and i32 %shl, -8
305   %shr1 = lshr i32 %x1, 5
306   %and3 = and i32 %shr1, 7
307   %or1 = or i32 %and2, %and3
308   %shl1 = shl i32 %or1, 2
309   store i32 %shl1, i32* %y, align 8
310   ret void
311 }
312
313 ; Check if we can still catch bfm instruction when we drop some high bits
314 ; and some low bits
315 ; (i64 version)
316 define void @fct15(i64* nocapture %y, i64 %x, i64 %x1) nounwind optsize inlinehint ssp {
317 entry:
318 ; CHECK-LABEL: fct15:
319 ; CHECK: ldr [[REG1:x[0-9]+]],
320 ; CHECK-NEXT: bfm [[REG1]], x1, #16, #23
321 ; lsr is an alias of ubfm
322 ; CHECK-NEXT: lsr [[REG2:x[0-9]+]], [[REG1]], #4
323 ; CHECK-NEXT: bfm [[REG2]], x2, #5, #7
324 ; lsl is an alias of ubfm
325 ; CHECK-NEXT: lsl [[REG3:x[0-9]+]], [[REG2]], #2
326 ; CHECK-NEXT: str [[REG3]],
327 ; CHECK-NEXT: ret
328   %0 = load i64* %y, align 8
329   %and = and i64 %0, -256
330   %shr = lshr i64 %x, 16
331   %and1 = and i64 %shr, 255
332   %or = or i64 %and, %and1
333   %shl = lshr i64 %or, 4
334   %and2 = and i64 %shl, -8
335   %shr1 = lshr i64 %x1, 5
336   %and3 = and i64 %shr1, 7
337   %or1 = or i64 %and2, %and3
338   %shl1 = shl i64 %or1, 2
339   store i64 %shl1, i64* %y, align 8
340   ret void
341 }
342
343 ; Check if we can still catch bfm instruction when we drop some high bits
344 ; and some low bits and a masking operation has to be kept
345 define void @fct16(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp {
346 entry:
347 ; CHECK-LABEL: fct16:
348 ; CHECK: ldr [[REG1:w[0-9]+]],
349 ; Create the constant
350 ; CHECK: movz [[REGCST:w[0-9]+]], #26, lsl #16
351 ; CHECK: movk [[REGCST]], #33120
352 ; Do the masking
353 ; CHECK: and [[REG2:w[0-9]+]], [[REG1]], [[REGCST]]
354 ; CHECK-NEXT: bfm [[REG2]], w1, #16, #18
355 ; lsr is an alias of ubfm
356 ; CHECK-NEXT: ubfm [[REG3:w[0-9]+]], [[REG2]], #2, #29
357 ; CHECK-NEXT: str [[REG3]],
358 ; CHECK-NEXT: ret
359   %0 = load i32* %y, align 8
360   %and = and i32 %0, 1737056
361   %shr = lshr i32 %x, 16
362   %and1 = and i32 %shr, 7
363   %or = or i32 %and, %and1
364   %shl = shl i32 %or, 2
365   %shr2 = lshr i32 %shl, 4
366   store i32 %shr2, i32* %y, align 8
367   ret void
368 }
369
370
371 ; Check if we can still catch bfm instruction when we drop some high bits
372 ; and some low bits and a masking operation has to be kept
373 ; (i64 version)
374 define void @fct17(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp {
375 entry:
376 ; CHECK-LABEL: fct17:
377 ; CHECK: ldr [[REG1:x[0-9]+]],
378 ; Create the constant
379 ; CHECK: movz [[REGCST:x[0-9]+]], #26, lsl #16
380 ; CHECK: movk [[REGCST]], #33120
381 ; Do the masking
382 ; CHECK: and [[REG2:x[0-9]+]], [[REG1]], [[REGCST]]
383 ; CHECK-NEXT: bfm [[REG2]], x1, #16, #18
384 ; lsr is an alias of ubfm
385 ; CHECK-NEXT: ubfm [[REG3:x[0-9]+]], [[REG2]], #2, #61
386 ; CHECK-NEXT: str [[REG3]],
387 ; CHECK-NEXT: ret
388   %0 = load i64* %y, align 8
389   %and = and i64 %0, 1737056
390   %shr = lshr i64 %x, 16
391   %and1 = and i64 %shr, 7
392   %or = or i64 %and, %and1
393   %shl = shl i64 %or, 2
394   %shr2 = lshr i64 %shl, 4
395   store i64 %shr2, i64* %y, align 8
396   ret void
397 }
398
399 define i64 @fct18(i32 %xor72) nounwind ssp {
400 ; CHECK-LABEL: fct18:
401 ; CHECK: ubfm x0, x0, #9, #16
402   %shr81 = lshr i32 %xor72, 9
403   %conv82 = zext i32 %shr81 to i64
404   %result = and i64 %conv82, 255
405   ret i64 %result
406 }