[clang] 23a96b8 - [AArch64][SVE] Support implicit lax vector conversions for SVE types
Joe Ellis via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 17 06:50:30 PST 2020
Author: Joe Ellis
Date: 2020-11-17T14:50:17Z
New Revision: 23a96b84a8d985b686a4e06dec1f7aebc0cca6c6
URL: https://github.com/llvm/llvm-project/commit/23a96b84a8d985b686a4e06dec1f7aebc0cca6c6
DIFF: https://github.com/llvm/llvm-project/commit/23a96b84a8d985b686a4e06dec1f7aebc0cca6c6.diff
LOG: [AArch64][SVE] Support implicit lax vector conversions for SVE types
Lax vector conversions was behaving incorrectly for implicit casts
between scalable and fixed-length vector types. For example, this:
#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;
void allowed_depending() {
fixed_float32_t fs32;
svfloat64_t s64;
fs32 = s64;
}
... would fail because the vectors have differing lane sizes. This patch
implements the correct behaviour for
-flax-vector-conversions={none,all,integer}. Specifically:
- -flax-vector-conversions=none prevents all lax vector conversions
between scalable and fixed-sized vectors.
- -flax-vector-conversions=integer allows lax vector conversions between
scalable and fixed-size vectors whose element types are integers.
- -flax-vector-conversions=all allows all lax vector conversions between
scalable and fixed-size vectors (including those with floating point
element types).
The implicit conversions are implemented as bitcasts.
Reviewed By: fpetrogalli
Differential Revision: https://reviews.llvm.org/D91067
Added:
clang/test/Sema/aarch64-sve-lax-vector-conversions.c
clang/test/SemaCXX/aarch64-sve-lax-vector-conversions.cpp
Modified:
clang/include/clang/AST/ASTContext.h
clang/lib/AST/ASTContext.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaOverload.cpp
clang/test/Sema/attr-arm-sve-vector-bits.c
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 9fc9c924b51c..8c0930237583 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2088,6 +2088,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// vector-length.
bool areCompatibleSveTypes(QualType FirstType, QualType SecondType);
+ /// Return true if the given vector types are lax-compatible SVE vector types,
+ /// false otherwise.
+ bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType);
+
/// Return true if the type has been explicitly qualified with ObjC ownership.
/// A type may be implicitly qualified with ownership under ObjC ARC, and in
/// some cases the compiler treats these
diff erently.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index d63f299f021f..836065291fea 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -8574,6 +8574,41 @@ bool ASTContext::areCompatibleSveTypes(QualType FirstType,
IsValidCast(SecondType, FirstType);
}
+bool ASTContext::areLaxCompatibleSveTypes(QualType FirstType,
+ QualType SecondType) {
+ assert(((FirstType->isSizelessBuiltinType() && SecondType->isVectorType()) ||
+ (FirstType->isVectorType() && SecondType->isSizelessBuiltinType())) &&
+ "Expected SVE builtin type and vector type!");
+
+ auto IsLaxCompatible = [this](QualType FirstType, QualType SecondType) {
+ if (!FirstType->getAs<BuiltinType>())
+ return false;
+
+ const auto *VecTy = SecondType->getAs<VectorType>();
+ if (VecTy &&
+ VecTy->getVectorKind() == VectorType::SveFixedLengthDataVector) {
+ const LangOptions::LaxVectorConversionKind LVCKind =
+ getLangOpts().getLaxVectorConversions();
+
+ // If -flax-vector-conversions=all is specified, the types are
+ // certainly compatible.
+ if (LVCKind == LangOptions::LaxVectorConversionKind::All)
+ return true;
+
+ // If -flax-vector-conversions=integer is specified, the types are
+ // compatible if the elements are integer types.
+ if (LVCKind == LangOptions::LaxVectorConversionKind::Integer)
+ return VecTy->getElementType().getCanonicalType()->isIntegerType() &&
+ FirstType->getSveEltType(*this)->isIntegerType();
+ }
+
+ return false;
+ };
+
+ return IsLaxCompatible(FirstType, SecondType) ||
+ IsLaxCompatible(SecondType, FirstType);
+}
+
bool ASTContext::hasDirectOwnershipQualifier(QualType Ty) const {
while (true) {
// __strong id
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0a25720c0f7b..e1a87ede3bdd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9003,12 +9003,13 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
}
// Allow assignments between fixed-length and sizeless SVE vectors.
- if (((LHSType->isSizelessBuiltinType() && RHSType->isVectorType()) ||
- (LHSType->isVectorType() && RHSType->isSizelessBuiltinType())) &&
- Context.areCompatibleSveTypes(LHSType, RHSType)) {
- Kind = CK_BitCast;
- return Compatible;
- }
+ if ((LHSType->isSizelessBuiltinType() && RHSType->isVectorType()) ||
+ (LHSType->isVectorType() && RHSType->isSizelessBuiltinType()))
+ if (Context.areCompatibleSveTypes(LHSType, RHSType) ||
+ Context.areLaxCompatibleSveTypes(LHSType, RHSType)) {
+ Kind = CK_BitCast;
+ return Compatible;
+ }
return Incompatible;
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 11fa0a634492..f43a2a2e88e8 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1644,11 +1644,12 @@ static bool IsVectorConversion(Sema &S, QualType FromType,
}
}
- if ((ToType->isSizelessBuiltinType() || FromType->isSizelessBuiltinType()) &&
- S.Context.areCompatibleSveTypes(FromType, ToType)) {
- ICK = ICK_SVE_Vector_Conversion;
- return true;
- }
+ if (ToType->isSizelessBuiltinType() || FromType->isSizelessBuiltinType())
+ if (S.Context.areCompatibleSveTypes(FromType, ToType) ||
+ S.Context.areLaxCompatibleSveTypes(FromType, ToType)) {
+ ICK = ICK_SVE_Vector_Conversion;
+ return true;
+ }
// We can perform the conversion between vector types in the following cases:
// 1)vector types are equivalent AltiVec and GCC vector types
diff --git a/clang/test/Sema/aarch64-sve-lax-vector-conversions.c b/clang/test/Sema/aarch64-sve-lax-vector-conversions.c
new file mode 100644
index 000000000000..68393275e54f
--- /dev/null
+++ b/clang/test/Sema/aarch64-sve-lax-vector-conversions.c
@@ -0,0 +1,34 @@
+// 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=lax-vector-none %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -flax-vector-conversions=integer -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify=lax-vector-integer %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -flax-vector-conversions=all -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify=lax-vector-all %s
+
+// lax-vector-all-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 svint32_t fixed_int32_t FIXED_ATTR;
+
+void allowed_with_integer_lax_conversions() {
+ fixed_int32_t fi32;
+ svint64_t si64;
+
+ // The implicit cast here should fail if -flax-vector-conversions=none, but pass if
+ // -flax-vector-conversions={integer,all}.
+ fi32 = si64;
+ // lax-vector-none-error at -1 {{assigning to 'fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
+}
+
+void allowed_with_all_lax_conversions() {
+ fixed_float32_t ff32;
+ svfloat64_t sf64;
+
+ // The implicit cast here should fail if -flax-vector-conversions={none,integer}, but pass if
+ // -flax-vector-conversions=all.
+ ff32 = sf64;
+ // lax-vector-none-error at -1 {{assigning to 'fixed_float32_t' (vector of 16 'float' values) from incompatible type}}
+ // lax-vector-integer-error at -2 {{assigning to 'fixed_float32_t' (vector of 16 'float' values) from incompatible type}}
+}
diff --git a/clang/test/Sema/attr-arm-sve-vector-bits.c b/clang/test/Sema/attr-arm-sve-vector-bits.c
index b4da3bd9f71d..667a49b0d76b 100644
--- a/clang/test/Sema/attr-arm-sve-vector-bits.c
+++ b/clang/test/Sema/attr-arm-sve-vector-bits.c
@@ -270,7 +270,6 @@ TEST_CAST_VECTOR(bfloat16)
TEST_CAST_COMMON(bool)
// Test the implicit conversion only applies to valid types
-fixed_int8_t to_fixed_int8_t__from_svuint8_t(svuint8_t x) { return x; } // expected-error-re {{returning 'svuint8_t' (aka '__SVUint8_t') from a function with incompatible result type 'fixed_int8_t' (vector of {{[0-9]+}} 'signed char' values)}}
fixed_bool_t to_fixed_bool_t__from_svint32_t(svint32_t x) { return x; } // expected-error-re {{returning 'svint32_t' (aka '__SVInt32_t') from a function with incompatible result type 'fixed_bool_t' (vector of {{[0-9]+}} 'unsigned char' values)}}
svint64_t to_svint64_t__from_gnu_int32_t(gnu_int32_t x) { return x; } // expected-error-re {{returning 'gnu_int32_t' (vector of {{[0-9]+}} 'int32_t' values) from a function with incompatible result type 'svint64_t' (aka '__SVInt64_t')}}
diff --git a/clang/test/SemaCXX/aarch64-sve-lax-vector-conversions.cpp b/clang/test/SemaCXX/aarch64-sve-lax-vector-conversions.cpp
new file mode 100644
index 000000000000..68393275e54f
--- /dev/null
+++ b/clang/test/SemaCXX/aarch64-sve-lax-vector-conversions.cpp
@@ -0,0 +1,34 @@
+// 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=lax-vector-none %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -flax-vector-conversions=integer -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify=lax-vector-integer %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -flax-vector-conversions=all -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify=lax-vector-all %s
+
+// lax-vector-all-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 svint32_t fixed_int32_t FIXED_ATTR;
+
+void allowed_with_integer_lax_conversions() {
+ fixed_int32_t fi32;
+ svint64_t si64;
+
+ // The implicit cast here should fail if -flax-vector-conversions=none, but pass if
+ // -flax-vector-conversions={integer,all}.
+ fi32 = si64;
+ // lax-vector-none-error at -1 {{assigning to 'fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
+}
+
+void allowed_with_all_lax_conversions() {
+ fixed_float32_t ff32;
+ svfloat64_t sf64;
+
+ // The implicit cast here should fail if -flax-vector-conversions={none,integer}, but pass if
+ // -flax-vector-conversions=all.
+ ff32 = sf64;
+ // lax-vector-none-error at -1 {{assigning to 'fixed_float32_t' (vector of 16 'float' values) from incompatible type}}
+ // lax-vector-integer-error at -2 {{assigning to 'fixed_float32_t' (vector of 16 'float' values) from incompatible type}}
+}
More information about the cfe-commits
mailing list