mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 13:16:49 +00:00

Reland https://github.com/llvm/llvm-project/pull/83237 --- (Original comments) Currently all the specializations of a template (including instantiation, specialization and partial specializations) will be loaded at once if we want to instantiate another instance for the template, or find instantiation for the template, or just want to complete the redecl chain. This means basically we need to load every specializations for the template once the template declaration got loaded. This is bad since when we load a specialization, we need to load all of its template arguments. Then we have to deserialize a lot of unnecessary declarations. For example, ``` // M.cppm export module M; export template <class T> class A {}; export class ShouldNotBeLoaded {}; export class Temp { A<ShouldNotBeLoaded> AS; }; // use.cpp import M; A<int> a; ``` We have a specialization ` A<ShouldNotBeLoaded>` in `M.cppm` and we instantiate the template `A` in `use.cpp`. Then we will deserialize `ShouldNotBeLoaded` surprisingly when compiling `use.cpp`. And this patch tries to avoid that. Given that the templates are heavily used in C++, this is a pain point for the performance. This patch adds MultiOnDiskHashTable for specializations in the ASTReader. Then we will only deserialize the specializations with the same template arguments. We made that by using ODRHash for the template arguments as the key of the hash table. To review this patch, I think `ASTReaderDecl::AddLazySpecializations` may be a good entry point.
35 lines
1.7 KiB
C++
35 lines
1.7 KiB
C++
//===- TemplateArgumentHasher.h - Hash Template Arguments -------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/TemplateBase.h"
|
|
|
|
namespace clang {
|
|
namespace serialization {
|
|
|
|
/// Calculate a stable hash value for template arguments. We guarantee that
|
|
/// the same template arguments must have the same hashed values. But we don't
|
|
/// guarantee that the template arguments with the same hashed value are the
|
|
/// same template arguments.
|
|
///
|
|
/// ODR hashing may not be the best mechanism to hash the template
|
|
/// arguments. ODR hashing is (or perhaps, should be) about determining whether
|
|
/// two things are spelled the same way and have the same meaning (as required
|
|
/// by the C++ ODR), whereas what we want here is whether they have the same
|
|
/// meaning regardless of spelling. Maybe we can get away with reusing ODR
|
|
/// hashing anyway, on the basis that any canonical, non-dependent template
|
|
/// argument should have the same (invented) spelling in every translation
|
|
/// unit, but it is not sure that's true in all cases. There may still be cases
|
|
/// where the canonical type includes some aspect of "whatever we saw first",
|
|
/// in which case the ODR hash can differ across translation units for
|
|
/// non-dependent, canonical template arguments that are spelled differently
|
|
/// but have the same meaning. But it is not easy to raise examples.
|
|
unsigned StableHashForTemplateArguments(llvm::ArrayRef<TemplateArgument> Args);
|
|
|
|
} // namespace serialization
|
|
} // namespace clang
|