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