[flang-commits] [flang] d169e9b - [Flang] Avoid deep template recursion (#233865)
via flang-commits
flang-commits at lists.llvm.org
Wed Oct 21 02:44:34 PDT 2026
Author: Michael Kruse
Date: 2026-10-21T11:44:30+02:00
New Revision: d169e9baea06f14a7033f881c6ad50e443afd8cc
URL: https://github.com/llvm/llvm-project/commit/d169e9baea06f14a7033f881c6ad50e443afd8cc
DIFF: https://github.com/llvm/llvm-project/commit/d169e9baea06f14a7033f881c6ad50e443afd8cc.diff
LOG: [Flang] Avoid deep template recursion (#233865)
The names of all runtime functions is stored as variadic template
parameters of a `RuntimeTableEntry`, but the preprocessor macro that
creates the template instantiation (`FirMacroExpandKey`) expands to
exactly 50 characters. A recursive function `filter` then was used to
strip the unnecessary trailing `'\0'` characters out of the variadic
template. On the msvc compiler this 50x template recursion hits a
hard-coded limit
([C1202](https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/fatal-error-c1202)).
#218985 exposed this limted because this 50x template recursion started
to happen in a deeper context, maybe because the instantiation order
stopped making use of a previous memoization.
The updated code is non-recursive, using a constexpr loop instead of
template recursion.
This should fix
[flang-x86_64-windows](https://lab.llvm.org/buildbot/#/builders/166)
buildbot.
Code suggested by AI
Added:
Modified:
flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index 67bdf6867251a5..07bb0fea2ef61d 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -27,7 +27,9 @@
#include "mlir/IR/MLIRContext.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include <cstddef>
#include <cstdint>
+#include <utility>
#ifdef _MSC_VER
// On Windows* OS GetCurrentProcessId returns DWORD aka uint32_t
@@ -762,32 +764,34 @@ template <char... Cs>
using RuntimeIdentifier = std::integer_sequence<char, Cs...>;
namespace details {
-template <typename T, T... As, T... Bs>
-static constexpr std::integer_sequence<T, As..., Bs...>
-concat(std::integer_sequence<T, As...>, std::integer_sequence<T, Bs...>) {
- return {};
+template <typename T, std::size_t N>
+static constexpr std::size_t leadingNonZero(const T (&arr)[N]) {
+ std::size_t i = 0;
+ while (i < N && arr[i] != 0)
+ ++i;
+ return i;
}
-template <typename T, T... As, T... Bs, typename... Cs>
-static constexpr auto concat(std::integer_sequence<T, As...>,
- std::integer_sequence<T, Bs...>, Cs...) {
- return concat(std::integer_sequence<T, As..., Bs...>{}, Cs{}...);
-}
-template <typename T>
-static constexpr std::integer_sequence<T> concat(std::integer_sequence<T>) {
- return {};
-}
-template <typename T, T a>
-static constexpr auto filterZero(std::integer_sequence<T, a>) {
- if constexpr (a != 0) {
- return std::integer_sequence<T, a>{};
- } else {
- return std::integer_sequence<T>{};
- }
+template <typename T, T... b>
+struct LeadingNonZero {
+ static constexpr T arr[] = {b...};
+ static constexpr std::size_t value = leadingNonZero(arr);
+};
+template <typename T, T... b, std::size_t... I>
+static constexpr auto take(std::integer_sequence<T, b...>,
+ std::index_sequence<I...>) {
+ return std::integer_sequence<T, LeadingNonZero<T, b...>::arr[I]...>{};
}
+
+/// This is a helper for the mkRTKey macro; FirMacroExpandKey encodes runtime
+/// function names fixed-width template sequences of exactly 50 characters. This
+/// filter function removes the trailing '\0' characters. This is deliberately
+/// non-recursive because 50 nested template expansions might hit compiler
+/// limits, such as msvc's C1202.
template <typename T, T... b>
static constexpr auto filter(std::integer_sequence<T, b...>) {
if constexpr (sizeof...(b) > 0) {
- return details::concat(filterZero(std::integer_sequence<T, b>{})...);
+ return take(std::integer_sequence<T, b...>{},
+ std::make_index_sequence<LeadingNonZero<T, b...>::value>{});
} else {
return std::integer_sequence<T>{};
}
More information about the flang-commits
mailing list