(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.target/
aarch64/
advsimd-intrinsics/
pr98852.c
       1  /* { dg-do compile } */
       2  /* { dg-additional-options "-std=c99" } */
       3  
       4  #include <arm_neon.h>
       5  
       6  typedef __typeof(((int32x4_t *) 0)[0][0]) int32_elt;
       7  typedef __typeof(((uint32x4_t *) 0)[0][0]) uint32_elt;
       8  
       9  typedef int32_elt gnu_int32x4_t __attribute__((vector_size(16)));
      10  typedef uint32_elt gnu_uint32x4_t __attribute__((vector_size(16)));
      11  
      12  #define X_gnu_int32x4_t 1
      13  #define X_gnu_uint32x4_t 2
      14  #define X_int32x4_t 3
      15  #define X_uint32x4_t 4
      16  
      17  #define CHECK(T) T: X_##T
      18  
      19  #define CHECK_TYPE(EXPR, TYPE) \
      20    do { \
      21      int x[_Generic (EXPR, \
      22  		    CHECK (gnu_int32x4_t), \
      23  		    CHECK (gnu_uint32x4_t), \
      24  		    CHECK (int32x4_t), \
      25  		    CHECK (uint32x4_t), \
      26  		    default : 0) == X_##TYPE ? 1 : -1]; \
      27    } while (0)
      28  
      29  void
      30  f (gnu_int32x4_t sg, gnu_uint32x4_t ug, int32x4_t sn, uint32x4_t un, int c)
      31  {
      32    CHECK_TYPE (sg, gnu_int32x4_t);
      33    CHECK_TYPE (ug, gnu_uint32x4_t);
      34    CHECK_TYPE (sn, int32x4_t);
      35    CHECK_TYPE (un, uint32x4_t);
      36  
      37    CHECK_TYPE (sg + 1, gnu_int32x4_t);
      38    CHECK_TYPE (ug + 1, gnu_uint32x4_t);
      39    CHECK_TYPE (sn + 1, int32x4_t);
      40    CHECK_TYPE (un + 1, uint32x4_t);
      41  
      42    CHECK_TYPE (1 + sg, gnu_int32x4_t);
      43    CHECK_TYPE (1 + ug, gnu_uint32x4_t);
      44    CHECK_TYPE (1 + sn, int32x4_t);
      45    CHECK_TYPE (1 + un, uint32x4_t);
      46  
      47    CHECK_TYPE (sg + sg, gnu_int32x4_t);
      48    CHECK_TYPE (ug + ug, gnu_uint32x4_t);
      49    CHECK_TYPE (sn + sn, int32x4_t);
      50    CHECK_TYPE (un + un, uint32x4_t);
      51  
      52    /* Traditional behavior for mixed signs is to pick the signedness of the
      53       first operand.  We don't have any Arm-specific reason for preferring that
      54       behavior, but including the tests helps to demonstrate the points in the
      55       comments below.  */
      56    CHECK_TYPE (sg + ug, gnu_int32x4_t);
      57    CHECK_TYPE (ug + sg, gnu_uint32x4_t);
      58    CHECK_TYPE (sn + un, int32x4_t);
      59    CHECK_TYPE (un + sn, uint32x4_t);
      60  
      61    /* Nothing specifies the type of mixed GNU and arm_neon.h operations, but:
      62  
      63       - it would be surprising if sg + un had a different signedness from
      64         sg + ug
      65  
      66       - it would also be mildly surprising if sg + un had a different type from
      67         both of its operands
      68  
      69       So in cases where the operands differ in both signedness and ABI, it seems
      70       more consistent to ignore the ABI difference and apply the usual rules for
      71       differences in sign.  */
      72    CHECK_TYPE (sg + un, gnu_int32x4_t);
      73    CHECK_TYPE (ug + sn, gnu_uint32x4_t);
      74    CHECK_TYPE (sn + ug, int32x4_t);
      75    CHECK_TYPE (un + sg, uint32x4_t);
      76  
      77    /* And if the first vector wins when operands differ in both signedness
      78       and ABI, it seems more consistent to do the same if the operands differ
      79       only in ABI.  */
      80    CHECK_TYPE (sg + sn, gnu_int32x4_t);
      81    CHECK_TYPE (ug + un, gnu_uint32x4_t);
      82    CHECK_TYPE (sn + sg, int32x4_t);
      83    CHECK_TYPE (un + ug, uint32x4_t);
      84  
      85    CHECK_TYPE (c ? sg + sg : sg, gnu_int32x4_t);
      86    CHECK_TYPE (c ? ug + ug : ug, gnu_uint32x4_t);
      87    CHECK_TYPE (c ? sn + sn : sn, int32x4_t);
      88    CHECK_TYPE (c ? un + un : un, uint32x4_t);
      89  
      90    CHECK_TYPE (c ? sg + 1 : sg, gnu_int32x4_t);
      91    CHECK_TYPE (c ? ug + 1 : ug, gnu_uint32x4_t);
      92    CHECK_TYPE (c ? sn + 1 : sn, int32x4_t);
      93    CHECK_TYPE (c ? un + 1 : un, uint32x4_t);
      94  
      95    CHECK_TYPE (c ? 1 + sg : sg, gnu_int32x4_t);
      96    CHECK_TYPE (c ? 1 + ug : ug, gnu_uint32x4_t);
      97    CHECK_TYPE (c ? 1 + sn : sn, int32x4_t);
      98    CHECK_TYPE (c ? 1 + un : un, uint32x4_t);
      99  
     100    CHECK_TYPE (c ? sg : sg + sg, gnu_int32x4_t);
     101    CHECK_TYPE (c ? ug : ug + ug, gnu_uint32x4_t);
     102    CHECK_TYPE (c ? sn : sn + sn, int32x4_t);
     103    CHECK_TYPE (c ? un : un + un, uint32x4_t);
     104  
     105    CHECK_TYPE (c ? sg : sg + 1, gnu_int32x4_t);
     106    CHECK_TYPE (c ? ug : ug + 1, gnu_uint32x4_t);
     107    CHECK_TYPE (c ? sn : sn + 1, int32x4_t);
     108    CHECK_TYPE (c ? un : un + 1, uint32x4_t);
     109  
     110    CHECK_TYPE (c ? sg : 1 + sg, gnu_int32x4_t);
     111    CHECK_TYPE (c ? ug : 1 + ug, gnu_uint32x4_t);
     112    CHECK_TYPE (c ? sn : 1 + sn, int32x4_t);
     113    CHECK_TYPE (c ? un : 1 + un, uint32x4_t);
     114  
     115    CHECK_TYPE (c ? sg + sg : sg + sg, gnu_int32x4_t);
     116    CHECK_TYPE (c ? ug + ug : ug + ug, gnu_uint32x4_t);
     117    CHECK_TYPE (c ? sn + sn : sn + sn, int32x4_t);
     118    CHECK_TYPE (c ? un + un : un + un, uint32x4_t);
     119  
     120    CHECK_TYPE (c ? sg + sg : sg + 1, gnu_int32x4_t);
     121    CHECK_TYPE (c ? ug + ug : ug + 1, gnu_uint32x4_t);
     122    CHECK_TYPE (c ? sn + sn : sn + 1, int32x4_t);
     123    CHECK_TYPE (c ? un + un : un + 1, uint32x4_t);
     124  
     125    CHECK_TYPE (c ? 1 + sg : sg + sg, gnu_int32x4_t);
     126    CHECK_TYPE (c ? 1 + ug : ug + ug, gnu_uint32x4_t);
     127    CHECK_TYPE (c ? 1 + sn : sn + sn, int32x4_t);
     128    CHECK_TYPE (c ? 1 + un : un + un, uint32x4_t);
     129  }