[clang] [Clang][RVV][SVE] Cache getScalableVectorType lookups (PR #160108)
Shaoce SUN via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 22 09:11:19 PDT 2025
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 <sunshaoce at outlook.com>
Date: Mon, 22 Sep 2025 21:36:23 +0800
Subject: [PATCH] [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();
More information about the cfe-commits
mailing list