Repository: llvm/llvm-project
File: llvm/include/llvm/Analysis/DominanceFrontierImpl.h (C/C++)

Code before:
    }
    OS << '\n';
  }
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
template <class BlockT, bool IsPostDom>
void DominanceFrontierBase<BlockT, IsPostDom>::dump() const {
  print(dbgs());
}
#endif

template <class BlockT, bool IsPostDom>
void DominanceFrontierBase<BlockT, IsPostDom>::calculate(const DomTreeT &DT) {
  // NOTE: RootNode might be virtual for `IsPostDom == true`.
  const DomTreeNodeT *RootNode = DT.getRootNode();
  BlockT *BB = RootNode->getBlock();

  std::vector<DFCalculateWorkObject<BlockT>> workList;
  SmallPtrSet<BlockT *, 32> visited;

  workList.push_back(
      DFCalculateWorkObject<BlockT>(BB, nullptr, RootNode, nullptr));
  do {
    DFCalculateWorkObject<BlockT> *currentW = &workList.back();
    assert(currentW && "Missing work object.");

    BlockT *currentBB = currentW->currentBB;
    BlockT *parentBB = currentW->parentBB;
    const DomTreeNodeT *currentNode = currentW->Node;
    const DomTreeNodeT *parentNode = currentW->parentNode;
    assert(currentNode && "Invalid work object. Missing current Node");

    // Visit each block only once.
    if (visited.insert(currentBB).second) {
      // Loop over CFG successors to calculate DFlocal[currentNode].
      //
      // Note that for `IsPostDom == true`, virtual root node (empty currentBB)
      // is an immediate post-dominator for all the exit nodes (which are
      // virtual node's CFG successors).
      if (currentBB) {
        DomSetType &S = this->Frontiers[currentBB];
        for (const auto Child : children<GraphTy>(currentBB)) {
          // Does Node immediately dominate this successor?
          if (DT[Child]->getIDom() != currentNode)
            S.insert(Child);
        }
      }
    }

    // At this point, S is DFlocal.  Now we union in DFup's of our children...

Review comment (bug):
Instead of pushing a null block/virtual root onto the worklist, could you just check if the root is virtual at the start here and push its children on? e.g.


```suggestion
  if (DT.isVirtualRoot(RootNode)) {
    for (DomTreeNodeT *IDominee : *RootNode)
      workList.push_back(DFCalculateWorkObject<BlockT>(
          IDominee->getBlock(), nullptr, IDominee, nullptr));
  } else
    workList.push_back(
        DFCalculateWorkObject<BlockT>(BB, nullptr, RootNode, nullptr));
```

That way you wouldn't need to check `if (currentBB)` on line 104 or `!parentBB` on line 138

Code after:
    }
    OS << '\n';
  }
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
template <class BlockT, bool IsPostDom>
void DominanceFrontierBase<BlockT, IsPostDom>::dump() const {
  print(dbgs());
}
#endif

template <class BlockT, bool IsPostDom>
void DominanceFrontierBase<BlockT, IsPostDom>::analyze(const DomTreeT &DT) {
  // NOTE: RootNode might be virtual for `IsPostDom == true`.
  const DomTreeNodeT *RootNode = DT.getRootNode();
  assert(IsPostDom ||
         (DT.root_size() == 1 && RootNode->getBlock() == *DT.root_begin()) &&
             "Multiple roots for forward dominators?");
  BlockT *BB = RootNode->getBlock();

  std::vector<DFCalculateWorkObject<BlockT>> workList;
  SmallPtrSet<BlockT *, 32> visited;

  workList.push_back(
      DFCalculateWorkObject<BlockT>(BB, nullptr, RootNode, nullptr));
  do {
    DFCalculateWorkObject<BlockT> *currentW = &workList.back();
    assert(currentW && "Missing work object.");

    BlockT *currentBB = currentW->currentBB;
    BlockT *parentBB = currentW->parentBB;
    const DomTreeNodeT *currentNode = currentW->Node;
    const DomTreeNodeT *parentNode = currentW->parentNode;
    assert(currentNode && "Invalid work object. Missing current Node");
    assert((currentBB || DT.isVirtualRoot(currentNode)) &&
           "Invalid work object. Missing current Basic Block");

    // Note that for `IsPostDom == true`, the virtual root node (null currentBB)
    // is an immediate post-dominator for all the exit nodes (which are
    // virtual node's CFG successors).

    // Visit each block only once.
    if (currentBB && visited.insert(currentBB).second) {
      // Loop over CFG successors to calculate DFlocal[currentNode].
      DomSetType &S = this->Frontiers[currentBB];
      for (const auto Child : children<GraphTy>(currentBB)) {
        // Does Node immediately dominate this successor?
        if (DT[Child]->getIDom() != currentNode)
          S.insert(Child);
      }