1 /* { dg-do run } */
2 /* { dg-options "-O2 -fdump-rtl-combine --save-temps" } */
3
4 /* Test that we don't generate BSL when in DImode with values in integer
5 registers, and do generate it where we have values in floating-point
6 registers. This is useful, as it allows us to avoid register moves
7 in the general case.
8
9 We want:
10 eor x0, x0, x1
11 and x0, x0, x2
12 eor x0, x0, x1
13 ret
14
15 Rather than:
16 fmov d2, x0
17 fmov d0, x2
18 fmov d1, x1
19 bsl v0.8b, v2.8b, v1.8b
20 fmov x0, d0
21 ret */
22
23 extern void abort (void);
24
25 unsigned long long __attribute__ ((noinline))
26 foo (unsigned long long a, unsigned long long b, unsigned long long c)
27 {
28 return ((a ^ b) & c) ^ b;
29 }
30
31 unsigned long long __attribute__ ((noinline))
32 foo2 (unsigned long long a, unsigned long long b, unsigned long long c)
33 {
34 return ((a ^ b) & c) ^ a;
35 }
36
37 #define force_simd(V1) asm volatile ("mov %d0, %1.d[0]" \
38 : "=w"(V1) \
39 : "w"(V1) \
40 : /* No clobbers */);
41
42 unsigned long long __attribute__ ((noinline))
43 bar (unsigned long long a, unsigned long long b, unsigned long long c)
44 {
45 force_simd (a);
46 force_simd (b);
47 force_simd (c);
48 c = ((a ^ b) & c) ^ b;
49 force_simd (c);
50 return c;
51 }
52
53 unsigned long long __attribute__ ((noinline))
54 bar2 (unsigned long long a, unsigned long long b, unsigned long long c)
55 {
56 force_simd (a);
57 force_simd (b);
58 force_simd (c);
59 c = ((a ^ b) & c) ^ a;
60 force_simd (c);
61 return c;
62 }
63
64 int
65 main (int argc, char** argv)
66 {
67 unsigned long long a = 0x0123456789abcdefULL;
68 unsigned long long b = 0xfedcba9876543210ULL;
69 unsigned long long c = 0xaabbccddeeff7777ULL;
70 if (foo (a, b, c) != bar (a, b, c))
71 abort ();
72 if (foo2 (a, b, c) != bar2 (a, b, c))
73 abort ();
74 return 0;
75 }
76
77 /* 2 BSL, 6 FMOV (to floating-point registers), and 2 FMOV (to general
78 purpose registers) for the "bar" tests, which should still use BSL. */
79 /* { dg-final { scan-assembler-times "bsl\tv\[0-9\]" 2 } } */
80 /* { dg-final { scan-assembler-times "fmov\td\[0-9\]" 6 } } */
81 /* { dg-final { scan-assembler-times "fmov\tx\[0-9\]" 2 } } */
82
83 /* { dg-final { scan-assembler-not "bif\tv\[0-9\]" } } */
84 /* { dg-final { scan-assembler-not "bit\tv\[0-9\]" } } */
85
86 /* We always match the idiom during combine. */
87 /* { dg-final { scan-rtl-dump-times "aarch64_simd_bsldi_internal" 2 "combine" } } */
88 /* { dg-final { scan-rtl-dump-times "aarch64_simd_bsldi_alt" 2 "combine" } } */