https://github.com/sunshaoce updated https://github.com/llvm/llvm-project/pull/160108
>From beb8b36b348437a8722a3f86cb9261351b568ca2 Mon Sep 17 00:00:00 2001 From: Shaoce SUN <sunsha...@outlook.com> Date: Mon, 22 Sep 2025 21:36:23 +0800 Subject: [PATCH 1/2] [Clang][RVV][SVE]Cache getScalableVectorType lookups Currently, RVV/SVE intrinsics are cached, but the corresponding type construction is not. As a result, `ASTContext::getScalableVectorType` can become a performance hotspot, since every query must run through a long sequence of type checks and macro expansions. --- clang/include/clang/AST/ASTContext.h | 33 ++++++++++++++++++++++++++++ clang/lib/AST/ASTContext.cpp | 19 ++++++++++------ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a2c55c71e09ae..402d3324e2918 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -29,6 +29,7 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -51,6 +52,35 @@ class FixedPointSemantics; struct fltSemantics; template <typename T, unsigned N> class SmallPtrSet; +struct ScalableVecTyKey { + uintptr_t EltTy; + unsigned NumElts; + unsigned NumFields; + + bool operator==(const ScalableVecTyKey &RHS) const { + return EltTy == RHS.EltTy && NumElts == RHS.NumElts && + NumFields == RHS.NumFields; + } +}; + +// Provide a DenseMapInfo specialization so that ScalableVecTyKey can be used +// as a key in DenseMap. +template <> struct DenseMapInfo<ScalableVecTyKey> { + static inline ScalableVecTyKey getEmptyKey() { + return {DenseMapInfo<uintptr_t>::getEmptyKey(), ~0U, ~0U}; + } + static inline ScalableVecTyKey getTombstoneKey() { + return {DenseMapInfo<uintptr_t>::getTombstoneKey(), ~0U, ~0U}; + } + static unsigned getHashValue(const ScalableVecTyKey &Val) { + return hash_combine(Val.EltTy, Val.NumElts, Val.NumFields); + } + static bool isEqual(const ScalableVecTyKey &LHS, + const ScalableVecTyKey &RHS) { + return LHS == RHS; + } +}; + } // namespace llvm namespace clang { @@ -505,6 +535,9 @@ class ASTContext : public RefCountedBase<ASTContext> { SmallVector<const ObjCInterfaceDecl *, 4>> ObjCSubClasses; + // A mapping from Scalable Vector Type keys to their corresponding QualType. + mutable llvm::DenseMap<llvm::ScalableVecTyKey, QualType> ScalableVecTyMap; + ASTContext &this_() { return *this; } public: diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 97c59b2ceec2f..e979b268b246e 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4567,6 +4567,11 @@ QualType ASTContext::getWebAssemblyExternrefType() const { /// type. QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts, unsigned NumFields) const { + auto K = llvm::ScalableVecTyKey{ + reinterpret_cast<uintptr_t>(EltTy.getAsOpaquePtr()), NumElts, NumFields}; + if (auto It = ScalableVecTyMap.find(K); It != ScalableVecTyMap.end()) + return It->second; + if (Target->hasAArch64ACLETypes()) { uint64_t EltTySize = getTypeSize(EltTy); @@ -4575,29 +4580,29 @@ QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts, if (EltTy->hasIntegerRepresentation() && !EltTy->isBooleanType() && \ EltTy->hasSignedIntegerRepresentation() == IsSigned && \ EltTySize == ElBits && NumElts == (NumEls * NF) && NumFields == 1) { \ - return SingletonId; \ + return ScalableVecTyMap[K] = SingletonId; \ } #define SVE_VECTOR_TYPE_FLOAT(Name, MangledName, Id, SingletonId, NumEls, \ ElBits, NF) \ if (EltTy->hasFloatingRepresentation() && !EltTy->isBFloat16Type() && \ EltTySize == ElBits && NumElts == (NumEls * NF) && NumFields == 1) { \ - return SingletonId; \ + return ScalableVecTyMap[K] = SingletonId; \ } #define SVE_VECTOR_TYPE_BFLOAT(Name, MangledName, Id, SingletonId, NumEls, \ ElBits, NF) \ if (EltTy->hasFloatingRepresentation() && EltTy->isBFloat16Type() && \ EltTySize == ElBits && NumElts == (NumEls * NF) && NumFields == 1) { \ - return SingletonId; \ + return ScalableVecTyMap[K] = SingletonId; \ } #define SVE_VECTOR_TYPE_MFLOAT(Name, MangledName, Id, SingletonId, NumEls, \ ElBits, NF) \ if (EltTy->isMFloat8Type() && EltTySize == ElBits && \ NumElts == (NumEls * NF) && NumFields == 1) { \ - return SingletonId; \ + return ScalableVecTyMap[K] = SingletonId; \ } #define SVE_PREDICATE_TYPE_ALL(Name, MangledName, Id, SingletonId, NumEls, NF) \ if (EltTy->isBooleanType() && NumElts == (NumEls * NF) && NumFields == 1) \ - return SingletonId; + return ScalableVecTyMap[K] = SingletonId; #include "clang/Basic/AArch64ACLETypes.def" } else if (Target->hasRISCVVTypes()) { uint64_t EltTySize = getTypeSize(EltTy); @@ -4611,10 +4616,10 @@ QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts, (EltTy->hasFloatingRepresentation() && EltTy->isBFloat16Type() && \ IsBF && !IsFP)) && \ EltTySize == ElBits && NumElts == NumEls && NumFields == NF) \ - return SingletonId; + return ScalableVecTyMap[K] = SingletonId; #define RVV_PREDICATE_TYPE(Name, Id, SingletonId, NumEls) \ if (EltTy->isBooleanType() && NumElts == NumEls) \ - return SingletonId; + return ScalableVecTyMap[K] = SingletonId; #include "clang/Basic/RISCVVTypes.def" } return QualType(); >From da90102363396d949d34f096694e9dfed28c4562 Mon Sep 17 00:00:00 2001 From: Shaoce SUN <sunsha...@outlook.com> Date: Fri, 26 Sep 2025 00:01:32 +0800 Subject: [PATCH 2/2] Use QualType in ScalableVecTyKey --- clang/include/clang/AST/ASTContext.h | 10 ++++++---- clang/lib/AST/ASTContext.cpp | 3 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 402d3324e2918..12351e98e5a2b 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -25,6 +25,7 @@ #include "clang/AST/RawCommentList.h" #include "clang/AST/SYCLKernelInfo.h" #include "clang/AST/TemplateName.h" +#include "clang/AST/TypeOrdering.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" @@ -53,7 +54,7 @@ struct fltSemantics; template <typename T, unsigned N> class SmallPtrSet; struct ScalableVecTyKey { - uintptr_t EltTy; + clang::QualType EltTy; unsigned NumElts; unsigned NumFields; @@ -67,13 +68,14 @@ struct ScalableVecTyKey { // as a key in DenseMap. template <> struct DenseMapInfo<ScalableVecTyKey> { static inline ScalableVecTyKey getEmptyKey() { - return {DenseMapInfo<uintptr_t>::getEmptyKey(), ~0U, ~0U}; + return {DenseMapInfo<clang::QualType>::getEmptyKey(), ~0U, ~0U}; } static inline ScalableVecTyKey getTombstoneKey() { - return {DenseMapInfo<uintptr_t>::getTombstoneKey(), ~0U, ~0U}; + return {DenseMapInfo<clang::QualType>::getTombstoneKey(), ~0U, ~0U}; } static unsigned getHashValue(const ScalableVecTyKey &Val) { - return hash_combine(Val.EltTy, Val.NumElts, Val.NumFields); + return hash_combine(DenseMapInfo<clang::QualType>::getHashValue(Val.EltTy), + Val.NumElts, Val.NumFields); } static bool isEqual(const ScalableVecTyKey &LHS, const ScalableVecTyKey &RHS) { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index e979b268b246e..07d42e7e2f3b3 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4567,8 +4567,7 @@ QualType ASTContext::getWebAssemblyExternrefType() const { /// type. QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts, unsigned NumFields) const { - auto K = llvm::ScalableVecTyKey{ - reinterpret_cast<uintptr_t>(EltTy.getAsOpaquePtr()), NumElts, NumFields}; + auto K = llvm::ScalableVecTyKey{EltTy, NumElts, NumFields}; if (auto It = ScalableVecTyMap.find(K); It != ScalableVecTyMap.end()) return It->second; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits