Page MenuHomePhabricator

[clang][aarch64] Support implicit casts between GNU and SVE vectors
ClosedPublic

Authored by c-rhodes on Sep 14 2020, 5:45 AM.

Details

Summary

This patch adds support for implicit casting between GNU vectors and SVE
vectors when __ARM_FEATURE_SVE_BITS==N, as defined by the Arm C
Language Extensions (ACLE, version 00bet5, section 3.7.3.3) for SVE [1].

This behavior makes it possible to use GNU vectors with ACLE functions
that operate on VLAT. For example:

typedef int8_t vec __attribute__((vector_size(32)));
vec f(vec x) { return svasrd_x(svptrue_b8(), x, 1); }

Tests are also added for implicit casting between GNU and fixed-length
SVE vectors created by the 'arm_sve_vector_bits' attribute. This
behavior makes it possible to use VLST with existing interfaces that
operate on GNUT. For example:

typedef int8_t vec1 __attribute__((vector_size(32)));
void f(vec1);
#if __ARM_FEATURE_SVE_BITS==256 && __ARM_FEATURE_SVE_VECTOR_OPERATORS
typedef svint8_t vec2 __attribute__((arm_sve_vector_bits(256)));
void g(vec2 x) { f(x); } // OK
#endif

The __ARM_FEATURE_SVE_VECTOR_OPERATORS feature macro indicates
interoperability with the GNU vector extension. This is the first patch
providing support for this feature, which once complete will be enabled
by the -msve-vector-bits flag, as the __ARM_FEATURE_SVE_BITS feature
currently is.

[1] https://developer.arm.com/documentation/100987/latest

Diff Detail

Event Timeline

c-rhodes created this revision.Sep 14 2020, 5:45 AM
Herald added a project: Restricted Project. · View Herald Transcript
c-rhodes requested review of this revision.Sep 14 2020, 5:45 AM
efriedma added inline comments.Sep 14 2020, 11:30 AM
clang/lib/AST/ASTContext.cpp
8522

We allow casting SVE fixed-width vectors only if the element type is identical, but we allow casting to GNU fixed-width vectors if the vector width is the same? That seems sort of loose; could allow weird casts, particularly when bool vectors are involved.

c-rhodes added inline comments.Sep 15 2020, 3:22 AM
clang/lib/AST/ASTContext.cpp
8522

We allow casting SVE fixed-width vectors only if the element type is identical, but we allow casting to GNU fixed-width vectors if the vector width is the same? That seems sort of loose; could allow weird casts, particularly when bool vectors are involved.

Fixed-length SVE vectors are created with the attribute and the vector width must match -msve-vector-bits, which should guarantee consistent vector widths for a given input. This is checking the vector width is the same and the element type matches when casting between GNU and SVE vectors, although since neither of those types are created by the attribute it's necessary to check the vector width to validate __ARM_FEATURE_SVE_BITS==N.

Predicates are treated differently in the ACLE and it doesn't mention supporting casts between GNU bool vectors and SVE VLS/VLA predicates. I'm also not sure the GNU vector_size extension is defined for bool elements yet, but I did notice Simon Moll is working on this (D81083).

c-rhodes updated this revision to Diff 291891.Sep 15 2020, 6:38 AM
c-rhodes edited the summary of this revision. (Show Details)

Added tests for implicit casts between GNU and fixed-length SVE vectors. I was planning to create a separate patch for this but since it's only tests and no functional changes I've included it in this patch.

c-rhodes added inline comments.Sep 15 2020, 6:50 AM
clang/test/Sema/attr-arm-sve-vector-bits.c
233–234

I expected similar diagnostics when casting between GNU and fixed-length SVE vectors where the element type doesn't match but the vector size is equal but that wasn't the case. Since no functional changes were necessary to support casting between these types I tried the following:

#include <stdint.h>

#define N 128

typedef float float32_t;
typedef double float64_t;

typedef float32_t gnu_float32_t __attribute__((vector_size(N/8)));
typedef float64_t gnu_float64_t __attribute__((vector_size(N/8)));

gnu_float32_t foo(gnu_float64_t x) { return (gnu_float32_t)x; }
gnu_float64_t bar(gnu_float32_t x) { return (gnu_float64_t)x; }

It seems Clang considers this implicit cast valid whereas GCC doesn't, even with lax vector conversions enabled.

c-rhodes added inline comments.Sep 15 2020, 7:45 AM
clang/test/Sema/attr-arm-sve-vector-bits.c
233–234

I pasted the wrong example, the explicit cast shouldn't be there:

#include <stdint.h>

#define N 128

typedef float float32_t;
typedef double float64_t;

typedef float32_t gnu_float32_t __attribute__((vector_size(N/8)));
typedef float64_t gnu_float64_t __attribute__((vector_size(N/8)));

gnu_float32_t foo(gnu_float64_t x) { return x; }
gnu_float64_t bar(gnu_float32_t x) { return x; }
efriedma added inline comments.Sep 15 2020, 12:02 PM
clang/lib/AST/ASTContext.cpp
8522

I think you need to check both the size and the element type here?

clang/test/Sema/attr-arm-sve-vector-bits.c
237

This test isn't checking what it says it is; int4 and svint64_t have different element types.

c-rhodes added inline comments.Sep 16 2020, 2:46 AM
clang/lib/AST/ASTContext.cpp
8522

I think you need to check both the size and the element type here?

Compare the size of a scalable and fixed-length vector?

c-rhodes updated this revision to Diff 292162.Sep 16 2020, 3:24 AM

Address comments

clang/test/Sema/attr-arm-sve-vector-bits.c
237

This test isn't checking what it says it is; int4 and svint64_t have different element types.

Good spot! Fixed

This revision is now accepted and ready to land.Sep 16 2020, 4:30 PM