[clang] 1e2da38 - [AArch64][SVE] Allow C-style casts between fixed-size and scalable vectors
Joe Ellis via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 19 03:18:52 PST 2020
Author: Joe Ellis
Date: 2020-11-19T11:18:35Z
New Revision: 1e2da3839cc3543629ecb847fd3aa34edb64b42a
URL: https://github.com/llvm/llvm-project/commit/1e2da3839cc3543629ecb847fd3aa34edb64b42a
DIFF: https://github.com/llvm/llvm-project/commit/1e2da3839cc3543629ecb847fd3aa34edb64b42a.diff
LOG: [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
Added:
clang/test/Sema/aarch64-sve-explicit-casts-fixed-size.c
clang/test/SemaCXX/aarch64-sve-explicit-casts-fixed-size.cpp
Modified:
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaCast.cpp
clang/lib/Sema/SemaExpr.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index fb95b8cbd193..20c7e8c2ed1b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11501,6 +11501,8 @@ class Sema final {
QualType CheckMatrixMultiplyOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign);
+ bool isValidSveBitcast(QualType srcType, QualType destType);
+
bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
bool isLaxVectorConversion(QualType srcType, QualType destType);
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 0bd240585bd7..671820afd485 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -2219,6 +2219,12 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
bool destIsVector = DestType->isVectorType();
bool srcIsVector = SrcType->isVectorType();
if (srcIsVector || destIsVector) {
+ // Allow bitcasting between SVE VLATs and VLSTs, and vice-versa.
+ if (Self.isValidSveBitcast(SrcType, DestType)) {
+ Kind = CK_BitCast;
+ return TC_Success;
+ }
+
// The non-vector type, if any, must have integral type. This is
// the same rule that C vector casts use; note, however, that enum
// types are not integral in C++.
@@ -2752,6 +2758,13 @@ void CastOperation::CheckCStyleCast() {
return;
}
+ // Allow bitcasting between compatible SVE vector types.
+ if ((SrcType->isVectorType() || DestType->isVectorType()) &&
+ Self.isValidSveBitcast(SrcType, DestType)) {
+ Kind = CK_BitCast;
+ return;
+ }
+
if (!DestType->isScalarType() && !DestType->isVectorType()) {
const RecordType *DestRecordTy = DestType->getAs<RecordType>();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e1a87ede3bdd..7a8124fadfd7 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7197,6 +7197,28 @@ static bool breakDownVectorType(QualType type, uint64_t &len,
return true;
}
+/// Are the two types SVE-bitcast-compatible types? I.e. is bitcasting from the
+/// first SVE type (e.g. an SVE VLAT) to the second type (e.g. an SVE VLST)
+/// allowed?
+///
+/// This will also return false if the two given types do not make sense from
+/// the perspective of SVE bitcasts.
+bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) {
+ assert(srcTy->isVectorType() || destTy->isVectorType());
+
+ auto ValidScalableConversion = [](QualType FirstType, QualType SecondType) {
+ if (!FirstType->isSizelessBuiltinType())
+ return false;
+
+ const auto *VecTy = SecondType->getAs<VectorType>();
+ return VecTy &&
+ VecTy->getVectorKind() == VectorType::SveFixedLengthDataVector;
+ };
+
+ return ValidScalableConversion(srcTy, destTy) ||
+ ValidScalableConversion(destTy, srcTy);
+}
+
/// Are the two types lax-compatible vector types? That is, given
/// that one of them is a vector, do they have equal storage sizes,
/// where the storage size is the number of elements times the element
diff --git a/clang/test/Sema/aarch64-sve-explicit-casts-fixed-size.c b/clang/test/Sema/aarch64-sve-explicit-casts-fixed-size.c
new file mode 100644
index 000000000000..a93110db7cce
--- /dev/null
+++ b/clang/test/Sema/aarch64-sve-explicit-casts-fixed-size.c
@@ -0,0 +1,49 @@
+// 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
+// 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
+// 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
+// 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
+// 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
+
+// expected-no-diagnostics
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS
+#define FIXED_ATTR __attribute__((arm_sve_vector_bits(N)))
+
+typedef svfloat32_t fixed_float32_t FIXED_ATTR;
+typedef svfloat64_t fixed_float64_t FIXED_ATTR;
+typedef svint32_t fixed_int32_t FIXED_ATTR;
+typedef svint64_t fixed_int64_t FIXED_ATTR;
+
+// SVE VLSTs can be cast to SVE VLATs, regardless of lane size.
+// NOTE: the list below is NOT exhaustive for all SVE types.
+
+#define CAST(from, to) \
+ void from##_to_##to(from a, to b) { \
+ b = (to) a; \
+ }
+
+#define TESTCASE(ty1, ty2) \
+ CAST(ty1, ty2) \
+ CAST(ty2, ty1)
+
+TESTCASE(fixed_float32_t, svfloat32_t)
+TESTCASE(fixed_float32_t, svfloat64_t)
+TESTCASE(fixed_float32_t, svint32_t)
+TESTCASE(fixed_float32_t, svint64_t)
+
+TESTCASE(fixed_float64_t, svfloat32_t)
+TESTCASE(fixed_float64_t, svfloat64_t)
+TESTCASE(fixed_float64_t, svint32_t)
+TESTCASE(fixed_float64_t, svint64_t)
+
+TESTCASE(fixed_int32_t, svfloat32_t)
+TESTCASE(fixed_int32_t, svfloat64_t)
+TESTCASE(fixed_int32_t, svint32_t)
+TESTCASE(fixed_int32_t, svint64_t)
+
+TESTCASE(fixed_int64_t, svfloat32_t)
+TESTCASE(fixed_int64_t, svfloat64_t)
+TESTCASE(fixed_int64_t, svint32_t)
+TESTCASE(fixed_int64_t, svint64_t)
diff --git a/clang/test/SemaCXX/aarch64-sve-explicit-casts-fixed-size.cpp b/clang/test/SemaCXX/aarch64-sve-explicit-casts-fixed-size.cpp
new file mode 100644
index 000000000000..a93110db7cce
--- /dev/null
+++ b/clang/test/SemaCXX/aarch64-sve-explicit-casts-fixed-size.cpp
@@ -0,0 +1,49 @@
+// 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
+// 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
+// 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
+// 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
+// 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
+
+// expected-no-diagnostics
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS
+#define FIXED_ATTR __attribute__((arm_sve_vector_bits(N)))
+
+typedef svfloat32_t fixed_float32_t FIXED_ATTR;
+typedef svfloat64_t fixed_float64_t FIXED_ATTR;
+typedef svint32_t fixed_int32_t FIXED_ATTR;
+typedef svint64_t fixed_int64_t FIXED_ATTR;
+
+// SVE VLSTs can be cast to SVE VLATs, regardless of lane size.
+// NOTE: the list below is NOT exhaustive for all SVE types.
+
+#define CAST(from, to) \
+ void from##_to_##to(from a, to b) { \
+ b = (to) a; \
+ }
+
+#define TESTCASE(ty1, ty2) \
+ CAST(ty1, ty2) \
+ CAST(ty2, ty1)
+
+TESTCASE(fixed_float32_t, svfloat32_t)
+TESTCASE(fixed_float32_t, svfloat64_t)
+TESTCASE(fixed_float32_t, svint32_t)
+TESTCASE(fixed_float32_t, svint64_t)
+
+TESTCASE(fixed_float64_t, svfloat32_t)
+TESTCASE(fixed_float64_t, svfloat64_t)
+TESTCASE(fixed_float64_t, svint32_t)
+TESTCASE(fixed_float64_t, svint64_t)
+
+TESTCASE(fixed_int32_t, svfloat32_t)
+TESTCASE(fixed_int32_t, svfloat64_t)
+TESTCASE(fixed_int32_t, svint32_t)
+TESTCASE(fixed_int32_t, svint64_t)
+
+TESTCASE(fixed_int64_t, svfloat32_t)
+TESTCASE(fixed_int64_t, svfloat64_t)
+TESTCASE(fixed_int64_t, svint32_t)
+TESTCASE(fixed_int64_t, svint64_t)
More information about the cfe-commits
mailing list