[Dominators] Always recalculate postdominators when update yields different roots
Summary:
This patch makes postdominators always recalculate the tree when an update causes to change the tree roots.
As @dmgreen noticed in [[ https://reviews.llvm.org/D41298  D41298 ]], the previous implementation was not conservative enough and it was possible to end up with a PostDomTree that was different than a freshly computed one.
The patch also compares postdominators with a freshly computed tree at the end of full verification to make sure we don't hit similar issues in the future.
This should (ideally) be also backported to 6.0 before the release, although I don't have any reports of this causing an observable error. It should be safe to do it even if it's late in the release, as the change only makes the current behavior more conservative.
Reviewers: dmgreen, dberlin, davide, brzycki, grosser
Reviewed By: brzycki, grosser
Subscribers: llvmcommits, dmgreen
Differential Revision: https://reviews.llvm.org/D43140
gitsvnid: https://llvm.org/svn/llvmproject/llvm/trunk@324962 911773080d340410b5e696231b3b80d8
Jakub Kuderski
2 years ago
697  697  return; 
698  698  
699  699  // Recalculate the set of roots. 
700  DT.Roots = FindRoots(DT, BUI);  
701  for (const NodePtr R : DT.Roots) {  
702  const TreeNodePtr TN = DT.getNode(R);  
703  // A CFG node was selected as a tree root, but the corresponding tree node  
704  // is not connected to the virtual root. This is because the incremental  
705  // algorithm does not really know or use the set of roots and can make a  
706  // different (implicit) decision about which nodes within an infinite loop  
707  // becomes a root.  
708  if (TN && !DT.isVirtualRoot(TN>getIDom())) {  
709  DEBUG(dbgs() << "Root " << BlockNamePrinter(R)  
710  << " is not virtual root's child\n"  
711  << "The entire tree needs to be rebuilt\n");  
712  // It should be possible to rotate the subtree instead of recalculating  
713  // the whole tree, but this situation happens extremely rarely in  
714  // practice.  
715  CalculateFromScratch(DT, BUI);  
716  return;  
717 


700  auto Roots = FindRoots(DT, BUI);⏎  
701  if (DT.Roots.size() != Roots.size()   
702  !std::is_permutation(DT.Roots.begin(), DT.Roots.end(), Roots.begin())) {  
703  // The roots chosen in the CFG have changed. This is because the  
704  // incremental algorithm does not really know or use the set of roots and  
705  // can make a different (implicit) decision about which node within an  
706  // infinite loop becomes a root.  
707  
708  DEBUG(dbgs() << "Roots are different in updated trees\n"  
709  << "The entire tree needs to be rebuilt\n");  
710  // It may be possible to update the tree without recalculating it, but  
711  // we do not know yet how to do it, and it happens rarely in practise.  
712  CalculateFromScratch(DT, BUI);  
713  return;  
718  714  } 
719  715  } 
720  716  
1659  1655  case DomTreeT::VerificationLevel::Basic: 
1660  1656  return SNCA.verifyParentProperty(DT) && SNCA.IsSameAsFreshTree(DT); 
1661  1657  
1662  case DomTreeT::VerificationLevel::Full:  
1663 


1658  case DomTreeT::VerificationLevel::Full: {⏎  
1659  bool FullRes  
1660  = SNCA.verifyParentProperty(DT) && SNCA.verifySiblingProperty(DT);  
1661  
1662  // Postdominators depend on root selection, make sure that a fresh tree  
1663  // looks the same.  
1664  if (DT.isPostDominator())  
1665  FullRes &= SNCA.IsSameAsFreshTree(DT);  
1666  
1667  return FullRes;  
1668  }  
1664  1669  } 
1665  1670  
1666  1671  llvm_unreachable("Unhandled DomTree VerificationLevel"); 