From 77f2e2724dc488bbf032e87f8f25f333730a0fb5 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 21 Feb 2010 06:03:07 +0000 Subject: [PATCH] implement the last known missing feature: updating uses of results of the matched pattern to use the newly created node results. Onto the "making it actually work" phase! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@96724 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/DAGISelHeader.h | 62 +++++++++++++++++++----- utils/TableGen/DAGISelEmitter.cpp | 2 +- utils/TableGen/DAGISelMatcher.cpp | 3 +- utils/TableGen/DAGISelMatcher.h | 24 +++++---- utils/TableGen/DAGISelMatcherEmitter.cpp | 16 ++++-- utils/TableGen/DAGISelMatcherGen.cpp | 8 +-- 6 files changed, 84 insertions(+), 31 deletions(-) diff --git a/include/llvm/CodeGen/DAGISelHeader.h b/include/llvm/CodeGen/DAGISelHeader.h index 41e3b2fb0a1..9acd4067927 100644 --- a/include/llvm/CodeGen/DAGISelHeader.h +++ b/include/llvm/CodeGen/DAGISelHeader.h @@ -101,7 +101,8 @@ void SelectRoot(SelectionDAG &DAG) { // a reference to the root node, preventing it from being deleted, // and tracking any changes of the root. HandleSDNode Dummy(CurDAG->getRoot()); - ISelPosition = llvm::next(SelectionDAG::allnodes_iterator(CurDAG->getRoot().getNode())); + ISelPosition = SelectionDAG::allnodes_iterator(CurDAG->getRoot().getNode()); + ++ISelPosition; // The AllNodes list is now topological-sorted. Visit the // nodes by starting at the end of the list (the root of the @@ -114,21 +115,15 @@ void SelectRoot(SelectionDAG &DAG) { // makes it theoretically possible to disable the DAGCombiner. if (Node->use_empty()) continue; -#if 0 - DAG.setSubgraphColor(Node, "red"); -#endif + SDNode *ResNode = Select(Node); // If node should not be replaced, continue with the next one. if (ResNode == Node) continue; // Replace node. - if (ResNode) { -#if 0 - DAG.setSubgraphColor(ResNode, "yellow"); - DAG.setSubgraphColor(ResNode, "black"); -#endif + if (ResNode) ReplaceUses(Node, ResNode); - } + // If after the replacement this node is not used any more, // remove this dead node. if (Node->use_empty()) { // Don't delete EntryToken, etc. @@ -232,7 +227,8 @@ enum BuiltinOpcodes { OPC_EmitMergeInputChains, OPC_EmitCopyToReg, OPC_EmitNodeXForm, - OPC_EmitNode + OPC_EmitNode, + OPC_CompleteMatch }; enum { @@ -572,6 +568,7 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, if (NumChains == 1) { unsigned RecNo = MatcherTable[MatcherIndex++]; assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + ChainNodesMatched.push_back(RecordedNodes[RecNo].getNode()); InputChain = RecordedNodes[RecNo].getOperand(0); assert(InputChain.getValueType() == MVT::Other && "Not a chain"); continue; @@ -707,6 +704,49 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, } continue; } + + case OPC_CompleteMatch: { + // The match has been completed, and any new nodes (if any) have been + // created. Patch up references to the matched dag to use the newly + // created nodes. + unsigned NumResults = MatcherTable[MatcherIndex++]; + + for (unsigned i = 0; i != NumResults; ++i) { + unsigned ResSlot = MatcherTable[MatcherIndex++]; + assert(ResSlot < RecordedNodes.size() && "Invalid CheckSame"); + SDValue Res = RecordedNodes[ResSlot]; + assert(NodeToMatch->getValueType(i) == Res.getValueType() && + "invalid replacement"); + ReplaceUses(SDValue(NodeToMatch, i), Res); + } + + // Now that all the normal results are replaced, we replace the chain and + // flag results if present. + if (!ChainNodesMatched.empty()) { + assert(InputChain.getNode() != 0 && + "Matched input chains but didn't produce a chain"); + // Loop over all of the nodes we matched that produced a chain result. + // Replace all the chain results with the final chain we ended up with. + for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { + SDNode *ChainNode = ChainNodesMatched[i]; + SDValue ChainVal = SDValue(ChainNode, ChainNode->getNumValues()-1); + if (ChainVal.getValueType() == MVT::Flag) + ChainVal = ChainVal.getValue(ChainVal->getNumValues()-2); + assert(ChainVal.getValueType() == MVT::Other && "Not a chain?"); + ReplaceUses(ChainVal, InputChain); + } + } + // If the root node produces a flag, make sure to replace its flag + // result with the resultant flag. + if (NodeToMatch->getValueType(NodeToMatch->getNumValues()-1) == + MVT::Flag) + ReplaceUses(SDValue(NodeToMatch, NodeToMatch->getNumValues()-1), + InputFlag); + + // FIXME: We just return here, which interacts correctly with SelectRoot + // above. We should fix this to not return an SDNode* anymore. + return 0; + } } // If the code reached this point, then the match failed pop out to the next diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 55a9d36588c..d0da11479c3 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -1917,7 +1917,7 @@ void DAGISelEmitter::run(raw_ostream &OS) { // definitions. Emit the resultant instruction selector. EmitInstructionSelector(OS); -#if 0 +#if 1 MatcherNode *Matcher = 0; // Walk the patterns backwards, building a matcher for each and adding it to // the matcher for the whole target. diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index eaaaefb3ab7..b3c846c9cef 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -180,7 +180,8 @@ void EmitNodeMatcherNode::print(raw_ostream &OS, unsigned indent) const { printNext(OS, indent); } -void PatternMarkerMatcherNode::print(raw_ostream &OS, unsigned indent) const { +void CompleteMatchMatcherNode::print(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CompleteMatch \n"; OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n"; OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n"; printNext(OS, indent); diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index 4dcb4d6af71..c162a0cbaa5 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -70,7 +70,7 @@ public: EmitCopyToReg, // Emit a copytoreg into a physreg. EmitNode, // Create a DAG node EmitNodeXForm, // Run a SDNodeXForm - PatternMarker // Comment for printing. + CompleteMatch // Finish a match and update the results. }; const KindTy Kind; @@ -601,19 +601,25 @@ public: virtual void print(raw_ostream &OS, unsigned indent = 0) const; }; - -/// PatternMarkerMatcherNode - This prints as a comment indicating the source -/// and dest patterns. -class PatternMarkerMatcherNode : public MatcherNode { + +/// CompleteMatchMatcherNode - Complete a match by replacing the results of the +/// pattern with the newly generated nodes. This also prints a comment +/// indicating the source and dest patterns. +class CompleteMatchMatcherNode : public MatcherNode { + SmallVector Results; const PatternToMatch &Pattern; public: - PatternMarkerMatcherNode(const PatternToMatch &pattern) - : MatcherNode(PatternMarker), Pattern(pattern) {} - + CompleteMatchMatcherNode(const unsigned *results, unsigned numresults, + const PatternToMatch &pattern) + : MatcherNode(CompleteMatch), Results(results, results+numresults), + Pattern(pattern) {} + + unsigned getNumResults() const { return Results.size(); } + unsigned getResult(unsigned R) const { return Results[R]; } const PatternToMatch &getPattern() const { return Pattern; } static inline bool classof(const MatcherNode *N) { - return N->getKind() == PatternMarker; + return N->getKind() == CompleteMatch; } virtual void print(raw_ostream &OS, unsigned indent = 0) const; diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 077dd5df4dd..de17005576b 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -305,13 +305,19 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) { OS << '\n'; return 5+EN->getNumVTs()+EN->getNumOperands(); } - case MatcherNode::PatternMarker: - OS << "// Src: " - << *cast(N)->getPattern().getSrcPattern() << '\n'; - OS.PadToColumn(Indent*2) << "// Dst: " - << *cast(N)->getPattern().getDstPattern() << '\n'; + case MatcherNode::CompleteMatch: { + const CompleteMatchMatcherNode *CM = cast(N); + OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", "; + for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i) + OS << CM->getResult(i) << ", "; + OS << '\n'; + OS.PadToColumn(Indent*2) << "// Src: " + << *CM->getPattern().getSrcPattern() << '\n'; + OS.PadToColumn(Indent*2) << "// Dst: " + << *CM->getPattern().getDstPattern() << '\n'; return 0; } + } assert(0 && "Unreachable"); return 0; } diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 693c4ccf8d3..b22fa875e06 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -723,8 +723,8 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // The newly emitted node gets recorded. // FIXME2: This should record all of the results except the (implicit) one. - OutputOps.push_back(NextRecordedOperandNo++); - + if (ResultVTs[0] != MVT::Other) + OutputOps.push_back(NextRecordedOperandNo++); // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode // variants. Call MorphNodeTo instead of SelectNodeTo. @@ -776,11 +776,11 @@ void MatcherGen::EmitResultCode() { // We know that the resulting pattern has exactly one result/ // FIXME2: why? what about something like (set a,b,c, (complexpat)) // FIXME2: Implicit results should be pushed here I guess? - assert(Ops.size() == 1); + assert(Ops.size() <= 1); // FIXME: Handle Ops. // FIXME: Handle (set EAX, (foo)) but not (implicit EFLAGS) - AddMatcherNode(new PatternMarkerMatcherNode(Pattern)); + AddMatcherNode(new CompleteMatchMatcherNode(Ops.data(), Ops.size(), Pattern)); }