| //==-llvm/CodeGen/DAGISelHeader.h - Common DAG ISel definitions -*- C++ -*-==// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file provides definitions of the common, target-independent methods and |
| // 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. |
| // 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 |
| |
| /// 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; |
| if (Chain->getOpcode() == ISD::TokenFactor) |
| return false; |
| if (Chain->getNumOperands() > 0) { |
| SDValue C0 = Chain->getOperand(0); |
| if (C0.getValueType() == MVT::Other) |
| return C0.getNode() != Op && IsChainCompatible(C0.getNode(), Op); |
| } |
| return true; |
| } |
| |
| /// 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; |
| } |
| |
| /// 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(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(); |
| ISelUpdater ISU(ISelPosition); |
| if (FNumVals != TNumVals) { |
| for (unsigned i = 0, e = std::min(FNumVals, TNumVals); i < e; ++i) |
| CurDAG->ReplaceAllUsesOfValueWith(SDValue(F, i), SDValue(T, i), &ISU); |
| } else { |
| CurDAG->ReplaceAllUsesWith(F, T, &ISU); |
| } |
| } |
| |
| /// SelectRoot - Top level entry to DAG instruction selector. |
| /// Selects instructions starting at the root of the current DAG. |
| void SelectRoot(SelectionDAG &DAG) { |
| SelectRootInit(); |
| |
| // 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()); |
| 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; |
| #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 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. |
| ISelUpdater ISU(ISelPosition); |
| CurDAG->RemoveDeadNode(Node, &ISU); |
| } |
| } |
| |
| CurDAG->setRoot(Dummy.getValue()); |
| } |
| |
| #endif /* LLVM_CODEGEN_DAGISEL_HEADER_H */ |