Skip to content

Commit d404c37

Browse files
authored
[Clang][RVV][SVE] Cache getScalableVectorType lookups (#160108)
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.
1 parent bba9172 commit d404c37

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
#include "clang/AST/RawCommentList.h"
2626
#include "clang/AST/SYCLKernelInfo.h"
2727
#include "clang/AST/TemplateName.h"
28+
#include "clang/AST/TypeOrdering.h"
2829
#include "clang/Basic/LLVM.h"
2930
#include "clang/Basic/PartialDiagnostic.h"
3031
#include "clang/Basic/SourceLocation.h"
3132
#include "llvm/ADT/DenseMap.h"
33+
#include "llvm/ADT/DenseMapInfo.h"
3234
#include "llvm/ADT/DenseSet.h"
3335
#include "llvm/ADT/FoldingSet.h"
3436
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -51,6 +53,36 @@ class FixedPointSemantics;
5153
struct fltSemantics;
5254
template <typename T, unsigned N> class SmallPtrSet;
5355

56+
struct ScalableVecTyKey {
57+
clang::QualType EltTy;
58+
unsigned NumElts;
59+
unsigned NumFields;
60+
61+
bool operator==(const ScalableVecTyKey &RHS) const {
62+
return EltTy == RHS.EltTy && NumElts == RHS.NumElts &&
63+
NumFields == RHS.NumFields;
64+
}
65+
};
66+
67+
// Provide a DenseMapInfo specialization so that ScalableVecTyKey can be used
68+
// as a key in DenseMap.
69+
template <> struct DenseMapInfo<ScalableVecTyKey> {
70+
static inline ScalableVecTyKey getEmptyKey() {
71+
return {DenseMapInfo<clang::QualType>::getEmptyKey(), ~0U, ~0U};
72+
}
73+
static inline ScalableVecTyKey getTombstoneKey() {
74+
return {DenseMapInfo<clang::QualType>::getTombstoneKey(), ~0U, ~0U};
75+
}
76+
static unsigned getHashValue(const ScalableVecTyKey &Val) {
77+
return hash_combine(DenseMapInfo<clang::QualType>::getHashValue(Val.EltTy),
78+
Val.NumElts, Val.NumFields);
79+
}
80+
static bool isEqual(const ScalableVecTyKey &LHS,
81+
const ScalableVecTyKey &RHS) {
82+
return LHS == RHS;
83+
}
84+
};
85+
5486
} // namespace llvm
5587

5688
namespace clang {
@@ -505,6 +537,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
505537
SmallVector<const ObjCInterfaceDecl *, 4>>
506538
ObjCSubClasses;
507539

540+
// A mapping from Scalable Vector Type keys to their corresponding QualType.
541+
mutable llvm::DenseMap<llvm::ScalableVecTyKey, QualType> ScalableVecTyMap;
542+
508543
ASTContext &this_() { return *this; }
509544

510545
public:

clang/lib/AST/ASTContext.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4567,6 +4567,10 @@ QualType ASTContext::getWebAssemblyExternrefType() const {
45674567
/// type.
45684568
QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts,
45694569
unsigned NumFields) const {
4570+
auto K = llvm::ScalableVecTyKey{EltTy, NumElts, NumFields};
4571+
if (auto It = ScalableVecTyMap.find(K); It != ScalableVecTyMap.end())
4572+
return It->second;
4573+
45704574
if (Target->hasAArch64ACLETypes()) {
45714575
uint64_t EltTySize = getTypeSize(EltTy);
45724576

@@ -4575,29 +4579,29 @@ QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts,
45754579
if (EltTy->hasIntegerRepresentation() && !EltTy->isBooleanType() && \
45764580
EltTy->hasSignedIntegerRepresentation() == IsSigned && \
45774581
EltTySize == ElBits && NumElts == (NumEls * NF) && NumFields == 1) { \
4578-
return SingletonId; \
4582+
return ScalableVecTyMap[K] = SingletonId; \
45794583
}
45804584
#define SVE_VECTOR_TYPE_FLOAT(Name, MangledName, Id, SingletonId, NumEls, \
45814585
ElBits, NF) \
45824586
if (EltTy->hasFloatingRepresentation() && !EltTy->isBFloat16Type() && \
45834587
EltTySize == ElBits && NumElts == (NumEls * NF) && NumFields == 1) { \
4584-
return SingletonId; \
4588+
return ScalableVecTyMap[K] = SingletonId; \
45854589
}
45864590
#define SVE_VECTOR_TYPE_BFLOAT(Name, MangledName, Id, SingletonId, NumEls, \
45874591
ElBits, NF) \
45884592
if (EltTy->hasFloatingRepresentation() && EltTy->isBFloat16Type() && \
45894593
EltTySize == ElBits && NumElts == (NumEls * NF) && NumFields == 1) { \
4590-
return SingletonId; \
4594+
return ScalableVecTyMap[K] = SingletonId; \
45914595
}
45924596
#define SVE_VECTOR_TYPE_MFLOAT(Name, MangledName, Id, SingletonId, NumEls, \
45934597
ElBits, NF) \
45944598
if (EltTy->isMFloat8Type() && EltTySize == ElBits && \
45954599
NumElts == (NumEls * NF) && NumFields == 1) { \
4596-
return SingletonId; \
4600+
return ScalableVecTyMap[K] = SingletonId; \
45974601
}
45984602
#define SVE_PREDICATE_TYPE_ALL(Name, MangledName, Id, SingletonId, NumEls, NF) \
45994603
if (EltTy->isBooleanType() && NumElts == (NumEls * NF) && NumFields == 1) \
4600-
return SingletonId;
4604+
return ScalableVecTyMap[K] = SingletonId;
46014605
#include "clang/Basic/AArch64ACLETypes.def"
46024606
} else if (Target->hasRISCVVTypes()) {
46034607
uint64_t EltTySize = getTypeSize(EltTy);
@@ -4611,10 +4615,10 @@ QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts,
46114615
(EltTy->hasFloatingRepresentation() && EltTy->isBFloat16Type() && \
46124616
IsBF && !IsFP)) && \
46134617
EltTySize == ElBits && NumElts == NumEls && NumFields == NF) \
4614-
return SingletonId;
4618+
return ScalableVecTyMap[K] = SingletonId;
46154619
#define RVV_PREDICATE_TYPE(Name, Id, SingletonId, NumEls) \
46164620
if (EltTy->isBooleanType() && NumElts == NumEls) \
4617-
return SingletonId;
4621+
return ScalableVecTyMap[K] = SingletonId;
46184622
#include "clang/Basic/RISCVVTypes.def"
46194623
}
46204624
return QualType();

0 commit comments

Comments
 (0)