[flang-commits] [flang] [flang][Lower] Explicitly instantiate all templates from Utils.h (PR #125216)

via flang-commits flang-commits at lists.llvm.org
Fri Jan 31 04:56:49 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Krzysztof Parzyszek (kparzysz)

<details>
<summary>Changes</summary>

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.

---

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:

- (modified) flang/include/flang/Lower/Support/Utils.h (+1052-394) 
- (added) flang/include/flang/Lower/Support/UtilsInstantiations.def (+6214) 
- (added) flang/include/flang/Lower/Support/print-instantiation-declarations.py (+300) 
- (modified) flang/lib/Lower/CMakeLists.txt (+1) 
- (added) flang/lib/Lower/Support/Utils.cpp (+1563) 


``````````diff
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]

``````````

</details>


https://github.com/llvm/llvm-project/pull/125216


More information about the flang-commits mailing list