1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
3
4; https://bugs.llvm.org/show_bug.cgi?id=37104
5
6; X: [byte3]              [byte0]
7; Y:        [byte2][byte1]
8
9define i8 @out8_constmask(i8 %x, i8 %y) {
10; CHECK-LABEL: out8_constmask:
11; CHECK:       // %bb.0:
12; CHECK-NEXT:    lsr w8, w0, #2
13; CHECK-NEXT:    bfi w1, w8, #2, #4
14; CHECK-NEXT:    mov w0, w1
15; CHECK-NEXT:    ret
16  %mx = and i8 %x, 60
17  %my = and i8 %y, -61
18  %r = or i8 %mx, %my
19  ret i8 %r
20}
21
22define i16 @out16_constmask(i16 %x, i16 %y) {
23; CHECK-LABEL: out16_constmask:
24; CHECK:       // %bb.0:
25; CHECK-NEXT:    lsr w8, w0, #4
26; CHECK-NEXT:    bfi w1, w8, #4, #8
27; CHECK-NEXT:    mov w0, w1
28; CHECK-NEXT:    ret
29  %mx = and i16 %x, 4080
30  %my = and i16 %y, -4081
31  %r = or i16 %mx, %my
32  ret i16 %r
33}
34
35define i32 @out32_constmask(i32 %x, i32 %y) {
36; CHECK-LABEL: out32_constmask:
37; CHECK:       // %bb.0:
38; CHECK-NEXT:    lsr w8, w0, #8
39; CHECK-NEXT:    bfi w1, w8, #8, #16
40; CHECK-NEXT:    mov w0, w1
41; CHECK-NEXT:    ret
42  %mx = and i32 %x, 16776960
43  %my = and i32 %y, -16776961
44  %r = or i32 %mx, %my
45  ret i32 %r
46}
47
48define i64 @out64_constmask(i64 %x, i64 %y) {
49; CHECK-LABEL: out64_constmask:
50; CHECK:       // %bb.0:
51; CHECK-NEXT:    lsr x8, x0, #16
52; CHECK-NEXT:    bfi x1, x8, #16, #32
53; CHECK-NEXT:    mov x0, x1
54; CHECK-NEXT:    ret
55  %mx = and i64 %x, 281474976645120
56  %my = and i64 %y, -281474976645121
57  %r = or i64 %mx, %my
58  ret i64 %r
59}
60
61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62; Should be the same as the previous one.
63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64
65define i8 @in8_constmask(i8 %x, i8 %y) {
66; CHECK-LABEL: in8_constmask:
67; CHECK:       // %bb.0:
68; CHECK-NEXT:    eor w8, w0, w1
69; CHECK-NEXT:    and w8, w8, #0x3c
70; CHECK-NEXT:    eor w0, w8, w1
71; CHECK-NEXT:    ret
72  %n0 = xor i8 %x, %y
73  %n1 = and i8 %n0, 60
74  %r = xor i8 %n1, %y
75  ret i8 %r
76}
77
78define i16 @in16_constmask(i16 %x, i16 %y) {
79; CHECK-LABEL: in16_constmask:
80; CHECK:       // %bb.0:
81; CHECK-NEXT:    eor w8, w0, w1
82; CHECK-NEXT:    and w8, w8, #0xff0
83; CHECK-NEXT:    eor w0, w8, w1
84; CHECK-NEXT:    ret
85  %n0 = xor i16 %x, %y
86  %n1 = and i16 %n0, 4080
87  %r = xor i16 %n1, %y
88  ret i16 %r
89}
90
91define i32 @in32_constmask(i32 %x, i32 %y) {
92; CHECK-LABEL: in32_constmask:
93; CHECK:       // %bb.0:
94; CHECK-NEXT:    eor w8, w0, w1
95; CHECK-NEXT:    and w8, w8, #0xffff00
96; CHECK-NEXT:    eor w0, w8, w1
97; CHECK-NEXT:    ret
98  %n0 = xor i32 %x, %y
99  %n1 = and i32 %n0, 16776960
100  %r = xor i32 %n1, %y
101  ret i32 %r
102}
103
104define i64 @in64_constmask(i64 %x, i64 %y) {
105; CHECK-LABEL: in64_constmask:
106; CHECK:       // %bb.0:
107; CHECK-NEXT:    eor x8, x0, x1
108; CHECK-NEXT:    and x8, x8, #0xffffffff0000
109; CHECK-NEXT:    eor x0, x8, x1
110; CHECK-NEXT:    ret
111  %n0 = xor i64 %x, %y
112  %n1 = and i64 %n0, 281474976645120
113  %r = xor i64 %n1, %y
114  ret i64 %r
115}
116
117; ============================================================================ ;
118; Constant Commutativity tests.
119; ============================================================================ ;
120
121define i32 @in_constmask_commutativity_0_1(i32 %x, i32 %y) {
122; CHECK-LABEL: in_constmask_commutativity_0_1:
123; CHECK:       // %bb.0:
124; CHECK-NEXT:    eor w8, w0, w1
125; CHECK-NEXT:    and w8, w8, #0xffff00
126; CHECK-NEXT:    eor w0, w1, w8
127; CHECK-NEXT:    ret
128  %n0 = xor i32 %x, %y
129  %n1 = and i32 %n0, 16776960
130  %r = xor i32 %y, %n1 ; swapped
131  ret i32 %r
132}
133
134define i32 @in_constmask_commutativity_1_0(i32 %x, i32 %y) {
135; CHECK-LABEL: in_constmask_commutativity_1_0:
136; CHECK:       // %bb.0:
137; CHECK-NEXT:    eor w8, w0, w1
138; CHECK-NEXT:    and w8, w8, #0xffff00
139; CHECK-NEXT:    eor w0, w8, w0
140; CHECK-NEXT:    ret
141  %n0 = xor i32 %x, %y
142  %n1 = and i32 %n0, 16776960
143  %r = xor i32 %n1, %x ; %x instead of %y
144  ret i32 %r
145}
146
147define i32 @in_constmask_commutativity_1_1(i32 %x, i32 %y) {
148; CHECK-LABEL: in_constmask_commutativity_1_1:
149; CHECK:       // %bb.0:
150; CHECK-NEXT:    eor w8, w0, w1
151; CHECK-NEXT:    and w8, w8, #0xffff00
152; CHECK-NEXT:    eor w0, w0, w8
153; CHECK-NEXT:    ret
154  %n0 = xor i32 %x, %y
155  %n1 = and i32 %n0, 16776960
156  %r = xor i32 %x, %n1 ; swapped, %x instead of %y
157  ret i32 %r
158}
159
160; ============================================================================ ;
161; Y is an 'and' too.
162; ============================================================================ ;
163
164define i32 @in_complex_y0_constmask(i32 %x, i32 %y_hi, i32 %y_low) {
165; CHECK-LABEL: in_complex_y0_constmask:
166; CHECK:       // %bb.0:
167; CHECK-NEXT:    and w8, w1, w2
168; CHECK-NEXT:    eor w9, w0, w8
169; CHECK-NEXT:    and w9, w9, #0xffff00
170; CHECK-NEXT:    eor w0, w9, w8
171; CHECK-NEXT:    ret
172  %y = and i32 %y_hi, %y_low
173  %n0 = xor i32 %x, %y
174  %n1 = and i32 %n0, 16776960
175  %r = xor i32 %n1, %y
176  ret i32 %r
177}
178
179define i32 @in_complex_y1_constmask(i32 %x, i32 %y_hi, i32 %y_low) {
180; CHECK-LABEL: in_complex_y1_constmask:
181; CHECK:       // %bb.0:
182; CHECK-NEXT:    and w8, w1, w2
183; CHECK-NEXT:    eor w9, w0, w8
184; CHECK-NEXT:    and w9, w9, #0xffff00
185; CHECK-NEXT:    eor w0, w8, w9
186; CHECK-NEXT:    ret
187  %y = and i32 %y_hi, %y_low
188  %n0 = xor i32 %x, %y
189  %n1 = and i32 %n0, 16776960
190  %r = xor i32 %y, %n1
191  ret i32 %r
192}
193
194; ============================================================================ ;
195; Negative tests. Should not be folded.
196; ============================================================================ ;
197
198; Multi-use tests.
199
200declare void @use32(i32) nounwind
201
202define i32 @in_multiuse_A_constmask(i32 %x, i32 %y, i32 %z) nounwind {
203; CHECK-LABEL: in_multiuse_A_constmask:
204; CHECK:       // %bb.0:
205; CHECK-NEXT:    str x30, [sp, #-32]! // 8-byte Folded Spill
206; CHECK-NEXT:    eor w8, w0, w1
207; CHECK-NEXT:    stp x20, x19, [sp, #16] // 16-byte Folded Spill
208; CHECK-NEXT:    and w20, w8, #0xffff00
209; CHECK-NEXT:    mov w0, w20
210; CHECK-NEXT:    mov w19, w1
211; CHECK-NEXT:    bl use32
212; CHECK-NEXT:    eor w0, w20, w19
213; CHECK-NEXT:    ldp x20, x19, [sp, #16] // 16-byte Folded Reload
214; CHECK-NEXT:    ldr x30, [sp], #32 // 8-byte Folded Reload
215; CHECK-NEXT:    ret
216  %n0 = xor i32 %x, %y
217  %n1 = and i32 %n0, 16776960
218  call void @use32(i32 %n1)
219  %r = xor i32 %n1, %y
220  ret i32 %r
221}
222
223define i32 @in_multiuse_B_constmask(i32 %x, i32 %y, i32 %z) nounwind {
224; CHECK-LABEL: in_multiuse_B_constmask:
225; CHECK:       // %bb.0:
226; CHECK-NEXT:    str x30, [sp, #-32]! // 8-byte Folded Spill
227; CHECK-NEXT:    eor w0, w0, w1
228; CHECK-NEXT:    stp x20, x19, [sp, #16] // 16-byte Folded Spill
229; CHECK-NEXT:    mov w19, w1
230; CHECK-NEXT:    and w20, w0, #0xffff00
231; CHECK-NEXT:    bl use32
232; CHECK-NEXT:    eor w0, w20, w19
233; CHECK-NEXT:    ldp x20, x19, [sp, #16] // 16-byte Folded Reload
234; CHECK-NEXT:    ldr x30, [sp], #32 // 8-byte Folded Reload
235; CHECK-NEXT:    ret
236  %n0 = xor i32 %x, %y
237  %n1 = and i32 %n0, 16776960
238  call void @use32(i32 %n0)
239  %r = xor i32 %n1, %y
240  ret i32 %r
241}
242
243; Various bad variants
244
245define i32 @n0_badconstmask(i32 %x, i32 %y) {
246; CHECK-LABEL: n0_badconstmask:
247; CHECK:       // %bb.0:
248; CHECK-NEXT:    mov w9, #256
249; CHECK-NEXT:    movk w9, #65280, lsl #16
250; CHECK-NEXT:    and w8, w0, #0xffff00
251; CHECK-NEXT:    and w9, w1, w9
252; CHECK-NEXT:    orr w0, w8, w9
253; CHECK-NEXT:    ret
254  %mx = and i32 %x, 16776960
255  %my = and i32 %y, -16776960 ; instead of -16776961
256  %r = or i32 %mx, %my
257  ret i32 %r
258}
259
260define i32 @n1_thirdvar_constmask(i32 %x, i32 %y, i32 %z) {
261; CHECK-LABEL: n1_thirdvar_constmask:
262; CHECK:       // %bb.0:
263; CHECK-NEXT:    eor w8, w0, w1
264; CHECK-NEXT:    and w8, w8, #0xffff00
265; CHECK-NEXT:    eor w0, w8, w2
266; CHECK-NEXT:    ret
267  %n0 = xor i32 %x, %y
268  %n1 = and i32 %n0, 16776960
269  %r = xor i32 %n1, %z ; instead of %y
270  ret i32 %r
271}
272