[llvm] [PatternMatchHelpers] Avoid std::apply for compile time (PR #191413)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 10 06:51:11 PDT 2026


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/191413

>From 865fe215938e31448ce114fa7b44c1b56f7fac1c Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Fri, 10 Apr 2026 13:06:55 +0100
Subject: [PATCH 1/2] [PatternMatchHelpers] Avoid std::apply for compile time

Squelch the stage-2 compile time regression introduced by the variadiac
m_Combine(And|Or) matchers, by replacing the std::apply on a std::tuple
with a more lightweight solution.
---
 .../llvm/Support/PatternMatchHelpers.h        | 36 +++++++++++++++----
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/Support/PatternMatchHelpers.h b/llvm/include/llvm/Support/PatternMatchHelpers.h
index e351f96b10545..16f44fa0c9b8e 100644
--- a/llvm/include/llvm/Support/PatternMatchHelpers.h
+++ b/llvm/include/llvm/Support/PatternMatchHelpers.h
@@ -16,23 +16,47 @@
 
 #include "llvm/Support/Casting.h"
 #include <tuple>
+#include <type_traits>
+#include <utility>
 
 namespace llvm::PatternMatchHelpers {
+// A naive std::apply would cost more in compile-time.
+template <typename TupleT, typename IndicesT> class PatternStorage;
+
+template <typename TupleT, size_t... Indices>
+class PatternStorage<TupleT, std::index_sequence<Indices...>> {
+  TupleT Patterns;
+
+public:
+  template <typename... Ty>
+  constexpr PatternStorage(Ty &&...Ps) : Patterns(std::forward<Ty>(Ps)...) {}
+  template <typename ITy> bool combineAnd(ITy *V) const {
+    return (std::get<Indices>(Patterns).match(V) && ...);
+  }
+  template <typename ITy> bool combineOr(ITy *V) const {
+    return (std::get<Indices>(Patterns).match(V) || ...);
+  }
+};
+
 /// Matching or combinator.
 template <typename... Ty> struct match_combine_or { // NOLINT
-  std::tuple<Ty...> Ps;
-  match_combine_or(const Ty &...Ps) : Ps(Ps...) {}
+  PatternStorage<std::tuple<std::decay_t<Ty>...>,
+                 std::index_sequence_for<Ty...>>
+      Storage;
+  match_combine_or(const Ty &...Ps) : Storage(Ps...) {}
   template <typename ITy> bool match(ITy *V) const {
-    return std::apply([V](auto &&...Ps) { return (Ps.match(V) || ...); }, Ps);
+    return Storage.combineOr(V);
   }
 };
 
 /// Matching and combinator.
 template <typename... Ty> struct match_combine_and { // NOLINT
-  std::tuple<Ty...> Ps;
-  match_combine_and(const Ty &...Ps) : Ps(Ps...) {}
+  PatternStorage<std::tuple<std::decay_t<Ty>...>,
+                 std::index_sequence_for<Ty...>>
+      Storage;
+  match_combine_and(const Ty &...Ps) : Storage(Ps...) {}
   template <typename ITy> bool match(ITy *V) const {
-    return std::apply([V](auto &&...Ps) { return (Ps.match(V) && ...); }, Ps);
+    return Storage.combineAnd(V);
   }
 };
 

>From c5d951bdceb1a8066bc37dd6bb1f1f8c0b90635b Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Fri, 10 Apr 2026 14:18:26 +0100
Subject: [PATCH 2/2] [PatternMatchHelpers] Use recursive inheritance

---
 .../llvm/Support/PatternMatchHelpers.h        | 53 ++++++++-----------
 1 file changed, 22 insertions(+), 31 deletions(-)

diff --git a/llvm/include/llvm/Support/PatternMatchHelpers.h b/llvm/include/llvm/Support/PatternMatchHelpers.h
index 16f44fa0c9b8e..5bfa99d9ce93b 100644
--- a/llvm/include/llvm/Support/PatternMatchHelpers.h
+++ b/llvm/include/llvm/Support/PatternMatchHelpers.h
@@ -15,48 +15,39 @@
 #define LLVM_SUPPORT_PATTERNMATCHHELPERS_H
 
 #include "llvm/Support/Casting.h"
-#include <tuple>
-#include <type_traits>
-#include <utility>
 
 namespace llvm::PatternMatchHelpers {
-// A naive std::apply would cost more in compile-time.
-template <typename TupleT, typename IndicesT> class PatternStorage;
-
-template <typename TupleT, size_t... Indices>
-class PatternStorage<TupleT, std::index_sequence<Indices...>> {
-  TupleT Patterns;
-
-public:
-  template <typename... Ty>
-  constexpr PatternStorage(Ty &&...Ps) : Patterns(std::forward<Ty>(Ps)...) {}
-  template <typename ITy> bool combineAnd(ITy *V) const {
-    return (std::get<Indices>(Patterns).match(V) && ...);
-  }
-  template <typename ITy> bool combineOr(ITy *V) const {
-    return (std::get<Indices>(Patterns).match(V) || ...);
-  }
+/// Matching or combinator leaf case.
+template <typename... Tys> struct match_combine_or { // NOLINT
+  template <typename ITy> bool match(ITy *) const { return false; }
 };
 
 /// Matching or combinator.
-template <typename... Ty> struct match_combine_or { // NOLINT
-  PatternStorage<std::tuple<std::decay_t<Ty>...>,
-                 std::index_sequence_for<Ty...>>
-      Storage;
-  match_combine_or(const Ty &...Ps) : Storage(Ps...) {}
+template <typename Ty, typename... Tys>
+struct match_combine_or<Ty, Tys...> : match_combine_or<Tys...> {
+  Ty P;
+  match_combine_or(const Ty &P, const Tys &...Ps)
+      : match_combine_or<Tys...>(Ps...), P(P) {}
+
   template <typename ITy> bool match(ITy *V) const {
-    return Storage.combineOr(V);
+    return P.match(V) || match_combine_or<Tys...>::match(V);
   }
 };
 
+/// Matching and combinator leaf case.
+template <typename... Tys> struct match_combine_and { // NOLINT
+  template <typename ITy> bool match(ITy *) const { return true; }
+};
+
 /// Matching and combinator.
-template <typename... Ty> struct match_combine_and { // NOLINT
-  PatternStorage<std::tuple<std::decay_t<Ty>...>,
-                 std::index_sequence_for<Ty...>>
-      Storage;
-  match_combine_and(const Ty &...Ps) : Storage(Ps...) {}
+template <typename Ty, typename... Tys>
+struct match_combine_and<Ty, Tys...> : match_combine_and<Tys...> {
+  Ty P;
+  match_combine_and(const Ty &P, const Tys &...Ps)
+      : match_combine_and<Tys...>(Ps...), P(P) {}
+
   template <typename ITy> bool match(ITy *V) const {
-    return Storage.combineAnd(V);
+    return P.match(V) && match_combine_and<Tys...>::match(V);
   }
 };
 



More information about the llvm-commits mailing list