https://github.com/michele-scandale updated https://github.com/llvm/llvm-project/pull/197624
>From 542632c6a1544795c7efd23b981667605664a5f1 Mon Sep 17 00:00:00 2001 From: Michele Scandale <[email protected]> Date: Mon, 5 Oct 2026 10:54:00 -0700 Subject: [PATCH 1/2] Fix vector types w.r.t. qualified element type. This commit changes the way vector types are constructed to ensure that qualifiers on the element type are moved to the vector type itself -- i.e. a canonical vector type has always an unqualified element type. RFC: https://discourse.llvm.org/t/90783 --- clang/include/clang/AST/ASTContext.h | 5 +- clang/include/clang/AST/TypeBase.h | 36 +++++--- clang/lib/AST/ASTContext.cpp | 126 +++++++++++++-------------- clang/lib/AST/Type.cpp | 80 ++++++++++++++--- clang/test/Sema/types.c | 12 +++ clang/test/SemaCXX/vector.cpp | 14 +++ 6 files changed, 183 insertions(+), 90 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index b04b6335616615..2e6fa05cc885f0 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -256,13 +256,12 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable std::vector<VariableArrayType*> VariableArrayTypes; mutable llvm::ContextualFoldingSet<DependentSizedArrayType, ASTContext &> DependentSizedArrayTypes; - mutable llvm::ContextualFoldingSet<DependentSizedExtVectorType, ASTContext &> + mutable llvm::FoldingSet<DependentSizedExtVectorType> DependentSizedExtVectorTypes; mutable llvm::ContextualFoldingSet<DependentAddressSpaceType, ASTContext &> DependentAddressSpaceTypes; mutable llvm::FoldingSet<VectorType> VectorTypes; - mutable llvm::ContextualFoldingSet<DependentVectorType, ASTContext &> - DependentVectorTypes; + mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes; mutable llvm::FoldingSet<ConstantMatrixType> MatrixTypes; mutable llvm::ContextualFoldingSet<DependentSizedMatrixType, ASTContext &> DependentSizedMatrixTypes; diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index 6373794bb69f54..2d13a95c57e05c 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -4201,13 +4201,14 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { Expr *SizeExpr; - /// The element type of the array. + /// The element type of the vector. QualType ElementType; SourceLocation loc; + const ASTContext &Context; - DependentSizedExtVectorType(QualType ElementType, QualType can, - Expr *SizeExpr, SourceLocation loc); + DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, + QualType can, Expr *SizeExpr, SourceLocation loc); public: Expr *getSizeExpr() const { return SizeExpr; } @@ -4217,11 +4218,13 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + SplitQualType getSplitUnqualifiedType() const; + static bool classof(const Type *T) { return T->getTypeClass() == DependentSizedExtVector; } - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getElementType(), getSizeExpr()); } @@ -4277,12 +4280,14 @@ class VectorType : public Type, public llvm::FoldingSetNode { /// The element type of the vector. QualType ElementType; - VectorType(QualType vecType, unsigned nElements, QualType canonType, - VectorKind vecKind); + const ASTContext &Context; - VectorType(TypeClass tc, QualType vecType, unsigned nElements, + VectorType(const ASTContext &Context, QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind); + VectorType(const ASTContext &Context, TypeClass tc, QualType vecType, + unsigned nElements, QualType canonType, VectorKind vecKind); + public: QualType getElementType() const { return ElementType; } unsigned getNumElements() const { return VectorTypeBits.NumElements; } @@ -4290,6 +4295,8 @@ class VectorType : public Type, public llvm::FoldingSetNode { bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + SplitQualType getSplitUnqualifiedType() const; + VectorKind getVectorKind() const { return VectorKind(VectorTypeBits.VecKind); } @@ -4328,9 +4335,11 @@ class DependentVectorType : public Type, public llvm::FoldingSetNode { QualType ElementType; Expr *SizeExpr; SourceLocation Loc; + const ASTContext &Context; - DependentVectorType(QualType ElementType, QualType CanonType, Expr *SizeExpr, - SourceLocation Loc, VectorKind vecKind); + DependentVectorType(const ASTContext &Context, QualType ElementType, + QualType CanonType, Expr *SizeExpr, SourceLocation Loc, + VectorKind vecKind); public: Expr *getSizeExpr() const { return SizeExpr; } @@ -4343,11 +4352,13 @@ class DependentVectorType : public Type, public llvm::FoldingSetNode { bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + SplitQualType getSplitUnqualifiedType() const; + static bool classof(const Type *T) { return T->getTypeClass() == DependentVector; } - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); } @@ -4365,8 +4376,9 @@ class DependentVectorType : public Type, public llvm::FoldingSetNode { class ExtVectorType : public VectorType { friend class ASTContext; // ASTContext creates these. - ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) - : VectorType(ExtVector, vecType, nElements, canonType, + ExtVectorType(const ASTContext &Context, QualType vecType, unsigned nElements, + QualType canonType) + : VectorType(Context, ExtVector, vecType, nElements, canonType, VectorKind::Generic) {} public: diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index e925a1f44795bc..4ff04134c1f9b2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -924,8 +924,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, TranslationUnitKind TUKind) : ConstantArrayTypes(this_(), ConstantArrayTypesLog2InitSize), - DependentSizedArrayTypes(this_()), DependentSizedExtVectorTypes(this_()), - DependentAddressSpaceTypes(this_()), DependentVectorTypes(this_()), + DependentSizedArrayTypes(this_()), DependentAddressSpaceTypes(this_()), DependentSizedMatrixTypes(this_()), FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize), DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()), @@ -4771,18 +4770,20 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, if (VectorType *VTP = VectorTypes.lookup(ID, Token)) return QualType(VTP, 0); - // If the element type isn't canonical, this won't be a canonical type either, - // so fill in the canonical type field. + // If the element type isn't canonical or has qualifiers, this won't be a + // canonical type either, so fill in the canonical type field. QualType Canonical; - if (!vecType.isCanonical()) { - Canonical = getVectorType(getCanonicalType(vecType), NumElts, VecKind); + if (!vecType.isCanonical() || vecType.hasLocalQualifiers()) { + SplitQualType canonSplit = getCanonicalType(vecType).split(); + Canonical = getVectorType(QualType(canonSplit.Ty, 0), NumElts, VecKind); + Canonical = getQualifiedType(Canonical, canonSplit.Quals); // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.lookup(ID, Token); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } auto *New = new (*this, alignof(VectorType)) - VectorType(vecType, NumElts, Canonical, VecKind); + VectorType(*this, vecType, NumElts, Canonical, VecKind); VectorTypes.insert(New, Token); Types.push_back(New); return QualType(New, 0); @@ -4791,35 +4792,36 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, QualType ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr, SourceLocation AttrLoc, VectorKind VecKind) const { + SplitQualType CanonVecType = getCanonicalType(VecType).split(); + llvm::FoldingSetNodeID ID; - DependentVectorType::Profile(ID, *this, getCanonicalType(VecType), SizeExpr, - VecKind); + DependentVectorType::Profile(ID, *this, QualType(CanonVecType.Ty, 0), + SizeExpr, VecKind); llvm::FoldingSetInsertToken Token; DependentVectorType *Canon = DependentVectorTypes.lookup(ID, Token); - DependentVectorType *New; - if (Canon) { - New = new (*this, alignof(DependentVectorType)) DependentVectorType( - VecType, QualType(Canon, 0), SizeExpr, AttrLoc, VecKind); - } else { - QualType CanonVecTy = getCanonicalType(VecType); - if (CanonVecTy == VecType) { - New = new (*this, alignof(DependentVectorType)) - DependentVectorType(VecType, QualType(), SizeExpr, AttrLoc, VecKind); - - DependentVectorType *CanonCheck = DependentVectorTypes.lookup(ID, Token); - assert(!CanonCheck && - "Dependent-sized vector_size canonical type broken"); - (void)CanonCheck; - DependentVectorTypes.insert(New, Token); - } else { - QualType CanonTy = getDependentVectorType(CanonVecTy, SizeExpr, - SourceLocation(), VecKind); - New = new (*this, alignof(DependentVectorType)) - DependentVectorType(VecType, CanonTy, SizeExpr, AttrLoc, VecKind); - } + // If we don't have one, build one. + if (!Canon) { + Canon = new (*this, TypeAlignment) + DependentVectorType(*this, QualType(CanonVecType.Ty, 0), QualType(), + SizeExpr, AttrLoc, VecKind); + DependentVectorTypes.insert(Canon, Token); + Types.push_back(Canon); } + // Apply qualifiers from the element type to the vector. + QualType CanonTy = getQualifiedType(QualType(Canon, 0), CanonVecType.Quals); + + // If we didn't need extra canonicalization for the element type or the size + // expression, then just use that as our result. + if (QualType(CanonVecType.Ty, 0) == VecType && + Canon->getSizeExpr() == SizeExpr) + return CanonTy; + + // Otherwise, we need to build a type which follows the spelling + // of the element type. + auto *New = new (*this, TypeAlignment) + DependentVectorType(*this, VecType, CanonTy, SizeExpr, AttrLoc, VecKind); Types.push_back(New); return QualType(New, 0); } @@ -4841,60 +4843,58 @@ QualType ASTContext::getExtVectorType(QualType vecType, if (VectorType *VTP = VectorTypes.lookup(ID, Token)) return QualType(VTP, 0); - // If the element type isn't canonical, this won't be a canonical type either, - // so fill in the canonical type field. + // If the element type isn't canonical or has qualifiers, this won't be a + // canonical type either, so fill in the canonical type field. QualType Canonical; - if (!vecType.isCanonical()) { - Canonical = getExtVectorType(getCanonicalType(vecType), NumElts); + if (!vecType.isCanonical() || vecType.hasLocalQualifiers()) { + SplitQualType canonSplit = getCanonicalType(vecType).split(); + Canonical = getExtVectorType(QualType(canonSplit.Ty, 0), NumElts); + Canonical = getQualifiedType(Canonical, canonSplit.Quals); // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.lookup(ID, Token); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } auto *New = new (*this, alignof(ExtVectorType)) - ExtVectorType(vecType, NumElts, Canonical); + ExtVectorType(*this, vecType, NumElts, Canonical); VectorTypes.insert(New, Token); Types.push_back(New); return QualType(New, 0); } QualType -ASTContext::getDependentSizedExtVectorType(QualType vecType, - Expr *SizeExpr, +ASTContext::getDependentSizedExtVectorType(QualType VecType, Expr *SizeExpr, SourceLocation AttrLoc) const { + SplitQualType CanonVecType = getCanonicalType(VecType).split(); + llvm::FoldingSetNodeID ID; - DependentSizedExtVectorType::Profile(ID, *this, getCanonicalType(vecType), + DependentSizedExtVectorType::Profile(ID, *this, QualType(CanonVecType.Ty, 0), SizeExpr); - llvm::FoldingSetInsertToken Token; DependentSizedExtVectorType *Canon = DependentSizedExtVectorTypes.lookup(ID, Token); - DependentSizedExtVectorType *New; - if (Canon) { - // We already have a canonical version of this array type; use it as - // the canonical type for a newly-built type. - New = new (*this, alignof(DependentSizedExtVectorType)) - DependentSizedExtVectorType(vecType, QualType(Canon, 0), SizeExpr, - AttrLoc); - } else { - QualType CanonVecTy = getCanonicalType(vecType); - if (CanonVecTy == vecType) { - New = new (*this, alignof(DependentSizedExtVectorType)) - DependentSizedExtVectorType(vecType, QualType(), SizeExpr, AttrLoc); - - DependentSizedExtVectorType *CanonCheck = - DependentSizedExtVectorTypes.lookup(ID, Token); - assert(!CanonCheck && "Dependent-sized ext_vector canonical type broken"); - (void)CanonCheck; - DependentSizedExtVectorTypes.insert(New, Token); - } else { - QualType CanonExtTy = getDependentSizedExtVectorType(CanonVecTy, SizeExpr, - SourceLocation()); - New = new (*this, alignof(DependentSizedExtVectorType)) - DependentSizedExtVectorType(vecType, CanonExtTy, SizeExpr, AttrLoc); - } + + // If we don't have one, build one. + if (!Canon) { + Canon = new (*this, TypeAlignment) DependentSizedExtVectorType( + *this, QualType(CanonVecType.Ty, 0), QualType(), SizeExpr, AttrLoc); + DependentSizedExtVectorTypes.insert(Canon, Token); + Types.push_back(Canon); } + // Apply qualifiers from the element type to the vector. + QualType CanonTy = getQualifiedType(QualType(Canon, 0), CanonVecType.Quals); + + // If we didn't need extra canonicalization for the element type or the size + // expression, then just use that as our result. + if (QualType(CanonVecType.Ty, 0) == VecType && + Canon->getSizeExpr() == SizeExpr) + return CanonTy; + + // Otherwise, we need to build a type which follows the spelling + // of the element type. + auto *New = new (*this, TypeAlignment) + DependentSizedExtVectorType(*this, VecType, CanonTy, SizeExpr, AttrLoc); Types.push_back(New); return QualType(New, 0); } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 823a48cbab7c69..6f834491dfaee7 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -418,7 +418,8 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, E->Profile(ID, Context, true); } -DependentVectorType::DependentVectorType(QualType ElementType, +DependentVectorType::DependentVectorType(const ASTContext &Context, + QualType ElementType, QualType CanonType, Expr *SizeExpr, SourceLocation Loc, VectorKind VecKind) : Type(DependentVector, CanonType, @@ -426,10 +427,21 @@ DependentVectorType::DependentVectorType(QualType ElementType, ElementType->getDependence() | (SizeExpr ? toTypeDependence(SizeExpr->getDependence()) : TypeDependence::None)), - ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) { + ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc), Context(Context) { VectorTypeBits.VecKind = llvm::to_underlying(VecKind); } +SplitQualType DependentVectorType::getSplitUnqualifiedType() const { + auto SplitElem = ElementType.getSplitUnqualifiedType(); + QualType UnqualElemTy(SplitElem.Ty, 0); + if (UnqualElemTy == ElementType) + return SplitQualType(this, Qualifiers()); + + auto UnqualVecTy = Context.getDependentVectorType( + UnqualElemTy, getSizeExpr(), getAttributeLoc(), getVectorKind()); + return SplitQualType(UnqualVecTy.getTypePtr(), SplitElem.Quals); +} + void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType ElementType, const Expr *SizeExpr, @@ -439,16 +451,27 @@ void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID, SizeExpr->Profile(ID, Context, true); } -DependentSizedExtVectorType::DependentSizedExtVectorType(QualType ElementType, - QualType can, - Expr *SizeExpr, - SourceLocation loc) +DependentSizedExtVectorType::DependentSizedExtVectorType( + const ASTContext &Context, QualType ElementType, QualType can, + Expr *SizeExpr, SourceLocation loc) : Type(DependentSizedExtVector, can, TypeDependence::DependentInstantiation | ElementType->getDependence() | (SizeExpr ? toTypeDependence(SizeExpr->getDependence()) : TypeDependence::None)), - SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {} + SizeExpr(SizeExpr), ElementType(ElementType), loc(loc), Context(Context) { +} + +SplitQualType DependentSizedExtVectorType::getSplitUnqualifiedType() const { + auto SplitElem = ElementType.getSplitUnqualifiedType(); + QualType UnqualElemTy(SplitElem.Ty, 0); + if (UnqualElemTy == ElementType) + return SplitQualType(this, Qualifiers()); + + auto UnqualVecTy = Context.getDependentSizedExtVectorType( + UnqualElemTy, getSizeExpr(), getAttributeLoc()); + return SplitQualType(UnqualVecTy.getTypePtr(), SplitElem.Quals); +} void DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, @@ -526,17 +549,34 @@ void DependentSizedMatrixType::Profile(llvm::FoldingSetNodeID &ID, ColumnExpr->Profile(ID, CTX, true); } -VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType, +VectorType::VectorType(const ASTContext &Context, QualType vecType, + unsigned nElements, QualType canonType, VectorKind vecKind) - : VectorType(Vector, vecType, nElements, canonType, vecKind) {} + : VectorType(Context, Vector, vecType, nElements, canonType, vecKind) {} -VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements, - QualType canonType, VectorKind vecKind) - : Type(tc, canonType, vecType->getDependence()), ElementType(vecType) { +VectorType::VectorType(const ASTContext &Context, TypeClass tc, + QualType vecType, unsigned nElements, QualType canonType, + VectorKind vecKind) + : Type(tc, canonType, vecType->getDependence()), ElementType(vecType), + Context(Context) { VectorTypeBits.VecKind = llvm::to_underlying(vecKind); VectorTypeBits.NumElements = nElements; } +SplitQualType VectorType::getSplitUnqualifiedType() const { + auto SplitElem = ElementType.getSplitUnqualifiedType(); + QualType UnqualElemTy(SplitElem.Ty, 0); + if (UnqualElemTy == ElementType) + return SplitQualType(this, Qualifiers()); + + auto UnqualVecTy = + getTypeClass() == ExtVector + ? Context.getExtVectorType(UnqualElemTy, getNumElements()) + : Context.getVectorType(UnqualElemTy, getNumElements(), + getVectorKind()); + return SplitQualType(UnqualVecTy.getTypePtr(), SplitElem.Quals); +} + bool Type::isPackedVectorBoolType(const ASTContext &ctx) const { if (ctx.getLangOpts().HLSL) return false; @@ -713,6 +753,22 @@ SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) { } done: + // Vector types can have qualified element type. We need to recursively + // process the element type, and possibly construct a new vector type with the + // unqualified version of the element type. + SplitQualType SplitVec; + if (auto *VTy = dyn_cast<VectorType>(split.Ty)) + SplitVec = VTy->getSplitUnqualifiedType(); + else if (auto *DVTy = dyn_cast<DependentVectorType>(split.Ty)) + SplitVec = DVTy->getSplitUnqualifiedType(); + else if (auto *DSEVTy = dyn_cast<DependentSizedExtVectorType>(split.Ty)) + SplitVec = DSEVTy->getSplitUnqualifiedType(); + + if (SplitVec.Ty) { + quals.addConsistentQualifiers(SplitVec.Quals); + return SplitQualType(SplitVec.Ty, quals); + } + // An overflow behavior type can have a qualified underlying type. It is not // sugar, so the loop above cannot desugar through it to reach the // qualifiers; rebuild it with an unqualified underlying type instead. diff --git a/clang/test/Sema/types.c b/clang/test/Sema/types.c index 858e2433b5629e..ad7e47aa43597e 100644 --- a/clang/test/Sema/types.c +++ b/clang/test/Sema/types.c @@ -87,6 +87,18 @@ char __attribute__((vector_size(8388609))) v5; // expected-error {{vector size char __attribute__((vector_size(8388608))) v6; int __attribute__((vector_size(0x10000001))) v7; // expected-error {{vector size too large}} +typedef const int cint; +typedef int __attribute__((vector_size(16))) vec4_int; +typedef cint __attribute__((vector_size(16))) vec4_cint; +_Static_assert(!__builtin_types_compatible_p(vec4_int*, const vec4_int*), "'vec4_int' and 'const vec4_int' are not different"); +_Static_assert(!__builtin_types_compatible_p(vec4_int*, volatile vec4_int*), "'vec4_int' and 'const vec4_int' are not different"); +_Static_assert(__builtin_types_compatible_p(const vec4_int*, vec4_cint*), "'const vec4_int' and 'vec4_cint' are different"); +typedef int __attribute__((ext_vector_type(4))) ext_vec4_int; +typedef cint __attribute__((ext_vector_type(4))) ext_vec4_cint; +_Static_assert(!__builtin_types_compatible_p(ext_vec4_int*, const ext_vec4_int*), "'ext_vec4_int' and 'const ext_vec4_int' are not different"); +_Static_assert(!__builtin_types_compatible_p(ext_vec4_int*, volatile ext_vec4_int*), "'ext_vec4_int' and 'const ext_vec4_int' are not different"); +_Static_assert(__builtin_types_compatible_p(const ext_vec4_int*, ext_vec4_cint*), "'const ext_vec4_int' and 'ext_vec4_cint' are different"); + // no support for vector enum type enum { e_2 } x3 __attribute__((vector_size(64))); // expected-error {{invalid vector element type}} diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp index 581d829560ea69..b65993ce65c64d 100644 --- a/clang/test/SemaCXX/vector.cpp +++ b/clang/test/SemaCXX/vector.cpp @@ -822,3 +822,17 @@ namespace GH173347 { typedef short __attribute__((__vector_size__(8))) V; template <int N> V test(V x) { return (x % 5) * N; } } + +namespace test_canonical_quals { +typedef const int cint; +typedef int __attribute__((vector_size(16))) vec4_int; +typedef cint __attribute__((vector_size(16))) vec4_cint; +_Static_assert(!__is_same(vec4_int, const vec4_int), "'vec4_int' and 'const vec4_int' are not different"); +_Static_assert(!__is_same(vec4_int, volatile vec4_int), "'vec4_int' and 'const vec4_int' are not different"); +_Static_assert(__is_same(const vec4_int, vec4_cint), "'const vec4_int' and 'vec4_cint' are different"); +typedef int __attribute__((ext_vector_type(4))) ext_vec4_int; +typedef cint __attribute__((ext_vector_type(4))) ext_vec4_cint; +_Static_assert(!__is_same(ext_vec4_int, const ext_vec4_int), "'ext_vec4_int' and 'const ext_vec4_int' are not different"); +_Static_assert(!__is_same(ext_vec4_int, volatile ext_vec4_int), "'ext_vec4_int' and 'const ext_vec4_int' are not different"); +_Static_assert(__is_same(const ext_vec4_int, ext_vec4_cint), "'const ext_vec4_int' and 'ext_vec4_cint' are different"); +} // namespace test_canonical_quals >From c4cc201e6e3ff8138882cc7db209b8ea366d1c5e Mon Sep 17 00:00:00 2001 From: Michele Scandale <[email protected]> Date: Mon, 5 Oct 2026 10:54:00 -0700 Subject: [PATCH 2/2] [libcxx] Drop qualifiers on element type for `__simd_vector<T, N>`. --- libcxx/include/__algorithm/simd_utils.h | 20 +++++++++++-------- .../include/__cxx03/__algorithm/simd_utils.h | 16 +++++++++------ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/libcxx/include/__algorithm/simd_utils.h b/libcxx/include/__algorithm/simd_utils.h index 495aed4e21216a..dcd6daf6377be4 100644 --- a/libcxx/include/__algorithm/simd_utils.h +++ b/libcxx/include/__algorithm/simd_utils.h @@ -15,6 +15,7 @@ #include <__bit/countr.h> #include <__config> #include <__cstddef/size_t.h> +#include <__type_traits/remove_cv.h> #include <__utility/integer_sequence.h> #include <cstdint> @@ -88,7 +89,10 @@ inline constexpr size_t __native_vector_size = 1; # endif template <class _ArithmeticT, size_t _Np> -using __simd_vector __attribute__((__ext_vector_type__(_Np))) _LIBCPP_NODEBUG = _ArithmeticT; +using __simd_vector_impl __attribute__((__ext_vector_type__(_Np))) _LIBCPP_NODEBUG = _ArithmeticT; + +template <class _ArithmeticT, size_t _Np> +using __simd_vector _LIBCPP_NODEBUG = __simd_vector_impl<__remove_cv_t<_ArithmeticT>, _Np>; _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wpsabi") @@ -99,10 +103,10 @@ inline constexpr size_t __simd_vector_size_v = []<bool _False = false>() -> size }(); template <class _Tp, size_t _Np> -inline constexpr size_t __simd_vector_size_v<__simd_vector<_Tp, _Np>> = _Np; +inline constexpr size_t __simd_vector_size_v<__simd_vector_impl<_Tp, _Np>> = _Np; template <class _Tp, size_t _Np> -_LIBCPP_HIDE_FROM_ABI _Tp __simd_vector_underlying_type_impl(__simd_vector<_Tp, _Np>) { +_LIBCPP_HIDE_FROM_ABI _Tp __simd_vector_underlying_type_impl(__simd_vector_impl<_Tp, _Np>) { return _Tp{}; } @@ -127,22 +131,22 @@ template <class _VecT, size_t _Np, class _Iter> } template <class _Tp, size_t _Np> -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __any_of(__simd_vector<_Tp, _Np> __vec) noexcept { +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __any_of(__simd_vector_impl<_Tp, _Np> __vec) noexcept { return __builtin_reduce_or(__builtin_convertvector(__vec, __simd_vector<bool, _Np>)); } template <class _Tp, size_t _Np> -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept { +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector_impl<_Tp, _Np> __vec) noexcept { return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector<bool, _Np>)); } template <class _Tp, size_t _Np> -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __none_of(__simd_vector<_Tp, _Np> __vec) noexcept { +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __none_of(__simd_vector_impl<_Tp, _Np> __vec) noexcept { return !__builtin_reduce_or(__builtin_convertvector(__vec, __simd_vector<bool, _Np>)); } template <class _Tp, size_t _Np> -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept { +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector_impl<_Tp, _Np> __vec) noexcept { using __mask_vec = __simd_vector<bool, _Np>; // This has MSan disabled du to https://llvm.org/PR85876 @@ -171,7 +175,7 @@ template <class _Tp, size_t _Np> } template <class _Tp, size_t _Np> -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept { +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector_impl<_Tp, _Np> __vec) noexcept { return std::__find_first_set(~__vec); } _LIBCPP_DIAGNOSTIC_POP diff --git a/libcxx/include/__cxx03/__algorithm/simd_utils.h b/libcxx/include/__cxx03/__algorithm/simd_utils.h index 7b0e825afaa1f1..7758aee7e74bd2 100644 --- a/libcxx/include/__cxx03/__algorithm/simd_utils.h +++ b/libcxx/include/__cxx03/__algorithm/simd_utils.h @@ -15,6 +15,7 @@ #include <__cxx03/__config> #include <__cxx03/__type_traits/is_arithmetic.h> #include <__cxx03/__type_traits/is_same.h> +#include <__cxx03/__type_traits/remove_cv.h> #include <__cxx03/__utility/integer_sequence.h> #include <__cxx03/cstddef> #include <__cxx03/cstdint> @@ -85,7 +86,10 @@ inline constexpr size_t __native_vector_size = 1; # endif template <class _ArithmeticT, size_t _Np> -using __simd_vector __attribute__((__ext_vector_type__(_Np))) = _ArithmeticT; +using __simd_vector_impl __attribute__((__ext_vector_type__(_Np))) = _ArithmeticT; + +template <class _ArithmeticT, size_t _Np> +using __simd_vector = __simd_vector_impl<__remove_cv_t<_ArithmeticT>, _Np>; template <class _VecT> inline constexpr size_t __simd_vector_size_v = []<bool _False = false>() -> size_t { @@ -93,10 +97,10 @@ inline constexpr size_t __simd_vector_size_v = []<bool _False = false>() -> size }(); template <class _Tp, size_t _Np> -inline constexpr size_t __simd_vector_size_v<__simd_vector<_Tp, _Np>> = _Np; +inline constexpr size_t __simd_vector_size_v<__simd_vector_impl<_Tp, _Np>> = _Np; template <class _Tp, size_t _Np> -_LIBCPP_HIDE_FROM_ABI _Tp __simd_vector_underlying_type_impl(__simd_vector<_Tp, _Np>) { +_LIBCPP_HIDE_FROM_ABI _Tp __simd_vector_underlying_type_impl(__simd_vector_impl<_Tp, _Np>) { return _Tp{}; } @@ -112,12 +116,12 @@ _LIBCPP_NODISCARD _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _VecT __load_vecto } template <class _Tp, size_t _Np> -_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector_impl<_Tp, _Np> __vec) noexcept { return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector<bool, _Np>)); } template <class _Tp, size_t _Np> -_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector_impl<_Tp, _Np> __vec) noexcept { using __mask_vec = __simd_vector<bool, _Np>; // This has MSan disabled du to https://github.com/llvm/llvm-project/issues/85876 @@ -146,7 +150,7 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_T } template <class _Tp, size_t _Np> -_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector_impl<_Tp, _Np> __vec) noexcept { return std::__find_first_set(~__vec); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
