diff --git a/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/llvm/include/llvm/CodeGen/SelectionDAGISel.h index 233e94c4e7439..c604e7eaa0887 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -143,6 +143,15 @@ class SelectionDAGISel : public MachineFunctionPass { OPC_MoveChild5, OPC_MoveChild6, OPC_MoveChild7, + OPC_MoveSibling, + OPC_MoveSibling0, + OPC_MoveSibling1, + OPC_MoveSibling2, + OPC_MoveSibling3, + OPC_MoveSibling4, + OPC_MoveSibling5, + OPC_MoveSibling6, + OPC_MoveSibling7, OPC_MoveParent, OPC_CheckSame, OPC_CheckChild0Same, diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index b43847db32aa3..dd28ec09d0e2b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -3285,6 +3285,29 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch, continue; } + case OPC_MoveSibling: + case OPC_MoveSibling0: + case OPC_MoveSibling1: + case OPC_MoveSibling2: + case OPC_MoveSibling3: + case OPC_MoveSibling4: + case OPC_MoveSibling5: + case OPC_MoveSibling6: + case OPC_MoveSibling7: { + // Pop the current node off the NodeStack. + NodeStack.pop_back(); + assert(!NodeStack.empty() && "Node stack imbalance!"); + N = NodeStack.back(); + + unsigned SiblingNo = Opcode == OPC_MoveSibling + ? MatcherTable[MatcherIndex++] + : Opcode - OPC_MoveSibling0; + if (SiblingNo >= N.getNumOperands()) + break; // Match fails if out of range sibling #. + N = N.getOperand(SiblingNo); + NodeStack.push_back(N); + continue; + } case OPC_MoveParent: // Pop the current node off the NodeStack. NodeStack.pop_back(); diff --git a/llvm/utils/TableGen/DAGISelMatcher.cpp b/llvm/utils/TableGen/DAGISelMatcher.cpp index 0609f006763bc..1a5c728fafd9c 100644 --- a/llvm/utils/TableGen/DAGISelMatcher.cpp +++ b/llvm/utils/TableGen/DAGISelMatcher.cpp @@ -145,6 +145,10 @@ void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "MoveChild " << ChildNo << '\n'; } +void MoveSiblingMatcher::printImpl(raw_ostream &OS, unsigned Indent) const { + OS.indent(Indent) << "MoveSibling " << SiblingNo << '\n'; +} + void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "MoveParent\n"; } diff --git a/llvm/utils/TableGen/DAGISelMatcher.h b/llvm/utils/TableGen/DAGISelMatcher.h index e3cf847edd127..e69f8fa9c5d30 100644 --- a/llvm/utils/TableGen/DAGISelMatcher.h +++ b/llvm/utils/TableGen/DAGISelMatcher.h @@ -52,28 +52,29 @@ class Matcher { public: enum KindTy { // Matcher state manipulation. - Scope, // Push a checking scope. - RecordNode, // Record the current node. - RecordChild, // Record a child of the current node. - RecordMemRef, // Record the memref in the current node. - CaptureGlueInput, // If the current node has an input glue, save it. - MoveChild, // Move current node to specified child. - MoveParent, // Move current node to parent. + Scope, // Push a checking scope. + RecordNode, // Record the current node. + RecordChild, // Record a child of the current node. + RecordMemRef, // Record the memref in the current node. + CaptureGlueInput, // If the current node has an input glue, save it. + MoveChild, // Move current node to specified child. + MoveSibling, // Move current node to specified sibling. + MoveParent, // Move current node to parent. // Predicate checking. - CheckSame, // Fail if not same as prev match. - CheckChildSame, // Fail if child not same as prev match. + CheckSame, // Fail if not same as prev match. + CheckChildSame, // Fail if child not same as prev match. CheckPatternPredicate, - CheckPredicate, // Fail if node predicate fails. - CheckOpcode, // Fail if not opcode. - SwitchOpcode, // Dispatch based on opcode. - CheckType, // Fail if not correct type. - SwitchType, // Dispatch based on type. - CheckChildType, // Fail if child has wrong type. - CheckInteger, // Fail if wrong val. - CheckChildInteger, // Fail if child is wrong val. - CheckCondCode, // Fail if not condcode. - CheckChild2CondCode, // Fail if child is wrong condcode. + CheckPredicate, // Fail if node predicate fails. + CheckOpcode, // Fail if not opcode. + SwitchOpcode, // Dispatch based on opcode. + CheckType, // Fail if not correct type. + SwitchType, // Dispatch based on type. + CheckChildType, // Fail if child has wrong type. + CheckInteger, // Fail if wrong val. + CheckChildInteger, // Fail if child is wrong val. + CheckCondCode, // Fail if not condcode. + CheckChild2CondCode, // Fail if child is wrong condcode. CheckValueType, CheckComplexPat, CheckAndImm, @@ -342,6 +343,26 @@ class MoveChildMatcher : public Matcher { } }; +/// MoveSiblingMatcher - This tells the interpreter to move into the +/// specified sibling node. +class MoveSiblingMatcher : public Matcher { + unsigned SiblingNo; + +public: + MoveSiblingMatcher(unsigned SiblingNo) + : Matcher(MoveSibling), SiblingNo(SiblingNo) {} + + unsigned getSiblingNo() const { return SiblingNo; } + + static bool classof(const Matcher *N) { return N->getKind() == MoveSibling; } + +private: + void printImpl(raw_ostream &OS, unsigned Indent) const override; + bool isEqualImpl(const Matcher *M) const override { + return cast(M)->getSiblingNo() == getSiblingNo(); + } +}; + /// MoveParentMatcher - This tells the interpreter to move to the parent /// of the current node. class MoveParentMatcher : public Matcher { diff --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp index 2ba57c30046ef..5f96f11279f24 100644 --- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -456,6 +456,17 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx, return (MCM->getChildNo() >= 8) ? 2 : 1; } + case Matcher::MoveSibling: { + const auto *MSM = cast(N); + + OS << "OPC_MoveSibling"; + // Handle the specialized forms. + if (MSM->getSiblingNo() >= 8) + OS << ", "; + OS << MSM->getSiblingNo() << ",\n"; + return (MSM->getSiblingNo() >= 8) ? 2 : 1; + } + case Matcher::MoveParent: OS << "OPC_MoveParent,\n"; return 1; @@ -1128,6 +1139,8 @@ static StringRef getOpcodeString(Matcher::KindTy Kind) { return "OPC_CaptureGlueInput"; case Matcher::MoveChild: return "OPC_MoveChild"; + case Matcher::MoveSibling: + return "OPC_MoveSibling"; case Matcher::MoveParent: return "OPC_MoveParent"; case Matcher::CheckSame: diff --git a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp index bf2a24241e846..c4c25dc1a5fde 100644 --- a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp @@ -155,6 +155,30 @@ static void ContractNodes(std::unique_ptr &MatcherPtr, CheckType->setNext(Tail); return ContractNodes(MatcherPtr, CGP); } + + // If we have a MoveParent followed by a MoveChild, we convert it to + // MoveSibling. + if (auto *MP = dyn_cast(N)) { + if (auto *MC = dyn_cast(MP->getNext())) { + auto *MS = new MoveSiblingMatcher(MC->getChildNo()); + MS->setNext(MC->takeNext()); + MatcherPtr.reset(MS); + return ContractNodes(MatcherPtr, CGP); + } + if (auto *RC = dyn_cast(MP->getNext())) { + if (auto *MC = dyn_cast(RC->getNext())) { + if (RC->getChildNo() == MC->getChildNo()) { + auto *MS = new MoveSiblingMatcher(MC->getChildNo()); + auto *RM = new RecordMatcher(RC->getWhatFor(), RC->getResultNo()); + // Insert the new node. + RM->setNext(MC->takeNext()); + MS->setNext(RM); + MatcherPtr.reset(MS); + return ContractNodes(MatcherPtr, CGP); + } + } + } + } } /// FindNodeWithKind - Scan a series of matchers looking for a matcher with a