[llvm] 755a693 - [DAG] SDPatternMatch - Replace runtime data structures with lengths known at compile time (#172064)

via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 14 02:48:12 PST 2025


Author: Artur Bermond Torres
Date: 2025-12-14T10:48:08Z
New Revision: 755a6932993b8ef02082860fad2c72df4ca85a72

URL: https://github.com/llvm/llvm-project/commit/755a6932993b8ef02082860fad2c72df4ca85a72
DIFF: https://github.com/llvm/llvm-project/commit/755a6932993b8ef02082860fad2c72df4ca85a72.diff

LOG: [DAG] SDPatternMatch - Replace runtime data structures with lengths known at compile time (#172064)

Following the suggestions in #170061, I replaced `SmallVector<SDValue>`
with `std::array<SDValue, NumPatterns>` and `SmallBitVector` with
`Bitset<NumPatterns>`.

I had to make some changes to the `collectLeaves` and
`reassociatableMatchHelper` functions. In `collectLeaves` specifically,
I changed the return type so I could propagate a failure in case the
number of found leaves is greater than the number of expected patterns.
I also added a new unit test that, together with the one already present
in the previous line, checks if the matching fails in the cases where
the number of patterns is less or more than the number of leaves.

I don't think this is going to completely address the increased compile
time reported in #169644, but hopefully it leads to an improvement.

Added: 
    

Modified: 
    llvm/include/llvm/CodeGen/SDPatternMatch.h
    llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h
index dda3b3827c7aa..026ee035fcf54 100644
--- a/llvm/include/llvm/CodeGen/SDPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h
@@ -1302,20 +1302,20 @@ inline BinaryOpc_match<ValTy, AllOnes_match, true> m_Not(const ValTy &V) {
 template <typename... PatternTs> struct ReassociatableOpc_match {
   unsigned Opcode;
   std::tuple<PatternTs...> Patterns;
+  constexpr static size_t NumPatterns =
+      std::tuple_size_v<std::tuple<PatternTs...>>;
 
   ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
       : Opcode(Opcode), Patterns(Patterns...) {}
 
   template <typename MatchContext>
   bool match(const MatchContext &Ctx, SDValue N) {
-    constexpr size_t NumPatterns = std::tuple_size_v<std::tuple<PatternTs...>>;
-
-    SmallVector<SDValue> Leaves;
-    collectLeaves(N, Leaves);
-    if (Leaves.size() != NumPatterns)
+    std::array<SDValue, NumPatterns> Leaves;
+    size_t LeavesIdx = 0;
+    if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
       return false;
 
-    SmallBitVector Used(NumPatterns);
+    Bitset<NumPatterns> Used;
     return std::apply(
         [&](auto &...P) -> bool {
           return reassociatableMatchHelper(Ctx, Leaves, Used, P...);
@@ -1323,36 +1323,41 @@ template <typename... PatternTs> struct ReassociatableOpc_match {
         Patterns);
   }
 
-  void collectLeaves(SDValue V, SmallVector<SDValue> &Leaves) {
+  bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
+                     std::size_t &LeafIdx) {
     if (V->getOpcode() == Opcode) {
       for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
-        collectLeaves(V->getOperand(I), Leaves);
+        if ((LeafIdx == NumPatterns) ||
+            !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
+          return false;
     } else {
-      Leaves.emplace_back(V);
+      Leaves[LeafIdx] = V;
+      LeafIdx++;
     }
+    return true;
   }
 
   // Searchs for a matching leaf for every sub-pattern.
   template <typename MatchContext, typename PatternHd, typename... PatternTl>
   [[nodiscard]] inline bool
   reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
-                            SmallBitVector &Used, PatternHd &HeadPattern,
+                            Bitset<NumPatterns> &Used, PatternHd &HeadPattern,
                             PatternTl &...TailPatterns) {
     for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
       if (Used[Match] || !(sd_context_match(Leaves[Match], Ctx, HeadPattern)))
         continue;
-      Used[Match] = true;
+      Used.set(Match);
       if (reassociatableMatchHelper(Ctx, Leaves, Used, TailPatterns...))
         return true;
-      Used[Match] = false;
+      Used.reset(Match);
     }
     return false;
   }
 
   template <typename MatchContext>
-  [[nodiscard]] inline bool reassociatableMatchHelper(const MatchContext &Ctx,
-                                                      ArrayRef<SDValue> Leaves,
-                                                      SmallBitVector &Used) {
+  [[nodiscard]] inline bool
+  reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
+                            Bitset<NumPatterns> &Used) {
     return true;
   }
 };

diff  --git a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
index 4fcd3fcb8c5c7..1afc034dd7b9e 100644
--- a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
+++ b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
@@ -803,6 +803,8 @@ TEST_F(SelectionDAGPatternMatchTest, matchReassociatableOp) {
   SDValue ADD = DAG->getNode(ISD::ADD, DL, Int32VT, ADD01, ADD23);
 
   EXPECT_FALSE(sd_match(ADD01, m_ReassociatableAdd(m_Value())));
+  EXPECT_FALSE(
+      sd_match(ADD01, m_ReassociatableAdd(m_Value(), m_Value(), m_Value())));
   EXPECT_TRUE(sd_match(ADD01, m_ReassociatableAdd(m_Value(), m_Value())));
   EXPECT_TRUE(sd_match(ADD23, m_ReassociatableAdd(m_Value(), m_Value())));
   EXPECT_TRUE(sd_match(


        


More information about the llvm-commits mailing list