[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