Split EVT into MVT and EVT, the former representing _just_ a primitive type, while
[oota-llvm.git] / include / llvm / CodeGen / DAGISelHeader.h
index 3ac9affb357437c5889530587ab56388844c1d4e..b2acbc174559c7a4eca81fcf080ef11818988b9f 100644 (file)
 // data, which is used by SelectionDAG-based instruction selectors.
 //
 // *** NOTE: This file is #included into the middle of the target
-// *** instruction selector class.  These functions are really methods.
+// instruction selector class.  These functions are really methods.
+// This is a little awkward, but it allows this code to be shared
+// by all the targets while still being able to call into
+// target-specific code without using a virtual function call.
+//
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CODEGEN_DAGISEL_HEADER_H
 #define LLVM_CODEGEN_DAGISEL_HEADER_H
 
-/// ISelQueue - Instruction selector priority queue sorted 
-/// in the order of increasing NodeId() values.
-std::vector<SDNode*> ISelQueue;
-
-/// Keep track of nodes which have already been added to queue.
-unsigned char *ISelQueued;
-
-/// Keep track of nodes which have already been selected.
-unsigned char *ISelSelected;
+/// ISelPosition - Node iterator marking the current position of
+/// instruction selection as it procedes through the topologically-sorted
+/// node list.
+SelectionDAG::allnodes_iterator ISelPosition;
 
 /// IsChainCompatible - Returns true if Chain is Op or Chain does
 /// not reach Op.
 static bool IsChainCompatible(SDNode *Chain, SDNode *Op) {
   if (Chain->getOpcode() == ISD::EntryToken)
     return true;
-  else if (Chain->getOpcode() == ISD::TokenFactor)
+  if (Chain->getOpcode() == ISD::TokenFactor)
     return false;
-  else if (Chain->getNumOperands() > 0) {
-    SDOperand C0 = Chain->getOperand(0);
+  if (Chain->getNumOperands() > 0) {
+    SDValue C0 = Chain->getOperand(0);
     if (C0.getValueType() == MVT::Other)
-      return C0.Val != Op && IsChainCompatible(C0.Val, Op);
+      return C0.getNode() != Op && IsChainCompatible(C0.getNode(), Op);
   }
   return true;
 }
 
-/// isel_sort - Sorting functions for the selection queue in the
-/// increasing NodeId order.
-struct isel_sort : public std::binary_function<SDNode*, SDNode*, bool> {
-  bool operator()(const SDNode* left, const SDNode* right) const {
-    return (left->getNodeId() > right->getNodeId());
+/// ISelUpdater - helper class to handle updates of the 
+/// instruciton selection graph.
+class VISIBILITY_HIDDEN ISelUpdater : public SelectionDAG::DAGUpdateListener {
+  SelectionDAG::allnodes_iterator &ISelPosition;
+public:
+  explicit ISelUpdater(SelectionDAG::allnodes_iterator &isp)
+    : ISelPosition(isp) {}
+  
+  /// NodeDeleted - Handle nodes deleted from the graph. If the
+  /// node being deleted is the current ISelPosition node, update
+  /// ISelPosition.
+  ///
+  virtual void NodeDeleted(SDNode *N, SDNode *E) {
+    if (ISelPosition == SelectionDAG::allnodes_iterator(N))
+      ++ISelPosition;
   }
-};
-
-/// setQueued - marks the node with a given NodeId() as element of the 
-/// instruction selection queue.
-inline void setQueued(int Id) {
-  ISelQueued[Id / 8] |= 1 << (Id % 8);
-}
-
-/// isSelected - checks if the node with a given NodeId() is
-/// in the instruction selection queue already.
-inline bool isQueued(int Id) {
-  return ISelQueued[Id / 8] & (1 << (Id % 8));
-}
-
-/// setSelected - marks the node with a given NodeId() as selected.
-inline void setSelected(int Id) {
-  ISelSelected[Id / 8] |= 1 << (Id % 8);
-}
-
-/// isSelected - checks if the node with a given NodeId() is
-/// selected already.
-inline bool isSelected(int Id) {
-  return ISelSelected[Id / 8] & (1 << (Id % 8));
-}
-
-/// AddToISelQueue - adds a node to the instruction 
-/// selection queue.
-void AddToISelQueue(SDOperand N) DISABLE_INLINE {
-  int Id = N.Val->getNodeId();
-  if (Id != -1 && !isQueued(Id)) {
-    ISelQueue.push_back(N.Val);
-    std::push_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());
-    setQueued(Id);
-  }
-}
-
-/// ISelQueueUpdater - helper class to handle updates of the 
-/// instruciton selection queue.
-class VISIBILITY_HIDDEN ISelQueueUpdater :
-  public SelectionDAG::DAGUpdateListener {
-    std::vector<SDNode*> &ISelQueue;
-    bool HadDelete; // Indicate if any deletions were done.
-  public:
-    explicit ISelQueueUpdater(std::vector<SDNode*> &isq)
-      : ISelQueue(isq), HadDelete(false) {}
-    
-    bool hadDelete() const { return HadDelete; }
-
-    /// NodeDeleted - remove node from the selection queue.
-    virtual void NodeDeleted(SDNode *N, SDNode *E) {
-      ISelQueue.erase(std::remove(ISelQueue.begin(), ISelQueue.end(), N),
-                      ISelQueue.end());
-      HadDelete = true;
-    }
-
-    /// NodeUpdated - Ignore updates for now.
-    virtual void NodeUpdated(SDNode *N) {}
-  };
-
-/// UpdateQueue - update the instruction selction queue to maintain 
-/// the increasing NodeId() ordering property.
-inline void UpdateQueue(const ISelQueueUpdater &ISQU) {
-  if (ISQU.hadDelete())
-    std::make_heap(ISelQueue.begin(), ISelQueue.end(),isel_sort());
-}
 
+  /// NodeUpdated - Ignore updates for now.
+  virtual void NodeUpdated(SDNode *N) {}
+};
 
 /// ReplaceUses - replace all uses of the old node F with the use
 /// of the new node T.
-void ReplaceUses(SDOperand F, SDOperand T) DISABLE_INLINE {
-  ISelQueueUpdater ISQU(ISelQueue);
-  CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISQU);
-  setSelected(F.Val->getNodeId());
-  UpdateQueue(ISQU);
+void ReplaceUses(SDValue F, SDValue T) DISABLE_INLINE {
+  ISelUpdater ISU(ISelPosition);
+  CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISU);
+}
+
+/// ReplaceUses - replace all uses of the old nodes F with the use
+/// of the new nodes T.
+void ReplaceUses(const SDValue *F, const SDValue *T,
+                 unsigned Num) DISABLE_INLINE {
+  ISelUpdater ISU(ISelPosition);
+  CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num, &ISU);
 }
 
 /// ReplaceUses - replace all uses of the old node F with the use
 /// of the new node T.
 void ReplaceUses(SDNode *F, SDNode *T) DISABLE_INLINE {
-  unsigned FNumVals = F->getNumValues();
-  unsigned TNumVals = T->getNumValues();
-  ISelQueueUpdater ISQU(ISelQueue);
-  if (FNumVals != TNumVals) {
-    for (unsigned i = 0, e = std::min(FNumVals, TNumVals); i < e; ++i)
-     CurDAG->ReplaceAllUsesOfValueWith(SDOperand(F, i), SDOperand(T, i), &ISQU);
-  } else {
-    CurDAG->ReplaceAllUsesWith(F, T, &ISQU);
-  }
-  setSelected(F->getNodeId());
-  UpdateQueue(ISQU);
+  ISelUpdater ISU(ISelPosition);
+  CurDAG->ReplaceAllUsesWith(F, T, &ISU);
 }
 
 /// SelectRoot - Top level entry to DAG instruction selector.
 /// Selects instructions starting at the root of the current DAG.
-SDOperand SelectRoot(SDOperand Root) {
+void SelectRoot(SelectionDAG &DAG) {
   SelectRootInit();
-  unsigned NumBytes = (DAGSize + 7) / 8;
-  ISelQueued   = new unsigned char[NumBytes];
-  ISelSelected = new unsigned char[NumBytes];
-  memset(ISelQueued,   0, NumBytes);
-  memset(ISelSelected, 0, NumBytes);
 
   // Create a dummy node (which is not added to allnodes), that adds
   // a reference to the root node, preventing it from being deleted,
   // and tracking any changes of the root.
   HandleSDNode Dummy(CurDAG->getRoot());
-  ISelQueue.push_back(CurDAG->getRoot().Val);
-
-  // Select pending nodes from the instruction selection queue
-  // until no more nodes are left for selection.
-  while (!ISelQueue.empty()) {
-    SDNode *Node = ISelQueue.front();
-    std::pop_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());
-    ISelQueue.pop_back();
-    // Skip already selected nodes.
-    if (isSelected(Node->getNodeId()))
+  ISelPosition = next(SelectionDAG::allnodes_iterator(CurDAG->getRoot().getNode()));
+
+  // The AllNodes list is now topological-sorted. Visit the
+  // nodes by starting at the end of the list (the root of the
+  // graph) and preceding back toward the beginning (the entry
+  // node).
+  while (ISelPosition != CurDAG->allnodes_begin()) {
+    SDNode *Node = --ISelPosition;
+    // Skip dead nodes. DAGCombiner is expected to eliminate all dead nodes,
+    // but there are currently some corner cases that it misses. Also, this
+    // makes it theoretically possible to disable the DAGCombiner.
+    if (Node->use_empty())
       continue;
-    SDNode *ResNode = Select(SDOperand(Node, 0));
+#if 0
+    DAG.setSubgraphColor(Node, "red");
+#endif
+    SDNode *ResNode = Select(SDValue(Node, 0));
     // If node should not be replaced, 
     // continue with the next one.
     if (ResNode == Node)
       continue;
     // Replace node.
-    if (ResNode)
+    if (ResNode) {
+#if 0
+      DAG.setSubgraphColor(ResNode, "yellow");
+      DAG.setSubgraphColor(ResNode, "black");
+#endif
       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.
-          ISelQueueUpdater ISQU(ISelQueue);
-          CurDAG->RemoveDeadNode(Node, &ISQU);
-          UpdateQueue(ISQU);
+      ISelUpdater ISU(ISelPosition);
+      CurDAG->RemoveDeadNode(Node, &ISU);
     }
   }
 
-  delete[] ISelQueued;
-  ISelQueued = NULL;
-  delete[] ISelSelected;
-  ISelSelected = NULL;
-  return Dummy.getValue();
+  CurDAG->setRoot(Dummy.getValue());
 }
 
 #endif /* LLVM_CODEGEN_DAGISEL_HEADER_H */