(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.target/
aarch64/
bsl-idiom.c
       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" } } */