OPC_MorphNodeTo,
// Space-optimized forms that implicitly encode number of result VTs.
OPC_MorphNodeTo0, OPC_MorphNodeTo1, OPC_MorphNodeTo2,
- OPC_MarkGlueResults,
OPC_CompleteMatch
};
/// state machines that start with a OPC_SwitchOpcode node.
std::vector<unsigned> OpcodeOffset;
- void UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain,
- const SmallVectorImpl<SDNode*> &ChainNodesMatched,
- SDValue InputGlue, const SmallVectorImpl<SDNode*> &F,
- bool isMorphNodeTo);
-
+ void UpdateChains(SDNode *NodeToMatch, SDValue InputChain,
+ const SmallVectorImpl<SDNode *> &ChainNodesMatched,
+ bool isMorphNodeTo);
};
}
return Val;
}
-/// UpdateChainsAndGlue - When a match is complete, this method updates uses of
-/// interior glue and chain results to use the new glue and chain results.
-void SelectionDAGISel::
-UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain,
- const SmallVectorImpl<SDNode*> &ChainNodesMatched,
- SDValue InputGlue,
- const SmallVectorImpl<SDNode*> &GlueResultNodesMatched,
- bool isMorphNodeTo) {
+/// When a match is complete, this method updates uses of interior chain results
+/// to use the new results.
+void SelectionDAGISel::UpdateChains(
+ SDNode *NodeToMatch, SDValue InputChain,
+ const SmallVectorImpl<SDNode *> &ChainNodesMatched, bool isMorphNodeTo) {
SmallVector<SDNode*, 4> NowDeadNodes;
// Now that all the normal results are replaced, we replace the chain and
}
}
- // If the result produces glue, update any glue results in the matched
- // pattern with the glue result.
- if (InputGlue.getNode()) {
- // Handle any interior nodes explicitly marked.
- for (unsigned i = 0, e = GlueResultNodesMatched.size(); i != e; ++i) {
- SDNode *FRN = GlueResultNodesMatched[i];
-
- // If this node was already deleted, don't look at it.
- if (FRN->getOpcode() == ISD::DELETED_NODE)
- continue;
-
- assert(FRN->getValueType(FRN->getNumValues()-1) == MVT::Glue &&
- "Doesn't have a glue result");
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(FRN, FRN->getNumValues()-1),
- InputGlue);
-
- // If the node became dead and we haven't already seen it, delete it.
- if (FRN->use_empty() &&
- !std::count(NowDeadNodes.begin(), NowDeadNodes.end(), FRN))
- NowDeadNodes.push_back(FRN);
- }
- }
-
if (!NowDeadNodes.empty())
CurDAG->RemoveDeadNodes(NowDeadNodes);
SDValue InputChain, InputGlue;
/// HasChainNodesMatched - True if the ChainNodesMatched list is non-empty.
- bool HasChainNodesMatched, HasGlueResultNodesMatched;
+ bool HasChainNodesMatched;
};
/// \\brief A DAG update listener to keep the matching state
// which ones they are. The result is captured into this list so that we can
// update the chain results when the pattern is complete.
SmallVector<SDNode*, 3> ChainNodesMatched;
- SmallVector<SDNode*, 3> GlueResultNodesMatched;
DEBUG(dbgs() << "ISEL: Starting pattern match on root node: ";
NodeToMatch->dump(CurDAG);
NewEntry.InputChain = InputChain;
NewEntry.InputGlue = InputGlue;
NewEntry.HasChainNodesMatched = !ChainNodesMatched.empty();
- NewEntry.HasGlueResultNodesMatched = !GlueResultNodesMatched.empty();
MatchScopes.push_back(NewEntry);
continue;
}
// If this was a MorphNodeTo then we're completely done!
if (IsMorphNodeTo) {
- // Update chain and glue uses.
- UpdateChainsAndGlue(NodeToMatch, InputChain, ChainNodesMatched,
- InputGlue, GlueResultNodesMatched, true);
+ // Update chain uses.
+ UpdateChains(NodeToMatch, InputChain, ChainNodesMatched, true);
return Res;
}
continue;
}
- case OPC_MarkGlueResults: {
- unsigned NumNodes = MatcherTable[MatcherIndex++];
-
- // Read and remember all the glue-result nodes.
- for (unsigned i = 0; i != NumNodes; ++i) {
- unsigned RecNo = MatcherTable[MatcherIndex++];
- if (RecNo & 128)
- RecNo = GetVBR(RecNo, MatcherTable, MatcherIndex);
-
- assert(RecNo < RecordedNodes.size() && "Invalid MarkGlueResults");
- GlueResultNodesMatched.push_back(RecordedNodes[RecNo].first.getNode());
- }
- 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
CurDAG->ReplaceAllUsesOfValueWith(SDValue(NodeToMatch, i), Res);
}
- // If the root node defines glue, add it to the glue nodes to update list.
- if (NodeToMatch->getValueType(NodeToMatch->getNumValues()-1) == MVT::Glue)
- GlueResultNodesMatched.push_back(NodeToMatch);
+ // Update chain uses.
+ UpdateChains(NodeToMatch, InputChain, ChainNodesMatched, false);
- // Update chain and glue uses.
- UpdateChainsAndGlue(NodeToMatch, InputChain, ChainNodesMatched,
- InputGlue, GlueResultNodesMatched, false);
+ // If the root node defines glue, we need to update it to the glue result.
+ // TODO: This never happens in our tests and I think it can be removed /
+ // replaced with an assert, but if we do it this the way the change is
+ // NFC.
+ if (NodeToMatch->getValueType(NodeToMatch->getNumValues() - 1) ==
+ MVT::Glue &&
+ InputGlue.getNode())
+ CurDAG->ReplaceAllUsesOfValueWith(
+ SDValue(NodeToMatch, NodeToMatch->getNumValues() - 1), InputGlue);
assert(NodeToMatch->use_empty() &&
"Didn't replace all uses of the node?");
InputGlue = LastScope.InputGlue;
if (!LastScope.HasChainNodesMatched)
ChainNodesMatched.clear();
- if (!LastScope.HasGlueResultNodesMatched)
- GlueResultNodesMatched.clear();
// Check to see what the offset is at the new MatcherIndex. If it is zero
// we have reached the end of this scope, otherwise we have another child
OS << ")\n";
}
-void MarkGlueResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
- OS.indent(indent) << "MarkGlueResults <todo: args>\n";
-}
-
void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CompleteMatch <todo args>\n";
OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n";
void MorphNodeToMatcher::anchor() { }
-unsigned MarkGlueResultsMatcher::getHashImpl() const {
- return HashUnsigneds(GlueResultNodes.begin(), GlueResultNodes.end());
-}
-
unsigned CompleteMatchMatcher::getHashImpl() const {
return HashUnsigneds(Results.begin(), Results.end()) ^
((unsigned)(intptr_t)&Pattern << 8);
EmitCopyToReg, // Emit a copytoreg into a physreg.
EmitNode, // Create a DAG node
EmitNodeXForm, // Run a SDNodeXForm
- MarkGlueResults, // Indicate which interior nodes have glue results.
CompleteMatch, // Finish a match and update the results.
MorphNodeTo // Build a node, finish a match and update results.
};
}
};
-/// MarkGlueResultsMatcher - This node indicates which non-root nodes in the
-/// pattern produce glue. This allows CompleteMatchMatcher to update them
-/// with the output glue of the resultant code.
-class MarkGlueResultsMatcher : public Matcher {
- SmallVector<unsigned, 3> GlueResultNodes;
-public:
- MarkGlueResultsMatcher(ArrayRef<unsigned> nodes)
- : Matcher(MarkGlueResults), GlueResultNodes(nodes.begin(), nodes.end()) {}
-
- unsigned getNumNodes() const { return GlueResultNodes.size(); }
-
- unsigned getNode(unsigned i) const {
- assert(i < GlueResultNodes.size());
- return GlueResultNodes[i];
- }
-
- static inline bool classof(const Matcher *N) {
- return N->getKind() == MarkGlueResults;
- }
-
-private:
- void printImpl(raw_ostream &OS, unsigned indent) const override;
- bool isEqualImpl(const Matcher *M) const override {
- return cast<MarkGlueResultsMatcher>(M)->GlueResultNodes == GlueResultNodes;
- }
- unsigned getHashImpl() const override;
-};
-
/// CompleteMatchMatcher - 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.
return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes;
}
- case Matcher::MarkGlueResults: {
- const MarkGlueResultsMatcher *CFR = cast<MarkGlueResultsMatcher>(N);
- OS << "OPC_MarkGlueResults, " << CFR->getNumNodes() << ", ";
- unsigned NumOperandBytes = 0;
- for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i)
- NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS);
- OS << '\n';
- return 2+NumOperandBytes;
- }
case Matcher::CompleteMatch: {
const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
case Matcher::EmitNode: OS << "OPC_EmitNode"; break;
case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break;
case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break;
- case Matcher::MarkGlueResults: OS << "OPC_MarkGlueResults"; break;
case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break;
}
/// array of all of the recorded input nodes that have chains.
SmallVector<unsigned, 2> MatchedChainNodes;
- /// MatchedGlueResultNodes - This maintains the position in the recorded
- /// nodes array of all of the recorded input nodes that have glue results.
- SmallVector<unsigned, 2> MatchedGlueResultNodes;
-
/// MatchedComplexPatterns - This maintains a list of all of the
/// ComplexPatterns that we need to check. The second element of each pair
/// is the recorded operand number of the input node.
AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
"' glue output node",
NextRecordedOperandNo));
- // Remember all of the nodes with output glue our pattern will match.
- MatchedGlueResultNodes.push_back(NextRecordedOperandNo++);
}
// If this node is known to have an input glue or if it *might* have an input
assert(Ops.size() >= NumSrcResults && "Didn't provide enough results");
Ops.resize(NumSrcResults);
- // If the matched pattern covers nodes which define a glue result, emit a node
- // that tells the matcher about them so that it can update their results.
- if (!MatchedGlueResultNodes.empty())
- AddMatcher(new MarkGlueResultsMatcher(MatchedGlueResultNodes));
-
AddMatcher(new CompleteMatchMatcher(Ops, Pattern));
}
return ContractNodes(MatcherPtr, CGP);
}
- // Turn EmitNode->MarkFlagResults->CompleteMatch into
- // MarkFlagResults->EmitNode->CompleteMatch when we can to encourage
- // MorphNodeTo formation. This is safe because MarkFlagResults never refers
- // to the root of the pattern.
- if (isa<EmitNodeMatcher>(N) && isa<MarkGlueResultsMatcher>(N->getNext()) &&
- isa<CompleteMatchMatcher>(N->getNext()->getNext())) {
- // Unlink the two nodes from the list.
- Matcher *EmitNode = MatcherPtr.release();
- Matcher *MFR = EmitNode->takeNext();
- Matcher *Tail = MFR->takeNext();
-
- // Relink them.
- MatcherPtr.reset(MFR);
- MFR->setNext(EmitNode);
- EmitNode->setNext(Tail);
- return ContractNodes(MatcherPtr, CGP);
- }
-
// Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))
if (CompleteMatchMatcher *CM =