Skip to content

Commit 6780557

Browse files
committed
[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: llvm-commits, dmgreen Differential Revision: https://reviews.llvm.org/D43140 llvm-svn: 324962
1 parent de3e889 commit 6780557

File tree

1 file changed

+25
-20
lines changed

1 file changed

+25
-20
lines changed

llvm/include/llvm/Support/GenericDomTreeConstruction.h

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -698,24 +698,20 @@ struct SemiNCAInfo {
698698
return;
699699

700700
// Recalculate the set of roots.
701-
DT.Roots = FindRoots(DT, BUI);
702-
for (const NodePtr R : DT.Roots) {
703-
const TreeNodePtr TN = DT.getNode(R);
704-
// A CFG node was selected as a tree root, but the corresponding tree node
705-
// is not connected to the virtual root. This is because the incremental
706-
// algorithm does not really know or use the set of roots and can make a
707-
// different (implicit) decision about which nodes within an infinite loop
708-
// becomes a root.
709-
if (TN && !DT.isVirtualRoot(TN->getIDom())) {
710-
DEBUG(dbgs() << "Root " << BlockNamePrinter(R)
711-
<< " is not virtual root's child\n"
712-
<< "The entire tree needs to be rebuilt\n");
713-
// It should be possible to rotate the subtree instead of recalculating
714-
// the whole tree, but this situation happens extremely rarely in
715-
// practice.
716-
CalculateFromScratch(DT, BUI);
717-
return;
718-
}
701+
auto Roots = FindRoots(DT, BUI);
702+
if (DT.Roots.size() != Roots.size() ||
703+
!std::is_permutation(DT.Roots.begin(), DT.Roots.end(), Roots.begin())) {
704+
// The roots chosen in the CFG have changed. This is because the
705+
// incremental algorithm does not really know or use the set of roots and
706+
// can make a different (implicit) decision about which node within an
707+
// infinite loop becomes a root.
708+
709+
DEBUG(dbgs() << "Roots are different in updated trees\n"
710+
<< "The entire tree needs to be rebuilt\n");
711+
// It may be possible to update the tree without recalculating it, but
712+
// we do not know yet how to do it, and it happens rarely in practise.
713+
CalculateFromScratch(DT, BUI);
714+
return;
719715
}
720716
}
721717

@@ -1660,8 +1656,17 @@ bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) {
16601656
case DomTreeT::VerificationLevel::Basic:
16611657
return SNCA.verifyParentProperty(DT) && SNCA.IsSameAsFreshTree(DT);
16621658

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

16671672
llvm_unreachable("Unhandled DomTree VerificationLevel");

0 commit comments

Comments
 (0)