mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-17 05:29:24 +00:00
Optimize SelectionDAG's AssignTopologicalOrder even further.
Completely eliminate the TopOrder std::vector. Instead, sort the AllNodes list in place. This also eliminates the need to call AllNodes.size(), a linear-time operation, before performing the sort. Also, eliminate the Sources temporary std::vector, since it essentially duplicates the sorted result as it is being built. This also changes the direction of the topological sort from bottom-up to top-down. The AllNodes list starts out in roughly top-down order, so this reduces the amount of reordering needed. Top-down is also more convenient for Legalize, and ISel needed only minor adjustments. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56867 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
21420dfae1
commit
f06c835f76
@ -18,7 +18,7 @@
|
|||||||
#define LLVM_CODEGEN_DAGISEL_HEADER_H
|
#define LLVM_CODEGEN_DAGISEL_HEADER_H
|
||||||
|
|
||||||
/// ISelQueue - Instruction selector priority queue sorted
|
/// ISelQueue - Instruction selector priority queue sorted
|
||||||
/// in the order of increasing NodeId() values.
|
/// in the order of decreasing NodeId() values.
|
||||||
std::vector<SDNode*> ISelQueue;
|
std::vector<SDNode*> ISelQueue;
|
||||||
|
|
||||||
/// Keep track of nodes which have already been added to queue.
|
/// Keep track of nodes which have already been added to queue.
|
||||||
@ -43,10 +43,10 @@ static bool IsChainCompatible(SDNode *Chain, SDNode *Op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// isel_sort - Sorting functions for the selection queue in the
|
/// isel_sort - Sorting functions for the selection queue in the
|
||||||
/// increasing NodeId order.
|
/// decreasing NodeId order.
|
||||||
struct isel_sort : public std::binary_function<SDNode*, SDNode*, bool> {
|
struct isel_sort : public std::binary_function<SDNode*, SDNode*, bool> {
|
||||||
bool operator()(const SDNode* left, const SDNode* right) const {
|
bool operator()(const SDNode* left, const SDNode* right) const {
|
||||||
return (left->getNodeId() > right->getNodeId());
|
return left->getNodeId() < right->getNodeId();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ class VISIBILITY_HIDDEN ISelQueueUpdater :
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// UpdateQueue - update the instruction selction queue to maintain
|
/// UpdateQueue - update the instruction selction queue to maintain
|
||||||
/// the increasing NodeId() ordering property.
|
/// the decreasing NodeId() ordering property.
|
||||||
inline void UpdateQueue(const ISelQueueUpdater &ISQU) {
|
inline void UpdateQueue(const ISelQueueUpdater &ISQU) {
|
||||||
if (ISQU.hadDelete())
|
if (ISQU.hadDelete())
|
||||||
std::make_heap(ISelQueue.begin(), ISelQueue.end(),isel_sort());
|
std::make_heap(ISelQueue.begin(), ISelQueue.end(),isel_sort());
|
||||||
|
@ -663,10 +663,10 @@ public:
|
|||||||
unsigned Num,
|
unsigned Num,
|
||||||
DAGUpdateListener *UpdateListener = 0);
|
DAGUpdateListener *UpdateListener = 0);
|
||||||
|
|
||||||
/// AssignTopologicalOrder - Assign a unique node id for each node in the DAG
|
/// AssignTopologicalOrder - Topological-sort the AllNodes list and a
|
||||||
/// based on their topological order. It returns the maximum id and a vector
|
/// assign a unique node id for each node in the DAG based on their
|
||||||
/// of the SDNodes* in assigned order by reference.
|
/// topological order. Returns the number of nodes.
|
||||||
unsigned AssignTopologicalOrder(std::vector<SDNode*> &TopOrder);
|
unsigned AssignTopologicalOrder();
|
||||||
|
|
||||||
/// isCommutativeBinOp - Returns true if the opcode is a commutative binary
|
/// isCommutativeBinOp - Returns true if the opcode is a commutative binary
|
||||||
/// operation.
|
/// operation.
|
||||||
|
@ -48,7 +48,6 @@ public:
|
|||||||
AliasAnalysis *AA;
|
AliasAnalysis *AA;
|
||||||
GCFunctionInfo *GFI;
|
GCFunctionInfo *GFI;
|
||||||
bool Fast;
|
bool Fast;
|
||||||
std::vector<SDNode*> TopOrder;
|
|
||||||
static char ID;
|
static char ID;
|
||||||
|
|
||||||
explicit SelectionDAGISel(TargetLowering &tli, bool fast = false);
|
explicit SelectionDAGISel(TargetLowering &tli, bool fast = false);
|
||||||
@ -67,7 +66,7 @@ public:
|
|||||||
virtual void InstructionSelectPostProcessing() {}
|
virtual void InstructionSelectPostProcessing() {}
|
||||||
|
|
||||||
void SelectRootInit() {
|
void SelectRootInit() {
|
||||||
DAGSize = CurDAG->AssignTopologicalOrder(TopOrder);
|
DAGSize = CurDAG->AssignTopologicalOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SelectInlineAsmMemoryOperand - Select the specified address as a target
|
/// SelectInlineAsmMemoryOperand - Select the specified address as a target
|
||||||
|
@ -280,11 +280,10 @@ void SelectionDAGLegalize::LegalizeDAG() {
|
|||||||
// practice however, this causes us to run out of stack space on large basic
|
// practice however, this causes us to run out of stack space on large basic
|
||||||
// blocks. To avoid this problem, compute an ordering of the nodes where each
|
// blocks. To avoid this problem, compute an ordering of the nodes where each
|
||||||
// node is only legalized after all of its operands are legalized.
|
// node is only legalized after all of its operands are legalized.
|
||||||
std::vector<SDNode *> TopOrder;
|
DAG.AssignTopologicalOrder();
|
||||||
unsigned N = DAG.AssignTopologicalOrder(TopOrder);
|
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
|
||||||
for (unsigned i = N; i != 0; --i)
|
E = prior(DAG.allnodes_end()); I != next(E); ++I)
|
||||||
HandleOp(SDValue(TopOrder[i-1], 0));
|
HandleOp(SDValue(I, 0));
|
||||||
TopOrder.clear();
|
|
||||||
|
|
||||||
// Finally, it's possible the root changed. Get the new root.
|
// Finally, it's possible the root changed. Get the new root.
|
||||||
SDValue OldRoot = DAG.getRoot();
|
SDValue OldRoot = DAG.getRoot();
|
||||||
|
@ -587,7 +587,7 @@ void SelectionDAG::DeleteNode(SDNode *N) {
|
|||||||
|
|
||||||
void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
|
void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
|
||||||
|
|
||||||
// Drop all of the operands and decrement used nodes use counts.
|
// Drop all of the operands and decrement used node's use counts.
|
||||||
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
|
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
|
||||||
I->getVal()->removeUser(std::distance(N->op_begin(), I), N);
|
I->getVal()->removeUser(std::distance(N->op_begin(), I), N);
|
||||||
if (N->OperandsNeedDelete)
|
if (N->OperandsNeedDelete)
|
||||||
@ -4569,38 +4569,74 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
|
|||||||
/// AssignTopologicalOrder - Assign a unique node id for each node in the DAG
|
/// AssignTopologicalOrder - Assign a unique node id for each node in the DAG
|
||||||
/// based on their topological order. It returns the maximum id and a vector
|
/// based on their topological order. It returns the maximum id and a vector
|
||||||
/// of the SDNodes* in assigned order by reference.
|
/// of the SDNodes* in assigned order by reference.
|
||||||
unsigned SelectionDAG::AssignTopologicalOrder(std::vector<SDNode*> &TopOrder) {
|
unsigned SelectionDAG::AssignTopologicalOrder() {
|
||||||
unsigned DAGSize = AllNodes.size();
|
|
||||||
std::vector<SDNode*> Sources;
|
|
||||||
|
|
||||||
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I){
|
unsigned DAGSize = 0;
|
||||||
SDNode *N = I;
|
|
||||||
unsigned Degree = N->use_size();
|
|
||||||
// Temporarily use the Node Id as scratch space for the degree count.
|
|
||||||
N->setNodeId(Degree);
|
|
||||||
if (Degree == 0)
|
|
||||||
Sources.push_back(N);
|
|
||||||
}
|
|
||||||
|
|
||||||
TopOrder.clear();
|
// SortedPos tracks the progress of the algorithm. Nodes before it are
|
||||||
TopOrder.reserve(DAGSize);
|
// sorted, nodes after it are unsorted. When the algorithm completes
|
||||||
int Id = 0;
|
// it is at the end of the list.
|
||||||
while (!Sources.empty()) {
|
allnodes_iterator SortedPos = allnodes_begin();
|
||||||
SDNode *N = Sources.back();
|
|
||||||
Sources.pop_back();
|
// Visit all the nodes. Add nodes with no operands to the TopOrder result
|
||||||
TopOrder.push_back(N);
|
// array immediately. Annotate nodes that do have operands with their
|
||||||
N->setNodeId(Id++);
|
// operand count. Before we do this, the Node Id fields of the nodes
|
||||||
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
|
// may contain arbitrary values. After, the Node Id fields for nodes
|
||||||
SDNode *P = I->getVal();
|
// before SortedPos will contain the topological sort index, and the
|
||||||
unsigned Degree = P->getNodeId();
|
// Node Id fields for nodes At SortedPos and after will contain the
|
||||||
--Degree;
|
// count of outstanding operands.
|
||||||
P->setNodeId(Degree);
|
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) {
|
||||||
if (Degree == 0)
|
SDNode *N = I++;
|
||||||
Sources.push_back(P);
|
unsigned Degree = N->getNumOperands();
|
||||||
|
if (Degree == 0) {
|
||||||
|
// A node with no uses, add it to the result array immediately.
|
||||||
|
N->setNodeId(DAGSize++);
|
||||||
|
allnodes_iterator Q = N;
|
||||||
|
if (Q != SortedPos)
|
||||||
|
SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(Q));
|
||||||
|
++SortedPos;
|
||||||
|
} else {
|
||||||
|
// Temporarily use the Node Id as scratch space for the degree count.
|
||||||
|
N->setNodeId(Degree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Id;
|
// Visit all the nodes. As we iterate, moves nodes into sorted order,
|
||||||
|
// such that by the time the end is reached all nodes will be sorted.
|
||||||
|
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I) {
|
||||||
|
SDNode *N = I;
|
||||||
|
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
|
||||||
|
UI != UE; ++UI) {
|
||||||
|
SDNode *P = *UI;
|
||||||
|
unsigned Degree = P->getNodeId();
|
||||||
|
--Degree;
|
||||||
|
if (Degree == 0) {
|
||||||
|
// All of P's operands are sorted, so P may sorted now.
|
||||||
|
P->setNodeId(DAGSize++);
|
||||||
|
if (P != SortedPos)
|
||||||
|
SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(P));
|
||||||
|
++SortedPos;
|
||||||
|
} else {
|
||||||
|
// Update P's outstanding operand count.
|
||||||
|
P->setNodeId(Degree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(SortedPos == AllNodes.end() &&
|
||||||
|
"Topological sort incomplete!");
|
||||||
|
assert(AllNodes.front().getOpcode() == ISD::EntryToken &&
|
||||||
|
"First node in topological sort is not the entry token!");
|
||||||
|
assert(AllNodes.front().getNodeId() == 0 &&
|
||||||
|
"First node in topological sort has non-zero id!");
|
||||||
|
assert(AllNodes.front().getNumOperands() == 0 &&
|
||||||
|
"First node in topological sort has operands!");
|
||||||
|
assert(AllNodes.back().getNodeId() == (int)DAGSize-1 &&
|
||||||
|
"Last node in topologic sort has unexpected id!");
|
||||||
|
assert(AllNodes.back().use_empty() &&
|
||||||
|
"Last node in topologic sort has users!");
|
||||||
|
assert(DAGSize == allnodes_size() && "TopOrder result count mismatch!");
|
||||||
|
return DAGSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ static void findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse,
|
|||||||
SDNode *Root, bool &found,
|
SDNode *Root, bool &found,
|
||||||
SmallPtrSet<SDNode*, 16> &Visited) {
|
SmallPtrSet<SDNode*, 16> &Visited) {
|
||||||
if (found ||
|
if (found ||
|
||||||
Use->getNodeId() > Def->getNodeId() ||
|
Use->getNodeId() < Def->getNodeId() ||
|
||||||
!Visited.insert(Use))
|
!Visited.insert(Use))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user