[llvm] d280187 - [TableGen] Re-work FactorNodes to avoid an extra temporary vector.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 22 21:05:27 PDT 2023


Author: Craig Topper
Date: 2023-04-22T21:04:55-07:00
New Revision: d28018709375808ea147e66d96af1e81fd9fe8a6

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

LOG: [TableGen] Re-work FactorNodes to avoid an extra temporary vector.

Instead of copying elements to the NewOptionsToMatchVector, we
now shift down elements in OptionsToMatch as we create holes by
pulling out equal matchers. After we finish processing the vector,
we'll trim the size to just the elements that are still in use.

Added: 
    

Modified: 
    llvm/utils/TableGen/DAGISelMatcher.h
    llvm/utils/TableGen/DAGISelMatcherOpt.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/utils/TableGen/DAGISelMatcher.h b/llvm/utils/TableGen/DAGISelMatcher.h
index 826080f2b3ed..468daf00b192 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.h
+++ b/llvm/utils/TableGen/DAGISelMatcher.h
@@ -215,6 +215,10 @@ class ScopeMatcher : public Matcher {
     return Res;
   }
 
+  void setChildren(SmallVectorImpl<Matcher *> &&children) {
+    Children = std::move(children);
+  }
+
   void setNumChildren(unsigned NC) {
     if (NC < Children.size()) {
       // delete any children we're about to lose pointers to.

diff  --git a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
index 06bf7e2f447b..bf2a24241e84 100644
--- a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -214,18 +214,20 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
     }
   }
 
-  SmallVector<Matcher *, 32> NewOptionsToMatch;
-
   // Loop over options to match, merging neighboring patterns with identical
   // starting nodes into a shared matcher.
-  for (unsigned OptionIdx = 0, e = OptionsToMatch.size(); OptionIdx != e;) {
-    // Find the set of matchers that start with this node.
-    Matcher *Optn = OptionsToMatch[OptionIdx++];
+  auto E = OptionsToMatch.end();
+  for (auto I = OptionsToMatch.begin(); I != E; ++I) {
+    // If there are no other matchers left, there's nothing to merge with.
+    auto J = std::next(I);
+    if (J == E)
+      break;
 
-    if (OptionIdx == e) {
-      NewOptionsToMatch.push_back(Optn);
-      continue;
-    }
+    // Remember where we started. We'll use this to move non-equal elements.
+    auto K = J;
+
+    // Find the set of matchers that start with this node.
+    Matcher *Optn = *I;
 
     // See if the next option starts with the same matcher.  If the two
     // neighbors *do* start with the same matcher, we can factor the matcher out
@@ -236,36 +238,30 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
 
     // Factor all of the known-equal matchers after this one into the same
     // group.
-    while (OptionIdx != e && OptionsToMatch[OptionIdx]->isEqual(Optn))
-      EqualMatchers.push_back(OptionsToMatch[OptionIdx++]);
+    while (J != E && (*J)->isEqual(Optn))
+      EqualMatchers.push_back(*J++);
 
     // If we found a non-equal matcher, see if it is contradictory with the
     // current node.  If so, we know that the ordering relation between the
     // current sets of nodes and this node don't matter.  Look past it to see if
     // we can merge anything else into this matching group.
-    unsigned Scan = OptionIdx;
-    while (true) {
-      // If we ran out of stuff to scan, we're done.
-      if (Scan == e)
-        break;
-
-      Matcher *ScanMatcher = OptionsToMatch[Scan];
+    while (J != E) {
+      Matcher *ScanMatcher = *J;
 
       // If we found an entry that matches out matcher, merge it into the set to
       // handle.
       if (Optn->isEqual(ScanMatcher)) {
-        // If is equal after all, add the option to EqualMatchers and remove it
-        // from OptionsToMatch.
+        // It is equal after all, add the option to EqualMatchers.
         EqualMatchers.push_back(ScanMatcher);
-        OptionsToMatch.erase(OptionsToMatch.begin() + Scan);
-        --e;
+        ++J;
         continue;
       }
 
       // If the option we're checking for contradicts the start of the list,
-      // skip over it.
+      // move it earlier in OptionsToMatch for the next iteration of the outer
+      // loop. Then continue searching for equal or contradictory matchers.
       if (Optn->isContradictory(ScanMatcher)) {
-        ++Scan;
+        *K++ = *J++;
         continue;
       }
 
@@ -278,7 +274,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
             (M2->isEqual(Optn) || M2->isContradictory(Optn))) {
           Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
           M2->setNext(MatcherWithoutM2);
-          OptionsToMatch[Scan] = M2;
+          *J = M2;
           continue;
         }
       }
@@ -287,21 +283,31 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
       break;
     }
 
-    if (Scan != e &&
-        // Don't print it's obvious nothing extra could be merged anyway.
-        Scan + 1 != e) {
+    if (J != E &&
+        // Don't print if it's obvious nothing extract could be merged anyway.
+        std::next(J) != E) {
       LLVM_DEBUG(errs() << "Couldn't merge this:\n"; Optn->print(errs(), 4);
                  errs() << "into this:\n";
-                 OptionsToMatch[Scan]->print(errs(), 4);
-                 if (Scan + 1 != e) OptionsToMatch[Scan + 1]->printOne(errs());
-                 if (Scan + 2 < e) OptionsToMatch[Scan + 2]->printOne(errs());
+                 (*J)->print(errs(), 4);
+                 (*std::next(J))->printOne(errs());
+                 if (std::next(J, 2) != E) (*std::next(J, 2))->printOne(errs());
                  errs() << "\n");
     }
 
+    // If we removed any equal matchers, we may need to slide the rest of the
+    // elements down for the next iteration of the outer loop.
+    if (J != K) {
+      while (J != E)
+        *K++ = *J++;
+
+      // Update end pointer for outer loop.
+      E = K;
+    }
+
     // If we only found one option starting with this matcher, no factoring is
-    // possible.
+    // possible. Put the Matcher back in OptionsToMatch.
     if (EqualMatchers.size() == 1) {
-      NewOptionsToMatch.push_back(EqualMatchers[0]);
+      *I = EqualMatchers[0];
       continue;
     }
 
@@ -326,17 +332,22 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
       FactorNodes(Shared->getNextPtr());
     }
 
-    NewOptionsToMatch.push_back(Shared);
+    // Put the new Matcher where we started in OptionsToMatch.
+    *I = Shared;
   }
 
+  // Trim the array to match the updated end.
+  if (E != OptionsToMatch.end())
+    OptionsToMatch.erase(E, OptionsToMatch.end());
+
   // If we're down to a single pattern to match, then we don't need this scope
   // anymore.
-  if (NewOptionsToMatch.size() == 1) {
-    MatcherPtr.reset(NewOptionsToMatch[0]);
+  if (OptionsToMatch.size() == 1) {
+    MatcherPtr.reset(OptionsToMatch[0]);
     return;
   }
 
-  if (NewOptionsToMatch.empty()) {
+  if (OptionsToMatch.empty()) {
     MatcherPtr.reset();
     return;
   }
@@ -347,13 +358,13 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
   // Check to see if all of the leading entries are now opcode checks.  If so,
   // we can convert this Scope to be a OpcodeSwitch instead.
   bool AllOpcodeChecks = true, AllTypeChecks = true;
-  for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+  for (unsigned i = 0, e = OptionsToMatch.size(); i != e; ++i) {
     // Check to see if this breaks a series of CheckOpcodeMatchers.
-    if (AllOpcodeChecks && !isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) {
+    if (AllOpcodeChecks && !isa<CheckOpcodeMatcher>(OptionsToMatch[i])) {
 #if 0
       if (i > 3) {
         errs() << "FAILING OPC #" << i << "\n";
-        NewOptionsToMatch[i]->dump();
+        OptionsToMatch[i]->dump();
       }
 #endif
       AllOpcodeChecks = false;
@@ -362,7 +373,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
     // Check to see if this breaks a series of CheckTypeMatcher's.
     if (AllTypeChecks) {
       CheckTypeMatcher *CTM = cast_or_null<CheckTypeMatcher>(
-          FindNodeWithKind(NewOptionsToMatch[i], Matcher::CheckType));
+          FindNodeWithKind(OptionsToMatch[i], Matcher::CheckType));
       if (!CTM ||
           // iPTR checks could alias any other case without us knowing, don't
           // bother with them.
@@ -371,11 +382,11 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
           CTM->getResNo() != 0 ||
           // If the CheckType isn't at the start of the list, see if we can move
           // it there.
-          !CTM->canMoveBefore(NewOptionsToMatch[i])) {
+          !CTM->canMoveBefore(OptionsToMatch[i])) {
 #if 0
         if (i > 3 && AllTypeChecks) {
           errs() << "FAILING TYPE #" << i << "\n";
-          NewOptionsToMatch[i]->dump();
+          OptionsToMatch[i]->dump();
         }
 #endif
         AllTypeChecks = false;
@@ -387,8 +398,8 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
   if (AllOpcodeChecks) {
     StringSet<> Opcodes;
     SmallVector<std::pair<const SDNodeInfo *, Matcher *>, 8> Cases;
-    for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
-      CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]);
+    for (unsigned i = 0, e = OptionsToMatch.size(); i != e; ++i) {
+      CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(OptionsToMatch[i]);
       assert(Opcodes.insert(COM->getOpcode().getEnumName()).second &&
              "Duplicate opcodes not factored?");
       Cases.push_back(std::make_pair(&COM->getOpcode(), COM->takeNext()));
@@ -403,12 +414,12 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
   if (AllTypeChecks) {
     DenseMap<unsigned, unsigned> TypeEntry;
     SmallVector<std::pair<MVT::SimpleValueType, Matcher *>, 8> Cases;
-    for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
-      Matcher *M = FindNodeWithKind(NewOptionsToMatch[i], Matcher::CheckType);
+    for (unsigned i = 0, e = OptionsToMatch.size(); i != e; ++i) {
+      Matcher *M = FindNodeWithKind(OptionsToMatch[i], Matcher::CheckType);
       assert(M && isa<CheckTypeMatcher>(M) && "Unknown Matcher type");
 
       auto *CTM = cast<CheckTypeMatcher>(M);
-      Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM);
+      Matcher *MatcherWithoutCTM = OptionsToMatch[i]->unlinkNode(CTM);
       MVT::SimpleValueType CTMTy = CTM->getType();
       delete CTM;
 
@@ -452,9 +463,9 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
   }
 
   // Reassemble the Scope node with the adjusted children.
-  Scope->setNumChildren(NewOptionsToMatch.size());
-  for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i)
-    Scope->resetChild(i, NewOptionsToMatch[i]);
+  Scope->setNumChildren(OptionsToMatch.size());
+  for (unsigned i = 0, e = OptionsToMatch.size(); i != e; ++i)
+    Scope->resetChild(i, OptionsToMatch[i]);
 }
 
 void llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,


        


More information about the llvm-commits mailing list