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;
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 -----------------------------------------------===//
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
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: \
#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);
/// 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,
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: \
#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<uint64_t, 9> 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<uint64_t, 9> 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);
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 = \
// CHECK: TypedefDecl {{.*}} implicit __SVBool_t '__SVBool_t'
// CHECK-NEXT: -BuiltinType {{.*}} '__SVBool_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVCount_t '__SVCount_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVCount_t'
// 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)
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
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.
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
// 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
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());
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) {
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());
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());
}