implement the last known missing feature: updating uses of results
authorChris Lattner <sabre@nondot.org>
Sun, 21 Feb 2010 06:03:07 +0000 (06:03 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 21 Feb 2010 06:03:07 +0000 (06:03 +0000)
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
utils/TableGen/DAGISelEmitter.cpp
utils/TableGen/DAGISelMatcher.cpp
utils/TableGen/DAGISelMatcher.h
utils/TableGen/DAGISelMatcherEmitter.cpp
utils/TableGen/DAGISelMatcherGen.cpp

index 41e3b2fb0a1d258025cbccddfb6f5b5de7c56d9e..9acd406792784ca9b62d916a7bc948d1922e9bb7 100644 (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
index 55a9d36588cc317bf6026e8539753564f98547bb..d0da11479c30627a6f694249701789e42f717d6d 100644 (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.
index eaaaefb3ab76dbe525b412dd2a95284df3037108..b3c846c9cef11386a39d04cdbcd78b6bd08bbda6 100644 (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);
index 4dcb4d6af7197e3fd16b6761b7d4b06aa6a10ed6..c162a0cbaa503d5755732c57f8c8bf3b3933f205 100644 (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;
 
@@ -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<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;
index 077dd5df4dd082409c2dbe3f33dcb860ea0a7858..de17005576bce2dfcc03f6680dec6d82df5e3f31 100644 (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';
-    OS.PadToColumn(Indent*2) << "// Dst: "
-    << *cast<PatternMarkerMatcherNode>(N)->getPattern().getDstPattern() << '\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: " 
+      << *CM->getPattern().getDstPattern() << '\n';
     return 0;
   }
+  }
   assert(0 && "Unreachable");
   return 0;
 }
index 693c4ccf8d3cbc4f274f2ad1a1e6f04d39cd8ff2..b22fa875e0609e4f6eecec2cf1e748e07b6918e2 100644 (file)
@@ -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));
 }