[llvm] 4833c51 - Revert "[TableGen] Introduce MatcherList to manage a linked list of Matchers. NFC (#177875)"
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 13 18:05:04 PST 2026
Author: Craig Topper
Date: 2026-02-13T18:04:40-08:00
New Revision: 4833c51d11e5ec0306fe0386d1be487de7a5e4b6
URL: https://github.com/llvm/llvm-project/commit/4833c51d11e5ec0306fe0386d1be487de7a5e4b6
DIFF: https://github.com/llvm/llvm-project/commit/4833c51d11e5ec0306fe0386d1be487de7a5e4b6.diff
LOG: Revert "[TableGen] Introduce MatcherList to manage a linked list of Matchers. NFC (#177875)"
This reverts commit 39613943855e6a82b1bb4c3d16fbaf2289a5d739.
It's failing across multiple build bots.
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 a7deaa1dd5dfd..dc66967584f71 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<MatcherList, 0> PatternMatchers;
+ SmallVector<Matcher *, 0> PatternMatchers;
for (const PatternToMatch *PTM : Patterns) {
for (unsigned Variant = 0;; ++Variant) {
- MatcherList ML = ConvertPatternToMatcher(*PTM, Variant, CGP);
- if (ML.empty())
+ if (Matcher *M = ConvertPatternToMatcher(*PTM, Variant, CGP))
+ PatternMatchers.push_back(M);
+ else
break;
- PatternMatchers.push_back(std::move(ML));
}
}
- MatcherList Matchers;
- Matchers.push_front(new ScopeMatcher(std::move(PatternMatchers)));
+ std::unique_ptr<Matcher> TheMatcher =
+ std::make_unique<ScopeMatcher>(std::move(PatternMatchers));
Timer.startTimer("Optimize matchers");
- OptimizeMatcher(Matchers, CGP);
+ OptimizeMatcher(TheMatcher, CGP);
// Matcher->dump();
Timer.startTimer("Emit matcher table");
- EmitMatcherTable(Matchers, CGP, OS);
+ EmitMatcherTable(TheMatcher.get(), CGP, OS);
}
static TableGen::Emitter::OptClass<DAGISelEmitter>
diff --git a/llvm/utils/TableGen/DAGISelMatcher.cpp b/llvm/utils/TableGen/DAGISelMatcher.cpp
index 05c6384409f10..0178998ab1ae2 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcher.cpp
@@ -17,10 +17,48 @@ using namespace llvm;
void Matcher::anchor() {}
-void Matcher::dump() const { printOne(errs()); }
+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::printOne(raw_ostream &OS, indent Indent) const {
- printImpl(OS, indent(0));
+ // We have to be able to move this node across the Other node.
+ if (!canMoveBeforeNode(Other))
+ return false;
+ }
}
/// canMoveBeforeNode - Return true if it is safe to move the current matcher
@@ -38,6 +76,21 @@ 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()),
@@ -60,11 +113,11 @@ unsigned CheckPredicateMatcher::getOperandNo(unsigned i) const {
void ScopeMatcher::printImpl(raw_ostream &OS, indent Indent) const {
OS << Indent << "Scope\n";
- for (const MatcherList &C : Children) {
- if (C.empty())
+ for (const Matcher *C : Children) {
+ if (!C)
OS << Indent + 1 << "NULL POINTER\n";
else
- C.print(OS, Indent + 2);
+ C->print(OS, Indent + 2);
}
}
@@ -121,7 +174,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";
}
@@ -134,7 +187,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";
}
@@ -394,10 +447,3 @@ 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 3f0329bd4ba85..5b1452e44857e 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.h
+++ b/llvm/utils/TableGen/DAGISelMatcher.h
@@ -26,7 +26,6 @@ class CodeGenRegister;
class CodeGenDAGPatterns;
class CodeGenInstruction;
class Matcher;
-class MatcherList;
class PatternToMatch;
class raw_ostream;
class ComplexPattern;
@@ -35,25 +34,21 @@ class SDNodeInfo;
class TreePredicateFn;
class TreePattern;
-MatcherList ConvertPatternToMatcher(const PatternToMatch &Pattern,
- unsigned Variant,
- const CodeGenDAGPatterns &CGP);
-void OptimizeMatcher(MatcherList &ML, const CodeGenDAGPatterns &CGP);
-void EmitMatcherTable(MatcherList &ML, const CodeGenDAGPatterns &CGP,
+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,
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 : public MatcherBase {
+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).
virtual void anchor();
public:
@@ -112,8 +107,17 @@ class Matcher : public MatcherBase {
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;
@@ -155,6 +159,16 @@ class Matcher : public MatcherBase {
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;
@@ -171,7 +185,8 @@ class Matcher : public MatcherBase {
return Other->isContradictoryImpl(this);
}
- void printOne(raw_ostream &OS, indent Indent = indent(0)) const;
+ void print(raw_ostream &OS, indent Indent = indent(0)) const;
+ void printOne(raw_ostream &OS) const;
void dump() const;
protected:
@@ -180,238 +195,34 @@ class Matcher : public MatcherBase {
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<MatcherList, 4> Children;
+ SmallVector<Matcher *, 4> Children;
public:
- ScopeMatcher(SmallVectorImpl<MatcherList> &&children)
+ ScopeMatcher(SmallVectorImpl<Matcher *> &&children)
: Matcher(Scope), Children(std::move(children)) {}
+ ~ScopeMatcher() override;
unsigned getNumChildren() const { return Children.size(); }
- MatcherList &getChild(unsigned i) { return Children[i]; }
- const MatcherList &getChild(unsigned i) const { return Children[i]; }
+ Matcher *getChild(unsigned i) { return Children[i]; }
+ const Matcher *getChild(unsigned i) const { return Children[i]; }
- SmallVectorImpl<MatcherList> &getChildren() { return Children; }
+ 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; }
static bool classof(const Matcher *N) { return N->getKind() == Scope; }
@@ -675,22 +486,21 @@ 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 *, MatcherList>, 8> Cases;
+ SmallVector<std::pair<const SDNodeInfo *, Matcher *>, 8> Cases;
public:
SwitchOpcodeMatcher(
- SmallVectorImpl<std::pair<const SDNodeInfo *, MatcherList>> &&cases)
+ SmallVectorImpl<std::pair<const SDNodeInfo *, Matcher *>> &&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; }
- MatcherList &getCaseMatcher(unsigned i) { return Cases[i].second; }
- const MatcherList &getCaseMatcher(unsigned i) const {
- return Cases[i].second;
- }
+ Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
+ const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
private:
void printImpl(raw_ostream &OS, indent Indent) const override;
@@ -725,21 +535,20 @@ 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, MatcherList>, 8> Cases;
+ SmallVector<std::pair<MVT, Matcher *>, 8> Cases;
public:
- SwitchTypeMatcher(SmallVectorImpl<std::pair<MVT, MatcherList>> &&cases)
+ SwitchTypeMatcher(SmallVectorImpl<std::pair<MVT, Matcher *>> &&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; }
- MatcherList &getCaseMatcher(unsigned i) { return Cases[i].second; }
- const MatcherList &getCaseMatcher(unsigned i) const {
- return Cases[i].second;
- }
+ Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
+ const Matcher *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 47323a1fa397b..1058e7567805d 100644
--- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -87,8 +87,7 @@ class MatcherTableEmitter {
}
public:
- MatcherTableEmitter(const MatcherList &TheMatcher,
- const CodeGenDAGPatterns &cgp)
+ MatcherTableEmitter(const Matcher *TheMatcher, const CodeGenDAGPatterns &cgp)
: CGP(cgp), OpcodeCounts(Matcher::HighestKind + 1, 0),
OperandTable(std::nullopt) {
// Record the usage of ComplexPattern.
@@ -99,38 +98,39 @@ class MatcherTableEmitter {
MapVector<TreePattern *, unsigned> PredicateUsage;
// Iterate the whole MatcherTable once and do some statistics.
- 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);
- }
+ 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]);
}
- };
+ OperandTable.add(OpBytes);
+ }
+
+ N = N->getNext();
+ }
+ };
Statistic(TheMatcher);
OperandTable.layout();
@@ -188,12 +188,12 @@ class MatcherTableEmitter {
}
}
- unsigned EmitMatcherList(const MatcherList &ML, const unsigned Indent,
+ unsigned EmitMatcherList(const Matcher *N, const unsigned Indent,
unsigned StartIdx, raw_ostream &OS);
void EmitOperandLists(raw_ostream &OS);
- unsigned SizeMatcherList(MatcherList &ML, raw_ostream &OS);
+ unsigned SizeMatcherList(Matcher *N, raw_ostream &OS);
void EmitPredicateFunctions(raw_ostream &OS);
@@ -335,11 +335,12 @@ 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(MatcherList &ML,
- raw_ostream &OS) {
+unsigned MatcherTableEmitter::SizeMatcherList(Matcher *N, raw_ostream &OS) {
unsigned Size = 0;
- for (Matcher *N : ML)
+ while (N) {
Size += SizeMatcher(N, OS);
+ N = N->getNext();
+ }
return Size;
}
@@ -355,11 +356,12 @@ 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.
@@ -377,17 +379,17 @@ unsigned MatcherTableEmitter::SizeMatcher(Matcher *N, raw_ostream &OS) {
else
NumCases = cast<SwitchTypeMatcher>(N)->getNumCases();
for (unsigned i = 0, e = NumCases; i != e; ++i) {
- MatcherList *Child;
+ Matcher *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.
@@ -512,15 +514,15 @@ unsigned MatcherTableEmitter::EmitMatcher(const Matcher *N,
}
}
- const MatcherList &Child = SM->getChild(i);
- unsigned ChildSize = Child.getSize();
+ const Matcher *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;
}
@@ -662,13 +664,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 MatcherList *Child;
+ const Matcher *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)
@@ -695,7 +697,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;
@@ -1230,17 +1232,21 @@ 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 MatcherList &ML,
+unsigned MatcherTableEmitter::EmitMatcherList(const Matcher *N,
const unsigned Indent,
unsigned CurrentIdx,
raw_ostream &OS) {
unsigned Size = 0;
- for (const Matcher *N : ML) {
+ while (N) {
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;
}
@@ -1526,8 +1532,8 @@ void MatcherTableEmitter::EmitHistogram(raw_ostream &OS) {
OS << '\n';
}
-void llvm::EmitMatcherTable(MatcherList &TheMatcher,
- const CodeGenDAGPatterns &CGP, raw_ostream &OS) {
+void llvm::EmitMatcherTable(Matcher *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 6d727b1fba451..e8f146264b1ec 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;
- /// This is the top level of the generated matcher, the result.
- MatcherList TheMatcher;
+ /// Matcher - This is the top level of the generated matcher, the result.
+ Matcher *TheMatcher = nullptr;
- /// As we emit matcher nodes, this points to the latest check which should
- /// have future checks inserted after it.
- MatcherList::iterator InsertPt;
+ /// 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;
public:
MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
@@ -105,7 +105,7 @@ class MatcherGen {
bool EmitMatcherCode(unsigned Variant);
void EmitResultCode();
- MatcherList GetMatcher() { return std::move(TheMatcher); }
+ Matcher *GetMatcher() const { return TheMatcher; }
private:
void AddMatcher(Matcher *NewNode);
@@ -146,7 +146,7 @@ class MatcherGen {
MatcherGen::MatcherGen(const PatternToMatch &pattern,
const CodeGenDAGPatterns &cgp)
- : Pattern(pattern), CGP(cgp), InsertPt(TheMatcher.before_begin()) {
+ : Pattern(pattern), CGP(cgp) {
// 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,7 +184,11 @@ void MatcherGen::InferPossibleTypes() {
/// AddMatcher - Add a matcher node to the current graph we're building.
void MatcherGen::AddMatcher(Matcher *NewNode) {
- InsertPt = TheMatcher.insert_after(InsertPt, NewNode);
+ if (CurPredicate)
+ CurPredicate->setNext(NewNode);
+ else
+ TheMatcher = NewNode;
+ CurPredicate = NewNode;
}
//===----------------------------------------------------------------------===//
@@ -1052,16 +1056,15 @@ void MatcherGen::EmitResultCode() {
}
/// ConvertPatternToMatcher - Create the matcher for the specified pattern with
-/// 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) {
+/// the specified variant. If the variant number is invalid, this returns null.
+Matcher *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 MatcherList();
+ return nullptr;
// 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 553242f7143d7..111c174dacc53 100644
--- a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -22,98 +22,101 @@ using namespace llvm;
/// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
/// into single compound nodes like RecordChild.
-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;
+static void ContractNodes(std::unique_ptr<Matcher> &InputMatcherPtr,
+ const CodeGenDAGPatterns &CGP) {
+ std::unique_ptr<Matcher> *MatcherPtr = &InputMatcherPtr;
+ while (true) {
+ Matcher *N = MatcherPtr->get();
// 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)
- ContractNodes(Scope->getChild(i), CGP);
+ 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());
+ }
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>(Next))
+ if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext()))
if (MC->getChildNo() < 8) // Only have RecordChild0...7
New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),
RM->getResultNo());
- if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(Next))
+ if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext()))
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>(Next))
+ if (CheckSameMatcher *CS = dyn_cast<CheckSameMatcher>(MC->getNext()))
if (MC->getChildNo() < 4) // Only have CheckChildSame0...3
New =
new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber());
- if (CheckIntegerMatcher *CI = dyn_cast<CheckIntegerMatcher>(Next))
+ if (CheckIntegerMatcher *CI =
+ dyn_cast<CheckIntegerMatcher>(MC->getNext()))
if (MC->getChildNo() < 5) // Only have CheckChildInteger0...4
New = new CheckChildIntegerMatcher(MC->getChildNo(), CI->getValue());
- if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(Next))
+ if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(MC->getNext()))
if (MC->getChildNo() == 2) // Only have CheckChild2CondCode
New = new CheckChild2CondCodeMatcher(CCC->getCondCodeName());
if (New) {
- // Erase the old node after the MoveChild.
- ML.erase_after(I);
- // Insert the new node before the MoveChild.
- I = ML.insert_after(P, New);
+ // Insert the new node.
+ New->setNext(MatcherPtr->release());
+ MatcherPtr->reset(New);
+ // Remove the old one.
+ MC->setNext(MC->getNext()->takeNext());
continue;
}
}
// Turn MoveParent->MoveChild into MoveSibling.
- if (isa<MoveParentMatcher>(N)) {
- auto J = std::next(I);
- if (auto *MC = dyn_cast<MoveChildMatcher>(*J)) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(N)) {
+ if (auto *MC = dyn_cast<MoveChildMatcher>(MP->getNext())) {
auto *MS = new MoveSiblingMatcher(MC->getChildNo());
- I = ML.insert_after(P, MS);
- // Erase the two old nodes.
- ML.erase_after(I, std::next(J));
+ MS->setNext(MC->takeNext());
+ MatcherPtr->reset(MS);
continue;
}
}
// Uncontract MoveSibling if it will help form other child operations.
if (auto *MS = dyn_cast<MoveSiblingMatcher>(N)) {
- auto J = std::next(I);
- if (auto *RM = dyn_cast<RecordMatcher>(*J)) {
- auto K = std::next(J);
+ if (auto *RM = dyn_cast<RecordMatcher>(MS->getNext())) {
// Turn MoveSibling->Record->MoveParent into MoveParent->RecordChild.
- if (isa<MoveParentMatcher>(*K)) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(RM->getNext())) {
if (MS->getSiblingNo() < 8) { // Only have RecordChild0...7
+ auto *NewMP = new MoveParentMatcher();
auto *NewRCM = new RecordChildMatcher(
MS->getSiblingNo(), RM->getWhatFor(), RM->getResultNo());
- I = ML.erase_after(P, K);
- ML.insert_after(I, NewRCM);
+ NewMP->setNext(NewRCM);
+ NewRCM->setNext(MP->takeNext());
+ MatcherPtr->reset(NewMP);
continue;
}
}
// Turn MoveSibling->Record->CheckType->MoveParent into
// MoveParent->RecordChild->CheckChildType.
- if (auto *CT = dyn_cast<CheckTypeMatcher>(*K)) {
- auto L = std::next(K);
- if (isa<MoveParentMatcher>(*L)) {
+ if (auto *CT = dyn_cast<CheckTypeMatcher>(RM->getNext())) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(CT->getNext())) {
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());
- I = ML.erase_after(P, L);
- ML.insert_after(I, {NewRCM, NewCCT});
+ NewMP->setNext(NewRCM);
+ NewRCM->setNext(NewCCT);
+ NewCCT->setNext(MP->takeNext());
+ MatcherPtr->reset(NewMP);
continue;
}
}
@@ -122,15 +125,16 @@ static void ContractNodes(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
// Turn MoveSibling->CheckType->MoveParent into
// MoveParent->CheckChildType.
- if (auto *CT = dyn_cast<CheckTypeMatcher>(*J)) {
- auto K = std::next(J);
- if (isa<MoveParentMatcher>(*K)) {
+ if (auto *CT = dyn_cast<CheckTypeMatcher>(MS->getNext())) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(CT->getNext())) {
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());
- I = ML.erase_after(P, K);
- ML.insert_after(I, NewCCT);
+ NewMP->setNext(NewCCT);
+ NewCCT->setNext(MP->takeNext());
+ MatcherPtr->reset(NewMP);
continue;
}
}
@@ -138,31 +142,34 @@ static void ContractNodes(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
// Turn MoveSibling->CheckInteger->MoveParent into
// MoveParent->CheckChildInteger.
- if (auto *CI = dyn_cast<CheckIntegerMatcher>(*J)) {
- auto K = std::next(J);
- if (isa<MoveParentMatcher>(*K)) {
+ if (auto *CI = dyn_cast<CheckIntegerMatcher>(MS->getNext())) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(CI->getNext())) {
if (MS->getSiblingNo() < 5) { // Only have CheckChildInteger0...4
+ auto *NewMP = new MoveParentMatcher();
auto *NewCCI = new CheckChildIntegerMatcher(MS->getSiblingNo(),
CI->getValue());
- I = ML.erase_after(P, K);
- ML.insert_after(I, NewCCI);
+ NewMP->setNext(NewCCI);
+ NewCCI->setNext(MP->takeNext());
+ MatcherPtr->reset(NewMP);
continue;
}
}
// Turn MoveSibling->CheckInteger->CheckType->MoveParent into
// MoveParent->CheckChildInteger->CheckType.
- if (auto *CT = dyn_cast<CheckTypeMatcher>(*K)) {
- auto L = std::next(K);
- if (isa<MoveParentMatcher>(*L)) {
+ if (auto *CT = dyn_cast<CheckTypeMatcher>(CI->getNext())) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(CT->getNext())) {
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());
- I = ML.erase_after(P, L);
- ML.insert_after(I, {NewCCI, NewCCT});
+ NewMP->setNext(NewCCI);
+ NewCCI->setNext(NewCCT);
+ NewCCT->setNext(MP->takeNext());
+ MatcherPtr->reset(NewMP);
continue;
}
}
@@ -171,14 +178,15 @@ static void ContractNodes(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
// Turn MoveSibling->CheckCondCode->MoveParent into
// MoveParent->CheckChild2CondCode.
- if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(*J)) {
- auto K = std::next(J);
- if (isa<MoveParentMatcher>(*K)) {
+ if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(MS->getNext())) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(CCC->getNext())) {
if (MS->getSiblingNo() == 2) { // Only have CheckChild2CondCode
+ auto *NewMP = new MoveParentMatcher();
auto *NewCCCC =
new CheckChild2CondCodeMatcher(CCC->getCondCodeName());
- I = ML.erase_after(P, K);
- ML.insert_after(I, NewCCCC);
+ NewMP->setNext(NewCCCC);
+ NewCCCC->setNext(MP->takeNext());
+ MatcherPtr->reset(NewMP);
continue;
}
}
@@ -186,31 +194,34 @@ static void ContractNodes(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
// Turn MoveSibling->CheckSame->MoveParent into
// MoveParent->CheckChildSame.
- if (auto *CS = dyn_cast<CheckSameMatcher>(*J)) {
- auto K = std::next(J);
- if (isa<MoveParentMatcher>(*K)) {
+ if (auto *CS = dyn_cast<CheckSameMatcher>(MS->getNext())) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(CS->getNext())) {
if (MS->getSiblingNo() < 4) { // Only have CheckChildSame0...3
+ auto *NewMP = new MoveParentMatcher();
auto *NewCCS = new CheckChildSameMatcher(MS->getSiblingNo(),
CS->getMatchNumber());
- I = ML.erase_after(P, K);
- ML.insert_after(I, NewCCS);
+ NewMP->setNext(NewCCS);
+ NewCCS->setNext(MP->takeNext());
+ MatcherPtr->reset(NewMP);
continue;
}
}
// Turn MoveSibling->CheckSame->CheckType->MoveParent into
// MoveParent->CheckChildSame->CheckChildType.
- if (auto *CT = dyn_cast<CheckTypeMatcher>(*K)) {
- auto L = std::next(K);
- if (isa<MoveParentMatcher>(*L)) {
+ if (auto *CT = dyn_cast<CheckTypeMatcher>(CS->getNext())) {
+ if (auto *MP = dyn_cast<MoveParentMatcher>(CT->getNext())) {
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());
- I = ML.erase_after(P, L);
- ML.insert_after(I, {NewCCS, NewCCT});
+ NewMP->setNext(NewCCS);
+ NewCCS->setNext(NewCCT);
+ NewCCT->setNext(MP->takeNext());
+ MatcherPtr->reset(NewMP);
continue;
}
}
@@ -218,25 +229,23 @@ static void ContractNodes(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
}
// Turn MoveSibling->MoveParent into MoveParent.
- if (isa<MoveParentMatcher>(*J)) {
- I = ML.erase_after(P, J);
+ if (isa<MoveParentMatcher>(MS->getNext())) {
+ MatcherPtr->reset(MS->takeNext());
continue;
}
}
// Zap movechild -> moveparent.
- if (isa<MoveChildMatcher>(N)) {
- auto J = std::next(I);
- if (isa<MoveParentMatcher>(*J)) {
- I = ML.erase_after(P, std::next(J));
+ if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N))
+ if (MoveParentMatcher *MP = dyn_cast<MoveParentMatcher>(MC->getNext())) {
+ MatcherPtr->reset(MP->takeNext());
continue;
}
- }
// Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N)) {
- auto J = std::next(I);
- if (auto *CM = dyn_cast<CompleteMatchMatcher>(*J)) {
+ if (CompleteMatchMatcher *CM =
+ dyn_cast<CompleteMatchMatcher>(EN->getNext())) {
// We can only use MorphNodeTo if the result values match up.
unsigned RootResultFirst = EN->getFirstResultSlot();
bool ResultsMatch = true;
@@ -275,12 +284,10 @@ static void ContractNodes(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
if (ResultsMatch) {
ArrayRef<ValueTypeByHwMode> VTs = EN->getVTList();
ArrayRef<unsigned> Operands = EN->getOperandList();
- auto *MNT = new MorphNodeToMatcher(
+ MatcherPtr->reset(new MorphNodeToMatcher(
EN->getInstruction(), VTs, Operands, EN->hasChain(),
EN->hasInGlue(), EN->hasOutGlue(), EN->hasMemRefs(),
- EN->getNumFixedArityOperands(), Pattern);
- ML.erase_after(P, std::next(J));
- ML.insert_after(P, MNT);
+ EN->getNumFixedArityOperands(), Pattern));
return;
}
}
@@ -290,54 +297,39 @@ static void ContractNodes(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
// 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>(*std::next(I))) {
- ML.splice_after(P, ML, I);
- // Restore I to the node after P.
- I = std::next(P);
+ 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);
continue;
}
- // Move to next node.
- P = I;
- ++I;
+ // 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;
}
}
/// 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 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 Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) {
+ for (; M; M = M->getNext())
+ if (M->getKind() == Kind)
+ return M;
+ return nullptr;
}
-/// 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);
+static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr);
/// Turn matches like this:
/// Scope
@@ -351,30 +343,26 @@ static void FactorNodes(MatcherList &ML);
/// ABC
/// XYZ
///
-/// \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));
+static void FactorScope(std::unique_ptr<Matcher> &MatcherPtr) {
+ ScopeMatcher *Scope = cast<ScopeMatcher>(MatcherPtr.get());
- SmallVectorImpl<MatcherList> &OptionsToMatch = Scope->getChildren();
+ SmallVectorImpl<Matcher *> &OptionsToMatch = Scope->getChildren();
for (auto I = OptionsToMatch.begin(); I != OptionsToMatch.end();) {
- assert(!I->empty());
+ // TODO: Store unique_ptr in ScopeMatcher.
// Factor the subexpression.
- FactorNodes(*I);
+ std::unique_ptr<Matcher> Child(*I);
+ FactorNodes(Child);
// If the child is a ScopeMatcher we can just merge its contents.
- 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()));
+ 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());
I += Children.size() - 1;
+ Children.clear();
} else {
+ Child.release();
++I;
}
}
@@ -392,32 +380,33 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
auto K = J;
// Find the set of matchers that start with this node.
- Matcher *Optn = I->front();
+ Matcher *Optn = *I;
// See if the next option starts with the same matcher. If the two
// neighbors *do* start with the same matcher, we can factor the matcher out
// of at least these two patterns. See what the maximal set we can merge
// together is.
- SmallVector<MatcherList, 8> EqualMatchers;
- EqualMatchers.push_back(std::move(*I));
+ SmallVector<Matcher *, 8> EqualMatchers;
+ EqualMatchers.push_back(Optn);
// Factor all of the known-equal matchers after this one into the same
// group.
- while (J != E && J->front()->isEqual(Optn))
- EqualMatchers.push_back(std::move(*J++));
+ while (J != E && (*J)->isEqual(Optn))
+ EqualMatchers.push_back(*J++);
// If we found a non-equal matcher, see if it is contradictory with the
// current node. If so, we know that the ordering relation between the
// current sets of nodes and this node don't matter. Look past it to see if
// we can merge anything else into this matching group.
while (J != E) {
- Matcher *ScanMatcher = J->front();
+ Matcher *ScanMatcher = *J;
// 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(std::move(*J++));
+ EqualMatchers.push_back(ScanMatcher);
+ ++J;
continue;
}
@@ -425,10 +414,7 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
// 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)) {
- if (J != K)
- *K = std::move(*J);
- ++J;
- ++K;
+ *K++ = *J++;
continue;
}
@@ -436,10 +422,12 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
// 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()) {
- auto [P, M2] = FindNodeWithKind(*J, Optn->getKind());
- if (M2 != J->end() && *M2 != ScanMatcher && canMoveToFront(*J, M2) &&
+ Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());
+ if (M2 && M2 != ScanMatcher && M2->canMoveBefore(ScanMatcher) &&
(M2->isEqual(Optn) || M2->isContradictory(Optn))) {
- J->splice_after(J->before_begin(), *J, P);
+ Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
+ M2->setNext(MatcherWithoutM2);
+ *J = M2;
continue;
}
}
@@ -451,51 +439,49 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
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"; 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");
+ 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");
}
// 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::move(J, E, K);
+ E = std::copy(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 = std::move(EqualMatchers[0]);
+ *I = 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.
- MatcherList Shared;
- Shared.splice_after(Shared.before_begin(), EqualMatchers[0],
- EqualMatchers[0].before_begin());
- Optn = EqualMatchers[0].empty() ? nullptr : EqualMatchers[0].front();
+ Matcher *Shared = Optn;
+ Optn = Optn->takeNext();
+ EqualMatchers[0] = Optn;
// Remove and delete the first node from the other matchers we're factoring.
for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) {
- EqualMatchers[i].pop_front();
- Matcher *Tmp =
- EqualMatchers[i].empty() ? nullptr : EqualMatchers[i].front();
+ Matcher *Tmp = EqualMatchers[i]->takeNext();
+ delete EqualMatchers[i];
+ EqualMatchers[i] = Tmp;
assert(!Optn == !Tmp && "Expected all to be null if any are null");
}
- if (!EqualMatchers[0].empty()) {
- Shared.insert_after(Shared.begin(),
- new ScopeMatcher(std::move(EqualMatchers)));
+ if (EqualMatchers[0]) {
+ Shared->setNext(new ScopeMatcher(std::move(EqualMatchers)));
// Recursively factor the newly created node.
- FactorScope(Shared, Shared.begin());
+ FactorScope(Shared->getNextPtr());
}
// Put the new Matcher where we started in OptionsToMatch.
- *I = std::move(Shared);
+ *I = Shared;
}
// Trim the array to match the updated end.
@@ -504,14 +490,12 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
// If we're down to a single pattern to match, then we don't need this scope
// anymore.
if (OptionsToMatch.size() == 1) {
- MatcherList Tmp = std::move(OptionsToMatch[0]);
- ML.erase_after(Prev);
- ML.splice_after(Prev, Tmp);
+ MatcherPtr.reset(OptionsToMatch.pop_back_val());
return;
}
if (OptionsToMatch.empty()) {
- ML.erase_after(Prev);
+ MatcherPtr.reset();
return;
}
@@ -521,9 +505,9 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
// 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 (MatcherList &Optn : OptionsToMatch) {
+ for (Matcher *Optn : OptionsToMatch) {
// Check to see if this breaks a series of CheckOpcodeMatchers.
- if (AllOpcodeChecks && !isa<CheckOpcodeMatcher>(Optn.front())) {
+ if (AllOpcodeChecks && !isa<CheckOpcodeMatcher>(Optn)) {
#if 0
if (i > 3) {
errs() << "FAILING OPC #" << i << "\n";
@@ -535,9 +519,8 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
// Check to see if this breaks a series of CheckTypeMatcher's.
if (AllTypeChecks) {
- auto [P, I] = FindNodeWithKind(Optn, Matcher::CheckType);
- auto *CTM =
- cast_or_null<CheckTypeMatcher>(I == Optn.end() ? nullptr : *I);
+ CheckTypeMatcher *CTM = cast_or_null<CheckTypeMatcher>(
+ FindNodeWithKind(Optn, Matcher::CheckType));
if (!CTM || !CTM->getType().isSimple() ||
// iPTR/cPTR checks could alias any other case without us knowing,
// don't bother with them.
@@ -547,7 +530,7 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
CTM->getResNo() != 0 ||
// If the CheckType isn't at the start of the list, see if we can move
// it there.
- !canMoveToFront(Optn, I)) {
+ !CTM->canMoveBefore(Optn)) {
#if 0
if (i > 3 && AllTypeChecks) {
errs() << "FAILING TYPE #" << i << "\n";
@@ -561,92 +544,89 @@ static void FactorScope(MatcherList &ML, MatcherList::iterator Prev) {
// If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.
if (AllOpcodeChecks) {
StringSet<> Opcodes;
- SmallVector<std::pair<const SDNodeInfo *, MatcherList>, 8> Cases;
- for (MatcherList &Optn : OptionsToMatch) {
- CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(Optn.front());
+ SmallVector<std::pair<const SDNodeInfo *, Matcher *>, 8> Cases;
+ for (Matcher *Optn : OptionsToMatch) {
+ CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(Optn);
assert(Opcodes.insert(COM->getOpcode().getEnumName()).second &&
"Duplicate opcodes not factored?");
- const SDNodeInfo &Opcode = COM->getOpcode();
- Optn.erase_after(Optn.before_begin());
- Cases.emplace_back(&Opcode, std::move(Optn));
+ Cases.emplace_back(&COM->getOpcode(), COM->takeNext());
+ delete COM;
}
+ OptionsToMatch.clear();
- ML.erase_after(Prev);
- ML.insert_after(Prev, new SwitchOpcodeMatcher(std::move(Cases)));
+ MatcherPtr.reset(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, MatcherList>, 8> Cases;
- for (MatcherList &Optn : OptionsToMatch) {
- auto [P, I] = FindNodeWithKind(Optn, Matcher::CheckType);
- assert(I != Optn.end() && isa<CheckTypeMatcher>(*I) &&
- "Unknown Matcher type");
+ 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");
- auto *CTM = cast<CheckTypeMatcher>(*I);
+ auto *CTM = cast<CheckTypeMatcher>(M);
+ Matcher *MatcherWithoutCTM = Optn->unlinkNode(CTM);
MVT CTMTy = CTM->getType().getSimple();
- Optn.erase_after(P);
+ delete CTM;
unsigned &Entry = TypeEntry[CTMTy.SimpleTy];
if (Entry != 0) {
// If we have unfactored duplicate types, then we should factor them.
- MatcherList &PrevMatcher = Cases[Entry - 1].second;
- if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher.front())) {
- SM->getChildren().push_back(std::move(Optn));
+ Matcher *PrevMatcher = Cases[Entry - 1].second;
+ if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {
+ SM->getChildren().push_back(MatcherWithoutCTM);
continue;
}
- 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)));
+ SmallVector<Matcher *, 2> Entries = {PrevMatcher, MatcherWithoutCTM};
+ Cases[Entry - 1].second = new ScopeMatcher(std::move(Entries));
continue;
}
Entry = Cases.size() + 1;
- Cases.emplace_back(CTMTy, std::move(Optn));
+ Cases.emplace_back(CTMTy, MatcherWithoutCTM);
}
- ML.erase_after(Prev);
+ OptionsToMatch.clear();
// Make sure we recursively factor any scopes we may have created.
for (auto &M : Cases) {
- if (isa<ScopeMatcher>(M.second.front())) {
- FactorScope(M.second, M.second.before_begin());
- assert(!M.second.empty() && "empty matcher list");
+ 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 (Cases.size() != 1) {
- ML.insert_after(Prev, new SwitchTypeMatcher(std::move(Cases)));
+ MatcherPtr.reset(new SwitchTypeMatcher(std::move(Cases)));
} else {
- // 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);
+ // 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);
}
return;
}
}
/// Search a ScopeMatcher to factor with FactorScope.
-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;
- }
+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());
}
-void llvm::OptimizeMatcher(MatcherList &ML, const CodeGenDAGPatterns &CGP) {
- ContractNodes(ML, CGP);
- FactorNodes(ML);
+void llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,
+ const CodeGenDAGPatterns &CGP) {
+ ContractNodes(MatcherPtr, CGP);
+ FactorNodes(MatcherPtr);
}
More information about the llvm-commits
mailing list