Even though "SVE type" and "SVE sizeless type" are marked as affecting type identity, the middle end doesn't truly believe it unless we also handle them in comp_type_attributes.
Tested on aarch64-linux-gnu. Pushed to trunk so far, but I'll backport to GCC 11 too. The GCC 10 version will look different. Richard gcc/ PR target/100270 * config/aarch64/aarch64.c (aarch64_comp_type_attributes): Handle SVE attributes. gcc/testsuite/ PR target/100270 * gcc.target/aarch64/sve/acle/general-c/pr100270_1.c: New test. * gcc.target/aarch64/sve/acle/general-c/sizeless-2.c: Change expected error message when subtracting pointers to different vector types. Expect warnings when mixing them elsewhere. * gcc.target/aarch64/sve/acle/general/attributes_7.c: Remove XFAILs. Tweak error messages for some cases. --- gcc/config/aarch64/aarch64.c | 4 + .../aarch64/sve/acle/general-c/pr100270_1.c | 103 ++++++++++++++++++ .../aarch64/sve/acle/general-c/sizeless-2.c | 36 +++--- .../aarch64/sve/acle/general/attributes_7.c | 72 ++++++------ 4 files changed, 166 insertions(+), 49 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pr100270_1.c diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 12625a4bee3..dbaf6fbe4c8 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -25173,6 +25173,10 @@ aarch64_comp_type_attributes (const_tree type1, const_tree type2) return 0; if (!check_attr ("Advanced SIMD type")) return 0; + if (!check_attr ("SVE type")) + return 0; + if (!check_attr ("SVE sizeless type")) + return 0; return 1; } diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pr100270_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pr100270_1.c new file mode 100644 index 00000000000..05232d79325 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pr100270_1.c @@ -0,0 +1,103 @@ +/* { dg-options "-msve-vector-bits=256" } */ + +#include <arm_sve.h> + +typedef svint32_t vls_svint32_t __attribute__((arm_sve_vector_bits(256))); +typedef svuint32_t vls_svuint32_t __attribute__((arm_sve_vector_bits(256))); + +typedef int32_t gnu_svint32_t __attribute__((vector_size(32))); +typedef uint32_t gnu_svuint32_t __attribute__((vector_size(32))); + +#define X_gnu_svint32_t 1 +#define X_gnu_svuint32_t 2 +#define X_vls_svint32_t 3 +#define X_vls_svuint32_t 4 + +#define CHECK(T) T: X_##T + +#define CHECK_TYPE(EXPR, TYPE) \ + do { \ + int x[_Generic (EXPR, \ + CHECK (gnu_svint32_t), \ + CHECK (gnu_svuint32_t), \ + CHECK (vls_svint32_t), \ + CHECK (vls_svuint32_t), \ + default : 0) == X_##TYPE ? 1 : -1]; \ + } while (0) + +void +f (gnu_svint32_t sg, gnu_svuint32_t ug, vls_svint32_t sn, vls_svuint32_t un, int c) +{ + CHECK_TYPE (sg, gnu_svint32_t); + CHECK_TYPE (ug, gnu_svuint32_t); + CHECK_TYPE (sn, vls_svint32_t); + CHECK_TYPE (un, vls_svuint32_t); + + CHECK_TYPE (sg + 1, gnu_svint32_t); + CHECK_TYPE (ug + 1, gnu_svuint32_t); + CHECK_TYPE (sn + 1, vls_svint32_t); + CHECK_TYPE (un + 1, vls_svuint32_t); + + CHECK_TYPE (1 + sg, gnu_svint32_t); + CHECK_TYPE (1 + ug, gnu_svuint32_t); + CHECK_TYPE (1 + sn, vls_svint32_t); + CHECK_TYPE (1 + un, vls_svuint32_t); + + CHECK_TYPE (sg + sg, gnu_svint32_t); + CHECK_TYPE (ug + ug, gnu_svuint32_t); + CHECK_TYPE (sn + sn, vls_svint32_t); + CHECK_TYPE (un + un, vls_svuint32_t); + + /* Traditional behavior for mixed signs is to pick the signedness of the + first operand. We don't have any Arm-specific reason for preferring that + behavior. */ + CHECK_TYPE (sg + ug, gnu_svint32_t); + CHECK_TYPE (ug + sg, gnu_svuint32_t); + CHECK_TYPE (sn + un, vls_svint32_t); + CHECK_TYPE (un + sn, vls_svuint32_t); + + CHECK_TYPE (c ? sg + sg : sg, gnu_svint32_t); + CHECK_TYPE (c ? ug + ug : ug, gnu_svuint32_t); + CHECK_TYPE (c ? sn + sn : sn, vls_svint32_t); + CHECK_TYPE (c ? un + un : un, vls_svuint32_t); + + CHECK_TYPE (c ? sg + 1 : sg, gnu_svint32_t); + CHECK_TYPE (c ? ug + 1 : ug, gnu_svuint32_t); + CHECK_TYPE (c ? sn + 1 : sn, vls_svint32_t); + CHECK_TYPE (c ? un + 1 : un, vls_svuint32_t); + + CHECK_TYPE (c ? 1 + sg : sg, gnu_svint32_t); + CHECK_TYPE (c ? 1 + ug : ug, gnu_svuint32_t); + CHECK_TYPE (c ? 1 + sn : sn, vls_svint32_t); + CHECK_TYPE (c ? 1 + un : un, vls_svuint32_t); + + CHECK_TYPE (c ? sg : sg + sg, gnu_svint32_t); + CHECK_TYPE (c ? ug : ug + ug, gnu_svuint32_t); + CHECK_TYPE (c ? sn : sn + sn, vls_svint32_t); + CHECK_TYPE (c ? un : un + un, vls_svuint32_t); + + CHECK_TYPE (c ? sg : sg + 1, gnu_svint32_t); + CHECK_TYPE (c ? ug : ug + 1, gnu_svuint32_t); + CHECK_TYPE (c ? sn : sn + 1, vls_svint32_t); + CHECK_TYPE (c ? un : un + 1, vls_svuint32_t); + + CHECK_TYPE (c ? sg : 1 + sg, gnu_svint32_t); + CHECK_TYPE (c ? ug : 1 + ug, gnu_svuint32_t); + CHECK_TYPE (c ? sn : 1 + sn, vls_svint32_t); + CHECK_TYPE (c ? un : 1 + un, vls_svuint32_t); + + CHECK_TYPE (c ? sg + sg : sg + sg, gnu_svint32_t); + CHECK_TYPE (c ? ug + ug : ug + ug, gnu_svuint32_t); + CHECK_TYPE (c ? sn + sn : sn + sn, vls_svint32_t); + CHECK_TYPE (c ? un + un : un + un, vls_svuint32_t); + + CHECK_TYPE (c ? sg + sg : sg + 1, gnu_svint32_t); + CHECK_TYPE (c ? ug + ug : ug + 1, gnu_svuint32_t); + CHECK_TYPE (c ? sn + sn : sn + 1, vls_svint32_t); + CHECK_TYPE (c ? un + un : un + 1, vls_svuint32_t); + + CHECK_TYPE (c ? 1 + sg : sg + sg, gnu_svint32_t); + CHECK_TYPE (c ? 1 + ug : ug + ug, gnu_svuint32_t); + CHECK_TYPE (c ? 1 + sn : sn + sn, vls_svint32_t); + CHECK_TYPE (c ? 1 + un : un + un, vls_svuint32_t); +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c index 3af36de9994..c575492c1f8 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c @@ -106,8 +106,8 @@ statements (int n) /* Pointer assignment. */ - gnu_sc_ptr = sve_sc_ptr; - sve_sc_ptr = gnu_sc_ptr; + gnu_sc_ptr = sve_sc_ptr; /* { dg-warning {incompatible pointer type} } */ + sve_sc_ptr = gnu_sc_ptr; /* { dg-warning {incompatible pointer type} } */ /* Pointer arithmetic. */ @@ -120,8 +120,8 @@ statements (int n) sve_sc_ptr -= 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ sve_sc_ptr -= 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ sve_sc_ptr - sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ - gnu_sc_ptr - sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ - sve_sc_ptr - gnu_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + gnu_sc_ptr - sve_sc_ptr; /* { dg-error {invalid operands to binary -} } */ + sve_sc_ptr - gnu_sc_ptr; /* { dg-error {invalid operands to binary -} } */ sve_sc1 = sve_sc_ptr[0]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ sve_sc1 = sve_sc_ptr[1]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ @@ -133,18 +133,18 @@ statements (int n) sve_sc_ptr <= &sve_sc1; sve_sc_ptr > &sve_sc1; sve_sc_ptr >= &sve_sc1; - gnu_sc_ptr == sve_sc_ptr; - gnu_sc_ptr != sve_sc_ptr; - gnu_sc_ptr < sve_sc_ptr; - gnu_sc_ptr <= sve_sc_ptr; - gnu_sc_ptr > sve_sc_ptr; - gnu_sc_ptr >= sve_sc_ptr; - sve_sc_ptr == gnu_sc_ptr; - sve_sc_ptr != gnu_sc_ptr; - sve_sc_ptr < gnu_sc_ptr; - sve_sc_ptr <= gnu_sc_ptr; - sve_sc_ptr > gnu_sc_ptr; - sve_sc_ptr >= gnu_sc_ptr; + gnu_sc_ptr == sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + gnu_sc_ptr != sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + gnu_sc_ptr < sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + gnu_sc_ptr <= sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + gnu_sc_ptr > sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + gnu_sc_ptr >= sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + sve_sc_ptr == gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + sve_sc_ptr != gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + sve_sc_ptr < gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + sve_sc_ptr <= gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + sve_sc_ptr > gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ + sve_sc_ptr >= gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types} } */ /* Conditional expressions. */ @@ -154,8 +154,8 @@ statements (int n) 0 ? 0 : sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ 0 ?: sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ 0 ? sve_sc_ptr : sve_sc_ptr; - 0 ? sve_sc_ptr : gnu_sc_ptr; - 0 ? gnu_sc_ptr : sve_sc_ptr; + 0 ? sve_sc_ptr : gnu_sc_ptr; /* { dg-warning {pointer type mismatch} } */ + 0 ? gnu_sc_ptr : sve_sc_ptr; /* { dg-warning {pointer type mismatch} } */ /* Generic associations. */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c index e2e74700a01..621666ce6c9 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c @@ -85,19 +85,19 @@ f (int c) (void) (c ? fs8 : ss8); // { dg-error {type mismatch|different types} } (void) (c ? fs8 : fs8); - (void) (c ? fs8 : gs8); // { dg-error {type mismatch|different types} "" { xfail c++ } } + (void) (c ? fs8 : gs8); // { dg-error {type mismatch|different types} } (void) (c ? gs8 : ss8); // { dg-error {type mismatch|different types} } - (void) (c ? gs8 : fs8); // { dg-error {type mismatch|different types} "" { xfail c++ } } + (void) (c ? gs8 : fs8); // { dg-error {type mismatch|different types} } (void) (c ? gs8 : gs8); sb = fb; fb = sb; (void) (c ? sb : sb); - (void) (c ? sb : fb); // { dg-error {type mismatch|different types} "" { xfail *-*-* } } + (void) (c ? sb : fb); // { dg-error {type mismatch|different types} "" { xfail c } } - (void) (c ? fb : sb); // { dg-error {type mismatch|different types} "" { xfail *-*-* } } + (void) (c ? fb : sb); // { dg-error {type mismatch|different types} "" { xfail c } } (void) (c ? fb : fb); } @@ -123,24 +123,22 @@ g (int c) void *select __attribute__((unused)); diff = ss8 - ss8; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } - diff = ss8 - fs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" { xfail c } } - // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} "bogus" { target c } .-1 } - diff = ss8 - gs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" { xfail c } } - // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} "bogus" { target c } .-1 } + diff = ss8 - fs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" } + diff = ss8 - gs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" } - diff = fs8 - ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" { xfail c } } - // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} "bogus" { target c } .-1 } + diff = fs8 - ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" } diff = fs8 - fs8; - diff = fs8 - gs8; + diff = fs8 - gs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" } - diff = gs8 - ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" { xfail c } } - // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} "bogus" { target c } .-1 } - diff = gs8 - fs8; + diff = gs8 - ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" } + diff = gs8 - fs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" } diff = gs8 - gs8; - fs8 = ss8; // { dg-error {invalid conversion} "" { xfail c } } + fs8 = ss8; // { dg-error {invalid conversion} "" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } fs8 = fs8; - fs8 = gs8; + fs8 = gs8; // { dg-error {invalid conversion} "" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } fs8 = su8; // { dg-error {cannot convert} "c++" { target c++ } } // { dg-warning {incompatible pointer type} "c" { target c } .-1 } @@ -150,36 +148,48 @@ g (int c) // { dg-warning {incompatible pointer type} "c" { target c } .-1 } fs8 = ss16; // { dg-error {cannot convert} "c++" { target c++ } } - // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } fs8 = fs16; // { dg-error {cannot convert} "c++" { target c++ } } - // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } fs8 = gs16; // { dg-error {cannot convert} "c++" { target c++ } } - // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } select = c ? ss8 : ss8; - select = c ? ss8 : fs8; // { dg-error {distinct pointer types} "" { xfail c } } - select = c ? ss8 : gs8; // { dg-error {distinct pointer types} "" { xfail c } } + select = c ? ss8 : fs8; // { dg-error {distinct pointer types} "" { target c++ } } + // { dg-warning {pointer type mismatch} "c" { target c } .-1 } + select = c ? ss8 : gs8; // { dg-error {distinct pointer types} "" { target c++ } } + // { dg-warning {pointer type mismatch} "c" { target c } .-1 } - select = c ? fs8 : ss8; // { dg-error {distinct pointer types} "" { xfail c } } + select = c ? fs8 : ss8; // { dg-error {distinct pointer types} "" { target c++ } } + // { dg-warning {pointer type mismatch} "c" { target c } .-1 } select = c ? fs8 : fs8; - select = c ? fs8 : gs8; // { dg-error {distinct pointer types} "" { xfail *-*-* } } + select = c ? fs8 : gs8; // { dg-error {distinct pointer types} "" { target c++ } } + // { dg-warning {pointer type mismatch} "c" { target c } .-1 } - select = c ? gs8 : ss8; // { dg-error {distinct pointer types} "" { xfail c } } - select = c ? gs8 : fs8; // { dg-error {distinct pointer types} "" { xfail *-*-* } } + select = c ? gs8 : ss8; // { dg-error {distinct pointer types} "" { target c++ } } + // { dg-warning {pointer type mismatch} "c" { target c } .-1 } + select = c ? gs8 : fs8; // { dg-error {distinct pointer types} "" { target c++ } } + // { dg-warning {pointer type mismatch} "c" { target c } .-1 } select = c ? gs8 : gs8; diff = sb - sb; // { dg-error {arithmetic on pointer to SVE type 'svbool_t'} } - diff = sb - fb; // { dg-error {arithmetic on pointer to SVE type 'svbool_t'} } + diff = sb - fb; // { dg-error {invalid operands} "" { target c++ } } + // { dg-error {arithmetic on pointer to SVE type 'svbool_t'} "c" { target c } .-1 } - diff = fb - sb; // { dg-error {arithmetic on pointer to SVE type 'svbool_t'} } + diff = fb - sb; // { dg-error {invalid operands} "" { target c++ } } + // { dg-error {arithmetic on pointer to SVE type 'svbool_t'} "c" { target c } .-1 } diff = fb - fb; - sb = fb; - fb = sb; + sb = fb; // { dg-error {invalid conversion} "" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c xfail c } .-1 } + fb = sb; // { dg-error {invalid conversion} "" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c xfail c } .-1 } select = c ? sb : sb; - select = c ? sb : fb; // { dg-error {type mismatch|different types} "" { xfail *-*-* } } + select = c ? sb : fb; // { dg-error {distinct pointer types} "" { target c++ } } + // { dg-warning {pointer type mismatch} "c" { target c xfail c } .-1 } - select = c ? fb : sb; // { dg-error {type mismatch|different types} "" { xfail *-*-* } } + select = c ? fb : sb; // { dg-error {distinct pointer types} "" { target c++ } } + // { dg-warning {pointer type mismatch} "c" { target c xfail c } .-1 } select = c ? fb : fb; }