c-rhodes created this revision. c-rhodes added reviewers: sdesmalen, efriedma, rsandifo-arm. Herald added subscribers: kristof.beyls, tschuett. Herald added a reviewer: rengolin. Herald added a project: clang. c-rhodes requested review of this revision.
This patch adds tests and support for operations on SVE vectors created by the 'arm_sve_vector_bits' attribute, described by the Arm C Language Extensions (ACLE, version 00bet5, section 3.7.3.3) for SVE [1]. This covers the following: - VLSTs support the same forms of element-wise initialization as GNU vectors. - VLSTs support the same built-in C and C++ operators as GNU vectors. - Conditional and binary expressions containing GNU and SVE vectors (fixed or sizeless) are invalid since the ambiguity around the result type affects the ABI. No functional changes were required to support vector initialization and operators. The functional changes are to address unsupported conditional and binary expressions. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D88233 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/AST/ASTContext.cpp clang/lib/Sema/SemaExpr.cpp clang/test/Sema/attr-arm-sve-vector-bits.c
Index: clang/test/Sema/attr-arm-sve-vector-bits.c =================================================================== --- clang/test/Sema/attr-arm-sve-vector-bits.c +++ clang/test/Sema/attr-arm-sve-vector-bits.c @@ -123,13 +123,38 @@ void f(int c) { fixed_int8_t fs8; svint8_t ss8; + gnu_int8_t gs8; + // Check conditional expressions where the result is ambiguous are + // ill-formed. void *sel __attribute__((unused)); - sel = c ? ss8 : fs8; // expected-error {{cannot convert between a fixed-length and a sizeless vector}} - sel = c ? fs8 : ss8; // expected-error {{cannot convert between a fixed-length and a sizeless vector}} + sel = c ? ss8 : fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + sel = c ? fs8 : ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} - sel = fs8 + ss8; // expected-error {{cannot convert between a fixed-length and a sizeless vector}} - sel = ss8 + fs8; // expected-error {{cannot convert between a fixed-length and a sizeless vector}} + sel = c ? gs8 : ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + sel = c ? ss8 : gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + sel = c ? gs8 : fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + sel = c ? fs8 : gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + // Check binary expressions where the result is ambiguous are ill-formed. + ss8 = ss8 + fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + ss8 = ss8 + gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + fs8 = fs8 + ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + fs8 = fs8 + gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + gs8 = gs8 + ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + gs8 = gs8 + fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + ss8 += fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + ss8 += gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + fs8 += ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + fs8 += gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + gs8 += ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + gs8 += fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} } // --------------------------------------------------------------------------// @@ -268,3 +293,78 @@ TEST_CALL(int32) TEST_CALL(float64) TEST_CALL(bool) + +// --------------------------------------------------------------------------// +// Vector initialization + +#if defined(__ARM_FEATURE_SVE_BITS) && __ARM_FEATURE_SVE_BITS == 256 + +typedef svint32_t int32x8 __attribute__((arm_sve_vector_bits(N))); +typedef svfloat64_t float64x4 __attribute__((arm_sve_vector_bits(N))); + +int32x8 foo = {1, 2, 3, 4, 5, 6, 7, 8}; +int32x8 foo2 = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // expected-warning{{excess elements in vector initializer}} + +float64x4 bar = {1.0, 2.0, 3.0, 4.0}; +float64x4 bar2 = {1.0, 2.0, 3.0, 4.0, 5.0}; // expected-warning{{excess elements in vector initializer}} + +#endif + +// --------------------------------------------------------------------------// +// Vector ops + +#define TEST_BINARY(TYPE, NAME, OP) \ + TYPE NAME##_##TYPE(TYPE op1, TYPE op2) { \ + return op1 OP op2; \ + } \ + TYPE compound##NAME##_##TYPE(TYPE op1, TYPE op2) { \ + op1 OP##= op2; \ + return op1; \ + } + +#define TEST_COMPARISON(TYPE, NAME, OP) \ + TYPE NAME##_##TYPE(TYPE op1, TYPE op2) { \ + return op1 OP op2; \ + } + +#define TEST_UNARY(TYPE, NAME, OP) \ + TYPE NAME##_##TYPE(TYPE op1) { \ + return OP op1; \ + } + +#define TEST_OPS(TYPE) \ + TEST_BINARY(TYPE, add, +) \ + TEST_BINARY(TYPE, sub, -) \ + TEST_BINARY(TYPE, mul, *) \ + TEST_BINARY(TYPE, div, /) \ + TEST_COMPARISON(TYPE, eq, ==) \ + TEST_COMPARISON(TYPE, ne, !=) \ + TEST_COMPARISON(TYPE, lt, <) \ + TEST_COMPARISON(TYPE, gt, >) \ + TEST_COMPARISON(TYPE, lte, <=) \ + TEST_COMPARISON(TYPE, gte, >=) \ + TEST_UNARY(TYPE, nop, +) \ + TEST_UNARY(TYPE, neg, -) + +#define TEST_INT_OPS(TYPE) \ + TEST_OPS(TYPE) \ + TEST_BINARY(TYPE, mod, %) \ + TEST_BINARY(TYPE, and, &) \ + TEST_BINARY(TYPE, or, |) \ + TEST_BINARY(TYPE, xor, ^) \ + TEST_BINARY(TYPE, shl, <<) \ + TEST_BINARY(TYPE, shr, <<) \ + TEST_UNARY(TYPE, not, ~) + +TEST_INT_OPS(fixed_int8_t) +TEST_INT_OPS(fixed_int16_t) +TEST_INT_OPS(fixed_int32_t) +TEST_INT_OPS(fixed_int64_t) +TEST_INT_OPS(fixed_uint8_t) +TEST_INT_OPS(fixed_uint16_t) +TEST_INT_OPS(fixed_uint32_t) +TEST_INT_OPS(fixed_uint64_t) + +TEST_OPS(fixed_float16_t) +TEST_OPS(fixed_float32_t) +TEST_OPS(fixed_float64_t) Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -9849,6 +9849,44 @@ } } + // Expressions containing fixed-length and sizeless SVE vectors are invalid + // since the ambiguity can affect the ABI. + auto IsSveConversion = [](QualType FirstType, QualType SecondType) { + const VectorType *VecType = SecondType->getAs<VectorType>(); + return FirstType->isSizelessBuiltinType() && VecType && + (VecType->getVectorKind() == VectorType::SveFixedLengthDataVector || + VecType->getVectorKind() == + VectorType::SveFixedLengthPredicateVector); + }; + + if (IsSveConversion(LHSType, RHSType) || IsSveConversion(RHSType, LHSType)) { + Diag(Loc, diag::err_typecheck_sve_ambiguous) << LHSType << RHSType; + return QualType(); + } + + // Expressions containing GNU and SVE (fixed or sizeless) vectors are invalid + // since the ambiguity can affect the ABI. + auto IsSveGnuConversion = [](QualType FirstType, QualType SecondType) { + const VectorType *FirstVecType = FirstType->getAs<VectorType>(); + const VectorType *SecondVecType = SecondType->getAs<VectorType>(); + + if (FirstVecType && SecondVecType) + return FirstVecType->getVectorKind() == VectorType::GenericVector && + (SecondVecType->getVectorKind() == + VectorType::SveFixedLengthDataVector || + SecondVecType->getVectorKind() == + VectorType::SveFixedLengthPredicateVector); + + return FirstType->isSizelessBuiltinType() && SecondVecType && + SecondVecType->getVectorKind() == VectorType::GenericVector; + }; + + if (IsSveGnuConversion(LHSType, RHSType) || + IsSveGnuConversion(RHSType, LHSType)) { + Diag(Loc, diag::err_typecheck_sve_gnu_ambiguous) << LHSType << RHSType; + return QualType(); + } + // If there's a vector type and a scalar, try to convert the scalar to // the vector element type and splat. unsigned DiagID = diag::err_typecheck_vector_not_convertable; @@ -9905,22 +9943,6 @@ // Okay, the expression is invalid. - // Returns true if the operands are SVE VLA and VLS types. - auto IsSveConversion = [](QualType FirstType, QualType SecondType) { - const VectorType *VecType = SecondType->getAs<VectorType>(); - return FirstType->isSizelessBuiltinType() && VecType && - (VecType->getVectorKind() == VectorType::SveFixedLengthDataVector || - VecType->getVectorKind() == - VectorType::SveFixedLengthPredicateVector); - }; - - // If there's a sizeless and fixed-length operand, diagnose that. - if (IsSveConversion(LHSType, RHSType) || IsSveConversion(RHSType, LHSType)) { - Diag(Loc, diag::err_typecheck_vector_not_convertable_sizeless) - << LHSType << RHSType; - return QualType(); - } - // If there's a non-vector, non-real operand, diagnose that. if ((!RHSVecType && !RHSType->isRealType()) || (!LHSVecType && !LHSType->isRealType())) { Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -8494,7 +8494,11 @@ First->getVectorKind() != VectorType::AltiVecPixel && First->getVectorKind() != VectorType::AltiVecBool && Second->getVectorKind() != VectorType::AltiVecPixel && - Second->getVectorKind() != VectorType::AltiVecBool) + Second->getVectorKind() != VectorType::AltiVecBool && + First->getVectorKind() != VectorType::SveFixedLengthDataVector && + First->getVectorKind() != VectorType::SveFixedLengthPredicateVector && + Second->getVectorKind() != VectorType::SveFixedLengthDataVector && + Second->getVectorKind() != VectorType::SveFixedLengthPredicateVector) return true; return false; Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2925,8 +2925,10 @@ "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero %0 size">; def err_attribute_size_too_large : Error<"%0 size too large">; -def err_typecheck_vector_not_convertable_sizeless : Error< - "cannot convert between a fixed-length and a sizeless vector (%0 and %1)">; +def err_typecheck_sve_ambiguous : Error< + "cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous (%0 and %1)">; +def err_typecheck_sve_gnu_ambiguous : Error< + "cannot combine GNU and SVE vectors in expression, result is ambiguous (%0 and %1)">; def err_typecheck_vector_not_convertable_implict_truncation : Error< "cannot convert between %select{scalar|vector}0 type %1 and vector type" " %2 as implicit conversion would cause truncation">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits