[clang] [Clang] Improve concept performance 1/N (PR #188421)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 30 21:03:56 PDT 2026
================
@@ -1611,13 +1618,28 @@ namespace {
}
return Type;
}
+
// Override the default version to handle a rewrite-template-arg-pack case
// for building a deduction guide.
bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
TemplateArgumentLoc &Output,
bool Uneval = false) {
const TemplateArgument &Arg = Input.getArgument();
std::vector<TemplateArgument> TArgs;
+ if (auto *Cache = SemaRef.CurrentCachedTemplateArgs;
+ TemplateArgsHashValue && Cache) {
+ llvm::FoldingSetNodeID ID = *TemplateArgsHashValue;
+ ID.AddInteger(SemaRef.ArgPackSubstIndex.toInternalRepresentation());
+ Input.getArgument().Profile(ID, SemaRef.Context);
----------------
zyn0217 wrote:
To demonstrate how badly performance was impacted, consider this example (which is a very common pattern extracted from libc++):
```cpp
template <class Tp, class Up>
concept common_with = same_as<common_type<Tp, Up>, common_type<Up, Tp>> && requires { /*expressions that use Tp and Up many times*/} && common_reference_with<const Tp, const Up> && ...;
```
After normalization, Tp and Up are substituted with their corresponding template arguments within the resulting atomic expressions. So we end up substituting into the same Tp and Up parameters multiple times, whereas they technically only need to be substituted once. (The one-shot-substitution behavior was a natural result of the previous substitution-first-normalization-second approach)
Clang always struggles with avoiding template transforms, and I think this approach is our best effort so far to alleviate the issue without an overhaul of the template instantiation stuffs.
https://github.com/llvm/llvm-project/pull/188421
More information about the cfe-commits
mailing list