Experimental substitution caching.

This commit is contained in:
Dan Katz
2025-02-13 14:39:42 -05:00
parent f35cbc2c3e
commit c94bb7fee1
3 changed files with 42 additions and 1 deletions

View File

@@ -2786,6 +2786,17 @@ bool substitute(APValue &Result, ASTContext &C, MetaActions &Meta,
SmallVector<TemplateArgument, 4> ExpandedTArgs;
expandTemplateArgPacks(TArgs, ExpandedTArgs);
// Lookup cached specialization; if found, return it.
llvm::FoldingSetNodeID ID;
{
ID.AddPointer(TDecl);
for (const TemplateArgument &TArg : ExpandedTArgs)
TArg.Profile(ID, C);
}
unsigned SubstitutionHash = ID.ComputeHash();
if (C.checkCachedSubstitution(SubstitutionHash, &Result))
return false;
if (!Meta.CheckTemplateArgumentList(TDecl, ExpandedTArgs, false,
Args[0]->getExprLoc()))
return true;
@@ -2810,6 +2821,7 @@ bool substitute(APValue &Result, ASTContext &C, MetaActions &Meta,
APValue RV(ReflectionKind::Type,
const_cast<Type *>(TSpecDecl->getTypeForDecl()));
C.recordCachedSubstitution(SubstitutionHash, RV);
return SetAndSucceed(Result, RV);
} else if (auto *TATD = dyn_cast<TypeAliasTemplateDecl>(TDecl)) {
TArgs.clear();
@@ -2818,12 +2830,16 @@ bool substitute(APValue &Result, ASTContext &C, MetaActions &Meta,
QualType QT = Meta.Substitute(TATD, TArgs, Range.getBegin());
assert(!QT.isNull() && "substitution failed after validating arguments?");
APValue RV = makeReflection(QT);
C.recordCachedSubstitution(SubstitutionHash, RV);
return SetAndSucceed(Result, makeReflection(QT));
} else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(TDecl)) {
FunctionDecl *Spec = Meta.Substitute(FTD, ExpandedTArgs, Range.getBegin());
assert(Spec && "substitution failed after validating arguments?");
return SetAndSucceed(Result, makeReflection(Spec));
APValue RV = makeReflection(Spec);
C.recordCachedSubstitution(SubstitutionHash, RV);
return SetAndSucceed(Result, RV);
} else if (auto *VTD = dyn_cast<VarTemplateDecl>(TDecl)) {
TArgs.clear();
expandTemplateArgPacks(ExpandedTArgs, TArgs);
@@ -2831,6 +2847,8 @@ bool substitute(APValue &Result, ASTContext &C, MetaActions &Meta,
VarDecl *Spec = Meta.Substitute(VTD, TArgs, Range.getBegin());
assert(Spec && "substitution failed after validating arguments?");
APValue RV = makeReflection(Spec);
C.recordCachedSubstitution(SubstitutionHash, RV);
return SetAndSucceed(Result, makeReflection(Spec));
} else if (auto *CD = dyn_cast<ConceptDecl>(TDecl)) {
TArgs.clear();
@@ -2843,6 +2861,8 @@ bool substitute(APValue &Result, ASTContext &C, MetaActions &Meta,
if (!Evaluator(SatisfiesConcept, Spec, true))
llvm_unreachable("failed to evaluate substituted concept");
APValue RV = SatisfiesConcept.Lift(C.BoolTy);
C.recordCachedSubstitution(SubstitutionHash, RV);
return SetAndSucceed(Result, SatisfiesConcept.Lift(C.BoolTy));
}
llvm_unreachable("unimplemented for template kind");