Skip to content

Commit 1e2da38

Browse files
author
Joe Ellis
committed
[AArch64][SVE] Allow C-style casts between fixed-size and scalable vectors
This patch allows C-style casting between fixed-size and scalable vectors. This kind of cast was previously blocked by the compiler, but it should be allowed. Differential Revision: https://reviews.llvm.org/D91262
1 parent a1de391 commit 1e2da38

File tree

5 files changed

+135
-0
lines changed

5 files changed

+135
-0
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11501,6 +11501,8 @@ class Sema final {
1150111501
QualType CheckMatrixMultiplyOperands(ExprResult &LHS, ExprResult &RHS,
1150211502
SourceLocation Loc, bool IsCompAssign);
1150311503

11504+
bool isValidSveBitcast(QualType srcType, QualType destType);
11505+
1150411506
bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
1150511507
bool isLaxVectorConversion(QualType srcType, QualType destType);
1150611508

clang/lib/Sema/SemaCast.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,6 +2219,12 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
22192219
bool destIsVector = DestType->isVectorType();
22202220
bool srcIsVector = SrcType->isVectorType();
22212221
if (srcIsVector || destIsVector) {
2222+
// Allow bitcasting between SVE VLATs and VLSTs, and vice-versa.
2223+
if (Self.isValidSveBitcast(SrcType, DestType)) {
2224+
Kind = CK_BitCast;
2225+
return TC_Success;
2226+
}
2227+
22222228
// The non-vector type, if any, must have integral type. This is
22232229
// the same rule that C vector casts use; note, however, that enum
22242230
// types are not integral in C++.
@@ -2752,6 +2758,13 @@ void CastOperation::CheckCStyleCast() {
27522758
return;
27532759
}
27542760

2761+
// Allow bitcasting between compatible SVE vector types.
2762+
if ((SrcType->isVectorType() || DestType->isVectorType()) &&
2763+
Self.isValidSveBitcast(SrcType, DestType)) {
2764+
Kind = CK_BitCast;
2765+
return;
2766+
}
2767+
27552768
if (!DestType->isScalarType() && !DestType->isVectorType()) {
27562769
const RecordType *DestRecordTy = DestType->getAs<RecordType>();
27572770

clang/lib/Sema/SemaExpr.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7197,6 +7197,28 @@ static bool breakDownVectorType(QualType type, uint64_t &len,
71977197
return true;
71987198
}
71997199

7200+
/// Are the two types SVE-bitcast-compatible types? I.e. is bitcasting from the
7201+
/// first SVE type (e.g. an SVE VLAT) to the second type (e.g. an SVE VLST)
7202+
/// allowed?
7203+
///
7204+
/// This will also return false if the two given types do not make sense from
7205+
/// the perspective of SVE bitcasts.
7206+
bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) {
7207+
assert(srcTy->isVectorType() || destTy->isVectorType());
7208+
7209+
auto ValidScalableConversion = [](QualType FirstType, QualType SecondType) {
7210+
if (!FirstType->isSizelessBuiltinType())
7211+
return false;
7212+
7213+
const auto *VecTy = SecondType->getAs<VectorType>();
7214+
return VecTy &&
7215+
VecTy->getVectorKind() == VectorType::SveFixedLengthDataVector;
7216+
};
7217+
7218+
return ValidScalableConversion(srcTy, destTy) ||
7219+
ValidScalableConversion(destTy, srcTy);
7220+
}
7221+
72007222
/// Are the two types lax-compatible vector types? That is, given
72017223
/// that one of them is a vector, do they have equal storage sizes,
72027224
/// where the storage size is the number of elements times the element
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=128 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=256 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
3+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
4+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=1024 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
5+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=2048 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
6+
7+
// expected-no-diagnostics
8+
9+
#include <arm_sve.h>
10+
11+
#define N __ARM_FEATURE_SVE_BITS
12+
#define FIXED_ATTR __attribute__((arm_sve_vector_bits(N)))
13+
14+
typedef svfloat32_t fixed_float32_t FIXED_ATTR;
15+
typedef svfloat64_t fixed_float64_t FIXED_ATTR;
16+
typedef svint32_t fixed_int32_t FIXED_ATTR;
17+
typedef svint64_t fixed_int64_t FIXED_ATTR;
18+
19+
// SVE VLSTs can be cast to SVE VLATs, regardless of lane size.
20+
// NOTE: the list below is NOT exhaustive for all SVE types.
21+
22+
#define CAST(from, to) \
23+
void from##_to_##to(from a, to b) { \
24+
b = (to) a; \
25+
}
26+
27+
#define TESTCASE(ty1, ty2) \
28+
CAST(ty1, ty2) \
29+
CAST(ty2, ty1)
30+
31+
TESTCASE(fixed_float32_t, svfloat32_t)
32+
TESTCASE(fixed_float32_t, svfloat64_t)
33+
TESTCASE(fixed_float32_t, svint32_t)
34+
TESTCASE(fixed_float32_t, svint64_t)
35+
36+
TESTCASE(fixed_float64_t, svfloat32_t)
37+
TESTCASE(fixed_float64_t, svfloat64_t)
38+
TESTCASE(fixed_float64_t, svint32_t)
39+
TESTCASE(fixed_float64_t, svint64_t)
40+
41+
TESTCASE(fixed_int32_t, svfloat32_t)
42+
TESTCASE(fixed_int32_t, svfloat64_t)
43+
TESTCASE(fixed_int32_t, svint32_t)
44+
TESTCASE(fixed_int32_t, svint64_t)
45+
46+
TESTCASE(fixed_int64_t, svfloat32_t)
47+
TESTCASE(fixed_int64_t, svfloat64_t)
48+
TESTCASE(fixed_int64_t, svint32_t)
49+
TESTCASE(fixed_int64_t, svint64_t)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=128 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=256 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
3+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
4+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=1024 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
5+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=2048 -flax-vector-conversions=none -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify %s
6+
7+
// expected-no-diagnostics
8+
9+
#include <arm_sve.h>
10+
11+
#define N __ARM_FEATURE_SVE_BITS
12+
#define FIXED_ATTR __attribute__((arm_sve_vector_bits(N)))
13+
14+
typedef svfloat32_t fixed_float32_t FIXED_ATTR;
15+
typedef svfloat64_t fixed_float64_t FIXED_ATTR;
16+
typedef svint32_t fixed_int32_t FIXED_ATTR;
17+
typedef svint64_t fixed_int64_t FIXED_ATTR;
18+
19+
// SVE VLSTs can be cast to SVE VLATs, regardless of lane size.
20+
// NOTE: the list below is NOT exhaustive for all SVE types.
21+
22+
#define CAST(from, to) \
23+
void from##_to_##to(from a, to b) { \
24+
b = (to) a; \
25+
}
26+
27+
#define TESTCASE(ty1, ty2) \
28+
CAST(ty1, ty2) \
29+
CAST(ty2, ty1)
30+
31+
TESTCASE(fixed_float32_t, svfloat32_t)
32+
TESTCASE(fixed_float32_t, svfloat64_t)
33+
TESTCASE(fixed_float32_t, svint32_t)
34+
TESTCASE(fixed_float32_t, svint64_t)
35+
36+
TESTCASE(fixed_float64_t, svfloat32_t)
37+
TESTCASE(fixed_float64_t, svfloat64_t)
38+
TESTCASE(fixed_float64_t, svint32_t)
39+
TESTCASE(fixed_float64_t, svint64_t)
40+
41+
TESTCASE(fixed_int32_t, svfloat32_t)
42+
TESTCASE(fixed_int32_t, svfloat64_t)
43+
TESTCASE(fixed_int32_t, svint32_t)
44+
TESTCASE(fixed_int32_t, svint64_t)
45+
46+
TESTCASE(fixed_int64_t, svfloat32_t)
47+
TESTCASE(fixed_int64_t, svfloat64_t)
48+
TESTCASE(fixed_int64_t, svint32_t)
49+
TESTCASE(fixed_int64_t, svint64_t)

0 commit comments

Comments
 (0)