More constification of things. More comments added. No functionality
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeTypes.cpp
index f843957fd2170c3f6a225b7af124139e040e79f1..3d419552826b16552b0abe0fce033007d7a5ca6d 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by Chris Lattner and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
 #include "LegalizeTypes.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MathExtras.h"
 using namespace llvm;
 
+#ifndef NDEBUG
+static cl::opt<bool>
+ViewLegalizeTypesDAGs("view-legalize-types-dags", cl::Hidden,
+                cl::desc("Pop up a window to show dags before legalize types"));
+#else
+static const bool ViewLegalizeTypesDAGs = 0;
+#endif
+
+
+
 /// run - This is the main entry point for the type legalizer.  This does a
 /// top-down traversal of the dag, legalizing types as it goes.
 void DAGTypeLegalizer::run() {
@@ -68,8 +79,8 @@ void DAGTypeLegalizer::run() {
           ExpandResult(N, i);
         else if (MVT::getVectorNumElements(ResultVT) == 1)
           ScalarizeResult(N, i);     // Scalarize the single-element vector.
-        else         // Split the vector in half.
-          assert(0 && "Vector splitting not implemented");
+        else
+          SplitResult(N, i);         // Split the vector in half.
         goto NodeDone;
       } else {
         assert(Action == Legal && "Unknown action!");
@@ -96,8 +107,7 @@ void DAGTypeLegalizer::run() {
           // Scalarize the single-element vector.
           NeedsRevisit = ScalarizeOperand(N, i);
         } else {
-          // Split the vector in half.
-          assert(0 && "Vector splitting not implemented");
+          NeedsRevisit = SplitOperand(N, i); // Split the vector in half.
         }
         break;
       } else {
@@ -207,6 +217,35 @@ void DAGTypeLegalizer::MarkNewNodes(SDNode *N) {
     Worklist.push_back(N);
 }
 
+namespace {
+  /// NodeUpdateListener - This class is a DAGUpdateListener that listens for
+  /// updates to nodes and recomputes their ready state.
+  class VISIBILITY_HIDDEN NodeUpdateListener :
+    public SelectionDAG::DAGUpdateListener {
+    DAGTypeLegalizer &DTL;
+  public:
+    NodeUpdateListener(DAGTypeLegalizer &dtl) : DTL(dtl) {}
+
+    virtual void NodeDeleted(SDNode *N) {
+      // Ignore deletes.
+      assert(N->getNodeId() != DAGTypeLegalizer::Processed &&
+             N->getNodeId() != DAGTypeLegalizer::ReadyToProcess &&
+             "RAUW deleted processed node!");
+    }
+
+    virtual void NodeUpdated(SDNode *N) {
+      // Node updates can mean pretty much anything.  It is possible that an
+      // operand was set to something already processed (f.e.) in which case
+      // this node could become ready.  Recompute its flags.
+      assert(N->getNodeId() != DAGTypeLegalizer::Processed &&
+             N->getNodeId() != DAGTypeLegalizer::ReadyToProcess &&
+             "RAUW updated processed node!");
+      DTL.ReanalyzeNodeFlags(N);
+    }
+  };
+}
+
+
 /// ReplaceValueWith - The specified value was legalized to the specified other
 /// value.  If they are different, update the DAG and NodeIDs replacing any uses
 /// of From to use To instead.
@@ -219,26 +258,12 @@ void DAGTypeLegalizer::ReplaceValueWith(SDOperand From, SDOperand To) {
   
   // Anything that used the old node should now use the new one.  Note that this
   // can potentially cause recursive merging.
-  DAG.ReplaceAllUsesOfValueWith(From, To);
+  NodeUpdateListener NUL(*this);
+  DAG.ReplaceAllUsesOfValueWith(From, To, &NUL);
 
   // The old node may still be present in ExpandedNodes or PromotedNodes.
   // Inform them about the replacement.
   ReplacedNodes[From] = To;
-
-  // Since we just made an unstructured update to the DAG, which could wreak
-  // general havoc on anything that once used From and now uses To, walk all
-  // users of the result, updating their flags.
-  for (SDNode::use_iterator I = To.Val->use_begin(), E = To.Val->use_end();
-       I != E; ++I) {
-    SDNode *User = *I;
-    // If the node isn't already processed or in the worklist, mark it as new,
-    // then use MarkNewNodes to recompute its ID.
-    int NodeId = User->getNodeId();
-    if (NodeId != ReadyToProcess && NodeId != Processed) {
-      User->setNodeId(NewNode);
-      MarkNewNodes(User);
-    }
-  }
 }
 
 /// ReplaceNodeWith - Replace uses of the 'from' node's results with the 'to'
@@ -254,7 +279,8 @@ void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) {
   
   // Anything that used the old node should now use the new one.  Note that this
   // can potentially cause recursive merging.
-  DAG.ReplaceAllUsesWith(From, To);
+  NodeUpdateListener NUL(*this);
+  DAG.ReplaceAllUsesWith(From, To, &NUL);
   
   // The old node may still be present in ExpandedNodes or PromotedNodes.
   // Inform them about the replacement.
@@ -263,20 +289,6 @@ void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) {
            "Node results don't match");
     ReplacedNodes[SDOperand(From, i)] = SDOperand(To, i);
   }
-  
-  // Since we just made an unstructured update to the DAG, which could wreak
-  // general havoc on anything that once used From and now uses To, walk all
-  // users of the result, updating their flags.
-  for (SDNode::use_iterator I = To->use_begin(), E = To->use_end();I != E; ++I){
-    SDNode *User = *I;
-    // If the node isn't already processed or in the worklist, mark it as new,
-    // then use MarkNewNodes to recompute its ID.
-    int NodeId = User->getNodeId();
-    if (NodeId != ReadyToProcess && NodeId != Processed) {
-      User->setNodeId(NewNode);
-      MarkNewNodes(User);
-    }
-  }
 }
 
 
@@ -321,8 +333,7 @@ void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo,
   Hi = Entry.second;
 }
 
-void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, 
-                                     SDOperand Hi) {
+void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
   // Remember that this is the result of the node.
   std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
   assert(Entry.first.Val == 0 && "Node already expanded");
@@ -336,6 +347,30 @@ void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo,
     MarkNewNodes(Hi.Val);
 }
 
+void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
+  std::pair<SDOperand, SDOperand> &Entry = SplitNodes[Op];
+  RemapNode(Entry.first);
+  RemapNode(Entry.second);
+  assert(Entry.first.Val && "Operand isn't split");
+  Lo = Entry.first;
+  Hi = Entry.second;
+}
+
+void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
+  // Remember that this is the result of the node.
+  std::pair<SDOperand, SDOperand> &Entry = SplitNodes[Op];
+  assert(Entry.first.Val == 0 && "Node already split");
+  Entry.first = Lo;
+  Entry.second = Hi;
+  
+  // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant.
+  if (Lo.Val->getNodeId() == NewNode) 
+    MarkNewNodes(Lo.Val);
+  if (Hi.Val->getNodeId() == NewNode) 
+    MarkNewNodes(Hi.Val);
+}
+
+
 SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, 
                                                  MVT::ValueType DestVT) {
   // Create the stack frame object.
@@ -416,5 +451,7 @@ void DAGTypeLegalizer::SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
 /// Note that this is an involved process that may invalidate pointers into
 /// the graph.
 void SelectionDAG::LegalizeTypes() {
+  if (ViewLegalizeTypesDAGs) viewGraph();
+  
   DAGTypeLegalizer(*this).run();
 }