xref: /llvm-project/llvm/test/CodeGen/AArch64/logic-shift.ll (revision cc82f1290a1e2157a6c0530d78d8cc84d2b8553d)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s
3
4define i8 @or_lshr_commute0(i8 %x0, i8 %x1, i8 %y, i8 %z) {
5; CHECK-LABEL: or_lshr_commute0:
6; CHECK:       // %bb.0:
7; CHECK-NEXT:    orr w8, w0, w1
8; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
9; CHECK-NEXT:    and w8, w8, #0xff
10; CHECK-NEXT:    lsr w8, w8, w2
11; CHECK-NEXT:    orr w0, w8, w3
12; CHECK-NEXT:    ret
13  %sh1 = lshr i8 %x0, %y
14  %sh2 = lshr i8 %x1, %y
15  %logic = or i8 %sh1, %z
16  %r = or i8 %logic, %sh2
17  ret i8 %r
18}
19
20define i32 @or_lshr_commute1(i32 %x0, i32 %x1, i32 %y, i32 %z) {
21; CHECK-LABEL: or_lshr_commute1:
22; CHECK:       // %bb.0:
23; CHECK-NEXT:    orr w8, w0, w1
24; CHECK-NEXT:    lsr w8, w8, w2
25; CHECK-NEXT:    orr w0, w8, w3
26; CHECK-NEXT:    ret
27  %sh1 = lshr i32 %x0, %y
28  %sh2 = lshr i32 %x1, %y
29  %logic = or i32 %z, %sh1
30  %r = or i32 %logic, %sh2
31  ret i32 %r
32}
33
34define <8 x i16> @or_lshr_commute2(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
35; CHECK-LABEL: or_lshr_commute2:
36; CHECK:       // %bb.0:
37; CHECK-NEXT:    orr v0.16b, v0.16b, v1.16b
38; CHECK-NEXT:    neg v1.8h, v2.8h
39; CHECK-NEXT:    ushl v0.8h, v0.8h, v1.8h
40; CHECK-NEXT:    orr v0.16b, v0.16b, v3.16b
41; CHECK-NEXT:    ret
42  %sh1 = lshr <8 x i16> %x0, %y
43  %sh2 = lshr <8 x i16> %x1, %y
44  %logic = or <8 x i16> %sh1, %z
45  %r = or <8 x i16> %sh2, %logic
46  ret <8 x i16> %r
47}
48
49define <2 x i64> @or_lshr_commute3(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
50; CHECK-LABEL: or_lshr_commute3:
51; CHECK:       // %bb.0:
52; CHECK-NEXT:    orr v0.16b, v0.16b, v1.16b
53; CHECK-NEXT:    neg v1.2d, v2.2d
54; CHECK-NEXT:    ushl v0.2d, v0.2d, v1.2d
55; CHECK-NEXT:    orr v0.16b, v0.16b, v3.16b
56; CHECK-NEXT:    ret
57  %sh1 = lshr <2 x i64> %x0, %y
58  %sh2 = lshr <2 x i64> %x1, %y
59  %logic = or <2 x i64> %z, %sh1
60  %r = or <2 x i64> %sh2, %logic
61  ret <2 x i64> %r
62}
63
64define i16 @or_ashr_commute0(i16 %x0, i16 %x1, i16 %y, i16 %z) {
65; CHECK-LABEL: or_ashr_commute0:
66; CHECK:       // %bb.0:
67; CHECK-NEXT:    orr w8, w0, w1
68; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
69; CHECK-NEXT:    sxth w8, w8
70; CHECK-NEXT:    asr w8, w8, w2
71; CHECK-NEXT:    orr w0, w8, w3
72; CHECK-NEXT:    ret
73  %sh1 = ashr i16 %x0, %y
74  %sh2 = ashr i16 %x1, %y
75  %logic = or i16 %sh1, %z
76  %r = or i16 %logic, %sh2
77  ret i16 %r
78}
79
80define i64 @or_ashr_commute1(i64 %x0, i64 %x1, i64 %y, i64 %z) {
81; CHECK-LABEL: or_ashr_commute1:
82; CHECK:       // %bb.0:
83; CHECK-NEXT:    orr x8, x0, x1
84; CHECK-NEXT:    asr x8, x8, x2
85; CHECK-NEXT:    orr x0, x8, x3
86; CHECK-NEXT:    ret
87  %sh1 = ashr i64 %x0, %y
88  %sh2 = ashr i64 %x1, %y
89  %logic = or i64 %z, %sh1
90  %r = or i64 %logic, %sh2
91  ret i64 %r
92}
93
94define <4 x i32> @or_ashr_commute2(<4 x i32> %x0, <4 x i32> %x1, <4 x i32> %y, <4 x i32> %z) {
95; CHECK-LABEL: or_ashr_commute2:
96; CHECK:       // %bb.0:
97; CHECK-NEXT:    orr v0.16b, v0.16b, v1.16b
98; CHECK-NEXT:    neg v1.4s, v2.4s
99; CHECK-NEXT:    sshl v0.4s, v0.4s, v1.4s
100; CHECK-NEXT:    orr v0.16b, v0.16b, v3.16b
101; CHECK-NEXT:    ret
102  %sh1 = ashr <4 x i32> %x0, %y
103  %sh2 = ashr <4 x i32> %x1, %y
104  %logic = or <4 x i32> %sh1, %z
105  %r = or <4 x i32> %sh2, %logic
106  ret <4 x i32> %r
107}
108
109define <16 x i8> @or_ashr_commute3(<16 x i8> %x0, <16 x i8> %x1, <16 x i8> %y, <16 x i8> %z) {
110; CHECK-LABEL: or_ashr_commute3:
111; CHECK:       // %bb.0:
112; CHECK-NEXT:    orr v0.16b, v0.16b, v1.16b
113; CHECK-NEXT:    neg v1.16b, v2.16b
114; CHECK-NEXT:    sshl v0.16b, v0.16b, v1.16b
115; CHECK-NEXT:    orr v0.16b, v0.16b, v3.16b
116; CHECK-NEXT:    ret
117  %sh1 = ashr <16 x i8> %x0, %y
118  %sh2 = ashr <16 x i8> %x1, %y
119  %logic = or <16 x i8> %z, %sh1
120  %r = or <16 x i8> %sh2, %logic
121  ret <16 x i8> %r
122}
123
124define i32 @or_shl_commute0(i32 %x0, i32 %x1, i32 %y, i32 %z) {
125; CHECK-LABEL: or_shl_commute0:
126; CHECK:       // %bb.0:
127; CHECK-NEXT:    orr w8, w0, w1
128; CHECK-NEXT:    lsl w8, w8, w2
129; CHECK-NEXT:    orr w0, w8, w3
130; CHECK-NEXT:    ret
131  %sh1 = shl i32 %x0, %y
132  %sh2 = shl i32 %x1, %y
133  %logic = or i32 %sh1, %z
134  %r = or i32 %logic, %sh2
135  ret i32 %r
136}
137
138define i8 @or_shl_commute1(i8 %x0, i8 %x1, i8 %y, i8 %z) {
139; CHECK-LABEL: or_shl_commute1:
140; CHECK:       // %bb.0:
141; CHECK-NEXT:    orr w8, w0, w1
142; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
143; CHECK-NEXT:    lsl w8, w8, w2
144; CHECK-NEXT:    orr w0, w8, w3
145; CHECK-NEXT:    ret
146  %sh1 = shl i8 %x0, %y
147  %sh2 = shl i8 %x1, %y
148  %logic = or i8 %z, %sh1
149  %r = or i8 %logic, %sh2
150  ret i8 %r
151}
152
153define <2 x i64> @or_shl_commute2(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
154; CHECK-LABEL: or_shl_commute2:
155; CHECK:       // %bb.0:
156; CHECK-NEXT:    orr v0.16b, v0.16b, v1.16b
157; CHECK-NEXT:    ushl v0.2d, v0.2d, v2.2d
158; CHECK-NEXT:    orr v0.16b, v0.16b, v3.16b
159; CHECK-NEXT:    ret
160  %sh1 = shl <2 x i64> %x0, %y
161  %sh2 = shl <2 x i64> %x1, %y
162  %logic = or <2 x i64> %sh1, %z
163  %r = or <2 x i64> %sh2, %logic
164  ret <2 x i64> %r
165}
166
167define <8 x i16> @or_shl_commute3(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
168; CHECK-LABEL: or_shl_commute3:
169; CHECK:       // %bb.0:
170; CHECK-NEXT:    orr v0.16b, v0.16b, v1.16b
171; CHECK-NEXT:    ushl v0.8h, v0.8h, v2.8h
172; CHECK-NEXT:    orr v0.16b, v0.16b, v3.16b
173; CHECK-NEXT:    ret
174  %sh1 = shl <8 x i16> %x0, %y
175  %sh2 = shl <8 x i16> %x1, %y
176  %logic = or <8 x i16> %z, %sh1
177  %r = or <8 x i16> %sh2, %logic
178  ret <8 x i16> %r
179}
180
181; negative test - mismatched shift opcodes
182
183define i64 @or_mix_shr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
184; CHECK-LABEL: or_mix_shr:
185; CHECK:       // %bb.0:
186; CHECK-NEXT:    asr x8, x0, x2
187; CHECK-NEXT:    lsr x9, x1, x2
188; CHECK-NEXT:    orr x8, x8, x3
189; CHECK-NEXT:    orr x0, x8, x9
190; CHECK-NEXT:    ret
191  %sh1 = ashr i64 %x0, %y
192  %sh2 = lshr i64 %x1, %y
193  %logic = or i64 %sh1, %z
194  %r = or i64 %logic, %sh2
195  ret i64 %r
196}
197
198; negative test - mixed shift amounts
199
200define i64 @or_lshr_mix_shift_amount(i64 %x0, i64 %x1, i64 %y, i64 %z, i64 %w) {
201; CHECK-LABEL: or_lshr_mix_shift_amount:
202; CHECK:       // %bb.0:
203; CHECK-NEXT:    lsr x8, x0, x2
204; CHECK-NEXT:    lsr x9, x1, x4
205; CHECK-NEXT:    orr x8, x8, x3
206; CHECK-NEXT:    orr x0, x8, x9
207; CHECK-NEXT:    ret
208  %sh1 = lshr i64 %x0, %y
209  %sh2 = lshr i64 %x1, %w
210  %logic = or i64 %sh1, %z
211  %r = or i64 %logic, %sh2
212  ret i64 %r
213}
214
215; negative test - mismatched logic opcodes
216
217define i64 @mix_logic_lshr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
218; CHECK-LABEL: mix_logic_lshr:
219; CHECK:       // %bb.0:
220; CHECK-NEXT:    lsr x8, x0, x2
221; CHECK-NEXT:    lsr x9, x1, x2
222; CHECK-NEXT:    eor x8, x8, x3
223; CHECK-NEXT:    orr x0, x8, x9
224; CHECK-NEXT:    ret
225  %sh1 = lshr i64 %x0, %y
226  %sh2 = lshr i64 %x1, %y
227  %logic = xor i64 %sh1, %z
228  %r = or i64 %logic, %sh2
229  ret i64 %r
230}
231
232define i8 @xor_lshr_commute0(i8 %x0, i8 %x1, i8 %y, i8 %z) {
233; CHECK-LABEL: xor_lshr_commute0:
234; CHECK:       // %bb.0:
235; CHECK-NEXT:    eor w8, w0, w1
236; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
237; CHECK-NEXT:    and w8, w8, #0xff
238; CHECK-NEXT:    lsr w8, w8, w2
239; CHECK-NEXT:    eor w0, w8, w3
240; CHECK-NEXT:    ret
241  %sh1 = lshr i8 %x0, %y
242  %sh2 = lshr i8 %x1, %y
243  %logic = xor i8 %sh1, %z
244  %r = xor i8 %logic, %sh2
245  ret i8 %r
246}
247
248define i32 @xor_lshr_commute1(i32 %x0, i32 %x1, i32 %y, i32 %z) {
249; CHECK-LABEL: xor_lshr_commute1:
250; CHECK:       // %bb.0:
251; CHECK-NEXT:    eor w8, w0, w1
252; CHECK-NEXT:    lsr w8, w8, w2
253; CHECK-NEXT:    eor w0, w8, w3
254; CHECK-NEXT:    ret
255  %sh1 = lshr i32 %x0, %y
256  %sh2 = lshr i32 %x1, %y
257  %logic = xor i32 %z, %sh1
258  %r = xor i32 %logic, %sh2
259  ret i32 %r
260}
261
262define <8 x i16> @xor_lshr_commute2(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
263; CHECK-LABEL: xor_lshr_commute2:
264; CHECK:       // %bb.0:
265; CHECK-NEXT:    eor v0.16b, v0.16b, v1.16b
266; CHECK-NEXT:    neg v1.8h, v2.8h
267; CHECK-NEXT:    ushl v0.8h, v0.8h, v1.8h
268; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
269; CHECK-NEXT:    ret
270  %sh1 = lshr <8 x i16> %x0, %y
271  %sh2 = lshr <8 x i16> %x1, %y
272  %logic = xor <8 x i16> %sh1, %z
273  %r = xor <8 x i16> %sh2, %logic
274  ret <8 x i16> %r
275}
276
277define <2 x i64> @xor_lshr_commute3(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
278; CHECK-LABEL: xor_lshr_commute3:
279; CHECK:       // %bb.0:
280; CHECK-NEXT:    eor v0.16b, v0.16b, v1.16b
281; CHECK-NEXT:    neg v1.2d, v2.2d
282; CHECK-NEXT:    ushl v0.2d, v0.2d, v1.2d
283; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
284; CHECK-NEXT:    ret
285  %sh1 = lshr <2 x i64> %x0, %y
286  %sh2 = lshr <2 x i64> %x1, %y
287  %logic = xor <2 x i64> %z, %sh1
288  %r = xor <2 x i64> %sh2, %logic
289  ret <2 x i64> %r
290}
291
292define i16 @xor_ashr_commute0(i16 %x0, i16 %x1, i16 %y, i16 %z) {
293; CHECK-LABEL: xor_ashr_commute0:
294; CHECK:       // %bb.0:
295; CHECK-NEXT:    eor w8, w0, w1
296; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
297; CHECK-NEXT:    sxth w8, w8
298; CHECK-NEXT:    asr w8, w8, w2
299; CHECK-NEXT:    eor w0, w8, w3
300; CHECK-NEXT:    ret
301  %sh1 = ashr i16 %x0, %y
302  %sh2 = ashr i16 %x1, %y
303  %logic = xor i16 %sh1, %z
304  %r = xor i16 %logic, %sh2
305  ret i16 %r
306}
307
308define i64 @xor_ashr_commute1(i64 %x0, i64 %x1, i64 %y, i64 %z) {
309; CHECK-LABEL: xor_ashr_commute1:
310; CHECK:       // %bb.0:
311; CHECK-NEXT:    eor x8, x0, x1
312; CHECK-NEXT:    asr x8, x8, x2
313; CHECK-NEXT:    eor x0, x8, x3
314; CHECK-NEXT:    ret
315  %sh1 = ashr i64 %x0, %y
316  %sh2 = ashr i64 %x1, %y
317  %logic = xor i64 %z, %sh1
318  %r = xor i64 %logic, %sh2
319  ret i64 %r
320}
321
322define <4 x i32> @xor_ashr_commute2(<4 x i32> %x0, <4 x i32> %x1, <4 x i32> %y, <4 x i32> %z) {
323; CHECK-LABEL: xor_ashr_commute2:
324; CHECK:       // %bb.0:
325; CHECK-NEXT:    eor v0.16b, v0.16b, v1.16b
326; CHECK-NEXT:    neg v1.4s, v2.4s
327; CHECK-NEXT:    sshl v0.4s, v0.4s, v1.4s
328; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
329; CHECK-NEXT:    ret
330  %sh1 = ashr <4 x i32> %x0, %y
331  %sh2 = ashr <4 x i32> %x1, %y
332  %logic = xor <4 x i32> %sh1, %z
333  %r = xor <4 x i32> %sh2, %logic
334  ret <4 x i32> %r
335}
336
337define <16 x i8> @xor_ashr_commute3(<16 x i8> %x0, <16 x i8> %x1, <16 x i8> %y, <16 x i8> %z) {
338; CHECK-LABEL: xor_ashr_commute3:
339; CHECK:       // %bb.0:
340; CHECK-NEXT:    eor v0.16b, v0.16b, v1.16b
341; CHECK-NEXT:    neg v1.16b, v2.16b
342; CHECK-NEXT:    sshl v0.16b, v0.16b, v1.16b
343; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
344; CHECK-NEXT:    ret
345  %sh1 = ashr <16 x i8> %x0, %y
346  %sh2 = ashr <16 x i8> %x1, %y
347  %logic = xor <16 x i8> %z, %sh1
348  %r = xor <16 x i8> %sh2, %logic
349  ret <16 x i8> %r
350}
351
352define i32 @xor_shl_commute0(i32 %x0, i32 %x1, i32 %y, i32 %z) {
353; CHECK-LABEL: xor_shl_commute0:
354; CHECK:       // %bb.0:
355; CHECK-NEXT:    eor w8, w0, w1
356; CHECK-NEXT:    lsl w8, w8, w2
357; CHECK-NEXT:    eor w0, w8, w3
358; CHECK-NEXT:    ret
359  %sh1 = shl i32 %x0, %y
360  %sh2 = shl i32 %x1, %y
361  %logic = xor i32 %sh1, %z
362  %r = xor i32 %logic, %sh2
363  ret i32 %r
364}
365
366define i8 @xor_shl_commute1(i8 %x0, i8 %x1, i8 %y, i8 %z) {
367; CHECK-LABEL: xor_shl_commute1:
368; CHECK:       // %bb.0:
369; CHECK-NEXT:    eor w8, w0, w1
370; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
371; CHECK-NEXT:    lsl w8, w8, w2
372; CHECK-NEXT:    eor w0, w8, w3
373; CHECK-NEXT:    ret
374  %sh1 = shl i8 %x0, %y
375  %sh2 = shl i8 %x1, %y
376  %logic = xor i8 %z, %sh1
377  %r = xor i8 %logic, %sh2
378  ret i8 %r
379}
380
381define <2 x i64> @xor_shl_commute2(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
382; CHECK-LABEL: xor_shl_commute2:
383; CHECK:       // %bb.0:
384; CHECK-NEXT:    eor v0.16b, v0.16b, v1.16b
385; CHECK-NEXT:    ushl v0.2d, v0.2d, v2.2d
386; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
387; CHECK-NEXT:    ret
388  %sh1 = shl <2 x i64> %x0, %y
389  %sh2 = shl <2 x i64> %x1, %y
390  %logic = xor <2 x i64> %sh1, %z
391  %r = xor <2 x i64> %sh2, %logic
392  ret <2 x i64> %r
393}
394
395define <8 x i16> @xor_shl_commute3(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
396; CHECK-LABEL: xor_shl_commute3:
397; CHECK:       // %bb.0:
398; CHECK-NEXT:    eor v0.16b, v0.16b, v1.16b
399; CHECK-NEXT:    ushl v0.8h, v0.8h, v2.8h
400; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
401; CHECK-NEXT:    ret
402  %sh1 = shl <8 x i16> %x0, %y
403  %sh2 = shl <8 x i16> %x1, %y
404  %logic = xor <8 x i16> %z, %sh1
405  %r = xor <8 x i16> %sh2, %logic
406  ret <8 x i16> %r
407}
408
409; negative test - mismatched shift opcodes
410
411define i64 @xor_mix_shr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
412; CHECK-LABEL: xor_mix_shr:
413; CHECK:       // %bb.0:
414; CHECK-NEXT:    asr x8, x0, x2
415; CHECK-NEXT:    lsr x9, x1, x2
416; CHECK-NEXT:    eor x8, x8, x3
417; CHECK-NEXT:    eor x0, x8, x9
418; CHECK-NEXT:    ret
419  %sh1 = ashr i64 %x0, %y
420  %sh2 = lshr i64 %x1, %y
421  %logic = xor i64 %sh1, %z
422  %r = xor i64 %logic, %sh2
423  ret i64 %r
424}
425
426; negative test - mismatched shift amounts
427
428define i64 @xor_lshr_mix_shift_amount(i64 %x0, i64 %x1, i64 %y, i64 %z, i64 %w) {
429; CHECK-LABEL: xor_lshr_mix_shift_amount:
430; CHECK:       // %bb.0:
431; CHECK-NEXT:    lsr x8, x0, x2
432; CHECK-NEXT:    lsr x9, x1, x4
433; CHECK-NEXT:    eor x8, x8, x3
434; CHECK-NEXT:    eor x0, x8, x9
435; CHECK-NEXT:    ret
436  %sh1 = lshr i64 %x0, %y
437  %sh2 = lshr i64 %x1, %w
438  %logic = xor i64 %sh1, %z
439  %r = xor i64 %logic, %sh2
440  ret i64 %r
441}
442
443; negative test - mismatched logic opcodes
444
445define i64 @mix_logic_ashr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
446; CHECK-LABEL: mix_logic_ashr:
447; CHECK:       // %bb.0:
448; CHECK-NEXT:    asr x8, x0, x2
449; CHECK-NEXT:    asr x9, x1, x2
450; CHECK-NEXT:    orr x8, x8, x3
451; CHECK-NEXT:    eor x0, x8, x9
452; CHECK-NEXT:    ret
453  %sh1 = ashr i64 %x0, %y
454  %sh2 = ashr i64 %x1, %y
455  %logic = or i64 %sh1, %z
456  %r = xor i64 %logic, %sh2
457  ret i64 %r
458}
459
460define i8 @and_lshr_commute0(i8 %x0, i8 %x1, i8 %y, i8 %z) {
461; CHECK-LABEL: and_lshr_commute0:
462; CHECK:       // %bb.0:
463; CHECK-NEXT:    and w8, w0, w1
464; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
465; CHECK-NEXT:    and w8, w8, #0xff
466; CHECK-NEXT:    lsr w8, w8, w2
467; CHECK-NEXT:    and w0, w8, w3
468; CHECK-NEXT:    ret
469  %sh1 = lshr i8 %x0, %y
470  %sh2 = lshr i8 %x1, %y
471  %logic = and i8 %sh1, %z
472  %r = and i8 %logic, %sh2
473  ret i8 %r
474}
475
476define i32 @and_lshr_commute1(i32 %x0, i32 %x1, i32 %y, i32 %z) {
477; CHECK-LABEL: and_lshr_commute1:
478; CHECK:       // %bb.0:
479; CHECK-NEXT:    and w8, w0, w1
480; CHECK-NEXT:    lsr w8, w8, w2
481; CHECK-NEXT:    and w0, w8, w3
482; CHECK-NEXT:    ret
483  %sh1 = lshr i32 %x0, %y
484  %sh2 = lshr i32 %x1, %y
485  %logic = and i32 %z, %sh1
486  %r = and i32 %logic, %sh2
487  ret i32 %r
488}
489
490define <8 x i16> @and_lshr_commute2(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
491; CHECK-LABEL: and_lshr_commute2:
492; CHECK:       // %bb.0:
493; CHECK-NEXT:    and v0.16b, v0.16b, v1.16b
494; CHECK-NEXT:    neg v1.8h, v2.8h
495; CHECK-NEXT:    ushl v0.8h, v0.8h, v1.8h
496; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
497; CHECK-NEXT:    ret
498  %sh1 = lshr <8 x i16> %x0, %y
499  %sh2 = lshr <8 x i16> %x1, %y
500  %logic = and <8 x i16> %sh1, %z
501  %r = and <8 x i16> %sh2, %logic
502  ret <8 x i16> %r
503}
504
505define <2 x i64> @and_lshr_commute3(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
506; CHECK-LABEL: and_lshr_commute3:
507; CHECK:       // %bb.0:
508; CHECK-NEXT:    and v0.16b, v0.16b, v1.16b
509; CHECK-NEXT:    neg v1.2d, v2.2d
510; CHECK-NEXT:    ushl v0.2d, v0.2d, v1.2d
511; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
512; CHECK-NEXT:    ret
513  %sh1 = lshr <2 x i64> %x0, %y
514  %sh2 = lshr <2 x i64> %x1, %y
515  %logic = and <2 x i64> %z, %sh1
516  %r = and <2 x i64> %sh2, %logic
517  ret <2 x i64> %r
518}
519
520define i16 @and_ashr_commute0(i16 %x0, i16 %x1, i16 %y, i16 %z) {
521; CHECK-LABEL: and_ashr_commute0:
522; CHECK:       // %bb.0:
523; CHECK-NEXT:    and w8, w0, w1
524; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
525; CHECK-NEXT:    sxth w8, w8
526; CHECK-NEXT:    asr w8, w8, w2
527; CHECK-NEXT:    and w0, w8, w3
528; CHECK-NEXT:    ret
529  %sh1 = ashr i16 %x0, %y
530  %sh2 = ashr i16 %x1, %y
531  %logic = and i16 %sh1, %z
532  %r = and i16 %logic, %sh2
533  ret i16 %r
534}
535
536define i64 @and_ashr_commute1(i64 %x0, i64 %x1, i64 %y, i64 %z) {
537; CHECK-LABEL: and_ashr_commute1:
538; CHECK:       // %bb.0:
539; CHECK-NEXT:    and x8, x0, x1
540; CHECK-NEXT:    asr x8, x8, x2
541; CHECK-NEXT:    and x0, x8, x3
542; CHECK-NEXT:    ret
543  %sh1 = ashr i64 %x0, %y
544  %sh2 = ashr i64 %x1, %y
545  %logic = and i64 %z, %sh1
546  %r = and i64 %logic, %sh2
547  ret i64 %r
548}
549
550define <4 x i32> @and_ashr_commute2(<4 x i32> %x0, <4 x i32> %x1, <4 x i32> %y, <4 x i32> %z) {
551; CHECK-LABEL: and_ashr_commute2:
552; CHECK:       // %bb.0:
553; CHECK-NEXT:    and v0.16b, v0.16b, v1.16b
554; CHECK-NEXT:    neg v1.4s, v2.4s
555; CHECK-NEXT:    sshl v0.4s, v0.4s, v1.4s
556; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
557; CHECK-NEXT:    ret
558  %sh1 = ashr <4 x i32> %x0, %y
559  %sh2 = ashr <4 x i32> %x1, %y
560  %logic = and <4 x i32> %sh1, %z
561  %r = and <4 x i32> %sh2, %logic
562  ret <4 x i32> %r
563}
564
565define <16 x i8> @and_ashr_commute3(<16 x i8> %x0, <16 x i8> %x1, <16 x i8> %y, <16 x i8> %z) {
566; CHECK-LABEL: and_ashr_commute3:
567; CHECK:       // %bb.0:
568; CHECK-NEXT:    and v0.16b, v0.16b, v1.16b
569; CHECK-NEXT:    neg v1.16b, v2.16b
570; CHECK-NEXT:    sshl v0.16b, v0.16b, v1.16b
571; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
572; CHECK-NEXT:    ret
573  %sh1 = ashr <16 x i8> %x0, %y
574  %sh2 = ashr <16 x i8> %x1, %y
575  %logic = and <16 x i8> %z, %sh1
576  %r = and <16 x i8> %sh2, %logic
577  ret <16 x i8> %r
578}
579
580define i32 @and_shl_commute0(i32 %x0, i32 %x1, i32 %y, i32 %z) {
581; CHECK-LABEL: and_shl_commute0:
582; CHECK:       // %bb.0:
583; CHECK-NEXT:    and w8, w0, w1
584; CHECK-NEXT:    lsl w8, w8, w2
585; CHECK-NEXT:    and w0, w8, w3
586; CHECK-NEXT:    ret
587  %sh1 = shl i32 %x0, %y
588  %sh2 = shl i32 %x1, %y
589  %logic = and i32 %sh1, %z
590  %r = and i32 %logic, %sh2
591  ret i32 %r
592}
593
594define i8 @and_shl_commute1(i8 %x0, i8 %x1, i8 %y, i8 %z) {
595; CHECK-LABEL: and_shl_commute1:
596; CHECK:       // %bb.0:
597; CHECK-NEXT:    and w8, w0, w1
598; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
599; CHECK-NEXT:    lsl w8, w8, w2
600; CHECK-NEXT:    and w0, w8, w3
601; CHECK-NEXT:    ret
602  %sh1 = shl i8 %x0, %y
603  %sh2 = shl i8 %x1, %y
604  %logic = and i8 %z, %sh1
605  %r = and i8 %logic, %sh2
606  ret i8 %r
607}
608
609define <2 x i64> @and_shl_commute2(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
610; CHECK-LABEL: and_shl_commute2:
611; CHECK:       // %bb.0:
612; CHECK-NEXT:    and v0.16b, v0.16b, v1.16b
613; CHECK-NEXT:    ushl v0.2d, v0.2d, v2.2d
614; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
615; CHECK-NEXT:    ret
616  %sh1 = shl <2 x i64> %x0, %y
617  %sh2 = shl <2 x i64> %x1, %y
618  %logic = and <2 x i64> %sh1, %z
619  %r = and <2 x i64> %sh2, %logic
620  ret <2 x i64> %r
621}
622
623define <8 x i16> @and_shl_commute3(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
624; CHECK-LABEL: and_shl_commute3:
625; CHECK:       // %bb.0:
626; CHECK-NEXT:    and v0.16b, v0.16b, v1.16b
627; CHECK-NEXT:    ushl v0.8h, v0.8h, v2.8h
628; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
629; CHECK-NEXT:    ret
630  %sh1 = shl <8 x i16> %x0, %y
631  %sh2 = shl <8 x i16> %x1, %y
632  %logic = and <8 x i16> %z, %sh1
633  %r = and <8 x i16> %sh2, %logic
634  ret <8 x i16> %r
635}
636
637; negative test - mismatched shift opcodes
638
639define i64 @and_mix_shr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
640; CHECK-LABEL: and_mix_shr:
641; CHECK:       // %bb.0:
642; CHECK-NEXT:    lsr x8, x0, x2
643; CHECK-NEXT:    asr x9, x1, x2
644; CHECK-NEXT:    and x8, x8, x3
645; CHECK-NEXT:    and x0, x8, x9
646; CHECK-NEXT:    ret
647  %sh1 = lshr i64 %x0, %y
648  %sh2 = ashr i64 %x1, %y
649  %logic = and i64 %sh1, %z
650  %r = and i64 %logic, %sh2
651  ret i64 %r
652}
653
654; negative test - mismatched shift amounts
655
656define i64 @and_lshr_mix_shift_amount(i64 %x0, i64 %x1, i64 %y, i64 %z, i64 %w) {
657; CHECK-LABEL: and_lshr_mix_shift_amount:
658; CHECK:       // %bb.0:
659; CHECK-NEXT:    lsr x8, x0, x2
660; CHECK-NEXT:    lsr x9, x1, x4
661; CHECK-NEXT:    and x8, x8, x3
662; CHECK-NEXT:    and x0, x8, x9
663; CHECK-NEXT:    ret
664  %sh1 = lshr i64 %x0, %y
665  %sh2 = lshr i64 %x1, %w
666  %logic = and i64 %sh1, %z
667  %r = and i64 %logic, %sh2
668  ret i64 %r
669}
670
671; negative test - mismatched logic opcodes
672
673define i64 @mix_logic_shl(i64 %x0, i64 %x1, i64 %y, i64 %z) {
674; CHECK-LABEL: mix_logic_shl:
675; CHECK:       // %bb.0:
676; CHECK-NEXT:    lsl x8, x0, x2
677; CHECK-NEXT:    lsl x9, x1, x2
678; CHECK-NEXT:    eor x8, x8, x3
679; CHECK-NEXT:    and x0, x8, x9
680; CHECK-NEXT:    ret
681  %sh1 = shl i64 %x0, %y
682  %sh2 = shl i64 %x1, %y
683  %logic = xor i64 %sh1, %z
684  %r = and i64 %logic, %sh2
685  ret i64 %r
686}
687
688; (shl (X | Y), C1) | (srl X, C2) --> (rotl X, C1) | (shl Y, C1)
689
690define i32 @or_fshl_commute0(i32 %x, i32 %y) {
691; CHECK-LABEL: or_fshl_commute0:
692; CHECK:       // %bb.0:
693; CHECK-NEXT:    orr w8, w0, w1
694; CHECK-NEXT:    extr w0, w8, w0, #27
695; CHECK-NEXT:    ret
696  %or1 = or i32 %x, %y
697  %sh1 = shl i32 %or1, 5
698  %sh2 = lshr i32 %x, 27
699  %r = or i32 %sh1, %sh2
700  ret i32 %r
701}
702
703define i64 @or_fshl_commute1(i64 %x, i64 %y) {
704; CHECK-LABEL: or_fshl_commute1:
705; CHECK:       // %bb.0:
706; CHECK-NEXT:    orr w8, w1, w0
707; CHECK-NEXT:    extr x0, x8, x0, #29
708; CHECK-NEXT:    ret
709  %or1 = or i64 %y, %x
710  %sh1 = shl i64 %or1, 35
711  %sh2 = lshr i64 %x, 29
712  %r = or i64 %sh1, %sh2
713  ret i64 %r
714}
715
716define i16 @or_fshl_commute2(i16 %x, i16 %y) {
717; CHECK-LABEL: or_fshl_commute2:
718; CHECK:       // %bb.0:
719; CHECK-NEXT:    orr w8, w0, w1
720; CHECK-NEXT:    lsl w8, w8, #2
721; CHECK-NEXT:    bfxil w8, w0, #14, #2
722; CHECK-NEXT:    mov w0, w8
723; CHECK-NEXT:    ret
724  %or1 = or i16 %x, %y
725  %sh1 = shl i16 %or1, 2
726  %sh2 = lshr i16 %x, 14
727  %r = or i16 %sh2, %sh1
728  ret i16 %r
729}
730
731define i8 @or_fshl_commute3(i8 %x, i8 %y) {
732; CHECK-LABEL: or_fshl_commute3:
733; CHECK:       // %bb.0:
734; CHECK-NEXT:    orr w8, w1, w0
735; CHECK-NEXT:    lsl w8, w8, #5
736; CHECK-NEXT:    bfxil w8, w0, #3, #5
737; CHECK-NEXT:    mov w0, w8
738; CHECK-NEXT:    ret
739  %or1 = or i8 %y, %x
740  %sh1 = shl i8 %or1, 5
741  %sh2 = lshr i8 %x, 3
742  %r = or i8 %sh2, %sh1
743  ret i8 %r
744}
745
746define i32 @or_fshl_wrong_shift(i32 %x, i32 %y) {
747; CHECK-LABEL: or_fshl_wrong_shift:
748; CHECK:       // %bb.0:
749; CHECK-NEXT:    orr w8, w0, w1
750; CHECK-NEXT:    lsl w8, w8, #20
751; CHECK-NEXT:    orr w0, w8, w0, lsr #11
752; CHECK-NEXT:    ret
753  %or1 = or i32 %x, %y
754  %sh1 = shl i32 %or1, 20
755  %sh2 = lshr i32 %x, 11
756  %r = or i32 %sh1, %sh2
757  ret i32 %r
758}
759
760; (shl X, C1) | (srl (X | Y), C2) --> (rotl X, C1) | (srl Y, C2)
761
762define i64 @or_fshr_commute0(i64 %x, i64 %y) {
763; CHECK-LABEL: or_fshr_commute0:
764; CHECK:       // %bb.0:
765; CHECK-NEXT:    orr x8, x0, x1
766; CHECK-NEXT:    extr x0, x0, x8, #24
767; CHECK-NEXT:    ret
768  %or1 = or i64 %x, %y
769  %sh1 = shl i64 %x, 40
770  %sh2 = lshr i64 %or1, 24
771  %r = or i64 %sh1, %sh2
772  ret i64 %r
773}
774
775define i32 @or_fshr_commute1(i32 %x, i32 %y) {
776; CHECK-LABEL: or_fshr_commute1:
777; CHECK:       // %bb.0:
778; CHECK-NEXT:    orr w8, w1, w0
779; CHECK-NEXT:    extr w0, w0, w8, #29
780; CHECK-NEXT:    ret
781  %or1 = or i32 %y, %x
782  %sh1 = shl i32 %x, 3
783  %sh2 = lshr i32 %or1, 29
784  %r = or i32 %sh1, %sh2
785  ret i32 %r
786}
787
788define i16 @or_fshr_commute2(i16 %x, i16 %y) {
789; CHECK-LABEL: or_fshr_commute2:
790; CHECK:       // %bb.0:
791; CHECK-NEXT:    lsl w8, w0, #9
792; CHECK-NEXT:    orr w9, w0, w1
793; CHECK-NEXT:    bfxil w8, w9, #7, #9
794; CHECK-NEXT:    mov w0, w8
795; CHECK-NEXT:    ret
796  %or1 = or i16 %x, %y
797  %sh1 = shl i16 %x, 9
798  %sh2 = lshr i16 %or1, 7
799  %r = or i16 %sh2, %sh1
800  ret i16 %r
801}
802
803define i8 @or_fshr_commute3(i8 %x, i8 %y) {
804; CHECK-LABEL: or_fshr_commute3:
805; CHECK:       // %bb.0:
806; CHECK-NEXT:    lsl w8, w0, #2
807; CHECK-NEXT:    orr w9, w1, w0
808; CHECK-NEXT:    bfxil w8, w9, #6, #2
809; CHECK-NEXT:    mov w0, w8
810; CHECK-NEXT:    ret
811  %or1 = or i8 %y, %x
812  %sh1 = shl i8 %x, 2
813  %sh2 = lshr i8 %or1, 6
814  %r = or i8 %sh2, %sh1
815  ret i8 %r
816}
817
818define i32 @or_fshr_wrong_shift(i32 %x, i32 %y) {
819; CHECK-LABEL: or_fshr_wrong_shift:
820; CHECK:       // %bb.0:
821; CHECK-NEXT:    orr w8, w0, w1
822; CHECK-NEXT:    lsr w8, w8, #26
823; CHECK-NEXT:    orr w0, w8, w0, lsl #7
824; CHECK-NEXT:    ret
825  %or1 = or i32 %x, %y
826  %sh1 = shl i32 %x, 7
827  %sh2 = lshr i32 %or1, 26
828  %r = or i32 %sh1, %sh2
829  ret i32 %r
830}
831