[llvm] 3961394 - [TableGen] Introduce MatcherList to manage a linked list of Matchers. NFC (#177875)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 13 17:56:53 PST 2026


Author: Craig Topper
Date: 2026-02-13T17:56:48-08:00
New Revision: 39613943855e6a82b1bb4c3d16fbaf2289a5d739

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

LOG: [TableGen] Introduce MatcherList to manage a linked list of Matchers. NFC (#177875)

The previous memory management involved passing around references to the
std::unique_ptr next pointer in each Matcher. Scopes and
SwitchOpcode/SwitchType did not use std::unique_ptr internally, but
would sometimes need to have the pointers to their children moved to
temporary std::unique_ptrs that may be modified and then put back into
the Scope/Switch. Other code used manual deletion.

This patch introduces a MatcherList object that encapsulates list
management and ownership. The interface is based on std::forward_list
using the libcxx implementation for reference.

Once a Matcher is added to a MatcherList it can only be in that list or
spliced into another list. This ensures it is always owned by a list
that will be responsible for deleting it.

Scope and SwitchOpcode/Type children are now MatcherLists rather than
Matcher*. A nice side effect of this is that we no longer need a Size
field in each Matcher to store the size of Scope/Switch children during
emission. This field was only used for the Matcher that the Scope/Switch
children pointed to. Now we can store it in the MatcherList instead.

There is no change to the generated output.

There's still a little bit of cleanup that can be done in follow ups. For example,
renaming "TheMatcher" and merging FactorScope and FactorNodes together.

Added: 
    

Modified: 
    llvm/utils/TableGen/DAGISelEmitter.cpp
    llvm/utils/TableGen/DAGISelMatcher.cpp
    llvm/utils/TableGen/DAGISelMatcher.h
    llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
    llvm/utils/TableGen/DAGISelMatcherGen.cpp
    llvm/utils/TableGen/DAGISelMatcherOpt.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/utils/TableGen/DAGISelEmitter.cpp b/llvm/utils/TableGen/DAGISelEmitter.cpp
index dc66967584f71..a7deaa1dd5dfd 100644
--- a/llvm/utils/TableGen/DAGISelEmitter.cpp
+++ b/llvm/utils/TableGen/DAGISelEmitter.cpp
@@ -193,26 +193,26 @@ void DAGISelEmitter::run(raw_ostream &OS) {
 
   // Convert each variant of each pattern into a Matcher.
   Timer.startTimer("Convert to matchers");
-  SmallVector<Matcher *, 0> PatternMatchers;
+  SmallVector<MatcherList, 0> PatternMatchers;
   for (const PatternToMatch *PTM : Patterns) {
     for (unsigned Variant = 0;; ++Variant) {
-      if (Matcher *M = ConvertPatternToMatcher(*PTM, Variant, CGP))
-        PatternMatchers.push_back(M);
-      else
+      MatcherList ML = ConvertPatternToMatcher(*PTM, Variant, CGP);
+      if (ML.empty())
         break;
+      PatternMatchers.push_back(std::move(ML));
     }
   }
 
-  std::unique_ptr<Matcher> TheMatcher =
-      std::make_unique<ScopeMatcher>(std::move(PatternMatchers));
+  MatcherList Matchers;
+  Matchers.push_front(new ScopeMatcher(std::move(PatternMatchers)));
 
   Timer.startTimer("Optimize matchers");
-  OptimizeMatcher(TheMatcher, CGP);
+  OptimizeMatcher(Matchers, CGP);
 
   // Matcher->dump();
 
   Timer.startTimer("Emit matcher table");
-  EmitMatcherTable(TheMatcher.get(), CGP, OS);
+  EmitMatcherTable(Matchers, CGP, OS);
 }
 
 static TableGen::Emitter::OptClass<DAGISelEmitter>

diff  --git a/llvm/utils/TableGen/DAGISelMatcher.cpp b/llvm/utils/TableGen/DAGISelMatcher.cpp
index 0178998ab1ae2..05c6384409f10 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcher.cpp
@@ -17,48 +17,10 @@ using namespace llvm;
 
 void Matcher::anchor() {}
 
-void Matcher::dump() const { print(errs()); }
-
-void Matcher::print(raw_ostream &OS, indent Indent) const {
-  printImpl(OS, Indent);
-  if (Next)
-    return Next->print(OS, Indent);
-}
-
-void Matcher::printOne(raw_ostream &OS) const { printImpl(OS, indent(0)); }
-
-/// unlinkNode - Unlink the specified node from this chain.  If Other == this,
-/// we unlink the next pointer and return it.  Otherwise we unlink Other from
-/// the list and return this.
-Matcher *Matcher::unlinkNode(Matcher *Other) {
-  if (this == Other)
-    return takeNext();
-
-  // Scan until we find the predecessor of Other.
-  Matcher *Cur = this;
-  for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext())
-    /*empty*/;
-
-  if (!Cur)
-    return nullptr;
-  Cur->takeNext();
-  Cur->setNext(Other->takeNext());
-  return this;
-}
-
-/// canMoveBefore - Return true if this matcher is the same as Other, or if
-/// we can move this matcher past all of the nodes in-between Other and this
-/// node.  Other must be equal to or before this.
-bool Matcher::canMoveBefore(const Matcher *Other) const {
-  for (;; Other = Other->getNext()) {
-    assert(Other && "Other didn't come before 'this'?");
-    if (this == Other)
-      return true;
+void Matcher::dump() const { printOne(errs()); }
 
-    // We have to be able to move this node across the Other node.
-    if (!canMoveBeforeNode(Other))
-      return false;
-  }
+void Matcher::printOne(raw_ostream &OS, indent Indent) const {
+  printImpl(OS, indent(0));
 }
 
 /// canMoveBeforeNode - Return true if it is safe to move the current matcher
@@ -76,21 +38,6 @@ bool Matcher::canMoveBeforeNode(const Matcher *Other) const {
   return false;
 }
 
-ScopeMatcher::~ScopeMatcher() {
-  for (Matcher *C : Children)
-    delete C;
-}
-
-SwitchOpcodeMatcher::~SwitchOpcodeMatcher() {
-  for (auto &C : Cases)
-    delete C.second;
-}
-
-SwitchTypeMatcher::~SwitchTypeMatcher() {
-  for (auto &C : Cases)
-    delete C.second;
-}
-
 CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred,
                                              ArrayRef<unsigned> Ops)
     : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()),
@@ -113,11 +60,11 @@ unsigned CheckPredicateMatcher::getOperandNo(unsigned i) const {
 
 void ScopeMatcher::printImpl(raw_ostream &OS, indent Indent) const {
   OS << Indent << "Scope\n";
-  for (const Matcher *C : Children) {
-    if (!C)
+  for (const MatcherList &C : Children) {
+    if (C.empty())
       OS << Indent + 1 << "NULL POINTER\n";
     else
-      C->print(OS, Indent + 2);
+      C.print(OS, Indent + 2);
   }
 }
 
@@ -174,7 +121,7 @@ void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, indent Indent) const {
   OS << Indent << "SwitchOpcode: {\n";
   for (const auto &C : Cases) {
     OS << Indent << "case " << C.first->getEnumName() << ":\n";
-    C.second->print(OS, Indent + 2);
+    C.second.print(OS, Indent + 2);
   }
   OS << Indent << "}\n";
 }
@@ -187,7 +134,7 @@ void SwitchTypeMatcher::printImpl(raw_ostream &OS, indent Indent) const {
   OS << Indent << "SwitchType: {\n";
   for (const auto &C : Cases) {
     OS << Indent << "case " << getEnumName(C.first) << ":\n";
-    C.second->print(OS, Indent + 2);
+    C.second.print(OS, Indent + 2);
   }
   OS << Indent << "}\n";
 }
@@ -447,3 +394,10 @@ bool CheckChild2CondCodeMatcher::isContradictoryImpl(const Matcher *M) const {
     return CCCCM->getCondCodeName() != getCondCodeName();
   return false;
 }
+
+void MatcherList::print(raw_ostream &OS, indent Indent) const {
+  for (const Matcher *M : *this)
+    M->printOne(OS, Indent);
+}
+
+void MatcherList::dump() const { print(errs()); }

diff  --git a/llvm/utils/TableGen/DAGISelMatcher.h b/llvm/utils/TableGen/DAGISelMatcher.h
index 5b1452e44857e..3f0329bd4ba85 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.h
+++ b/llvm/utils/TableGen/DAGISelMatcher.h
@@ -26,6 +26,7 @@ class CodeGenRegister;
 class CodeGenDAGPatterns;
 class CodeGenInstruction;
 class Matcher;
+class MatcherList;
 class PatternToMatch;
 class raw_ostream;
 class ComplexPattern;
@@ -34,21 +35,25 @@ class SDNodeInfo;
 class TreePredicateFn;
 class TreePattern;
 
-Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,
-                                 unsigned Variant,
-                                 const CodeGenDAGPatterns &CGP);
-void OptimizeMatcher(std::unique_ptr<Matcher> &Matcher,
-                     const CodeGenDAGPatterns &CGP);
-void EmitMatcherTable(Matcher *Matcher, const CodeGenDAGPatterns &CGP,
+MatcherList ConvertPatternToMatcher(const PatternToMatch &Pattern,
+                                    unsigned Variant,
+                                    const CodeGenDAGPatterns &CGP);
+void OptimizeMatcher(MatcherList &ML, const CodeGenDAGPatterns &CGP);
+void EmitMatcherTable(MatcherList &ML, const CodeGenDAGPatterns &CGP,
                       raw_ostream &OS);
 
+/// Base class that holds a pointer to the next entry in the MatcherList.
+/// Separated from Matcher so that we can have an instance of it in
+/// MatcherList.
+class MatcherBase {
+  friend class MatcherList;
+
+  MatcherBase *Next = nullptr;
+};
+
 /// Matcher - Base class for all the DAG ISel Matcher representation
 /// nodes.
-class Matcher {
-  // The next matcher node that is executed after this one.  Null if this is
-  // the last stage of a match.
-  std::unique_ptr<Matcher> Next;
-  size_t Size = 0; // Size in bytes of matcher and all its children (if any).
+class Matcher : public MatcherBase {
   virtual void anchor();
 
 public:
@@ -107,17 +112,8 @@ class Matcher {
 public:
   virtual ~Matcher() = default;
 
-  unsigned getSize() const { return Size; }
-  void setSize(unsigned sz) { Size = sz; }
   KindTy getKind() const { return Kind; }
 
-  Matcher *getNext() { return Next.get(); }
-  const Matcher *getNext() const { return Next.get(); }
-  void setNext(Matcher *C) { Next.reset(C); }
-  Matcher *takeNext() { return Next.release(); }
-
-  std::unique_ptr<Matcher> &getNextPtr() { return Next; }
-
   bool isEqual(const Matcher *M) const {
     if (getKind() != M->getKind())
       return false;
@@ -159,16 +155,6 @@ class Matcher {
            getKind() == RecordChild;
   }
 
-  /// unlinkNode - Unlink the specified node from this chain.  If Other ==
-  /// this, we unlink the next pointer and return it.  Otherwise we unlink
-  /// Other from the list and return this.
-  Matcher *unlinkNode(Matcher *Other);
-
-  /// canMoveBefore - Return true if this matcher is the same as Other, or if
-  /// we can move this matcher past all of the nodes in-between Other and this
-  /// node.  Other must be equal to or before this.
-  bool canMoveBefore(const Matcher *Other) const;
-
   /// canMoveBeforeNode - Return true if it is safe to move the current
   /// matcher across the specified one.
   bool canMoveBeforeNode(const Matcher *Other) const;
@@ -185,8 +171,7 @@ class Matcher {
     return Other->isContradictoryImpl(this);
   }
 
-  void print(raw_ostream &OS, indent Indent = indent(0)) const;
-  void printOne(raw_ostream &OS) const;
+  void printOne(raw_ostream &OS, indent Indent = indent(0)) const;
   void dump() const;
 
 protected:
@@ -195,34 +180,238 @@ class Matcher {
   virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
 };
 
+/// Manages a singly linked list of Matcher objects. Interface based on
+/// std::forward_list. Once a Matcher is added to a list, it cannot be removed.
+/// It can only be erased or spliced to another position in this list or another
+/// list.
+class MatcherList {
+  MatcherBase BeforeBegin;
+
+  // Emitted size of all of the nodes in this list.
+  unsigned Size = 0;
+
+public:
+  MatcherList() = default;
+  MatcherList(const MatcherList &RHS) = delete;
+  MatcherList(MatcherList &&RHS) {
+    splice_after(before_begin(), RHS);
+    Size = RHS.Size;
+    RHS.Size = 0;
+  }
+  ~MatcherList() { clear(); }
+
+  MatcherList &operator=(const MatcherList &) = delete;
+  MatcherList &operator=(MatcherList &&RHS) {
+    clear();
+    splice_after(before_begin(), RHS);
+    Size = RHS.Size;
+    RHS.Size = 0;
+    return *this;
+  }
+
+  void clear() {
+    for (MatcherBase *P = BeforeBegin.Next; P != nullptr;) {
+      MatcherBase *Next = P->Next;
+      delete static_cast<Matcher *>(P);
+      P = Next;
+    }
+    BeforeBegin.Next = nullptr;
+    Size = 0;
+  }
+
+  template <bool IsConst> class iterator_impl {
+    friend class MatcherList;
+    using Base = std::conditional_t<IsConst, const MatcherBase, MatcherBase>;
+
+    Base *Pointer;
+
+    explicit iterator_impl(Base *P) { Pointer = P; }
+
+  public:
+    using iterator_category = std::forward_iterator_tag;
+    using value_type = std::conditional_t<IsConst, const Matcher *, Matcher *>;
+    using 
diff erence_type = std::ptr
diff _t;
+    using pointer = value_type *;
+    using reference = value_type &;
+
+    iterator_impl &operator++() {
+      Pointer = Pointer->Next;
+      return *this;
+    }
+
+    iterator_impl operator++(int) {
+      iterator Tmp(*this);
+      Pointer = Pointer->Next;
+      return Tmp;
+    }
+
+    value_type operator*() const { return static_cast<value_type>(Pointer); }
+
+    value_type operator->() const { return operator*(); }
+
+    bool operator==(const iterator_impl &X) const {
+      return Pointer == X.Pointer;
+    }
+    bool operator!=(const iterator_impl &X) const { return !operator==(X); }
+
+    // Allow conversion to a const iterator.
+    operator iterator_impl<true>() const {
+      return iterator_impl<true>(Pointer);
+    }
+  };
+
+  using iterator = iterator_impl<false>;
+  using const_iterator = iterator_impl<true>;
+
+  /// Return an iterator before the first Matcher in the list. This iterator
+  /// cannot be dereferenced. Incrementing returns the iterator to begin().
+  iterator before_begin() { return iterator(&BeforeBegin); }
+  const_iterator before_begin() const { return const_iterator(&BeforeBegin); }
+
+  iterator begin() { return iterator(BeforeBegin.Next); }
+  const_iterator begin() const { return const_iterator(BeforeBegin.Next); }
+
+  iterator end() { return iterator(nullptr); }
+  const_iterator end() const { return const_iterator(nullptr); }
+
+  Matcher *front() { return *begin(); }
+  const Matcher *front() const { return *begin(); }
+
+  bool empty() const { return BeforeBegin.Next == nullptr; }
+
+  void push_front(Matcher *M) { insert_after(before_begin(), M); }
+
+  /// Delete the first Matcher from the list.
+  void pop_front() {
+    assert(Size == 0 && "Should not modify list once size is set");
+    assert(!empty());
+    Matcher *N = *std::next(before_begin());
+    before_begin()->Next = N->Next;
+    delete N;
+  }
+
+  /// Insert the matcher \p N into this list after \p Pos.
+  iterator insert_after(iterator Pos, Matcher *N) {
+    assert(Size == 0 && "Should not modify list once size is set");
+    N->Next = Pos->Next;
+    Pos->Next = N;
+    return iterator(N);
+  }
+
+  /// Insert Matchers in the range [F, L) into this list.
+  template <class InIt> iterator insert_after(iterator Pos, InIt F, InIt L) {
+    MatcherBase *R = *Pos;
+    if (F != L) {
+      MatcherBase *First = *F;
+      MatcherBase *Last = First;
+
+      // Link the Matchers together.
+      for (++F; F != L; ++F, Last = Last->Next)
+        Last->Next = *F;
+
+      // Insert them into the list.
+      Last->Next = R->Next;
+      R->Next = First;
+      R = Last;
+    }
+
+    return iterator(R);
+  }
+
+  /// Insert multiple matchers into this list.
+  iterator insert_after(iterator Pos, std::initializer_list<Matcher *> IL) {
+    return insert_after(Pos, IL.begin(), IL.end());
+  }
+
+  /// Erase the Matcher after \p Pos.
+  iterator erase_after(iterator Pos) {
+    assert(Size == 0 && "Should not modify list once size is set");
+    Matcher *N = *std::next(Pos);
+    Pos->Next = N->Next;
+    delete N;
+    return iterator(Pos->Next);
+  }
+
+  iterator erase_after(iterator F, iterator L) {
+    Matcher *E = *L;
+    if (F != L) {
+      Matcher *N = *std::next(F);
+      if (N != E) {
+        F->Next = E;
+        do {
+          Matcher *Tmp = static_cast<Matcher *>(N->Next);
+          delete N;
+          N = Tmp;
+        } while (N != E);
+      }
+    }
+    return iterator(E);
+  }
+
+  /// Splice the contents of list \p X after \p Pos in this list.
+  void splice_after(iterator Pos, MatcherList &X) {
+    assert(Size == 0 && "Should not modify list once size is set");
+    if (!X.empty()) {
+      if (Pos->Next != nullptr) {
+        auto LM1 = X.before_begin();
+        while (LM1->Next != nullptr)
+          ++LM1;
+        LM1->Next = Pos->Next;
+      }
+      Pos->Next = X.before_begin()->Next;
+      X.before_begin()->Next = nullptr;
+    }
+  }
+
+  /// Splice the Matcher after \p I into this list after \p Pos.
+  void splice_after(iterator Pos, MatcherList &, iterator I) {
+    assert(Size == 0 && "Should not modify list once size is set");
+    auto LM1 = std::next(I);
+    if (Pos != I && Pos != LM1) {
+      I->Next = LM1->Next;
+      LM1->Next = Pos->Next;
+      Pos->Next = LM1.Pointer;
+    }
+  }
+
+  /// Splice the Matchers in the range (\p F, \p L) into this list after \p Pos.
+  void splice_after(iterator Pos, MatcherList &, iterator F, iterator L) {
+    assert(Size == 0 && "Should not modify list once size is set");
+    if (F != L && Pos != F) {
+      auto LM1 = F;
+      while (std::next(LM1) != L)
+        ++LM1;
+      if (F != LM1) {
+        LM1->Next = Pos->Next;
+        Pos->Next = F->Next;
+        F->Next = L.Pointer;
+      }
+    }
+  }
+
+  void setSize(unsigned Sz) { Size = Sz; }
+  unsigned getSize() const { return Size; }
+
+  void print(raw_ostream &OS, indent Indent = indent(0)) const;
+  void dump() const;
+};
+
 /// ScopeMatcher - This attempts to match each of its children to find the first
 /// one that successfully matches.  If one child fails, it tries the next child.
 /// If none of the children match then this check fails.  It never has a 'next'.
 class ScopeMatcher : public Matcher {
-  SmallVector<Matcher *, 4> Children;
+  SmallVector<MatcherList, 4> Children;
 
 public:
-  ScopeMatcher(SmallVectorImpl<Matcher *> &&children)
+  ScopeMatcher(SmallVectorImpl<MatcherList> &&children)
       : Matcher(Scope), Children(std::move(children)) {}
-  ~ScopeMatcher() override;
 
   unsigned getNumChildren() const { return Children.size(); }
 
-  Matcher *getChild(unsigned i) { return Children[i]; }
-  const Matcher *getChild(unsigned i) const { return Children[i]; }
+  MatcherList &getChild(unsigned i) { return Children[i]; }
+  const MatcherList &getChild(unsigned i) const { return Children[i]; }
 
-  void resetChild(unsigned i, Matcher *N) {
-    delete Children[i];
-    Children[i] = N;
-  }
-
-  Matcher *takeChild(unsigned i) {
-    Matcher *Res = Children[i];
-    Children[i] = nullptr;
-    return Res;
-  }
-
-  SmallVectorImpl<Matcher *> &getChildren() { return Children; }
+  SmallVectorImpl<MatcherList> &getChildren() { return Children; }
 
   static bool classof(const Matcher *N) { return N->getKind() == Scope; }
 
@@ -486,21 +675,22 @@ class CheckOpcodeMatcher : public Matcher {
 /// then the match fails.  This is semantically equivalent to a Scope node where
 /// every child does a CheckOpcode, but is much faster.
 class SwitchOpcodeMatcher : public Matcher {
-  SmallVector<std::pair<const SDNodeInfo *, Matcher *>, 8> Cases;
+  SmallVector<std::pair<const SDNodeInfo *, MatcherList>, 8> Cases;
 
 public:
   SwitchOpcodeMatcher(
-      SmallVectorImpl<std::pair<const SDNodeInfo *, Matcher *>> &&cases)
+      SmallVectorImpl<std::pair<const SDNodeInfo *, MatcherList>> &&cases)
       : Matcher(SwitchOpcode), Cases(std::move(cases)) {}
-  ~SwitchOpcodeMatcher() override;
 
   static bool classof(const Matcher *N) { return N->getKind() == SwitchOpcode; }
 
   unsigned getNumCases() const { return Cases.size(); }
 
   const SDNodeInfo &getCaseOpcode(unsigned i) const { return *Cases[i].first; }
-  Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
-  const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
+  MatcherList &getCaseMatcher(unsigned i) { return Cases[i].second; }
+  const MatcherList &getCaseMatcher(unsigned i) const {
+    return Cases[i].second;
+  }
 
 private:
   void printImpl(raw_ostream &OS, indent Indent) const override;
@@ -535,20 +725,21 @@ class CheckTypeMatcher : public Matcher {
 /// then the match fails.  This is semantically equivalent to a Scope node where
 /// every child does a CheckType, but is much faster.
 class SwitchTypeMatcher : public Matcher {
-  SmallVector<std::pair<MVT, Matcher *>, 8> Cases;
+  SmallVector<std::pair<MVT, MatcherList>, 8> Cases;
 
 public:
-  SwitchTypeMatcher(SmallVectorImpl<std::pair<MVT, Matcher *>> &&cases)
+  SwitchTypeMatcher(SmallVectorImpl<std::pair<MVT, MatcherList>> &&cases)
       : Matcher(SwitchType), Cases(std::move(cases)) {}
-  ~SwitchTypeMatcher() override;
 
   static bool classof(const Matcher *N) { return N->getKind() == SwitchType; }
 
   unsigned getNumCases() const { return Cases.size(); }
 
   MVT getCaseType(unsigned i) const { return Cases[i].first; }
-  Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
-  const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
+  MatcherList &getCaseMatcher(unsigned i) { return Cases[i].second; }
+  const MatcherList &getCaseMatcher(unsigned i) const {
+    return Cases[i].second;
+  }
 
 private:
   void printImpl(raw_ostream &OS, indent Indent) const override;

diff  --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index 1058e7567805d..47323a1fa397b 100644
--- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -87,7 +87,8 @@ class MatcherTableEmitter {
   }
 
 public:
-  MatcherTableEmitter(const Matcher *TheMatcher, const CodeGenDAGPatterns &cgp)
+  MatcherTableEmitter(const MatcherList &TheMatcher,
+                      const CodeGenDAGPatterns &cgp)
       : CGP(cgp), OpcodeCounts(Matcher::HighestKind + 1, 0),
         OperandTable(std::nullopt) {
     // Record the usage of ComplexPattern.
@@ -98,39 +99,38 @@ class MatcherTableEmitter {
     MapVector<TreePattern *, unsigned> PredicateUsage;
 
     // Iterate the whole MatcherTable once and do some statistics.
-    std::function<void(const Matcher *)> Statistic = [&](const Matcher *N) {
-      while (N) {
-        if (auto *SM = dyn_cast<ScopeMatcher>(N))
-          for (unsigned I = 0; I < SM->getNumChildren(); I++)
-            Statistic(SM->getChild(I));
-        else if (auto *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
-          for (unsigned I = 0; I < SOM->getNumCases(); I++)
-            Statistic(SOM->getCaseMatcher(I));
-        else if (auto *STM = dyn_cast<SwitchTypeMatcher>(N))
-          for (unsigned I = 0; I < STM->getNumCases(); I++)
-            Statistic(STM->getCaseMatcher(I));
-        else if (auto *CPM = dyn_cast<CheckComplexPatMatcher>(N))
-          ++ComplexPatternUsage[&CPM->getPattern()];
-        else if (auto *CPPM = dyn_cast<CheckPatternPredicateMatcher>(N))
-          ++PatternPredicateUsage[CPPM->getPredicate()];
-        else if (auto *PM = dyn_cast<CheckPredicateMatcher>(N))
-          ++PredicateUsage[PM->getPredicate().getOrigPatFragRecord()];
-
-        if (const auto *EN = dyn_cast<EmitNodeMatcherCommon>(N)) {
-          ArrayRef<unsigned> Ops = EN->getOperandList();
-          std::vector<uint8_t> OpBytes;
-          for (unsigned Op : Ops) {
-            uint8_t Buffer[5];
-            unsigned Len = encodeULEB128(Op, Buffer);
-            for (unsigned i = 0; i < Len; ++i)
-              OpBytes.push_back(Buffer[i]);
+    std::function<void(const MatcherList &)> Statistic =
+        [&](const MatcherList &ML) {
+          for (const Matcher *N : ML) {
+            if (auto *SM = dyn_cast<ScopeMatcher>(N))
+              for (unsigned I = 0; I < SM->getNumChildren(); I++)
+                Statistic(SM->getChild(I));
+            else if (auto *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
+              for (unsigned I = 0; I < SOM->getNumCases(); I++)
+                Statistic(SOM->getCaseMatcher(I));
+            else if (auto *STM = dyn_cast<SwitchTypeMatcher>(N))
+              for (unsigned I = 0; I < STM->getNumCases(); I++)
+                Statistic(STM->getCaseMatcher(I));
+            else if (auto *CPM = dyn_cast<CheckComplexPatMatcher>(N))
+              ++ComplexPatternUsage[&CPM->getPattern()];
+            else if (auto *CPPM = dyn_cast<CheckPatternPredicateMatcher>(N))
+              ++PatternPredicateUsage[CPPM->getPredicate()];
+            else if (auto *PM = dyn_cast<CheckPredicateMatcher>(N))
+              ++PredicateUsage[PM->getPredicate().getOrigPatFragRecord()];
+
+            if (const auto *EN = dyn_cast<EmitNodeMatcherCommon>(N)) {
+              ArrayRef<unsigned> Ops = EN->getOperandList();
+              std::vector<uint8_t> OpBytes;
+              for (unsigned Op : Ops) {
+                uint8_t Buffer[5];
+                unsigned Len = encodeULEB128(Op, Buffer);
+                for (unsigned i = 0; i < Len; ++i)
+                  OpBytes.push_back(Buffer[i]);
+              }
+              OperandTable.add(OpBytes);
+            }
           }
-          OperandTable.add(OpBytes);
-        }
-
-        N = N->getNext();
-      }
-    };
+        };
     Statistic(TheMatcher);
 
     OperandTable.layout();
@@ -188,12 +188,12 @@ class MatcherTableEmitter {
     }
   }
 
-  unsigned EmitMatcherList(const Matcher *N, const unsigned Indent,
+  unsigned EmitMatcherList(const MatcherList &ML, const unsigned Indent,
                            unsigned StartIdx, raw_ostream &OS);
 
   void EmitOperandLists(raw_ostream &OS);
 
-  unsigned SizeMatcherList(Matcher *N, raw_ostream &OS);
+  unsigned SizeMatcherList(MatcherList &ML, raw_ostream &OS);
 
   void EmitPredicateFunctions(raw_ostream &OS);
 
@@ -335,12 +335,11 @@ static std::string getIncludePath(const Record *R) {
 
 /// This function traverses the matcher tree and sizes all the nodes
 /// that are children of the three kinds of nodes that have them.
-unsigned MatcherTableEmitter::SizeMatcherList(Matcher *N, raw_ostream &OS) {
+unsigned MatcherTableEmitter::SizeMatcherList(MatcherList &ML,
+                                              raw_ostream &OS) {
   unsigned Size = 0;
-  while (N) {
+  for (Matcher *N : ML)
     Size += SizeMatcher(N, OS);
-    N = N->getNext();
-  }
   return Size;
 }
 
@@ -356,12 +355,11 @@ unsigned MatcherTableEmitter::SizeMatcher(Matcher *N, raw_ostream &OS) {
   // and a trailing zero.
   case Matcher::Scope: {
     ScopeMatcher *SM = cast<ScopeMatcher>(N);
-    assert(SM->getNext() == nullptr && "Scope matcher should not have next");
     unsigned Size = 1; // Count the kind.
     for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
       const unsigned ChildSize = SizeMatcherList(SM->getChild(i), OS);
       assert(ChildSize != 0 && "Matcher cannot have child of size 0");
-      SM->getChild(i)->setSize(ChildSize);
+      SM->getChild(i).setSize(ChildSize);
       Size += GetVBRSize(ChildSize) + ChildSize; // Count VBR and child size.
     }
     ++Size; // Count the zero sentinel.
@@ -379,17 +377,17 @@ unsigned MatcherTableEmitter::SizeMatcher(Matcher *N, raw_ostream &OS) {
     else
       NumCases = cast<SwitchTypeMatcher>(N)->getNumCases();
     for (unsigned i = 0, e = NumCases; i != e; ++i) {
-      Matcher *Child;
+      MatcherList *Child;
       if (SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
-        Child = SOM->getCaseMatcher(i);
+        Child = &SOM->getCaseMatcher(i);
         Size += 2; // Count the child's opcode.
       } else {
-        Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
+        Child = &cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
         Size += GetVBRSize(cast<SwitchTypeMatcher>(N)
                                ->getCaseType(i)
                                .SimpleTy); // Count the child's type.
       }
-      const unsigned ChildSize = SizeMatcherList(Child, OS);
+      const unsigned ChildSize = SizeMatcherList(*Child, OS);
       assert(ChildSize != 0 && "Matcher cannot have child of size 0");
       Child->setSize(ChildSize);
       Size += GetVBRSize(ChildSize) + ChildSize; // Count VBR and child size.
@@ -514,15 +512,15 @@ unsigned MatcherTableEmitter::EmitMatcher(const Matcher *N,
         }
       }
 
-      const Matcher *Child = SM->getChild(i);
-      unsigned ChildSize = Child->getSize();
+      const MatcherList &Child = SM->getChild(i);
+      unsigned ChildSize = Child.getSize();
       CurrentIdx += EmitVBRValue(ChildSize, OS);
       if (!OmitComments)
         OS << " // ->" << CurrentIdx + ChildSize;
       OS << '\n';
 
       ChildSize = EmitMatcherList(Child, Indent + 1, CurrentIdx, OS);
-      assert(ChildSize == Child->getSize() &&
+      assert(ChildSize == Child.getSize() &&
              "Emitted child size does not match calculated size");
       CurrentIdx += ChildSize;
     }
@@ -664,13 +662,13 @@ unsigned MatcherTableEmitter::EmitMatcher(const Matcher *N,
 
     // For each case we emit the size, then the opcode, then the matcher.
     for (unsigned i = 0, e = NumCases; i != e; ++i) {
-      const Matcher *Child;
+      const MatcherList *Child;
       unsigned IdxSize;
       if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
-        Child = SOM->getCaseMatcher(i);
+        Child = &SOM->getCaseMatcher(i);
         IdxSize = 2; // size of opcode in table is 2 bytes.
       } else {
-        Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
+        Child = &cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
         IdxSize = GetVBRSize(
             cast<SwitchTypeMatcher>(N)
                 ->getCaseType(i)
@@ -697,7 +695,7 @@ unsigned MatcherTableEmitter::EmitMatcher(const Matcher *N,
         OS << " // ->" << CurrentIdx + ChildSize;
       OS << '\n';
 
-      ChildSize = EmitMatcherList(Child, Indent + 1, CurrentIdx, OS);
+      ChildSize = EmitMatcherList(*Child, Indent + 1, CurrentIdx, OS);
       assert(ChildSize == Child->getSize() &&
              "Emitted child size does not match calculated size");
       CurrentIdx += ChildSize;
@@ -1232,21 +1230,17 @@ unsigned MatcherTableEmitter::EmitMatcher(const Matcher *N,
 
 /// This function traverses the matcher tree and emits all the nodes.
 /// The nodes have already been sized.
-unsigned MatcherTableEmitter::EmitMatcherList(const Matcher *N,
+unsigned MatcherTableEmitter::EmitMatcherList(const MatcherList &ML,
                                               const unsigned Indent,
                                               unsigned CurrentIdx,
                                               raw_ostream &OS) {
   unsigned Size = 0;
-  while (N) {
+  for (const Matcher *N : ML) {
     if (!OmitComments)
       OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/";
     unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS);
     Size += MatcherSize;
     CurrentIdx += MatcherSize;
-
-    // If there are other nodes in this list, iterate to them, otherwise we're
-    // done.
-    N = N->getNext();
   }
   return Size;
 }
@@ -1532,8 +1526,8 @@ void MatcherTableEmitter::EmitHistogram(raw_ostream &OS) {
   OS << '\n';
 }
 
-void llvm::EmitMatcherTable(Matcher *TheMatcher, const CodeGenDAGPatterns &CGP,
-                            raw_ostream &OS) {
+void llvm::EmitMatcherTable(MatcherList &TheMatcher,
+                            const CodeGenDAGPatterns &CGP, raw_ostream &OS) {
   OS << "#if defined(GET_DAGISEL_DECL) && defined(GET_DAGISEL_BODY)\n";
   OS << "#error GET_DAGISEL_DECL and GET_DAGISEL_BODY cannot be both defined, ";
   OS << "undef both for inline definitions\n";

diff  --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp
index e8f146264b1ec..6d727b1fba451 100644
--- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp
@@ -92,12 +92,12 @@ class MatcherGen {
   /// second is the recorded slot number the input pattern match saved it in.
   SmallVector<std::pair<const Record *, unsigned>, 2> PhysRegInputs;
 
-  /// Matcher - This is the top level of the generated matcher, the result.
-  Matcher *TheMatcher = nullptr;
+  /// This is the top level of the generated matcher, the result.
+  MatcherList TheMatcher;
 
-  /// CurPredicate - As we emit matcher nodes, this points to the latest check
-  /// which should have future checks stuck into its Next position.
-  Matcher *CurPredicate = nullptr;
+  /// As we emit matcher nodes, this points to the latest check which should
+  /// have future checks inserted after it.
+  MatcherList::iterator InsertPt;
 
 public:
   MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
@@ -105,7 +105,7 @@ class MatcherGen {
   bool EmitMatcherCode(unsigned Variant);
   void EmitResultCode();
 
-  Matcher *GetMatcher() const { return TheMatcher; }
+  MatcherList GetMatcher() { return std::move(TheMatcher); }
 
 private:
   void AddMatcher(Matcher *NewNode);
@@ -146,7 +146,7 @@ class MatcherGen {
 
 MatcherGen::MatcherGen(const PatternToMatch &pattern,
                        const CodeGenDAGPatterns &cgp)
-    : Pattern(pattern), CGP(cgp) {
+    : Pattern(pattern), CGP(cgp), InsertPt(TheMatcher.before_begin()) {
   // We need to produce the matcher tree for the patterns source pattern.  To
   // do this we need to match the structure as well as the types.  To do the
   // type matching, we want to figure out the fewest number of type checks we
@@ -184,11 +184,7 @@ void MatcherGen::InferPossibleTypes() {
 
 /// AddMatcher - Add a matcher node to the current graph we're building.
 void MatcherGen::AddMatcher(Matcher *NewNode) {
-  if (CurPredicate)
-    CurPredicate->setNext(NewNode);
-  else
-    TheMatcher = NewNode;
-  CurPredicate = NewNode;
+  InsertPt = TheMatcher.insert_after(InsertPt, NewNode);
 }
 
 //===----------------------------------------------------------------------===//
@@ -1056,15 +1052,16 @@ void MatcherGen::EmitResultCode() {
 }
 
 /// ConvertPatternToMatcher - Create the matcher for the specified pattern with
-/// the specified variant.  If the variant number is invalid, this returns null.
-Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,
-                                       unsigned Variant,
-                                       const CodeGenDAGPatterns &CGP) {
+/// the specified variant.  If the variant number is invalid, this returns an
+/// empty MatcherList.
+MatcherList llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,
+                                          unsigned Variant,
+                                          const CodeGenDAGPatterns &CGP) {
   MatcherGen Gen(Pattern, CGP);
 
   // Generate the code for the matcher.
   if (Gen.EmitMatcherCode(Variant))
-    return nullptr;
+    return MatcherList();
 
   // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence.
   // FIXME2: Split result code out to another table, and make the matcher end

diff  --git a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
index 111c174dacc53..553242f7143d7 100644
--- a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -22,101 +22,98 @@ using namespace llvm;
 
 /// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
 /// into single compound nodes like RecordChild.
-static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
-                          const CodeGenDAGPatterns &CGP) {
-  std::unique_ptr<Matcher> *MatcherPtr = &InputMatcherPtr;
-  while (true) {
-    Matcher *N = MatcherPtr->get();
+static void ContractNodes(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
+  auto P = ML.before_begin();
+  auto I = std::next(P);
+
+  while (I != ML.end()) {
+    Matcher *N = *I;
 
     // If we have a scope node, walk down all of the children.
     if (auto *Scope = dyn_cast<ScopeMatcher>(N)) {
-      for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
-        std::unique_ptr<Matcher> Child(Scope->takeChild(i));
-        ContractNodes(Child, CGP);
-        Scope->resetChild(i, Child.release());
-      }
+      for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i)
+        ContractNodes(Scope->getChild(i), CGP);
       return;
     }
 
     // If we found a movechild node with a node that comes in a 'foochild' form,
     // transform it.
     if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) {
+      Matcher *Next = *std::next(I);
       Matcher *New = nullptr;
-      if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext()))
+      if (RecordMatcher *RM = dyn_cast<RecordMatcher>(Next))
         if (MC->getChildNo() < 8) // Only have RecordChild0...7
           New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),
                                        RM->getResultNo());
 
-      if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext()))
+      if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(Next))
         if (MC->getChildNo() < 8 && // Only have CheckChildType0...7
             CT->getResNo() == 0)    // CheckChildType checks res #0
           New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());
 
-      if (CheckSameMatcher *CS = dyn_cast<CheckSameMatcher>(MC->getNext()))
+      if (CheckSameMatcher *CS = dyn_cast<CheckSameMatcher>(Next))
         if (MC->getChildNo() < 4) // Only have CheckChildSame0...3
           New =
               new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber());
 
-      if (CheckIntegerMatcher *CI =
-              dyn_cast<CheckIntegerMatcher>(MC->getNext()))
+      if (CheckIntegerMatcher *CI = dyn_cast<CheckIntegerMatcher>(Next))
         if (MC->getChildNo() < 5) // Only have CheckChildInteger0...4
           New = new CheckChildIntegerMatcher(MC->getChildNo(), CI->getValue());
 
-      if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(MC->getNext()))
+      if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(Next))
         if (MC->getChildNo() == 2) // Only have CheckChild2CondCode
           New = new CheckChild2CondCodeMatcher(CCC->getCondCodeName());
 
       if (New) {
-        // Insert the new node.
-        New->setNext(MatcherPtr->release());
-        MatcherPtr->reset(New);
-        // Remove the old one.
-        MC->setNext(MC->getNext()->takeNext());
+        // Erase the old node after the MoveChild.
+        ML.erase_after(I);
+        // Insert the new node before the MoveChild.
+        I = ML.insert_after(P, New);
         continue;
       }
     }
 
     // Turn MoveParent->MoveChild into MoveSibling.
-    if (auto *MP = dyn_cast<MoveParentMatcher>(N)) {
-      if (auto *MC = dyn_cast<MoveChildMatcher>(MP->getNext())) {
+    if (isa<MoveParentMatcher>(N)) {
+      auto J = std::next(I);
+      if (auto *MC = dyn_cast<MoveChildMatcher>(*J)) {
         auto *MS = new MoveSiblingMatcher(MC->getChildNo());
-        MS->setNext(MC->takeNext());
-        MatcherPtr->reset(MS);
+        I = ML.insert_after(P, MS);
+        // Erase the two old nodes.
+        ML.erase_after(I, std::next(J));
         continue;
       }
     }
 
     // Uncontract MoveSibling if it will help form other child operations.
     if (auto *MS = dyn_cast<MoveSiblingMatcher>(N)) {
-      if (auto *RM = dyn_cast<RecordMatcher>(MS->getNext())) {
+      auto J = std::next(I);
+      if (auto *RM = dyn_cast<RecordMatcher>(*J)) {
+        auto K = std::next(J);
         // Turn MoveSibling->Record->MoveParent into MoveParent->RecordChild.
-        if (auto *MP = dyn_cast<MoveParentMatcher>(RM->getNext())) {
+        if (isa<MoveParentMatcher>(*K)) {
           if (MS->getSiblingNo() < 8) { // Only have RecordChild0...7
-            auto *NewMP = new MoveParentMatcher();
             auto *NewRCM = new RecordChildMatcher(
                 MS->getSiblingNo(), RM->getWhatFor(), RM->getResultNo());
-            NewMP->setNext(NewRCM);
-            NewRCM->setNext(MP->takeNext());
-            MatcherPtr->reset(NewMP);
+            I = ML.erase_after(P, K);
+            ML.insert_after(I, NewRCM);
             continue;
           }
         }
 
         // Turn MoveSibling->Record->CheckType->MoveParent into
         // MoveParent->RecordChild->CheckChildType.
-        if (auto *CT = dyn_cast<CheckTypeMatcher>(RM->getNext())) {
-          if (auto *MP = dyn_cast<MoveParentMatcher>(CT->getNext())) {
+        if (auto *CT = dyn_cast<CheckTypeMatcher>(*K)) {
+          auto L = std::next(K);
+          if (isa<MoveParentMatcher>(*L)) {
             if (MS->getSiblingNo() < 8 && // Only have CheckChildType0...7
                 CT->getResNo() == 0) {    // CheckChildType checks res #0
-              auto *NewMP = new MoveParentMatcher();
               auto *NewRCM = new RecordChildMatcher(
                   MS->getSiblingNo(), RM->getWhatFor(), RM->getResultNo());
               auto *NewCCT =
                   new CheckChildTypeMatcher(MS->getSiblingNo(), CT->getType());
-              NewMP->setNext(NewRCM);
-              NewRCM->setNext(NewCCT);
-              NewCCT->setNext(MP->takeNext());
-              MatcherPtr->reset(NewMP);
+              I = ML.erase_after(P, L);
+              ML.insert_after(I, {NewRCM, NewCCT});
               continue;
             }
           }
@@ -125,16 +122,15 @@ static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
 
       // Turn MoveSibling->CheckType->MoveParent into
       // MoveParent->CheckChildType.
-      if (auto *CT = dyn_cast<CheckTypeMatcher>(MS->getNext())) {
-        if (auto *MP = dyn_cast<MoveParentMatcher>(CT->getNext())) {
+      if (auto *CT = dyn_cast<CheckTypeMatcher>(*J)) {
+        auto K = std::next(J);
+        if (isa<MoveParentMatcher>(*K)) {
           if (MS->getSiblingNo() < 8 && // Only have CheckChildType0...7
               CT->getResNo() == 0) {    // CheckChildType checks res #0
-            auto *NewMP = new MoveParentMatcher();
             auto *NewCCT =
                 new CheckChildTypeMatcher(MS->getSiblingNo(), CT->getType());
-            NewMP->setNext(NewCCT);
-            NewCCT->setNext(MP->takeNext());
-            MatcherPtr->reset(NewMP);
+            I = ML.erase_after(P, K);
+            ML.insert_after(I, NewCCT);
             continue;
           }
         }
@@ -142,34 +138,31 @@ static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
 
       // Turn MoveSibling->CheckInteger->MoveParent into
       // MoveParent->CheckChildInteger.
-      if (auto *CI = dyn_cast<CheckIntegerMatcher>(MS->getNext())) {
-        if (auto *MP = dyn_cast<MoveParentMatcher>(CI->getNext())) {
+      if (auto *CI = dyn_cast<CheckIntegerMatcher>(*J)) {
+        auto K = std::next(J);
+        if (isa<MoveParentMatcher>(*K)) {
           if (MS->getSiblingNo() < 5) { // Only have CheckChildInteger0...4
-            auto *NewMP = new MoveParentMatcher();
             auto *NewCCI = new CheckChildIntegerMatcher(MS->getSiblingNo(),
                                                         CI->getValue());
-            NewMP->setNext(NewCCI);
-            NewCCI->setNext(MP->takeNext());
-            MatcherPtr->reset(NewMP);
+            I = ML.erase_after(P, K);
+            ML.insert_after(I, NewCCI);
             continue;
           }
         }
 
         // Turn MoveSibling->CheckInteger->CheckType->MoveParent into
         // MoveParent->CheckChildInteger->CheckType.
-        if (auto *CT = dyn_cast<CheckTypeMatcher>(CI->getNext())) {
-          if (auto *MP = dyn_cast<MoveParentMatcher>(CT->getNext())) {
+        if (auto *CT = dyn_cast<CheckTypeMatcher>(*K)) {
+          auto L = std::next(K);
+          if (isa<MoveParentMatcher>(*L)) {
             if (MS->getSiblingNo() < 5 && // Only have CheckChildInteger0...4
                 CT->getResNo() == 0) {    // CheckChildType checks res #0
-              auto *NewMP = new MoveParentMatcher();
               auto *NewCCI = new CheckChildIntegerMatcher(MS->getSiblingNo(),
                                                           CI->getValue());
               auto *NewCCT =
                   new CheckChildTypeMatcher(MS->getSiblingNo(), CT->getType());
-              NewMP->setNext(NewCCI);
-              NewCCI->setNext(NewCCT);
-              NewCCT->setNext(MP->takeNext());
-              MatcherPtr->reset(NewMP);
+              I = ML.erase_after(P, L);
+              ML.insert_after(I, {NewCCI, NewCCT});
               continue;
             }
           }
@@ -178,15 +171,14 @@ static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
 
       // Turn MoveSibling->CheckCondCode->MoveParent into
       // MoveParent->CheckChild2CondCode.
-      if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(MS->getNext())) {
-        if (auto *MP = dyn_cast<MoveParentMatcher>(CCC->getNext())) {
+      if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(*J)) {
+        auto K = std::next(J);
+        if (isa<MoveParentMatcher>(*K)) {
           if (MS->getSiblingNo() == 2) { // Only have CheckChild2CondCode
-            auto *NewMP = new MoveParentMatcher();
             auto *NewCCCC =
                 new CheckChild2CondCodeMatcher(CCC->getCondCodeName());
-            NewMP->setNext(NewCCCC);
-            NewCCCC->setNext(MP->takeNext());
-            MatcherPtr->reset(NewMP);
+            I = ML.erase_after(P, K);
+            ML.insert_after(I, NewCCCC);
             continue;
           }
         }
@@ -194,34 +186,31 @@ static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
 
       // Turn MoveSibling->CheckSame->MoveParent into
       // MoveParent->CheckChildSame.
-      if (auto *CS = dyn_cast<CheckSameMatcher>(MS->getNext())) {
-        if (auto *MP = dyn_cast<MoveParentMatcher>(CS->getNext())) {
+      if (auto *CS = dyn_cast<CheckSameMatcher>(*J)) {
+        auto K = std::next(J);
+        if (isa<MoveParentMatcher>(*K)) {
           if (MS->getSiblingNo() < 4) { // Only have CheckChildSame0...3
-            auto *NewMP = new MoveParentMatcher();
             auto *NewCCS = new CheckChildSameMatcher(MS->getSiblingNo(),
                                                      CS->getMatchNumber());
-            NewMP->setNext(NewCCS);
-            NewCCS->setNext(MP->takeNext());
-            MatcherPtr->reset(NewMP);
+            I = ML.erase_after(P, K);
+            ML.insert_after(I, NewCCS);
             continue;
           }
         }
 
         // Turn MoveSibling->CheckSame->CheckType->MoveParent into
         // MoveParent->CheckChildSame->CheckChildType.
-        if (auto *CT = dyn_cast<CheckTypeMatcher>(CS->getNext())) {
-          if (auto *MP = dyn_cast<MoveParentMatcher>(CT->getNext())) {
+        if (auto *CT = dyn_cast<CheckTypeMatcher>(*K)) {
+          auto L = std::next(K);
+          if (isa<MoveParentMatcher>(*L)) {
             if (MS->getSiblingNo() < 4 && // Only have CheckChildSame0...3
                 CT->getResNo() == 0) {    // CheckChildType checks res #0
-              auto *NewMP = new MoveParentMatcher();
               auto *NewCCS = new CheckChildSameMatcher(MS->getSiblingNo(),
                                                        CS->getMatchNumber());
               auto *NewCCT =
                   new CheckChildTypeMatcher(MS->getSiblingNo(), CT->getType());
-              NewMP->setNext(NewCCS);
-              NewCCS->setNext(NewCCT);
-              NewCCT->setNext(MP->takeNext());
-              MatcherPtr->reset(NewMP);
+              I = ML.erase_after(P, L);
+              ML.insert_after(I, {NewCCS, NewCCT});
               continue;
             }
           }
@@ -229,23 +218,25 @@ static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
       }
 
       // Turn MoveSibling->MoveParent into MoveParent.
-      if (isa<MoveParentMatcher>(MS->getNext())) {
-        MatcherPtr->reset(MS->takeNext());
+      if (isa<MoveParentMatcher>(*J)) {
+        I = ML.erase_after(P, J);
         continue;
       }
     }
 
     // Zap movechild -> moveparent.
-    if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N))
-      if (MoveParentMatcher *MP = dyn_cast<MoveParentMatcher>(MC->getNext())) {
-        MatcherPtr->reset(MP->takeNext());
+    if (isa<MoveChildMatcher>(N)) {
+      auto J = std::next(I);
+      if (isa<MoveParentMatcher>(*J)) {
+        I = ML.erase_after(P, std::next(J));
         continue;
       }
+    }
 
     // Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
     if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N)) {
-      if (CompleteMatchMatcher *CM =
-              dyn_cast<CompleteMatchMatcher>(EN->getNext())) {
+      auto J = std::next(I);
+      if (auto *CM = dyn_cast<CompleteMatchMatcher>(*J)) {
         // We can only use MorphNodeTo if the result values match up.
         unsigned RootResultFirst = EN->getFirstResultSlot();
         bool ResultsMatch = true;
@@ -284,10 +275,12 @@ static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
         if (ResultsMatch) {
           ArrayRef<ValueTypeByHwMode> VTs = EN->getVTList();
           ArrayRef<unsigned> Operands = EN->getOperandList();
-          MatcherPtr->reset(new MorphNodeToMatcher(
+          auto *MNT = new MorphNodeToMatcher(
               EN->getInstruction(), VTs, Operands, EN->hasChain(),
               EN->hasInGlue(), EN->hasOutGlue(), EN->hasMemRefs(),
-              EN->getNumFixedArityOperands(), Pattern));
+              EN->getNumFixedArityOperands(), Pattern);
+          ML.erase_after(P, std::next(J));
+          ML.insert_after(P, MNT);
           return;
         }
       }
@@ -297,39 +290,54 @@ static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
     // We prefer to do structural checks before type checks, as this opens
     // opportunities for factoring on targets like X86 where many operations are
     // valid on multiple types.
-    if (isa<RecordMatcher>(N) && isa<CheckOpcodeMatcher>(N->getNext())) {
-      // Unlink the two nodes from the list.
-      Matcher *CheckType = MatcherPtr->release();
-      Matcher *CheckOpcode = CheckType->takeNext();
-      Matcher *Tail = CheckOpcode->takeNext();
-
-      // Relink them.
-      MatcherPtr->reset(CheckOpcode);
-      CheckOpcode->setNext(CheckType);
-      CheckType->setNext(Tail);
+    if (isa<RecordMatcher>(N) && isa<CheckOpcodeMatcher>(*std::next(I))) {
+      ML.splice_after(P, ML, I);
+      // Restore I to the node after P.
+      I = std::next(P);
       continue;
     }
 
-    // No contractions were performed, go to next node.
-    MatcherPtr = &(MatcherPtr->get()->getNextPtr());
-
-    // If we reached the end of the chain, we're done.
-    if (!*MatcherPtr)
-      return;
+    // Move to next node.
+    P = I;
+    ++I;
   }
 }
 
 /// FindNodeWithKind - Scan a series of matchers looking for a matcher with a
 /// specified kind.  Return null if we didn't find one otherwise return the
 /// matcher.
-static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) {
-  for (; M; M = M->getNext())
-    if (M->getKind() == Kind)
-      return M;
-  return nullptr;
+static std::pair<MatcherList::iterator, MatcherList::iterator>
+FindNodeWithKind(MatcherList &ML, Matcher::KindTy Kind) {
+  auto P = ML.before_begin();
+  auto I = std::next(P);
+  while (I != ML.end()) {
+    if (I->getKind() == Kind)
+      break;
+
+    P = I;
+    ++I;
+  }
+
+  return std::make_pair(P, I);
 }
 
-static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr);
+/// Return true if \p M is already the front, or if we can move \p M past
+/// all of the nodes before \p M.
+static bool canMoveToFront(const MatcherList &ML,
+                           MatcherList::const_iterator M) {
+  for (auto Other = ML.begin(); Other != ML.end(); ++Other) {
+    if (M == Other)
+      return true;
+
+    // We have to be able to move this node across the Other node.
+    if (!M->canMoveBeforeNode(*Other))
+      return false;
+  }
+
+  llvm_unreachable("M not part of list?");
+}
+
+static void FactorNodes(MatcherList &ML);
 
 /// Turn matches like this:
 ///   Scope
@@ -343,26 +351,30 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr);
 ///       ABC
 ///       XYZ
 ///
-static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
-  ScopeMatcher *Scope = cast<ScopeMatcher>(MatcherPtr.get());
+/// \p ML is a list that ends with a ScopeMatcher. \p Prev is the iterator
+/// before the ScopeMatcher in \p ML.
+static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
+  ScopeMatcher *Scope = cast<ScopeMatcher>(*std::next(Prev));
 
-  SmallVectorImpl<Matcher *> &OptionsToMatch = Scope->getChildren();
+  SmallVectorImpl<MatcherList> &OptionsToMatch = Scope->getChildren();
 
   for (auto I = OptionsToMatch.begin(); I != OptionsToMatch.end();) {
-    // TODO: Store unique_ptr in ScopeMatcher.
+    assert(!I->empty());
     // Factor the subexpression.
-    std::unique_ptr<Matcher> Child(*I);
-    FactorNodes(Child);
+    FactorNodes(*I);
 
     // If the child is a ScopeMatcher we can just merge its contents.
-    if (auto *SM = dyn_cast<ScopeMatcher>(Child.get())) {
-      SmallVectorImpl<Matcher *> &Children = SM->getChildren();
-      *I++ = *Children.begin();
-      I = OptionsToMatch.insert(I, Children.begin() + 1, Children.end());
+    if (auto *SM = dyn_cast<ScopeMatcher>(I->front())) {
+      // Move the MatcherList to a temporary so we can overwrite the location
+      // in OptionsToMatch without deleting the ScopeMatcher.
+      MatcherList Tmp = std::move(*I);
+      SmallVectorImpl<MatcherList> &Children = SM->getChildren();
+      *I++ = std::move(Children.front());
+      I = OptionsToMatch.insert(I,
+                                std::make_move_iterator(Children.begin() + 1),
+                                std::make_move_iterator(Children.end()));
       I += Children.size() - 1;
-      Children.clear();
     } else {
-      Child.release();
       ++I;
     }
   }
@@ -380,33 +392,32 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
     auto K = J;
 
     // Find the set of matchers that start with this node.
-    Matcher *Optn = *I;
+    Matcher *Optn = I->front();
 
     // 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
     // of at least these two patterns.  See what the maximal set we can merge
     // together is.
-    SmallVector<Matcher *, 8> EqualMatchers;
-    EqualMatchers.push_back(Optn);
+    SmallVector<MatcherList, 8> EqualMatchers;
+    EqualMatchers.push_back(std::move(*I));
 
     // Factor all of the known-equal matchers after this one into the same
     // group.
-    while (J != E && (*J)->isEqual(Optn))
-      EqualMatchers.push_back(*J++);
+    while (J != E && J->front()->isEqual(Optn))
+      EqualMatchers.push_back(std::move(*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.
     while (J != E) {
-      Matcher *ScanMatcher = *J;
+      Matcher *ScanMatcher = J->front();
 
       // If we found an entry that matches out matcher, merge it into the set to
       // handle.
       if (Optn->isEqual(ScanMatcher)) {
         // It is equal after all, add the option to EqualMatchers.
-        EqualMatchers.push_back(ScanMatcher);
-        ++J;
+        EqualMatchers.push_back(std::move(*J++));
         continue;
       }
 
@@ -414,7 +425,10 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
       // 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)) {
-        *K++ = *J++;
+        if (J != K)
+          *K = std::move(*J);
+        ++J;
+        ++K;
         continue;
       }
 
@@ -422,12 +436,10 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
       // sequence.  If so, and if we can move it up, it might be contradictory
       // or the same as what we're looking for.  If so, reorder it.
       if (Optn->isSimplePredicateOrRecordNode()) {
-        Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());
-        if (M2 && M2 != ScanMatcher && M2->canMoveBefore(ScanMatcher) &&
+        auto [P, M2] = FindNodeWithKind(*J, Optn->getKind());
+        if (M2 != J->end() && *M2 != ScanMatcher && canMoveToFront(*J, M2) &&
             (M2->isEqual(Optn) || M2->isContradictory(Optn))) {
-          Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
-          M2->setNext(MatcherWithoutM2);
-          *J = M2;
+          J->splice_after(J->before_begin(), *J, P);
           continue;
         }
       }
@@ -439,49 +451,51 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
     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(), indent(4)); errs() << "into this:\n";
-                 (*J)->print(errs(), indent(4));
-                 (*std::next(J))->printOne(errs());
-                 if (std::next(J, 2) != E)(*std::next(J, 2))->printOne(errs());
-                 errs() << "\n");
+      LLVM_DEBUG(
+          errs() << "Couldn't merge this:\n"; I->print(errs(), indent(4));
+          errs() << "into this:\n"; J->print(errs(), indent(4));
+          std::next(J)->front()->printOne(errs());
+          if (std::next(J, 2) != E) std::next(J, 2)->front()->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)
-      E = std::copy(J, E, K);
+      E = std::move(J, E, K);
 
     // If we only found one option starting with this matcher, no factoring is
     // possible. Put the Matcher back in OptionsToMatch.
     if (EqualMatchers.size() == 1) {
-      *I = EqualMatchers[0];
+      *I = std::move(EqualMatchers[0]);
       continue;
     }
 
     // Factor these checks by pulling the first node off each entry and
     // discarding it.  Take the first one off the first entry to reuse.
-    Matcher *Shared = Optn;
-    Optn = Optn->takeNext();
-    EqualMatchers[0] = Optn;
+    MatcherList Shared;
+    Shared.splice_after(Shared.before_begin(), EqualMatchers[0],
+                        EqualMatchers[0].before_begin());
+    Optn = EqualMatchers[0].empty() ? nullptr : EqualMatchers[0].front();
 
     // Remove and delete the first node from the other matchers we're factoring.
     for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) {
-      Matcher *Tmp = EqualMatchers[i]->takeNext();
-      delete EqualMatchers[i];
-      EqualMatchers[i] = Tmp;
+      EqualMatchers[i].pop_front();
+      Matcher *Tmp =
+          EqualMatchers[i].empty() ? nullptr : EqualMatchers[i].front();
       assert(!Optn == !Tmp && "Expected all to be null if any are null");
     }
 
-    if (EqualMatchers[0]) {
-      Shared->setNext(new ScopeMatcher(std::move(EqualMatchers)));
+    if (!EqualMatchers[0].empty()) {
+      Shared.insert_after(Shared.begin(),
+                          new ScopeMatcher(std::move(EqualMatchers)));
 
       // Recursively factor the newly created node.
-      FactorScope(Shared->getNextPtr());
+      FactorScope(Shared, Shared.begin());
     }
 
     // Put the new Matcher where we started in OptionsToMatch.
-    *I = Shared;
+    *I = std::move(Shared);
   }
 
   // Trim the array to match the updated end.
@@ -490,12 +504,14 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
   // If we're down to a single pattern to match, then we don't need this scope
   // anymore.
   if (OptionsToMatch.size() == 1) {
-    MatcherPtr.reset(OptionsToMatch.pop_back_val());
+    MatcherList Tmp = std::move(OptionsToMatch[0]);
+    ML.erase_after(Prev);
+    ML.splice_after(Prev, Tmp);
     return;
   }
 
   if (OptionsToMatch.empty()) {
-    MatcherPtr.reset();
+    ML.erase_after(Prev);
     return;
   }
 
@@ -505,9 +521,9 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
   // 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 (Matcher *Optn : OptionsToMatch) {
+  for (MatcherList &Optn : OptionsToMatch) {
     // Check to see if this breaks a series of CheckOpcodeMatchers.
-    if (AllOpcodeChecks && !isa<CheckOpcodeMatcher>(Optn)) {
+    if (AllOpcodeChecks && !isa<CheckOpcodeMatcher>(Optn.front())) {
 #if 0
       if (i > 3) {
         errs() << "FAILING OPC #" << i << "\n";
@@ -519,8 +535,9 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
 
     // Check to see if this breaks a series of CheckTypeMatcher's.
     if (AllTypeChecks) {
-      CheckTypeMatcher *CTM = cast_or_null<CheckTypeMatcher>(
-          FindNodeWithKind(Optn, Matcher::CheckType));
+      auto [P, I] = FindNodeWithKind(Optn, Matcher::CheckType);
+      auto *CTM =
+          cast_or_null<CheckTypeMatcher>(I == Optn.end() ? nullptr : *I);
       if (!CTM || !CTM->getType().isSimple() ||
           // iPTR/cPTR checks could alias any other case without us knowing,
           // don't bother with them.
@@ -530,7 +547,7 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
           CTM->getResNo() != 0 ||
           // If the CheckType isn't at the start of the list, see if we can move
           // it there.
-          !CTM->canMoveBefore(Optn)) {
+          !canMoveToFront(Optn, I)) {
 #if 0
         if (i > 3 && AllTypeChecks) {
           errs() << "FAILING TYPE #" << i << "\n";
@@ -544,89 +561,92 @@ static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
   // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.
   if (AllOpcodeChecks) {
     StringSet<> Opcodes;
-    SmallVector<std::pair<const SDNodeInfo *, Matcher *>, 8> Cases;
-    for (Matcher *Optn : OptionsToMatch) {
-      CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(Optn);
+    SmallVector<std::pair<const SDNodeInfo *, MatcherList>, 8> Cases;
+    for (MatcherList &Optn : OptionsToMatch) {
+      CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(Optn.front());
       assert(Opcodes.insert(COM->getOpcode().getEnumName()).second &&
              "Duplicate opcodes not factored?");
-      Cases.emplace_back(&COM->getOpcode(), COM->takeNext());
-      delete COM;
+      const SDNodeInfo &Opcode = COM->getOpcode();
+      Optn.erase_after(Optn.before_begin());
+      Cases.emplace_back(&Opcode, std::move(Optn));
     }
-    OptionsToMatch.clear();
 
-    MatcherPtr.reset(new SwitchOpcodeMatcher(std::move(Cases)));
+    ML.erase_after(Prev);
+    ML.insert_after(Prev, new SwitchOpcodeMatcher(std::move(Cases)));
     return;
   }
 
   // If all the options are CheckType's, we can form the SwitchType, woot.
   if (AllTypeChecks) {
     DenseMap<unsigned, unsigned> TypeEntry;
-    SmallVector<std::pair<MVT, Matcher *>, 8> Cases;
-    for (Matcher *Optn : OptionsToMatch) {
-      Matcher *M = FindNodeWithKind(Optn, Matcher::CheckType);
-      assert(M && isa<CheckTypeMatcher>(M) && "Unknown Matcher type");
+    SmallVector<std::pair<MVT, MatcherList>, 8> Cases;
+    for (MatcherList &Optn : OptionsToMatch) {
+      auto [P, I] = FindNodeWithKind(Optn, Matcher::CheckType);
+      assert(I != Optn.end() && isa<CheckTypeMatcher>(*I) &&
+             "Unknown Matcher type");
 
-      auto *CTM = cast<CheckTypeMatcher>(M);
-      Matcher *MatcherWithoutCTM = Optn->unlinkNode(CTM);
+      auto *CTM = cast<CheckTypeMatcher>(*I);
       MVT CTMTy = CTM->getType().getSimple();
-      delete CTM;
+      Optn.erase_after(P);
 
       unsigned &Entry = TypeEntry[CTMTy.SimpleTy];
       if (Entry != 0) {
         // If we have unfactored duplicate types, then we should factor them.
-        Matcher *PrevMatcher = Cases[Entry - 1].second;
-        if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {
-          SM->getChildren().push_back(MatcherWithoutCTM);
+        MatcherList &PrevMatcher = Cases[Entry - 1].second;
+        if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher.front())) {
+          SM->getChildren().push_back(std::move(Optn));
           continue;
         }
 
-        SmallVector<Matcher *, 2> Entries = {PrevMatcher, MatcherWithoutCTM};
-        Cases[Entry - 1].second = new ScopeMatcher(std::move(Entries));
+        SmallVector<MatcherList, 2> Entries;
+        Entries.push_back(std::move(PrevMatcher));
+        Entries.push_back(std::move(Optn));
+        assert(Cases[Entry - 1].second.empty());
+        Cases[Entry - 1].second.push_front(
+            new ScopeMatcher(std::move(Entries)));
         continue;
       }
 
       Entry = Cases.size() + 1;
-      Cases.emplace_back(CTMTy, MatcherWithoutCTM);
+      Cases.emplace_back(CTMTy, std::move(Optn));
     }
-    OptionsToMatch.clear();
+    ML.erase_after(Prev);
 
     // Make sure we recursively factor any scopes we may have created.
     for (auto &M : Cases) {
-      if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M.second)) {
-        std::unique_ptr<Matcher> Scope(SM);
-        FactorScope(Scope);
-        M.second = Scope.release();
-        assert(M.second && "null matcher");
+      if (isa<ScopeMatcher>(M.second.front())) {
+        FactorScope(M.second, M.second.before_begin());
+        assert(!M.second.empty() && "empty matcher list");
       }
     }
 
     if (Cases.size() != 1) {
-      MatcherPtr.reset(new SwitchTypeMatcher(std::move(Cases)));
+      ML.insert_after(Prev, new SwitchTypeMatcher(std::move(Cases)));
     } else {
-      // If we factored and ended up with one case, create it now.
-      MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0));
-      MatcherPtr->setNext(Cases[0].second);
+      // If we factored and ended up with one case, insert a type check and
+      // splice the rest.
+      auto I = ML.insert_after(Prev, new CheckTypeMatcher(Cases[0].first, 0));
+      ML.splice_after(I, Cases[0].second);
     }
     return;
   }
 }
 
 /// Search a ScopeMatcher to factor with FactorScope.
-static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
-  // Look for a scope matcher. Iterates instead of recurses to reduce stack
-  // usage.
-  std::unique_ptr<Matcher> *MatcherPtr = &InputMatcherPtr;
-  do {
-    if (isa<ScopeMatcher>(*MatcherPtr))
-      return FactorScope(*MatcherPtr);
-
-    // If this is not a scope matcher, go to the next node.
-    MatcherPtr = &(MatcherPtr->get()->getNextPtr());
-  } while (MatcherPtr->get());
+static void FactorNodes(MatcherList &ML) {
+  auto P = ML.before_begin();
+  auto I = std::next(P);
+
+  while (I != ML.end()) {
+    if (isa<ScopeMatcher>(*I))
+      return FactorScope(ML, P);
+
+    P = I;
+    ++I;
+  }
 }
 
-void llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,
-                           const CodeGenDAGPatterns &CGP) {
-  ContractNodes(MatcherPtr, CGP);
-  FactorNodes(MatcherPtr);
+void llvm::OptimizeMatcher(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
+  ContractNodes(ML, CGP);
+  FactorNodes(ML);
 }


        


More information about the llvm-commits mailing list