-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang][Lower] Explicitly instantiate all templates from Utils.h #125216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This is intended to reduce the memory usage while compiling flang sources. Specifically, this reduced the peak memory use when compiling OpenMP.cpp (on my machine) from 4.9g to 3.6g. The change was to only leave template declarations in the header file and explicitly instantiate every case that was previously instantiated implicitly. If a new implicit instantiation appears later on, it will cause a compilation error (and the explicit instantiation will need to be added manually). Most of the instantiation declarations are generated by an included python script (about 6000 cases). The remaining cases (~1000) are listed explicitly.
@llvm/pr-subscribers-flang-fir-hlfir Author: Krzysztof Parzyszek (kparzysz) ChangesThis is intended to reduce the memory usage while compiling flang sources. Specifically, this reduced the peak memory use when compiling OpenMP.cpp (on my machine) from 4.9g to 3.6g. The change was to only leave template declarations in the header file and explicitly instantiate every case that was previously instantiated implicitly. If a new implicit instantiation appears later on, it will cause a compilation error (and the explicit instantiation will need to be added manually). Most of the instantiation declarations are generated by an included python script (about 6000 cases). The remaining cases (~1000) are listed explicitly. Patch is 2.11 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125216.diff 5 Files Affected:
diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index 1cc74521e22d88..601274ceef4a83 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -86,6 +86,11 @@ A flatZip(const A &container1, const A &container2) {
return result;
}
+// NOTE: Due to excessive memory usage during implicit instantiations,
+// template definitions were moved to Utils.cpp, leaving only
+// template declarations in this file.
+// Any templates that would be implicitly instantiated were declared
+// as externally explicitly instantiated.
namespace Fortran::lower {
// Fortran::evaluate::Expr are functional values organized like an AST. A
// Fortran::evaluate::Expr is meant to be moved and cloned. Using the front end
@@ -106,247 +111,97 @@ class HashEvaluateExpr {
public:
// A Se::Symbol is the only part of an Fortran::evaluate::Expr with an
// identity property.
- static unsigned getHashValue(const Fortran::semantics::Symbol &x) {
- return static_cast<unsigned>(reinterpret_cast<std::intptr_t>(&x));
- }
+ static unsigned getHashValue(const Fortran::semantics::Symbol &x);
template <typename A, bool COPY>
- static unsigned getHashValue(const Fortran::common::Indirection<A, COPY> &x) {
- return getHashValue(x.value());
- }
+ static unsigned getHashValue(const Fortran::common::Indirection<A, COPY> &x);
template <typename A>
- static unsigned getHashValue(const std::optional<A> &x) {
- if (x.has_value())
- return getHashValue(x.value());
- return 0u;
- }
- static unsigned getHashValue(const Fortran::evaluate::Subscript &x) {
- return Fortran::common::visit(
- [&](const auto &v) { return getHashValue(v); }, x.u);
- }
- static unsigned getHashValue(const Fortran::evaluate::Triplet &x) {
- return getHashValue(x.lower()) - getHashValue(x.upper()) * 5u -
- getHashValue(x.stride()) * 11u;
- }
- static unsigned getHashValue(const Fortran::evaluate::Component &x) {
- return getHashValue(x.base()) * 83u - getHashValue(x.GetLastSymbol());
- }
- static unsigned getHashValue(const Fortran::evaluate::ArrayRef &x) {
- unsigned subs = 1u;
- for (const Fortran::evaluate::Subscript &v : x.subscript())
- subs -= getHashValue(v);
- return getHashValue(x.base()) * 89u - subs;
- }
- static unsigned getHashValue(const Fortran::evaluate::CoarrayRef &x) {
- unsigned subs = 1u;
- for (const Fortran::evaluate::Subscript &v : x.subscript())
- subs -= getHashValue(v);
- unsigned cosubs = 3u;
- for (const Fortran::evaluate::Expr<Fortran::evaluate::SubscriptInteger> &v :
- x.cosubscript())
- cosubs -= getHashValue(v);
- unsigned syms = 7u;
- for (const Fortran::evaluate::SymbolRef &v : x.base())
- syms += getHashValue(v);
- return syms * 97u - subs - cosubs + getHashValue(x.stat()) + 257u +
- getHashValue(x.team());
- }
- static unsigned getHashValue(const Fortran::evaluate::NamedEntity &x) {
- if (x.IsSymbol())
- return getHashValue(x.GetFirstSymbol()) * 11u;
- return getHashValue(x.GetComponent()) * 13u;
- }
- static unsigned getHashValue(const Fortran::evaluate::DataRef &x) {
- return Fortran::common::visit(
- [&](const auto &v) { return getHashValue(v); }, x.u);
- }
- static unsigned getHashValue(const Fortran::evaluate::ComplexPart &x) {
- return getHashValue(x.complex()) - static_cast<unsigned>(x.part());
- }
+ static unsigned getHashValue(const std::optional<A> &x);
+ static unsigned getHashValue(const Fortran::evaluate::Subscript &x);
+ static unsigned getHashValue(const Fortran::evaluate::Triplet &x);
+ static unsigned getHashValue(const Fortran::evaluate::Component &x);
+ static unsigned getHashValue(const Fortran::evaluate::ArrayRef &x);
+ static unsigned getHashValue(const Fortran::evaluate::CoarrayRef &x);
+ static unsigned getHashValue(const Fortran::evaluate::NamedEntity &x);
+ static unsigned getHashValue(const Fortran::evaluate::DataRef &x);
+ static unsigned getHashValue(const Fortran::evaluate::ComplexPart &x);
template <Fortran::common::TypeCategory TC1, int KIND,
Fortran::common::TypeCategory TC2>
static unsigned getHashValue(
const Fortran::evaluate::Convert<Fortran::evaluate::Type<TC1, KIND>, TC2>
- &x) {
- return getHashValue(x.left()) - (static_cast<unsigned>(TC1) + 2u) -
- (static_cast<unsigned>(KIND) + 5u);
- }
+ &x);
template <int KIND>
static unsigned
- getHashValue(const Fortran::evaluate::ComplexComponent<KIND> &x) {
- return getHashValue(x.left()) -
- (static_cast<unsigned>(x.isImaginaryPart) + 1u) * 3u;
- }
+ getHashValue(const Fortran::evaluate::ComplexComponent<KIND> &x);
template <typename T>
- static unsigned getHashValue(const Fortran::evaluate::Parentheses<T> &x) {
- return getHashValue(x.left()) * 17u;
- }
+ static unsigned getHashValue(const Fortran::evaluate::Parentheses<T> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
- const Fortran::evaluate::Negate<Fortran::evaluate::Type<TC, KIND>> &x) {
- return getHashValue(x.left()) - (static_cast<unsigned>(TC) + 5u) -
- (static_cast<unsigned>(KIND) + 7u);
- }
+ const Fortran::evaluate::Negate<Fortran::evaluate::Type<TC, KIND>> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
- const Fortran::evaluate::Add<Fortran::evaluate::Type<TC, KIND>> &x) {
- return (getHashValue(x.left()) + getHashValue(x.right())) * 23u +
- static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
- }
+ const Fortran::evaluate::Add<Fortran::evaluate::Type<TC, KIND>> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
- const Fortran::evaluate::Subtract<Fortran::evaluate::Type<TC, KIND>> &x) {
- return (getHashValue(x.left()) - getHashValue(x.right())) * 19u +
- static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
- }
+ const Fortran::evaluate::Subtract<Fortran::evaluate::Type<TC, KIND>> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
- const Fortran::evaluate::Multiply<Fortran::evaluate::Type<TC, KIND>> &x) {
- return (getHashValue(x.left()) + getHashValue(x.right())) * 29u +
- static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
- }
+ const Fortran::evaluate::Multiply<Fortran::evaluate::Type<TC, KIND>> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
- const Fortran::evaluate::Divide<Fortran::evaluate::Type<TC, KIND>> &x) {
- return (getHashValue(x.left()) - getHashValue(x.right())) * 31u +
- static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
- }
+ const Fortran::evaluate::Divide<Fortran::evaluate::Type<TC, KIND>> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
- const Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>> &x) {
- return (getHashValue(x.left()) - getHashValue(x.right())) * 37u +
- static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
- }
+ const Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
- const Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>> &x) {
- return (getHashValue(x.left()) + getHashValue(x.right())) * 41u +
- static_cast<unsigned>(TC) + static_cast<unsigned>(KIND) +
- static_cast<unsigned>(x.ordering) * 7u;
- }
+ const Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
const Fortran::evaluate::RealToIntPower<Fortran::evaluate::Type<TC, KIND>>
- &x) {
- return (getHashValue(x.left()) - getHashValue(x.right())) * 43u +
- static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
- }
+ &x);
template <int KIND>
static unsigned
- getHashValue(const Fortran::evaluate::ComplexConstructor<KIND> &x) {
- return (getHashValue(x.left()) - getHashValue(x.right())) * 47u +
- static_cast<unsigned>(KIND);
- }
+ getHashValue(const Fortran::evaluate::ComplexConstructor<KIND> &x);
template <int KIND>
- static unsigned getHashValue(const Fortran::evaluate::Concat<KIND> &x) {
- return (getHashValue(x.left()) - getHashValue(x.right())) * 53u +
- static_cast<unsigned>(KIND);
- }
+ static unsigned getHashValue(const Fortran::evaluate::Concat<KIND> &x);
template <int KIND>
- static unsigned getHashValue(const Fortran::evaluate::SetLength<KIND> &x) {
- return (getHashValue(x.left()) - getHashValue(x.right())) * 59u +
- static_cast<unsigned>(KIND);
- }
- static unsigned getHashValue(const Fortran::semantics::SymbolRef &sym) {
- return getHashValue(sym.get());
- }
- static unsigned getHashValue(const Fortran::evaluate::Substring &x) {
- return 61u *
- Fortran::common::visit(
- [&](const auto &p) { return getHashValue(p); }, x.parent()) -
- getHashValue(x.lower()) - (getHashValue(x.lower()) + 1u);
- }
+ static unsigned getHashValue(const Fortran::evaluate::SetLength<KIND> &x);
+ static unsigned getHashValue(const Fortran::semantics::SymbolRef &sym);
+ static unsigned getHashValue(const Fortran::evaluate::Substring &x);
static unsigned
- getHashValue(const Fortran::evaluate::StaticDataObject::Pointer &x) {
- return llvm::hash_value(x->name());
- }
- static unsigned getHashValue(const Fortran::evaluate::SpecificIntrinsic &x) {
- return llvm::hash_value(x.name);
- }
+ getHashValue(const Fortran::evaluate::StaticDataObject::Pointer &x);
+ static unsigned getHashValue(const Fortran::evaluate::SpecificIntrinsic &x);
template <typename A>
- static unsigned getHashValue(const Fortran::evaluate::Constant<A> &x) {
- // FIXME: Should hash the content.
- return 103u;
- }
- static unsigned getHashValue(const Fortran::evaluate::ActualArgument &x) {
- if (const Fortran::evaluate::Symbol *sym = x.GetAssumedTypeDummy())
- return getHashValue(*sym);
- return getHashValue(*x.UnwrapExpr());
- }
- static unsigned
- getHashValue(const Fortran::evaluate::ProcedureDesignator &x) {
- return Fortran::common::visit(
- [&](const auto &v) { return getHashValue(v); }, x.u);
- }
- static unsigned getHashValue(const Fortran::evaluate::ProcedureRef &x) {
- unsigned args = 13u;
- for (const std::optional<Fortran::evaluate::ActualArgument> &v :
- x.arguments())
- args -= getHashValue(v);
- return getHashValue(x.proc()) * 101u - args;
- }
+ static unsigned getHashValue(const Fortran::evaluate::Constant<A> &x);
+ static unsigned getHashValue(const Fortran::evaluate::ActualArgument &x);
+ static unsigned getHashValue(const Fortran::evaluate::ProcedureDesignator &x);
+ static unsigned getHashValue(const Fortran::evaluate::ProcedureRef &x);
template <typename A>
+ static unsigned getHashValue(const Fortran::evaluate::ArrayConstructor<A> &x);
+ static unsigned getHashValue(const Fortran::evaluate::ImpliedDoIndex &x);
+ static unsigned getHashValue(const Fortran::evaluate::TypeParamInquiry &x);
+ static unsigned getHashValue(const Fortran::evaluate::DescriptorInquiry &x);
static unsigned
- getHashValue(const Fortran::evaluate::ArrayConstructor<A> &x) {
- // FIXME: hash the contents.
- return 127u;
- }
- static unsigned getHashValue(const Fortran::evaluate::ImpliedDoIndex &x) {
- return llvm::hash_value(toStringRef(x.name).str()) * 131u;
- }
- static unsigned getHashValue(const Fortran::evaluate::TypeParamInquiry &x) {
- return getHashValue(x.base()) * 137u - getHashValue(x.parameter()) * 3u;
- }
- static unsigned getHashValue(const Fortran::evaluate::DescriptorInquiry &x) {
- return getHashValue(x.base()) * 139u -
- static_cast<unsigned>(x.field()) * 13u +
- static_cast<unsigned>(x.dimension());
- }
- static unsigned
- getHashValue(const Fortran::evaluate::StructureConstructor &x) {
- // FIXME: hash the contents.
- return 149u;
- }
+ getHashValue(const Fortran::evaluate::StructureConstructor &x);
template <int KIND>
- static unsigned getHashValue(const Fortran::evaluate::Not<KIND> &x) {
- return getHashValue(x.left()) * 61u + static_cast<unsigned>(KIND);
- }
+ static unsigned getHashValue(const Fortran::evaluate::Not<KIND> &x);
template <int KIND>
static unsigned
- getHashValue(const Fortran::evaluate::LogicalOperation<KIND> &x) {
- unsigned result = getHashValue(x.left()) + getHashValue(x.right());
- return result * 67u + static_cast<unsigned>(x.logicalOperator) * 5u;
- }
+ getHashValue(const Fortran::evaluate::LogicalOperation<KIND> &x);
template <Fortran::common::TypeCategory TC, int KIND>
static unsigned getHashValue(
const Fortran::evaluate::Relational<Fortran::evaluate::Type<TC, KIND>>
- &x) {
- return (getHashValue(x.left()) + getHashValue(x.right())) * 71u +
- static_cast<unsigned>(TC) + static_cast<unsigned>(KIND) +
- static_cast<unsigned>(x.opr) * 11u;
- }
+ &x);
template <typename A>
- static unsigned getHashValue(const Fortran::evaluate::Expr<A> &x) {
- return Fortran::common::visit(
- [&](const auto &v) { return getHashValue(v); }, x.u);
- }
+ static unsigned getHashValue(const Fortran::evaluate::Expr<A> &x);
static unsigned getHashValue(
- const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &x) {
- return Fortran::common::visit(
- [&](const auto &v) { return getHashValue(v); }, x.u);
- }
+ const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &x);
template <typename A>
- static unsigned getHashValue(const Fortran::evaluate::Designator<A> &x) {
- return Fortran::common::visit(
- [&](const auto &v) { return getHashValue(v); }, x.u);
- }
+ static unsigned getHashValue(const Fortran::evaluate::Designator<A> &x);
template <int BITS>
static unsigned
- getHashValue(const Fortran::evaluate::value::Integer<BITS> &x) {
- return static_cast<unsigned>(x.ToSInt());
- }
- static unsigned getHashValue(const Fortran::evaluate::NullPointer &x) {
- return ~179u;
- }
+ getHashValue(const Fortran::evaluate::value::Integer<BITS> &x);
+ static unsigned getHashValue(const Fortran::evaluate::NullPointer &x);
};
// Define the is equals test for using Fortran::evaluate::Expr values with
@@ -356,278 +211,130 @@ class IsEqualEvaluateExpr {
// A Se::Symbol is the only part of an Fortran::evaluate::Expr with an
// identity property.
static bool isEqual(const Fortran::semantics::Symbol &x,
- const Fortran::semantics::Symbol &y) {
- return isEqual(&x, &y);
- }
+ const Fortran::semantics::Symbol &y);
static bool isEqual(const Fortran::semantics::Symbol *x,
- const Fortran::semantics::Symbol *y) {
- return x == y;
- }
+ const Fortran::semantics::Symbol *y);
template <typename A, bool COPY>
static bool isEqual(const Fortran::common::Indirection<A, COPY> &x,
- const Fortran::common::Indirection<A, COPY> &y) {
- return isEqual(x.value(), y.value());
- }
+ const Fortran::common::Indirection<A, COPY> &y);
template <typename A>
- static bool isEqual(const std::optional<A> &x, const std::optional<A> &y) {
- if (x.has_value() && y.has_value())
- return isEqual(x.value(), y.value());
- return !x.has_value() && !y.has_value();
- }
+ static bool isEqual(const std::optional<A> &x, const std::optional<A> &y);
template <typename A>
- static bool isEqual(const std::vector<A> &x, const std::vector<A> &y) {
- if (x.size() != y.size())
- return false;
- const std::size_t size = x.size();
- for (std::remove_const_t<decltype(size)> i = 0; i < size; ++i)
- if (!isEqual(x[i], y[i]))
- return false;
- return true;
- }
+ static bool isEqual(const std::vector<A> &x, const std::vector<A> &y);
static bool isEqual(const Fortran::evaluate::Subscript &x,
- const Fortran::evaluate::Subscript &y) {
- return Fortran::common::visit(
- [&](const auto &v, const auto &w) { return isEqual(v, w); }, x.u, y.u);
- }
+ const Fortran::evaluate::Subscript &y);
static bool isEqual(const Fortran::evaluate::Triplet &x,
- const Fortran::evaluate::Triplet &y) {
- return isEqual(x.lower(), y.lower()) && isEqual(x.upper(), y.upper()) &&
- isEqual(x.stride(), y.stride());
- }
+ const Fortran::evaluate::Triplet &y);
static bool isEqual(const Fortran::evaluate::Component &x,
- const Fortran::evaluate::Component &y) {
- return isEqual(x.base(), y.base()) &&
- isEqual(x.GetLastSymbol(), y.GetLastSymbol());
- }
+ const Fortran::evaluate::Component &y);
static bool isEqual(const Fortran::evaluate::ArrayRef &x,
- const Fortran::evaluate::ArrayRef &y) {
- return isEqual(x.base(), y.base()) && isEqual(x.subscript(), y.subscript());
- }
+ const Fortran::evaluate::ArrayRef &y);
static bool isEqual(const Fortran::evaluate::CoarrayRef &x,
- const Fortran::evaluate::CoarrayRef &y) {
- return isEqual(x.base(), y.base()) &&
- isEqual(x.subscript(), y.subscript()) &&
- isEqual(x.cosubscript(), y.cosubscript()) &&
- isEqual(x.stat(), y.stat()) && isEqual(x.team(), y.team());
- }
+ const Fortran::evaluate::CoarrayRef &y);
static bool isEqual(const Fortran::evaluate::NamedEntity &x,
- const Fortran::evaluate::NamedEntity &y) {
- if (x.IsSymbol() && y.IsSymbol())
- return isEqual(x.GetFirstSymbol(), y.GetFirstSymbol());
- return !x.IsSymbol() && !y.IsSymbol() &&
- isEqual(x.GetComponent(), y.GetComponent());
- }
+ const Fortran::evaluate::NamedEntity &y);
static bool isEqual(const Fortran::evaluate::DataRef &x,
- const Fortran::evaluate::DataRef &y) {
- return Fortran::common::visit(
- [&](const auto &v, const auto &w) { return isEqual(v, w); }, x.u, y.u);
- }
+ const Fortran::evaluate::DataRef &y);
static bool isEqual(const Fortran::evaluate::ComplexPart &x,
- const Fortran::evaluate::ComplexPart &y) {
- return isEqual(x.complex(), y.complex()) && x.part() == y.part();
- }
+ const Fortran::evaluate::ComplexPart &y);
template <typename A, Fortran::common::TypeCategory TC2>
static bool isEqual(const Fortran::evaluate::Convert<A, TC2> &x,
- const Fortran::evaluate::Convert<A, TC2> &y) {
- return isEqual(x.left(), y.left());
- }
+ const Fortran::evaluate::Convert<A, TC2> &y);
template <int KIND>
static bool isEqual(const Fortran::evaluate::ComplexComponent<KIND> &x,
- const Fortran::evaluate::ComplexComponent<KIND> &y) {
- return isEqual(x.left(), y.left()) &&
- x.isImaginaryPart == y.isImaginaryPart;
- }
+ const Fortran::evaluate::ComplexComponent<KIND> &y);
template <typename T>
static bool isEqual(const Fortran::evaluate::Parentheses<T> &x,
- const Fortran::evaluate::Parentheses<T> &y) {
- return isEqual(x.left(), y.left());
- }
+ const Fortran::evaluate::Parentheses<T> &y);
template <typename A>
static bool isEqual(const Fortran::evaluate::Negate<A> &x,
- const Fortran::evaluate::Negate<A> &y) {
- return isEqual(x.left(), y.left());
- }
+ const Fortran::evaluate::Negate<A> &y);
template <typename A>
- static bool isBinaryEqual(const A &x, const A &y) {
- return isEqual(x.left(), y.left()) && isEqual(x.right(), y.right());
- }
+ static bool isBinaryEqual(const A &x, const A &y);
template <typename A>
static bool isEqual(const Fortran::evaluate::Add<A> &x,
- ...
[truncated]
|
Follow-up to #124919. |
✅ With the latest revision this PR passed the Python code formatter. |
This looks harder to maintain going forward than the current code, just to work around your C++ compiler (which is it?) in a small memory environment. |
The reports actually came from elsewhere. I wondered if my code was implicated, so I took a look at the issue, and this is what I found. |
I see exceptionally high memory usage compiling flang (compared to other parts of LLVM) across clang, gcc, and msvc. Sure the problem is more extreme on some compilers than others, but even when building with clang I have to limit the threads on my machine or use a memory-optimized instance because flang (and only flang) cannot be built with normal ratios of cores to memory. I do agree that maintenance is important. This may or may not be the solution but I think there is a real issue here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for having identified the cost here.
I think the HashEvaluateExpr and IsEqualEvaluateExpr classes may just not be needed to exposed at all, they could be defined and used in Utils.cpp. I see only one usage of them outside of the Utils.h header, and this is in lib/Lower/IterationSpace.cpp
in some function that is used for the legacy lowering and could just be moved to Utils.h/Utils.cpp for now.
I see little point of having all entry points accessible for future use cases (if needed, newly required ones could be exposed, but having all them may just be overkill unless there is a strong use case).
Thanks Jean, I'll give it a shot. |
Implemented in #125513. |
Superseded by #125513. |
This is intended to reduce the memory usage while compiling flang sources. Specifically, this reduced the peak memory use when compiling OpenMP.cpp (on my machine) from 4.9g to 3.6g.
The change was to only leave template declarations in the header file and explicitly instantiate every case that was previously instantiated implicitly. If a new implicit instantiation appears later on, it will cause a compilation error (and the explicit instantiation will need to be added manually).
Most of the instantiation declarations are generated by an included python script (about 6000 cases). The remaining cases (~1000) are listed explicitly.