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@-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@-1 {{assigning to 'fixed_float32_t' (vector of 16 'float' values) from incompatible type}} + // lax-vector-integer-error@-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@-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@-1 {{assigning to 'fixed_float32_t' (vector of 16 'float' values) from incompatible type}} + // lax-vector-integer-error@-2 {{assigning to 'fixed_float32_t' (vector of 16 'float' values) from incompatible type}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits