Revert 374373: [Codegen] Alter the default promotion for saturating adds and subs
[llvm-core.git] / test / CodeGen / AArch64 / unfold-masked-merge-scalar-variablemask.ll
blob186068643c8fac4a5bebcd5237329e0adc6525f7
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
4 ; https://bugs.llvm.org/show_bug.cgi?id=37104
6 define i8 @out8(i8 %x, i8 %y, i8 %mask) {
7 ; CHECK-LABEL: out8:
8 ; CHECK:       // %bb.0:
9 ; CHECK-NEXT:    and w8, w0, w2
10 ; CHECK-NEXT:    bic w9, w1, w2
11 ; CHECK-NEXT:    orr w0, w8, w9
12 ; CHECK-NEXT:    ret
13   %mx = and i8 %x, %mask
14   %notmask = xor i8 %mask, -1
15   %my = and i8 %y, %notmask
16   %r = or i8 %mx, %my
17   ret i8 %r
20 define i16 @out16(i16 %x, i16 %y, i16 %mask) {
21 ; CHECK-LABEL: out16:
22 ; CHECK:       // %bb.0:
23 ; CHECK-NEXT:    and w8, w0, w2
24 ; CHECK-NEXT:    bic w9, w1, w2
25 ; CHECK-NEXT:    orr w0, w8, w9
26 ; CHECK-NEXT:    ret
27   %mx = and i16 %x, %mask
28   %notmask = xor i16 %mask, -1
29   %my = and i16 %y, %notmask
30   %r = or i16 %mx, %my
31   ret i16 %r
34 define i32 @out32(i32 %x, i32 %y, i32 %mask) {
35 ; CHECK-LABEL: out32:
36 ; CHECK:       // %bb.0:
37 ; CHECK-NEXT:    and w8, w0, w2
38 ; CHECK-NEXT:    bic w9, w1, w2
39 ; CHECK-NEXT:    orr w0, w8, w9
40 ; CHECK-NEXT:    ret
41   %mx = and i32 %x, %mask
42   %notmask = xor i32 %mask, -1
43   %my = and i32 %y, %notmask
44   %r = or i32 %mx, %my
45   ret i32 %r
48 define i64 @out64(i64 %x, i64 %y, i64 %mask) {
49 ; CHECK-LABEL: out64:
50 ; CHECK:       // %bb.0:
51 ; CHECK-NEXT:    and x8, x0, x2
52 ; CHECK-NEXT:    bic x9, x1, x2
53 ; CHECK-NEXT:    orr x0, x8, x9
54 ; CHECK-NEXT:    ret
55   %mx = and i64 %x, %mask
56   %notmask = xor i64 %mask, -1
57   %my = and i64 %y, %notmask
58   %r = or i64 %mx, %my
59   ret i64 %r
61 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62 ; Should be the same as the previous one.
63 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65 define i8 @in8(i8 %x, i8 %y, i8 %mask) {
66 ; CHECK-LABEL: in8:
67 ; CHECK:       // %bb.0:
68 ; CHECK-NEXT:    bic w8, w1, w2
69 ; CHECK-NEXT:    and w9, w0, w2
70 ; CHECK-NEXT:    orr w0, w9, w8
71 ; CHECK-NEXT:    ret
72   %n0 = xor i8 %x, %y
73   %n1 = and i8 %n0, %mask
74   %r = xor i8 %n1, %y
75   ret i8 %r
78 define i16 @in16(i16 %x, i16 %y, i16 %mask) {
79 ; CHECK-LABEL: in16:
80 ; CHECK:       // %bb.0:
81 ; CHECK-NEXT:    bic w8, w1, w2
82 ; CHECK-NEXT:    and w9, w0, w2
83 ; CHECK-NEXT:    orr w0, w9, w8
84 ; CHECK-NEXT:    ret
85   %n0 = xor i16 %x, %y
86   %n1 = and i16 %n0, %mask
87   %r = xor i16 %n1, %y
88   ret i16 %r
91 define i32 @in32(i32 %x, i32 %y, i32 %mask) {
92 ; CHECK-LABEL: in32:
93 ; CHECK:       // %bb.0:
94 ; CHECK-NEXT:    bic w8, w1, w2
95 ; CHECK-NEXT:    and w9, w0, w2
96 ; CHECK-NEXT:    orr w0, w9, w8
97 ; CHECK-NEXT:    ret
98   %n0 = xor i32 %x, %y
99   %n1 = and i32 %n0, %mask
100   %r = xor i32 %n1, %y
101   ret i32 %r
104 define i64 @in64(i64 %x, i64 %y, i64 %mask) {
105 ; CHECK-LABEL: in64:
106 ; CHECK:       // %bb.0:
107 ; CHECK-NEXT:    bic x8, x1, x2
108 ; CHECK-NEXT:    and x9, x0, x2
109 ; CHECK-NEXT:    orr x0, x9, x8
110 ; CHECK-NEXT:    ret
111   %n0 = xor i64 %x, %y
112   %n1 = and i64 %n0, %mask
113   %r = xor i64 %n1, %y
114   ret i64 %r
116 ; ============================================================================ ;
117 ; Commutativity tests.
118 ; ============================================================================ ;
119 define i32 @in_commutativity_0_0_1(i32 %x, i32 %y, i32 %mask) {
120 ; CHECK-LABEL: in_commutativity_0_0_1:
121 ; CHECK:       // %bb.0:
122 ; CHECK-NEXT:    bic w8, w1, w2
123 ; CHECK-NEXT:    and w9, w0, w2
124 ; CHECK-NEXT:    orr w0, w9, w8
125 ; CHECK-NEXT:    ret
126   %n0 = xor i32 %x, %y
127   %n1 = and i32 %mask, %n0 ; swapped
128   %r = xor i32 %n1, %y
129   ret i32 %r
131 define i32 @in_commutativity_0_1_0(i32 %x, i32 %y, i32 %mask) {
132 ; CHECK-LABEL: in_commutativity_0_1_0:
133 ; CHECK:       // %bb.0:
134 ; CHECK-NEXT:    bic w8, w1, w2
135 ; CHECK-NEXT:    and w9, w0, w2
136 ; CHECK-NEXT:    orr w0, w9, w8
137 ; CHECK-NEXT:    ret
138   %n0 = xor i32 %x, %y
139   %n1 = and i32 %n0, %mask
140   %r = xor i32 %y, %n1 ; swapped
141   ret i32 %r
143 define i32 @in_commutativity_0_1_1(i32 %x, i32 %y, i32 %mask) {
144 ; CHECK-LABEL: in_commutativity_0_1_1:
145 ; CHECK:       // %bb.0:
146 ; CHECK-NEXT:    bic w8, w1, w2
147 ; CHECK-NEXT:    and w9, w0, w2
148 ; CHECK-NEXT:    orr w0, w9, w8
149 ; CHECK-NEXT:    ret
150   %n0 = xor i32 %x, %y
151   %n1 = and i32 %mask, %n0 ; swapped
152   %r = xor i32 %y, %n1 ; swapped
153   ret i32 %r
155 define i32 @in_commutativity_1_0_0(i32 %x, i32 %y, i32 %mask) {
156 ; CHECK-LABEL: in_commutativity_1_0_0:
157 ; CHECK:       // %bb.0:
158 ; CHECK-NEXT:    bic w8, w0, w2
159 ; CHECK-NEXT:    and w9, w1, w2
160 ; CHECK-NEXT:    orr w0, w9, w8
161 ; CHECK-NEXT:    ret
162   %n0 = xor i32 %x, %y
163   %n1 = and i32 %n0, %mask
164   %r = xor i32 %n1, %x ; %x instead of %y
165   ret i32 %r
167 define i32 @in_commutativity_1_0_1(i32 %x, i32 %y, i32 %mask) {
168 ; CHECK-LABEL: in_commutativity_1_0_1:
169 ; CHECK:       // %bb.0:
170 ; CHECK-NEXT:    bic w8, w0, w2
171 ; CHECK-NEXT:    and w9, w1, w2
172 ; CHECK-NEXT:    orr w0, w9, w8
173 ; CHECK-NEXT:    ret
174   %n0 = xor i32 %x, %y
175   %n1 = and i32 %mask, %n0 ; swapped
176   %r = xor i32 %n1, %x ; %x instead of %y
177   ret i32 %r
179 define i32 @in_commutativity_1_1_0(i32 %x, i32 %y, i32 %mask) {
180 ; CHECK-LABEL: in_commutativity_1_1_0:
181 ; CHECK:       // %bb.0:
182 ; CHECK-NEXT:    bic w8, w0, w2
183 ; CHECK-NEXT:    and w9, w1, w2
184 ; CHECK-NEXT:    orr w0, w9, w8
185 ; CHECK-NEXT:    ret
186   %n0 = xor i32 %x, %y
187   %n1 = and i32 %n0, %mask
188   %r = xor i32 %x, %n1 ; swapped, %x instead of %y
189   ret i32 %r
191 define i32 @in_commutativity_1_1_1(i32 %x, i32 %y, i32 %mask) {
192 ; CHECK-LABEL: in_commutativity_1_1_1:
193 ; CHECK:       // %bb.0:
194 ; CHECK-NEXT:    bic w8, w0, w2
195 ; CHECK-NEXT:    and w9, w1, w2
196 ; CHECK-NEXT:    orr w0, w9, w8
197 ; CHECK-NEXT:    ret
198   %n0 = xor i32 %x, %y
199   %n1 = and i32 %mask, %n0 ; swapped
200   %r = xor i32 %x, %n1 ; swapped, %x instead of %y
201   ret i32 %r
203 ; ============================================================================ ;
204 ; Y is an 'and' too.
205 ; ============================================================================ ;
206 define i32 @in_complex_y0(i32 %x, i32 %y_hi, i32 %y_low, i32 %mask) {
207 ; CHECK-LABEL: in_complex_y0:
208 ; CHECK:       // %bb.0:
209 ; CHECK-NEXT:    and w8, w1, w2
210 ; CHECK-NEXT:    and w9, w0, w3
211 ; CHECK-NEXT:    bic w8, w8, w3
212 ; CHECK-NEXT:    orr w0, w9, w8
213 ; CHECK-NEXT:    ret
214   %y = and i32 %y_hi, %y_low
215   %n0 = xor i32 %x, %y
216   %n1 = and i32 %n0, %mask
217   %r = xor i32 %n1, %y
218   ret i32 %r
220 define i32 @in_complex_y1(i32 %x, i32 %y_hi, i32 %y_low, i32 %mask) {
221 ; CHECK-LABEL: in_complex_y1:
222 ; CHECK:       // %bb.0:
223 ; CHECK-NEXT:    and w8, w1, w2
224 ; CHECK-NEXT:    and w9, w0, w3
225 ; CHECK-NEXT:    bic w8, w8, w3
226 ; CHECK-NEXT:    orr w0, w9, w8
227 ; CHECK-NEXT:    ret
228   %y = and i32 %y_hi, %y_low
229   %n0 = xor i32 %x, %y
230   %n1 = and i32 %n0, %mask
231   %r = xor i32 %y, %n1
232   ret i32 %r
234 ; ============================================================================ ;
235 ; M is an 'xor' too.
236 ; ============================================================================ ;
237 define i32 @in_complex_m0(i32 %x, i32 %y, i32 %m_a, i32 %m_b) {
238 ; CHECK-LABEL: in_complex_m0:
239 ; CHECK:       // %bb.0:
240 ; CHECK-NEXT:    eor w8, w2, w3
241 ; CHECK-NEXT:    bic w9, w1, w8
242 ; CHECK-NEXT:    and w8, w0, w8
243 ; CHECK-NEXT:    orr w0, w8, w9
244 ; CHECK-NEXT:    ret
245   %mask = xor i32 %m_a, %m_b
246   %n0 = xor i32 %x, %y
247   %n1 = and i32 %n0, %mask
248   %r = xor i32 %n1, %y
249   ret i32 %r
251 define i32 @in_complex_m1(i32 %x, i32 %y, i32 %m_a, i32 %m_b) {
252 ; CHECK-LABEL: in_complex_m1:
253 ; CHECK:       // %bb.0:
254 ; CHECK-NEXT:    eor w8, w2, w3
255 ; CHECK-NEXT:    bic w9, w1, w8
256 ; CHECK-NEXT:    and w8, w0, w8
257 ; CHECK-NEXT:    orr w0, w8, w9
258 ; CHECK-NEXT:    ret
259   %mask = xor i32 %m_a, %m_b
260   %n0 = xor i32 %x, %y
261   %n1 = and i32 %mask, %n0
262   %r = xor i32 %n1, %y
263   ret i32 %r
265 ; ============================================================================ ;
266 ; Both Y and M are complex.
267 ; ============================================================================ ;
268 define i32 @in_complex_y0_m0(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
269 ; CHECK-LABEL: in_complex_y0_m0:
270 ; CHECK:       // %bb.0:
271 ; CHECK-NEXT:    and w8, w1, w2
272 ; CHECK-NEXT:    eor w9, w3, w4
273 ; CHECK-NEXT:    bic w8, w8, w9
274 ; CHECK-NEXT:    and w9, w0, w9
275 ; CHECK-NEXT:    orr w0, w9, w8
276 ; CHECK-NEXT:    ret
277   %y = and i32 %y_hi, %y_low
278   %mask = xor i32 %m_a, %m_b
279   %n0 = xor i32 %x, %y
280   %n1 = and i32 %n0, %mask
281   %r = xor i32 %n1, %y
282   ret i32 %r
284 define i32 @in_complex_y1_m0(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
285 ; CHECK-LABEL: in_complex_y1_m0:
286 ; CHECK:       // %bb.0:
287 ; CHECK-NEXT:    and w8, w1, w2
288 ; CHECK-NEXT:    eor w9, w3, w4
289 ; CHECK-NEXT:    bic w8, w8, w9
290 ; CHECK-NEXT:    and w9, w0, w9
291 ; CHECK-NEXT:    orr w0, w9, w8
292 ; CHECK-NEXT:    ret
293   %y = and i32 %y_hi, %y_low
294   %mask = xor i32 %m_a, %m_b
295   %n0 = xor i32 %x, %y
296   %n1 = and i32 %n0, %mask
297   %r = xor i32 %y, %n1
298   ret i32 %r
300 define i32 @in_complex_y0_m1(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
301 ; CHECK-LABEL: in_complex_y0_m1:
302 ; CHECK:       // %bb.0:
303 ; CHECK-NEXT:    and w8, w1, w2
304 ; CHECK-NEXT:    eor w9, w3, w4
305 ; CHECK-NEXT:    bic w8, w8, w9
306 ; CHECK-NEXT:    and w9, w0, w9
307 ; CHECK-NEXT:    orr w0, w9, w8
308 ; CHECK-NEXT:    ret
309   %y = and i32 %y_hi, %y_low
310   %mask = xor i32 %m_a, %m_b
311   %n0 = xor i32 %x, %y
312   %n1 = and i32 %mask, %n0
313   %r = xor i32 %n1, %y
314   ret i32 %r
316 define i32 @in_complex_y1_m1(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
317 ; CHECK-LABEL: in_complex_y1_m1:
318 ; CHECK:       // %bb.0:
319 ; CHECK-NEXT:    and w8, w1, w2
320 ; CHECK-NEXT:    eor w9, w3, w4
321 ; CHECK-NEXT:    bic w8, w8, w9
322 ; CHECK-NEXT:    and w9, w0, w9
323 ; CHECK-NEXT:    orr w0, w9, w8
324 ; CHECK-NEXT:    ret
325   %y = and i32 %y_hi, %y_low
326   %mask = xor i32 %m_a, %m_b
327   %n0 = xor i32 %x, %y
328   %n1 = and i32 %mask, %n0
329   %r = xor i32 %y, %n1
330   ret i32 %r
332 ; ============================================================================ ;
333 ; Various cases with %x and/or %y being a constant
334 ; ============================================================================ ;
335 define i32 @out_constant_varx_mone(i32 %x, i32 %y, i32 %mask) {
336 ; CHECK-LABEL: out_constant_varx_mone:
337 ; CHECK:       // %bb.0:
338 ; CHECK-NEXT:    and w8, w2, w0
339 ; CHECK-NEXT:    orn w0, w8, w2
340 ; CHECK-NEXT:    ret
341   %notmask = xor i32 %mask, -1
342   %mx = and i32 %mask, %x
343   %my = and i32 %notmask, -1
344   %r = or i32 %mx, %my
345   ret i32 %r
347 define i32 @in_constant_varx_mone(i32 %x, i32 %y, i32 %mask) {
348 ; CHECK-LABEL: in_constant_varx_mone:
349 ; CHECK:       // %bb.0:
350 ; CHECK-NEXT:    bic w8, w2, w0
351 ; CHECK-NEXT:    mvn w0, w8
352 ; CHECK-NEXT:    ret
353   %n0 = xor i32 %x, -1 ; %x
354   %n1 = and i32 %n0, %mask
355   %r = xor i32 %n1, -1
356   ret i32 %r
358 ; This is not a canonical form. Testing for completeness only.
359 define i32 @out_constant_varx_mone_invmask(i32 %x, i32 %y, i32 %mask) {
360 ; CHECK-LABEL: out_constant_varx_mone_invmask:
361 ; CHECK:       // %bb.0:
362 ; CHECK-NEXT:    orr w0, w0, w2
363 ; CHECK-NEXT:    ret
364   %notmask = xor i32 %mask, -1
365   %mx = and i32 %notmask, %x
366   %my = and i32 %mask, -1
367   %r = or i32 %mx, %my
368   ret i32 %r
370 ; This is not a canonical form. Testing for completeness only.
371 define i32 @in_constant_varx_mone_invmask(i32 %x, i32 %y, i32 %mask) {
372 ; CHECK-LABEL: in_constant_varx_mone_invmask:
373 ; CHECK:       // %bb.0:
374 ; CHECK-NEXT:    mvn w8, w0
375 ; CHECK-NEXT:    bic w8, w8, w2
376 ; CHECK-NEXT:    mvn w0, w8
377 ; CHECK-NEXT:    ret
378   %notmask = xor i32 %mask, -1
379   %n0 = xor i32 %x, -1 ; %x
380   %n1 = and i32 %n0, %notmask
381   %r = xor i32 %n1, -1
382   ret i32 %r
384 define i32 @out_constant_varx_42(i32 %x, i32 %y, i32 %mask) {
385 ; CHECK-LABEL: out_constant_varx_42:
386 ; CHECK:       // %bb.0:
387 ; CHECK-NEXT:    mov w9, #42
388 ; CHECK-NEXT:    and w8, w2, w0
389 ; CHECK-NEXT:    bic w9, w9, w2
390 ; CHECK-NEXT:    orr w0, w8, w9
391 ; CHECK-NEXT:    ret
392   %notmask = xor i32 %mask, -1
393   %mx = and i32 %mask, %x
394   %my = and i32 %notmask, 42
395   %r = or i32 %mx, %my
396   ret i32 %r
398 define i32 @in_constant_varx_42(i32 %x, i32 %y, i32 %mask) {
399 ; CHECK-LABEL: in_constant_varx_42:
400 ; CHECK:       // %bb.0:
401 ; CHECK-NEXT:    mov w8, #42
402 ; CHECK-NEXT:    bic w8, w8, w2
403 ; CHECK-NEXT:    and w9, w0, w2
404 ; CHECK-NEXT:    orr w0, w9, w8
405 ; CHECK-NEXT:    ret
406   %n0 = xor i32 %x, 42 ; %x
407   %n1 = and i32 %n0, %mask
408   %r = xor i32 %n1, 42
409   ret i32 %r
411 ; This is not a canonical form. Testing for completeness only.
412 define i32 @out_constant_varx_42_invmask(i32 %x, i32 %y, i32 %mask) {
413 ; CHECK-LABEL: out_constant_varx_42_invmask:
414 ; CHECK:       // %bb.0:
415 ; CHECK-NEXT:    mov w9, #42
416 ; CHECK-NEXT:    bic w8, w0, w2
417 ; CHECK-NEXT:    and w9, w2, w9
418 ; CHECK-NEXT:    orr w0, w8, w9
419 ; CHECK-NEXT:    ret
420   %notmask = xor i32 %mask, -1
421   %mx = and i32 %notmask, %x
422   %my = and i32 %mask, 42
423   %r = or i32 %mx, %my
424   ret i32 %r
426 ; This is not a canonical form. Testing for completeness only.
427 define i32 @in_constant_varx_42_invmask(i32 %x, i32 %y, i32 %mask) {
428 ; CHECK-LABEL: in_constant_varx_42_invmask:
429 ; CHECK:       // %bb.0:
430 ; CHECK-NEXT:    mov w8, #42
431 ; CHECK-NEXT:    and w8, w2, w8
432 ; CHECK-NEXT:    bic w9, w0, w2
433 ; CHECK-NEXT:    orr w0, w9, w8
434 ; CHECK-NEXT:    ret
435   %notmask = xor i32 %mask, -1
436   %n0 = xor i32 %x, 42 ; %x
437   %n1 = and i32 %n0, %notmask
438   %r = xor i32 %n1, 42
439   ret i32 %r
441 define i32 @out_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
442 ; CHECK-LABEL: out_constant_mone_vary:
443 ; CHECK:       // %bb.0:
444 ; CHECK-NEXT:    orr w0, w1, w2
445 ; CHECK-NEXT:    ret
446   %notmask = xor i32 %mask, -1
447   %mx = and i32 %mask, -1
448   %my = and i32 %notmask, %y
449   %r = or i32 %mx, %my
450   ret i32 %r
452 define i32 @in_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
453 ; CHECK-LABEL: in_constant_mone_vary:
454 ; CHECK:       // %bb.0:
455 ; CHECK-NEXT:    bic w8, w2, w1
456 ; CHECK-NEXT:    eor w0, w8, w1
457 ; CHECK-NEXT:    ret
458   %n0 = xor i32 -1, %y ; %x
459   %n1 = and i32 %n0, %mask
460   %r = xor i32 %n1, %y
461   ret i32 %r
463 ; This is not a canonical form. Testing for completeness only.
464 define i32 @out_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
465 ; CHECK-LABEL: out_constant_mone_vary_invmask:
466 ; CHECK:       // %bb.0:
467 ; CHECK-NEXT:    and w8, w2, w1
468 ; CHECK-NEXT:    orn w0, w8, w2
469 ; CHECK-NEXT:    ret
470   %notmask = xor i32 %mask, -1
471   %mx = and i32 %notmask, -1
472   %my = and i32 %mask, %y
473   %r = or i32 %mx, %my
474   ret i32 %r
476 ; This is not a canonical form. Testing for completeness only.
477 define i32 @in_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
478 ; CHECK-LABEL: in_constant_mone_vary_invmask:
479 ; CHECK:       // %bb.0:
480 ; CHECK-NEXT:    mvn w8, w1
481 ; CHECK-NEXT:    bic w8, w8, w2
482 ; CHECK-NEXT:    eor w0, w8, w1
483 ; CHECK-NEXT:    ret
484   %notmask = xor i32 %mask, -1
485   %n0 = xor i32 -1, %y ; %x
486   %n1 = and i32 %n0, %notmask
487   %r = xor i32 %n1, %y
488   ret i32 %r
490 define i32 @out_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
491 ; CHECK-LABEL: out_constant_42_vary:
492 ; CHECK:       // %bb.0:
493 ; CHECK-NEXT:    mov w8, #42
494 ; CHECK-NEXT:    and w8, w2, w8
495 ; CHECK-NEXT:    bic w9, w1, w2
496 ; CHECK-NEXT:    orr w0, w8, w9
497 ; CHECK-NEXT:    ret
498   %notmask = xor i32 %mask, -1
499   %mx = and i32 %mask, 42
500   %my = and i32 %notmask, %y
501   %r = or i32 %mx, %my
502   ret i32 %r
504 define i32 @in_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
505 ; CHECK-LABEL: in_constant_42_vary:
506 ; CHECK:       // %bb.0:
507 ; CHECK-NEXT:    mov w9, #42
508 ; CHECK-NEXT:    bic w8, w1, w2
509 ; CHECK-NEXT:    and w9, w2, w9
510 ; CHECK-NEXT:    orr w0, w9, w8
511 ; CHECK-NEXT:    ret
512   %n0 = xor i32 42, %y ; %x
513   %n1 = and i32 %n0, %mask
514   %r = xor i32 %n1, %y
515   ret i32 %r
517 ; This is not a canonical form. Testing for completeness only.
518 define i32 @out_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
519 ; CHECK-LABEL: out_constant_42_vary_invmask:
520 ; CHECK:       // %bb.0:
521 ; CHECK-NEXT:    mov w8, #42
522 ; CHECK-NEXT:    bic w8, w8, w2
523 ; CHECK-NEXT:    and w9, w2, w1
524 ; CHECK-NEXT:    orr w0, w8, w9
525 ; CHECK-NEXT:    ret
526   %notmask = xor i32 %mask, -1
527   %mx = and i32 %notmask, 42
528   %my = and i32 %mask, %y
529   %r = or i32 %mx, %my
530   ret i32 %r
532 ; This is not a canonical form. Testing for completeness only.
533 define i32 @in_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
534 ; CHECK-LABEL: in_constant_42_vary_invmask:
535 ; CHECK:       // %bb.0:
536 ; CHECK-NEXT:    mov w9, #42
537 ; CHECK-NEXT:    and w8, w1, w2
538 ; CHECK-NEXT:    bic w9, w9, w2
539 ; CHECK-NEXT:    orr w0, w9, w8
540 ; CHECK-NEXT:    ret
541   %notmask = xor i32 %mask, -1
542   %n0 = xor i32 42, %y ; %x
543   %n1 = and i32 %n0, %notmask
544   %r = xor i32 %n1, %y
545   ret i32 %r
547 ; ============================================================================ ;
548 ; Negative tests. Should not be folded.
549 ; ============================================================================ ;
550 ; Multi-use tests.
551 declare void @use32(i32) nounwind
552 define i32 @in_multiuse_A(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
553 ; CHECK-LABEL: in_multiuse_A:
554 ; CHECK:       // %bb.0:
555 ; CHECK-NEXT:    str x30, [sp, #-32]! // 8-byte Folded Spill
556 ; CHECK-NEXT:    eor w8, w0, w1
557 ; CHECK-NEXT:    stp x20, x19, [sp, #16] // 16-byte Folded Spill
558 ; CHECK-NEXT:    and w20, w8, w3
559 ; CHECK-NEXT:    mov w0, w20
560 ; CHECK-NEXT:    mov w19, w1
561 ; CHECK-NEXT:    bl use32
562 ; CHECK-NEXT:    eor w0, w20, w19
563 ; CHECK-NEXT:    ldp x20, x19, [sp, #16] // 16-byte Folded Reload
564 ; CHECK-NEXT:    ldr x30, [sp], #32 // 8-byte Folded Reload
565 ; CHECK-NEXT:    ret
566   %n0 = xor i32 %x, %y
567   %n1 = and i32 %n0, %mask
568   call void @use32(i32 %n1)
569   %r = xor i32 %n1, %y
570   ret i32 %r
572 define i32 @in_multiuse_B(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
573 ; CHECK-LABEL: in_multiuse_B:
574 ; CHECK:       // %bb.0:
575 ; CHECK-NEXT:    str x30, [sp, #-32]! // 8-byte Folded Spill
576 ; CHECK-NEXT:    eor w0, w0, w1
577 ; CHECK-NEXT:    stp x20, x19, [sp, #16] // 16-byte Folded Spill
578 ; CHECK-NEXT:    mov w19, w1
579 ; CHECK-NEXT:    and w20, w0, w3
580 ; CHECK-NEXT:    bl use32
581 ; CHECK-NEXT:    eor w0, w20, w19
582 ; CHECK-NEXT:    ldp x20, x19, [sp, #16] // 16-byte Folded Reload
583 ; CHECK-NEXT:    ldr x30, [sp], #32 // 8-byte Folded Reload
584 ; CHECK-NEXT:    ret
585   %n0 = xor i32 %x, %y
586   %n1 = and i32 %n0, %mask
587   call void @use32(i32 %n0)
588   %r = xor i32 %n1, %y
589   ret i32 %r
591 ; Various bad variants
592 define i32 @n0_badmask(i32 %x, i32 %y, i32 %mask, i32 %mask2) {
593 ; CHECK-LABEL: n0_badmask:
594 ; CHECK:       // %bb.0:
595 ; CHECK-NEXT:    and w8, w0, w2
596 ; CHECK-NEXT:    bic w9, w1, w3
597 ; CHECK-NEXT:    orr w0, w8, w9
598 ; CHECK-NEXT:    ret
599   %mx = and i32 %x, %mask
600   %notmask = xor i32 %mask2, -1 ; %mask2 instead of %mask
601   %my = and i32 %y, %notmask
602   %r = or i32 %mx, %my
603   ret i32 %r
605 define i32 @n0_badxor(i32 %x, i32 %y, i32 %mask) {
606 ; CHECK-LABEL: n0_badxor:
607 ; CHECK:       // %bb.0:
608 ; CHECK-NEXT:    eor w9, w2, #0x1
609 ; CHECK-NEXT:    and w8, w0, w2
610 ; CHECK-NEXT:    and w9, w1, w9
611 ; CHECK-NEXT:    orr w0, w8, w9
612 ; CHECK-NEXT:    ret
613   %mx = and i32 %x, %mask
614   %notmask = xor i32 %mask, 1 ; instead of -1
615   %my = and i32 %y, %notmask
616   %r = or i32 %mx, %my
617   ret i32 %r
619 define i32 @n1_thirdvar(i32 %x, i32 %y, i32 %z, i32 %mask) {
620 ; CHECK-LABEL: n1_thirdvar:
621 ; CHECK:       // %bb.0:
622 ; CHECK-NEXT:    eor w8, w0, w1
623 ; CHECK-NEXT:    and w8, w8, w3
624 ; CHECK-NEXT:    eor w0, w8, w2
625 ; CHECK-NEXT:    ret
626   %n0 = xor i32 %x, %y
627   %n1 = and i32 %n0, %mask
628   %r = xor i32 %n1, %z ; instead of %y
629   ret i32 %r