22#ifndef LLVM_ADT_SCCITERATOR_H 
   23#define LLVM_ADT_SCCITERATOR_H 
   34#include <unordered_map> 
   35#include <unordered_set> 
   46template <
class GraphT, 
class GT = GraphTraits<GraphT>>
 
   48                         scc_iterator<GraphT, GT>, std::forward_iterator_tag,
 
   49                         const std::vector<typename GT::NodeRef>, ptrdiff_t> {
 
   50  using NodeRef = 
typename GT::NodeRef;
 
   51  using ChildItTy = 
typename GT::ChildIteratorType;
 
   52  using SccTy = std::vector<NodeRef>;
 
   53  using reference = 
typename scc_iterator::reference;
 
   61    StackElement(NodeRef 
Node, 
const ChildItTy &Child, 
unsigned Min)
 
   62        : 
Node(
Node), NextChild(Child), MinVisited(Min) {}
 
   66             NextChild == 
Other.NextChild &&
 
   67             MinVisited == 
Other.MinVisited;
 
   79  std::vector<NodeRef> SCCNodeStack;
 
   86  std::vector<StackElement> VisitStack;
 
   89  void DFSVisitOne(NodeRef 
N);
 
   92  void DFSVisitChildren();
 
   97  scc_iterator(NodeRef entryN) : visitNum(0) {
 
  103  scc_iterator() = 
default;
 
  106  static scc_iterator 
begin(
const GraphT &
G) {
 
  107    return scc_iterator(GT::getEntryNode(
G));
 
 
  109  static scc_iterator 
end(
const GraphT &) { 
return scc_iterator(); }
 
  114    assert(!CurrentSCC.empty() || VisitStack.empty());
 
  115    return CurrentSCC.empty();
 
 
  119    return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
 
 
  128    assert(!CurrentSCC.empty() && 
"Dereferencing END SCC iterator!");
 
 
  141    assert(nodeVisitNumbers.count(Old) && 
"Old not in scc_iterator?");
 
  144    auto tempVal = nodeVisitNumbers[Old];
 
  145    nodeVisitNumbers[New] = tempVal;
 
  146    nodeVisitNumbers.erase(Old);
 
 
 
  150template <
class GraphT, 
class GT>
 
  151void scc_iterator<GraphT, GT>::DFSVisitOne(NodeRef 
N) {
 
  153  nodeVisitNumbers[
N] = visitNum;
 
  154  SCCNodeStack.push_back(
N);
 
  155  VisitStack.push_back(StackElement(
N, GT::child_begin(
N), visitNum));
 
  157  dbgs() << 
"TarjanSCC: Node " << 
N <<
 
  158        " : visitNum = " << visitNum << 
"\n";
 
  162template <
class GraphT, 
class GT>
 
  163void scc_iterator<GraphT, GT>::DFSVisitChildren() {
 
  164  assert(!VisitStack.empty());
 
  165  while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) {
 
  167    NodeRef childN = *VisitStack.back().NextChild++;
 
  169        nodeVisitNumbers.find(childN);
 
  170    if (Visited == nodeVisitNumbers.end()) {
 
  176    unsigned childNum = Visited->second;
 
  177    if (VisitStack.back().MinVisited > childNum)
 
  178      VisitStack.back().MinVisited = childNum;
 
  182template <
class GraphT, 
class GT> 
void scc_iterator<GraphT, GT>::GetNextSCC() {
 
  184  while (!VisitStack.empty()) {
 
  188    NodeRef visitingN = VisitStack.back().Node;
 
  189    unsigned minVisitNum = VisitStack.back().MinVisited;
 
  190    assert(VisitStack.back().NextChild == GT::child_end(visitingN));
 
  191    VisitStack.pop_back();
 
  194    if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
 
  195      VisitStack.back().MinVisited = minVisitNum;
 
  198    dbgs() << 
"TarjanSCC: Popped node " << visitingN <<
 
  199          " : minVisitNum = " << minVisitNum << 
"; Node visit num = " <<
 
  200          nodeVisitNumbers[visitingN] << 
"\n";
 
  203    if (minVisitNum != nodeVisitNumbers[visitingN])
 
  211      CurrentSCC.push_back(SCCNodeStack.back());
 
  212      SCCNodeStack.pop_back();
 
  213      nodeVisitNumbers[CurrentSCC.back()] = ~0
U;
 
  214    } 
while (CurrentSCC.back() != visitingN);
 
  219template <
class GraphT, 
class GT>
 
  221    assert(!CurrentSCC.empty() && 
"Dereferencing END SCC iterator!");
 
  222    if (CurrentSCC.size() > 1)
 
  224    NodeRef 
N = CurrentSCC.front();
 
  225    for (ChildItTy CI = GT::child_begin(
N), CE = GT::child_end(
N); CI != CE;
 
 
  252template <
class GraphT, 
class GT = GraphTraits<GraphT>>
 
  254  using NodeType = 
typename GT::NodeType;
 
  255  using EdgeType = 
typename GT::EdgeType;
 
  256  using NodesType = std::vector<NodeType *>;
 
  260    NodeInfo *Group = 
this;
 
  262    bool Visited = 
false;
 
  268  NodeInfo *find(NodeInfo *
Node) {
 
  276  bool unionGroups(
const EdgeType *Edge) {
 
  277    NodeInfo *G1 = find(&NodeInfoMap[Edge->Source]);
 
  278    NodeInfo *G2 = find(&NodeInfoMap[Edge->Target]);
 
  285    if (G1->Rank < G2->Rank)
 
  290      if (G1->Rank == G2->Rank)
 
  296  std::unordered_map<NodeType *, NodeInfo> NodeInfoMap;
 
 
  305template <
class GraphT, 
class GT>
 
  307    const NodesType &InputNodes) {
 
  308  if (InputNodes.size() <= 1) {
 
  315  for (
auto *
Node : InputNodes) {
 
  319    NodeInfoMap.try_emplace(
Node);
 
  323  struct EdgeComparer {
 
  324    bool operator()(
const EdgeType *L, 
const EdgeType *R)
 const {
 
  325      return L->Weight > R->Weight;
 
  329  std::multiset<const EdgeType *, EdgeComparer> SortedEdges;
 
  330  for (
auto *
Node : InputNodes) {
 
  331    for (
auto &Edge : 
Node->Edges) {
 
  332      if (NodeInfoMap.count(Edge.Target))
 
  333        SortedEdges.insert(&Edge);
 
  339  std::unordered_set<const EdgeType *> MSTEdges;
 
  340  for (
auto *Edge : SortedEdges) {
 
  341    if (unionGroups(Edge))
 
  342      MSTEdges.insert(Edge);
 
  350  std::queue<NodeType *> Queue;
 
  351  for (
const auto *Edge : MSTEdges)
 
  352    NodeInfoMap[Edge->Target].IncomingMSTEdges.insert(Edge);
 
  356  for (
auto *Edge : SortedEdges) {
 
  357    auto &
Info = NodeInfoMap[Edge->Source];
 
  358    if (!
Info.Visited && 
Info.IncomingMSTEdges.empty()) {
 
  359      Queue.push(Edge->Source);
 
  364  while (!Queue.empty()) {
 
  365    auto *
Node = Queue.front();
 
  367    Nodes.push_back(
Node);
 
  368    for (
auto &Edge : 
Node->Edges) {
 
  369      NodeInfo &
Info = NodeInfoMap[Edge.Target];
 
  370      Info.IncomingMSTEdges.erase(&Edge);
 
  371      if (MSTEdges.count(&Edge) && 
Info.IncomingMSTEdges.empty()) {
 
  372        Queue.push(Edge.Target);
 
  377  assert(InputNodes.size() == Nodes.size() && 
"missing nodes in MST");
 
  378  std::reverse(Nodes.begin(), Nodes.end());
 
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
 
Analysis containing CSE Info
 
This file defines the DenseMap class.
 
This file defines the DenseSet and SmallDenseSet classes.
 
This file defines the little GraphTraits<X> template class that should be specialized by classes that...
 
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
 
Implements a dense probed hash-table based set.
 
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
 
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
 
scc_iterator & operator++()
 
static scc_iterator begin(const GraphT &G)
 
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
 
static scc_iterator end(const GraphT &)
 
bool operator==(const scc_iterator &x) const
 
void ReplaceNode(NodeRef Old, NodeRef New)
This informs the scc_iterator that the specified Old node has been deleted, and New is to be used in ...
 
bool hasCycle() const
Test if the current SCC has a cycle.
 
reference operator*() const
 
scc_member_iterator(const NodesType &InputNodes)
 
std::pair< NodeId, LaneBitmask > NodeRef
 
This is an optimization pass for GlobalISel generic memory operations.
 
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
 
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
 
scc_iterator< T > scc_end(const T &G)
Construct the end iterator for a deduced graph type T.