@@ -12610,17 +12610,87 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
1261012610/// based on their topological order. It returns the maximum id and a vector
1261112611/// of the SDNodes* in assigned order by reference.
1261212612unsigned SelectionDAG::AssignTopologicalOrder() {
12613- SmallVector<const SDNode *> SortedNodes(AllNodes.size());
12614- getTopologicallyOrderedNodes(SortedNodes);
12615-
12616- for (auto [Idx, ConstN] : enumerate(SortedNodes)) {
12617- auto *N = const_cast<SDNode *>(ConstN);
12618- N->setNodeId(Idx);
12619- if (N->getIterator() != std::prev(allnodes_end()))
12620- AllNodes.push_back(AllNodes.remove(N));
12621- }
12622-
12623- return SortedNodes.size();
12613+ unsigned DAGSize = 0;
12614+
12615+ // SortedPos tracks the progress of the algorithm. Nodes before it are
12616+ // sorted, nodes after it are unsorted. When the algorithm completes
12617+ // it is at the end of the list.
12618+ allnodes_iterator SortedPos = allnodes_begin();
12619+
12620+ // Visit all the nodes. Move nodes with no operands to the front of
12621+ // the list immediately. Annotate nodes that do have operands with their
12622+ // operand count. Before we do this, the Node Id fields of the nodes
12623+ // may contain arbitrary values. After, the Node Id fields for nodes
12624+ // before SortedPos will contain the topological sort index, and the
12625+ // Node Id fields for nodes At SortedPos and after will contain the
12626+ // count of outstanding operands.
12627+ for (SDNode &N : llvm::make_early_inc_range(allnodes())) {
12628+ checkForCycles(&N, this);
12629+ unsigned Degree = N.getNumOperands();
12630+ if (Degree == 0) {
12631+ // A node with no uses, add it to the result array immediately.
12632+ N.setNodeId(DAGSize++);
12633+ allnodes_iterator Q(&N);
12634+ if (Q != SortedPos)
12635+ SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(Q));
12636+ assert(SortedPos != AllNodes.end() && "Overran node list");
12637+ ++SortedPos;
12638+ } else {
12639+ // Temporarily use the Node Id as scratch space for the degree count.
12640+ N.setNodeId(Degree);
12641+ }
12642+ }
12643+
12644+ // Visit all the nodes. As we iterate, move nodes into sorted order,
12645+ // such that by the time the end is reached all nodes will be sorted.
12646+ for (SDNode &Node : allnodes()) {
12647+ SDNode *N = &Node;
12648+ checkForCycles(N, this);
12649+ // N is in sorted position, so all its uses have one less operand
12650+ // that needs to be sorted.
12651+ for (SDNode *P : N->users()) {
12652+ unsigned Degree = P->getNodeId();
12653+ assert(Degree != 0 && "Invalid node degree");
12654+ --Degree;
12655+ if (Degree == 0) {
12656+ // All of P's operands are sorted, so P may sorted now.
12657+ P->setNodeId(DAGSize++);
12658+ if (P->getIterator() != SortedPos)
12659+ SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(P));
12660+ assert(SortedPos != AllNodes.end() && "Overran node list");
12661+ ++SortedPos;
12662+ } else {
12663+ // Update P's outstanding operand count.
12664+ P->setNodeId(Degree);
12665+ }
12666+ }
12667+ if (Node.getIterator() == SortedPos) {
12668+ #ifndef NDEBUG
12669+ allnodes_iterator I(N);
12670+ SDNode *S = &*++I;
12671+ dbgs() << "Overran sorted position:\n";
12672+ S->dumprFull(this); dbgs() << "\n";
12673+ dbgs() << "Checking if this is due to cycles\n";
12674+ checkForCycles(this, true);
12675+ #endif
12676+ llvm_unreachable(nullptr);
12677+ }
12678+ }
12679+
12680+ assert(SortedPos == AllNodes.end() &&
12681+ "Topological sort incomplete!");
12682+ assert(AllNodes.front().getOpcode() == ISD::EntryToken &&
12683+ "First node in topological sort is not the entry token!");
12684+ assert(AllNodes.front().getNodeId() == 0 &&
12685+ "First node in topological sort has non-zero id!");
12686+ assert(AllNodes.front().getNumOperands() == 0 &&
12687+ "First node in topological sort has operands!");
12688+ assert(AllNodes.back().getNodeId() == (int)DAGSize-1 &&
12689+ "Last node in topologic sort has unexpected id!");
12690+ assert(AllNodes.back().use_empty() &&
12691+ "Last node in topologic sort has users!");
12692+ assert(DAGSize == allnodes_size() && "Node count mismatch!");
12693+ return DAGSize;
1262412694}
1262512695
1262612696void SelectionDAG::getTopologicallyOrderedNodes(
0 commit comments