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

Code before:
}
#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");

    // 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).

    // 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);
      }
    }

    // At this point, S is DFlocal.  Now we union in DFup's of our children...
    // Loop through and visit the nodes that Node immediately dominates (Node's
    // children in the IDomTree)
    bool visitChild = false;
    for (typename DomTreeNodeT::const_iterator NI = currentNode->begin(),
                                               NE = currentNode->end();
         NI != NE; ++NI) {
      DomTreeNodeT *IDominee = *NI;
      BlockT *childBB = IDominee->getBlock();

Review comment (suggestion):
Nit, keep the currentBB assert but relax it to only when the DT node is virtual

```suggestion
    assert(currentNode && "Invalid work object. Missing current Node");
    assert((currentBB || DT.isVirtualRoot(CurrentNode)) && "Invalid work object. Missing current Basic Block");
```

Code after:
}
#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);
      }
    }

    // At this point, S is DFlocal.  Now we union in DFup's of our children...
    // Loop through and visit the nodes that Node immediately dominates (Node's
    // children in the IDomTree)
    bool visitChild = false;
    for (typename DomTreeNodeT::const_iterator NI = currentNode->begin(),
                                               NE = currentNode->end();
         NI != NE; ++NI) {