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,
// 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

View File

@ -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.

View File

@ -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 <todo args>\n";
OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n";
OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n";
printNext(OS, indent);

View File

@ -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;
@ -602,18 +602,24 @@ 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<unsigned, 2> 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;

View File

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

View File

@ -723,9 +723,9 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// The newly emitted node gets recorded.
// FIXME2: This should record all of the results except the (implicit) one.
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));
}