diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2700,6 +2700,8 @@ bool isSVEBool() const { return getKind() == Kind::SveBool; } + bool isSVECount() const { return getKind() == Kind::SveCount; } + /// Determines whether the given kind corresponds to a placeholder type. static bool isPlaceholderTypeKind(Kind K) { return K >= Overload; diff --git a/clang/include/clang/Basic/AArch64SVEACLETypes.def b/clang/include/clang/Basic/AArch64SVEACLETypes.def --- a/clang/include/clang/Basic/AArch64SVEACLETypes.def +++ b/clang/include/clang/Basic/AArch64SVEACLETypes.def @@ -49,6 +49,11 @@ SVE_TYPE(Name, Id, SingletonId) #endif +#ifndef SVE_OPAQUE_TYPE +#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId) \ + SVE_TYPE(Name, Id, SingletonId) +#endif + //===- Vector point types -----------------------------------------------===// @@ -125,6 +130,9 @@ SVE_PREDICATE_TYPE("__SVBool_t", "__SVBool_t", SveBool, SveBoolTy, 16) +SVE_OPAQUE_TYPE("__SVCount_t", "__SVCount_t", SveCount, SveCountTy) + #undef SVE_VECTOR_TYPE #undef SVE_PREDICATE_TYPE +#undef SVE_OPAQUE_TYPE #undef SVE_TYPE diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2322,6 +2322,11 @@ Width = 0; \ Align = 16; \ break; +#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId) \ + case BuiltinType::Id: \ + Width = 0; \ + Align = 16; \ + break; #include "clang/Basic/AArch64SVEACLETypes.def" #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: \ @@ -4119,6 +4124,7 @@ #define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId, NumEls) \ if (EltTy->isBooleanType() && NumElts == NumEls) \ return SingletonId; +#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingleTonId) #include "clang/Basic/AArch64SVEACLETypes.def" } else if (Target->hasRISCVVTypes()) { uint64_t EltTySize = getTypeSize(EltTy); @@ -9549,9 +9555,10 @@ /// getSVETypeSize - Return SVE vector or predicate register size. static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty) { assert(Ty->isVLSTBuiltinType() && "Invalid SVE Type"); - return Ty->getKind() == BuiltinType::SveBool - ? (Context.getLangOpts().VScaleMin * 128) / Context.getCharWidth() - : Context.getLangOpts().VScaleMin * 128; + if (Ty->getKind() == BuiltinType::SveBool || + Ty->getKind() == BuiltinType::SveCount) + return (Context.getLangOpts().VScaleMin * 128) / Context.getCharWidth(); + return Context.getLangOpts().VScaleMin * 128; } bool ASTContext::areCompatibleSveTypes(QualType FirstType, diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3217,6 +3217,12 @@ Out << (type_name == InternalName ? "u" : "") << type_name.size() \ << type_name; \ break; +#define SVE_OPAQUE_TYPE(InternalName, MangledName, Id, SingletonId) \ + case BuiltinType::Id: \ + type_name = MangledName; \ + Out << (type_name == InternalName ? "u" : "") << type_name.size() \ + << type_name; \ + break; #include "clang/Basic/AArch64SVEACLETypes.def" #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: \ diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -727,24 +727,41 @@ #include "clang/Basic/AArch64SVEACLETypes.def" { ASTContext::BuiltinVectorTypeInfo Info = - CGM.getContext().getBuiltinVectorTypeInfo(BT); - unsigned NumElemsPerVG = (Info.EC.getKnownMinValue() * Info.NumVectors) / 2; + // For svcount_t, only the lower 2 bytes are relevant. + BT->getKind() == BuiltinType::SveCount + ? ASTContext::BuiltinVectorTypeInfo( + CGM.getContext().BoolTy, llvm::ElementCount::getFixed(16), + 1) + : CGM.getContext().getBuiltinVectorTypeInfo(BT); + + // A single vector of bytes may not suffice as the representation of + // svcount_t tuples because of the gap between the active 16bits of + // successive tuple members. Currently no such tuples are defined for + // svcount_t, so assert that NumVectors is 1. + assert((BT->getKind() != BuiltinType::SveCount || Info.NumVectors == 1) && + "Unsupported number of vectors for svcount_t"); // Debuggers can't extract 1bit from a vector, so will display a - // bitpattern for svbool_t instead. + // bitpattern for predicates instead. + unsigned NumElems = Info.EC.getKnownMinValue() * Info.NumVectors; if (Info.ElementType == CGM.getContext().BoolTy) { - NumElemsPerVG /= 8; + NumElems /= 8; Info.ElementType = CGM.getContext().UnsignedCharTy; } - auto *LowerBound = - llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned( - llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0)); - SmallVector Expr( - {llvm::dwarf::DW_OP_constu, NumElemsPerVG, llvm::dwarf::DW_OP_bregx, - /* AArch64::VG */ 46, 0, llvm::dwarf::DW_OP_mul, - llvm::dwarf::DW_OP_constu, 1, llvm::dwarf::DW_OP_minus}); - auto *UpperBound = DBuilder.createExpression(Expr); + llvm::Metadata *LowerBound, *UpperBound; + LowerBound = llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned( + llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0)); + if (Info.EC.isScalable()) { + unsigned NumElemsPerVG = NumElems / 2; + SmallVector Expr( + {llvm::dwarf::DW_OP_constu, NumElemsPerVG, llvm::dwarf::DW_OP_bregx, + /* AArch64::VG */ 46, 0, llvm::dwarf::DW_OP_mul, + llvm::dwarf::DW_OP_constu, 1, llvm::dwarf::DW_OP_minus}); + UpperBound = DBuilder.createExpression(Expr); + } else + UpperBound = llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned( + llvm::Type::getInt64Ty(CGM.getLLVMContext()), NumElems - 1)); llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange( /*count*/ nullptr, LowerBound, UpperBound, /*stride*/ nullptr); diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -618,6 +618,8 @@ Info.EC.getKnownMinValue() * Info.NumVectors); } + case BuiltinType::SveCount: + return llvm::TargetExtType::get(getLLVMContext(), "aarch64.svcount"); #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: \ ResultType = \ diff --git a/clang/test/AST/ast-dump-aarch64-sve-types.c b/clang/test/AST/ast-dump-aarch64-sve-types.c --- a/clang/test/AST/ast-dump-aarch64-sve-types.c +++ b/clang/test/AST/ast-dump-aarch64-sve-types.c @@ -47,3 +47,6 @@ // CHECK: TypedefDecl {{.*}} implicit __SVBool_t '__SVBool_t' // CHECK-NEXT: -BuiltinType {{.*}} '__SVBool_t' + +// CHECK: TypedefDecl {{.*}} implicit __SVCount_t '__SVCount_t' +// CHECK-NEXT: -BuiltinType {{.*}} '__SVCount_t' diff --git a/clang/test/CodeGen/aarch64-debug-sve-vector-types.c b/clang/test/CodeGen/aarch64-debug-sve-vector-types.c --- a/clang/test/CodeGen/aarch64-debug-sve-vector-types.c +++ b/clang/test/CodeGen/aarch64-debug-sve-vector-types.c @@ -9,6 +9,12 @@ // CHECK-DAG: ![[REALELTS1_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 1, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) __SVBool_t b8; + // CHECK-DAG: name: "__SVCount_t",{{.*}}, baseType: ![[CT1_2:[0-9]+]] + // CHECK-DAG: ![[CT1_2]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8]], flags: DIFlagVector, elements: ![[ELTS0_to_1:[0-9]+]]) + // CHECK-DAG: ![[ELTS0_to_1]] = !{![[REALELTS0_to_1:[0-9]+]]} + // CHECK-DAG: ![[REALELTS0_to_1]] = !DISubrange(lowerBound: 0, upperBound: 1) + __SVCount_t c8; + // CHECK-DAG: name: "__SVInt8_t",{{.*}}, baseType: ![[CT8:[0-9]+]] // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYS8:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]]) // CHECK-DAG: ![[ELTTYS8]] = !DIBasicType(name: "signed char", size: 8, encoding: DW_ATE_signed_char) diff --git a/clang/test/CodeGen/aarch64-sve-inline-asm-crash.c b/clang/test/CodeGen/aarch64-sve-inline-asm-crash.c --- a/clang/test/CodeGen/aarch64-sve-inline-asm-crash.c +++ b/clang/test/CodeGen/aarch64-sve-inline-asm-crash.c @@ -20,5 +20,17 @@ return ret ; } +__SVCount_t funcB1(__SVCount_t in) +{ + __SVCount_t ret ; + asm volatile ( + "mov %[ret].b, %[in].b \n" + : [ret] "=w" (ret) + : [in] "w" (in) + :); + + return ret ; +} + // CHECK: funcB1 // CHECK-ERROR: fatal error: error in backend: Cannot select diff --git a/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp b/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp --- a/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp +++ b/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp @@ -31,6 +31,8 @@ void f12(S<__SVBFloat16_t>) {} // CHECK: _Z3f131SIu10__SVBool_tE void f13(S<__SVBool_t>) {} +// CHECK: _Z3f141SIu11__SVCount_tE +void f14(S<__SVCount_t>) {} // The tuple types don't use the internal name for mangling. diff --git a/clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp b/clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp --- a/clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp +++ b/clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp @@ -22,6 +22,7 @@ auto &bf16 = typeid(__SVBFloat16_t); auto &b8 = typeid(__SVBool_t); +auto &c8 = typeid(__SVCount_t); // CHECK-DAG: @_ZTSu10__SVInt8_t = {{.*}} c"u10__SVInt8_t\00" // CHECK-DAG: @_ZTIu10__SVInt8_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu10__SVInt8_t @@ -61,3 +62,6 @@ // CHECK-DAG: @_ZTSu10__SVBool_t = {{.*}} c"u10__SVBool_t\00" // CHECK-DAG: @_ZTIu10__SVBool_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu10__SVBool_t + +// CHECK-DAG: @_ZTSu11__SVCount_t = {{.*}} c"u11__SVCount_t\00" +// CHECK-DAG: @_ZTIu11__SVCount_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu11__SVCount_t diff --git a/clang/unittests/AST/SizelessTypesTest.cpp b/clang/unittests/AST/SizelessTypesTest.cpp --- a/clang/unittests/AST/SizelessTypesTest.cpp +++ b/clang/unittests/AST/SizelessTypesTest.cpp @@ -45,6 +45,7 @@ ASSERT_TRUE(Ctx.SveBFloat16Ty->isSizelessBuiltinType()); ASSERT_TRUE(Ctx.SveBoolTy->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveCountTy->isSizelessBuiltinType()); ASSERT_FALSE(Ctx.VoidTy->isSizelessBuiltinType()); ASSERT_FALSE(Ctx.PseudoObjectTy->isSizelessBuiltinType()); @@ -55,6 +56,12 @@ Ctx.getLValueReferenceType(Ctx.SveBoolTy)->isSizelessBuiltinType()); ASSERT_FALSE( Ctx.getRValueReferenceType(Ctx.SveBoolTy)->isSizelessBuiltinType()); + + ASSERT_FALSE(Ctx.getPointerType(Ctx.SveCountTy)->isSizelessBuiltinType()); + ASSERT_FALSE( + Ctx.getLValueReferenceType(Ctx.SveCountTy)->isSizelessBuiltinType()); + ASSERT_FALSE( + Ctx.getRValueReferenceType(Ctx.SveCountTy)->isSizelessBuiltinType()); } TEST_F(SizelessTypeTester, TestSizeless) { @@ -75,6 +82,7 @@ ASSERT_TRUE(Ctx.SveBFloat16Ty->isSizelessType()); ASSERT_TRUE(Ctx.SveBoolTy->isSizelessType()); + ASSERT_TRUE(Ctx.SveCountTy->isSizelessType()); ASSERT_FALSE(Ctx.VoidTy->isSizelessType()); ASSERT_FALSE(Ctx.PseudoObjectTy->isSizelessType()); @@ -83,4 +91,8 @@ ASSERT_FALSE(Ctx.getPointerType(Ctx.SveBoolTy)->isSizelessType()); ASSERT_FALSE(Ctx.getLValueReferenceType(Ctx.SveBoolTy)->isSizelessType()); ASSERT_FALSE(Ctx.getRValueReferenceType(Ctx.SveBoolTy)->isSizelessType()); + + ASSERT_FALSE(Ctx.getPointerType(Ctx.SveCountTy)->isSizelessType()); + ASSERT_FALSE(Ctx.getLValueReferenceType(Ctx.SveCountTy)->isSizelessType()); + ASSERT_FALSE(Ctx.getRValueReferenceType(Ctx.SveCountTy)->isSizelessType()); }