mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-29 13:29:28 +00:00
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63214 91177308-0d34-0410-b5e6-96231b3b80d8
144 lines
5.0 KiB
C++
144 lines
5.0 KiB
C++
//==-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 */
|