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
This commit is contained in:
Chris Lattner 2010-02-21 06:03:07 +00:00
parent f1c6428164
commit 77f2e2724d
6 changed files with 84 additions and 31 deletions

View File

@ -101,7 +101,8 @@ void SelectRoot(SelectionDAG &DAG) {
// a reference to the root node, preventing it from being deleted, // a reference to the root node, preventing it from being deleted,
// and tracking any changes of the root. // and tracking any changes of the root.
HandleSDNode Dummy(CurDAG->getRoot()); 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 // The AllNodes list is now topological-sorted. Visit the
// nodes by starting at the end of the list (the root of 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. // makes it theoretically possible to disable the DAGCombiner.
if (Node->use_empty()) if (Node->use_empty())
continue; continue;
#if 0
DAG.setSubgraphColor(Node, "red");
#endif
SDNode *ResNode = Select(Node); SDNode *ResNode = Select(Node);
// If node should not be replaced, continue with the next one. // If node should not be replaced, continue with the next one.
if (ResNode == Node) if (ResNode == Node)
continue; continue;
// Replace node. // Replace node.
if (ResNode) { if (ResNode)
#if 0
DAG.setSubgraphColor(ResNode, "yellow");
DAG.setSubgraphColor(ResNode, "black");
#endif
ReplaceUses(Node, ResNode); ReplaceUses(Node, ResNode);
}
// If after the replacement this node is not used any more, // If after the replacement this node is not used any more,
// remove this dead node. // remove this dead node.
if (Node->use_empty()) { // Don't delete EntryToken, etc. if (Node->use_empty()) { // Don't delete EntryToken, etc.
@ -232,7 +227,8 @@ enum BuiltinOpcodes {
OPC_EmitMergeInputChains, OPC_EmitMergeInputChains,
OPC_EmitCopyToReg, OPC_EmitCopyToReg,
OPC_EmitNodeXForm, OPC_EmitNodeXForm,
OPC_EmitNode OPC_EmitNode,
OPC_CompleteMatch
}; };
enum { enum {
@ -572,6 +568,7 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
if (NumChains == 1) { if (NumChains == 1) {
unsigned RecNo = MatcherTable[MatcherIndex++]; unsigned RecNo = MatcherTable[MatcherIndex++];
assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); assert(RecNo < RecordedNodes.size() && "Invalid CheckSame");
ChainNodesMatched.push_back(RecordedNodes[RecNo].getNode());
InputChain = RecordedNodes[RecNo].getOperand(0); InputChain = RecordedNodes[RecNo].getOperand(0);
assert(InputChain.getValueType() == MVT::Other && "Not a chain"); assert(InputChain.getValueType() == MVT::Other && "Not a chain");
continue; continue;
@ -707,6 +704,49 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
} }
continue; 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 // If the code reached this point, then the match failed pop out to the next

View File

@ -1917,7 +1917,7 @@ void DAGISelEmitter::run(raw_ostream &OS) {
// definitions. Emit the resultant instruction selector. // definitions. Emit the resultant instruction selector.
EmitInstructionSelector(OS); EmitInstructionSelector(OS);
#if 0 #if 1
MatcherNode *Matcher = 0; MatcherNode *Matcher = 0;
// Walk the patterns backwards, building a matcher for each and adding it to // Walk the patterns backwards, building a matcher for each and adding it to
// the matcher for the whole target. // the matcher for the whole target.

View File

@ -180,7 +180,8 @@ void EmitNodeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
printNext(OS, indent); 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 <todo args>\n";
OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n"; OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n";
OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n"; OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n";
printNext(OS, indent); printNext(OS, indent);

View File

@ -70,7 +70,7 @@ public:
EmitCopyToReg, // Emit a copytoreg into a physreg. EmitCopyToReg, // Emit a copytoreg into a physreg.
EmitNode, // Create a DAG node EmitNode, // Create a DAG node
EmitNodeXForm, // Run a SDNodeXForm EmitNodeXForm, // Run a SDNodeXForm
PatternMarker // Comment for printing. CompleteMatch // Finish a match and update the results.
}; };
const KindTy Kind; const KindTy Kind;
@ -601,19 +601,25 @@ public:
virtual void print(raw_ostream &OS, unsigned indent = 0) const; virtual void print(raw_ostream &OS, unsigned indent = 0) const;
}; };
/// PatternMarkerMatcherNode - This prints as a comment indicating the source /// CompleteMatchMatcherNode - Complete a match by replacing the results of the
/// and dest patterns. /// pattern with the newly generated nodes. This also prints a comment
class PatternMarkerMatcherNode : public MatcherNode { /// indicating the source and dest patterns.
class CompleteMatchMatcherNode : public MatcherNode {
SmallVector<unsigned, 2> Results;
const PatternToMatch &Pattern; const PatternToMatch &Pattern;
public: public:
PatternMarkerMatcherNode(const PatternToMatch &pattern) CompleteMatchMatcherNode(const unsigned *results, unsigned numresults,
: MatcherNode(PatternMarker), Pattern(pattern) {} 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; } const PatternToMatch &getPattern() const { return Pattern; }
static inline bool classof(const MatcherNode *N) { 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; virtual void print(raw_ostream &OS, unsigned indent = 0) const;

View File

@ -305,13 +305,19 @@ EmitMatcher(const MatcherNode *N, unsigned Indent) {
OS << '\n'; OS << '\n';
return 5+EN->getNumVTs()+EN->getNumOperands(); return 5+EN->getNumVTs()+EN->getNumOperands();
} }
case MatcherNode::PatternMarker: case MatcherNode::CompleteMatch: {
OS << "// Src: " const CompleteMatchMatcherNode *CM = cast<CompleteMatchMatcherNode>(N);
<< *cast<PatternMarkerMatcherNode>(N)->getPattern().getSrcPattern() << '\n'; OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
OS.PadToColumn(Indent*2) << "// Dst: " for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
<< *cast<PatternMarkerMatcherNode>(N)->getPattern().getDstPattern() << '\n'; 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; return 0;
} }
}
assert(0 && "Unreachable"); assert(0 && "Unreachable");
return 0; return 0;
} }

View File

@ -723,8 +723,8 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// The newly emitted node gets recorded. // The newly emitted node gets recorded.
// FIXME2: This should record all of the results except the (implicit) one. // 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 // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode
// variants. Call MorphNodeTo instead of SelectNodeTo. // variants. Call MorphNodeTo instead of SelectNodeTo.
@ -776,11 +776,11 @@ void MatcherGen::EmitResultCode() {
// We know that the resulting pattern has exactly one result/ // We know that the resulting pattern has exactly one result/
// FIXME2: why? what about something like (set a,b,c, (complexpat)) // FIXME2: why? what about something like (set a,b,c, (complexpat))
// FIXME2: Implicit results should be pushed here I guess? // FIXME2: Implicit results should be pushed here I guess?
assert(Ops.size() == 1); assert(Ops.size() <= 1);
// FIXME: Handle Ops. // FIXME: Handle Ops.
// FIXME: Handle (set EAX, (foo)) but not (implicit EFLAGS) // FIXME: Handle (set EAX, (foo)) but not (implicit EFLAGS)
AddMatcherNode(new PatternMarkerMatcherNode(Pattern)); AddMatcherNode(new CompleteMatchMatcherNode(Ops.data(), Ops.size(), Pattern));
} }