[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