diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6638,6 +6638,8 @@ "subscript of pointer to function type %0">; def err_subscript_incomplete_or_sizeless_type : Error< "subscript of pointer to %select{incomplete|sizeless}0 type %1">; +def err_subscript_svbool_t : Error< + "subscript of svbool_t is not allowed">; def err_dereference_incomplete_type : Error< "dereference of pointer to incomplete type %0">; def ext_gnu_subscript_void_type : Extension< diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8423,7 +8423,8 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { // FIXME: Deal with vectors as array subscript bases. - if (E->getBase()->getType()->isVectorType()) + if (E->getBase()->getType()->isVectorType() || + E->getBase()->getType()->isVLSTBuiltinType()) return Error(E); APSInt Index; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1767,7 +1767,8 @@ // loads the lvalue formed by the subscript expr. However, we have to be // careful, because the base of a vector subscript is occasionally an rvalue, // so we can't get it as an lvalue. - if (!E->getBase()->getType()->isVectorType()) + if (!E->getBase()->getType()->isVectorType() && + !E->getBase()->getType()->isVLSTBuiltinType()) return EmitLoadOfLValue(E); // Handle the vector case. The base must be a vector, the index must be an diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -27,11 +27,13 @@ #include "clang/AST/OperationKinds.h" #include "clang/AST/ParentMapContext.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" @@ -5683,6 +5685,33 @@ OK = OK_VectorComponent; ResultType = VTy->getElementType(); + QualType BaseType = BaseExpr->getType(); + Qualifiers BaseQuals = BaseType.getQualifiers(); + Qualifiers MemberQuals = ResultType.getQualifiers(); + Qualifiers Combined = BaseQuals + MemberQuals; + if (Combined != MemberQuals) + ResultType = Context.getQualifiedType(ResultType, Combined); + } else if (LHSTy->isBuiltinType() && + LHSTy->getAs()->isVLSTBuiltinType()) { + const BuiltinType *BTy = LHSTy->getAs(); + if (BTy->isSVEBool()) + return ExprError(Diag(LLoc, diag::err_subscript_svbool_t) + << LHSExp->getSourceRange() << RHSExp->getSourceRange()); + + BaseExpr = LHSExp; + IndexExpr = RHSExp; + if (getLangOpts().CPlusPlus11 && LHSExp->isPRValue()) { + ExprResult Materialized = TemporaryMaterializationConversion(LHSExp); + if (Materialized.isInvalid()) + return ExprError(); + LHSExp = Materialized.get(); + } + VK = LHSExp->getValueKind(); + if (VK != VK_PRValue) + OK = OK_VectorComponent; + + ResultType = BTy->getSveEltType(Context); + QualType BaseType = BaseExpr->getType(); Qualifiers BaseQuals = BaseType.getQualifiers(); Qualifiers MemberQuals = ResultType.getQualifiers(); diff --git a/clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c b/clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c @@ -0,0 +1,90 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ +// RUN: -fallow-half-arguments-and-returns -disable-O0-optnone \ +// RUN: -emit-llvm -o - %s | opt -S -sroa | FileCheck %s + +// REQUIRES: aarch64-registered-target + +#include +#include + +// CHECK-LABEL: @subscript_int16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret i16 [[VECEXT]] +// +int16_t subscript_int16(svint16_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_uint16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret i16 [[VECEXT]] +// +uint16_t subscript_uint16(svuint16_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_int32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret i32 [[VECEXT]] +// +int32_t subscript_int32(svint32_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_uint32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret i32 [[VECEXT]] +// +uint32_t subscript_uint32(svuint32_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_int64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret i64 [[VECEXT]] +// +int64_t subscript_int64(svint64_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_uint64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret i64 [[VECEXT]] +// +uint64_t subscript_uint64(svuint64_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_float16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret half [[VECEXT]] +// +__fp16 subscript_float16(svfloat16_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_float32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret float [[VECEXT]] +// +float subscript_float32(svfloat32_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_float64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: ret double [[VECEXT]] +// +double subscript_float64(svfloat64_t a, size_t b) { + return a[b]; +} diff --git a/clang/test/Sema/aarch64-sve-vector-subscript-ops.c b/clang/test/Sema/aarch64-sve-vector-subscript-ops.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/aarch64-sve-vector-subscript-ops.c @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -verify -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only %s + +// REQUIRES: aarch64-registered-target + +#include + +void subscript(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, + svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, + svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, + svbool_t b) { + (void)b[0]; // expected-error{{subscript of svbool_t is not allowed}} + (void)b[0.f]; // expected-error{{subscript of svbool_t is not allowed}} + (void)b[0.]; // expected-error{{subscript of svbool_t is not allowed}} + + (void)i8[0.f]; // expected-error{{array subscript is not an integer}} + (void)i8[0.]; // expected-error{{array subscript is not an integer}} + + (void)u8[0.f]; // expected-error{{array subscript is not an integer}} + (void)u8[0.]; // expected-error{{array subscript is not an integer}} + + (void)i16[0.f]; // expected-error{{array subscript is not an integer}} + (void)i16[0.]; // expected-error{{array subscript is not an integer}} + + (void)u16[0.f]; // expected-error{{array subscript is not an integer}} + (void)u16[0.]; // expected-error{{array subscript is not an integer}} + + (void)i32[0.f]; // expected-error{{array subscript is not an integer}} + (void)i32[0.]; // expected-error{{array subscript is not an integer}} + + (void)u32[0.f]; // expected-error{{array subscript is not an integer}} + (void)u32[0.]; // expected-error{{array subscript is not an integer}} + + (void)i64[0.f]; // expected-error{{array subscript is not an integer}} + (void)i64[0.]; // expected-error{{array subscript is not an integer}} + + (void)u64[0.f]; // expected-error{{array subscript is not an integer}} + (void)u64[0.]; // expected-error{{array subscript is not an integer}} + + (void)f16[0.f]; // expected-error{{array subscript is not an integer}} + (void)f16[0.]; // expected-error{{array subscript is not an integer}} + + (void)f32[0.f]; // expected-error{{array subscript is not an integer}} + (void)f32[0.]; // expected-error{{array subscript is not an integer}} + + (void)f64[0.f]; // expected-error{{array subscript is not an integer}} + (void)f64[0.]; // expected-error{{array subscript is not an integer}} +}