[DominatorTree] Simplify ChildrenGetter.

Summary:
Simplify ChildrenGetter to a simple wrapper around a GraphDiff call.
GraphDiff already handles nullptr in children, so the special casing in
clang can also be removed.

Reviewers: kuhar, dblaikie

Subscribers: llvm-commits, cfe-commits

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D84713
This commit is contained in:
Alina Sbirlea 2020-07-24 18:36:18 -07:00
parent 0b161def6c
commit e22de4e46d
2 changed files with 11 additions and 101 deletions

View File

@ -273,76 +273,6 @@ public:
namespace llvm { namespace llvm {
/// Clang's CFG contains nullpointers for unreachable succesors, e.g. when an
/// if statement's condition is always false, it's 'then' branch is represented
/// with a nullptr. This however will result in a nullpointer derefernece for
/// dominator tree calculation.
///
/// To circumvent this, let's just crudely specialize the children getters
/// used in LLVM's dominator tree builder.
namespace DomTreeBuilder {
using ClangCFGDomChildrenGetter =
SemiNCAInfo<clang::CFGDomTree::DominatorTreeBase>::ChildrenGetter<
/*Inverse=*/false>;
template <>
template <>
inline ClangCFGDomChildrenGetter::ResultTy ClangCFGDomChildrenGetter::Get(
clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/false>) {
auto RChildren = reverse(children<NodePtr>(N));
ResultTy Ret(RChildren.begin(), RChildren.end());
Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
return Ret;
}
using ClangCFGDomReverseChildrenGetter =
SemiNCAInfo<clang::CFGDomTree::DominatorTreeBase>::ChildrenGetter<
/*Inverse=*/true>;
template <>
template <>
inline ClangCFGDomReverseChildrenGetter::ResultTy
ClangCFGDomReverseChildrenGetter::Get(
clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/true>) {
auto IChildren = inverse_children<NodePtr>(N);
ResultTy Ret(IChildren.begin(), IChildren.end());
Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
return Ret;
}
using ClangCFGPostDomChildrenGetter =
SemiNCAInfo<clang::CFGPostDomTree::DominatorTreeBase>::ChildrenGetter<
/*Inverse=*/false>;
template <>
template <>
inline ClangCFGPostDomChildrenGetter::ResultTy
ClangCFGPostDomChildrenGetter::Get(
clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/false>) {
auto RChildren = reverse(children<NodePtr>(N));
ResultTy Ret(RChildren.begin(), RChildren.end());
Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
return Ret;
}
using ClangCFGPostDomReverseChildrenGetter =
SemiNCAInfo<clang::CFGPostDomTree::DominatorTreeBase>::ChildrenGetter<
/*Inverse=*/true>;
template <>
template <>
inline ClangCFGPostDomReverseChildrenGetter::ResultTy
ClangCFGPostDomReverseChildrenGetter::Get(
clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/true>) {
auto IChildren = inverse_children<NodePtr>(N);
ResultTy Ret(IChildren.begin(), IChildren.end());
Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
return Ret;
}
} // end of namespace DomTreeBuilder
//===------------------------------------- //===-------------------------------------
/// DominatorTree GraphTraits specialization so the DominatorTree can be /// DominatorTree GraphTraits specialization so the DominatorTree can be
/// iterable by generic graph iterators. /// iterable by generic graph iterators.

View File

@ -103,31 +103,13 @@ struct SemiNCAInfo {
// in progress, we need this information to continue it. // in progress, we need this information to continue it.
} }
template <bool Inversed> struct ChildrenGetter { template <bool Inversed>
using ResultTy = SmallVector<NodePtr, 8>; static SmallVector<NodePtr, 8> getChildren(NodePtr N, BatchUpdatePtr BUI) {
if (BUI)
static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) {
auto RChildren = reverse(children<NodePtr>(N));
return ResultTy(RChildren.begin(), RChildren.end());
}
static ResultTy Get(NodePtr N, std::integral_constant<bool, true>) {
auto IChildren = inverse_children<NodePtr>(N);
return ResultTy(IChildren.begin(), IChildren.end());
}
using Tag = std::integral_constant<bool, Inversed>;
// The function below is the core part of the batch updater. It allows the
// Depth Based Search algorithm to perform incremental updates in lockstep
// with updates to the CFG. We emulated lockstep CFG updates by getting its
// next snapshots by reverse-applying future updates.
static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) {
if (!BUI)
return Get(N, Tag());
return BUI->PreViewCFG.template getChildren<Inversed>(N); return BUI->PreViewCFG.template getChildren<Inversed>(N);
} GraphDiffT GD;
}; return GD.template getChildren<Inversed>(N);
}
NodePtr getIDom(NodePtr BB) const { NodePtr getIDom(NodePtr BB) const {
auto InfoIt = NodeToInfo.find(BB); auto InfoIt = NodeToInfo.find(BB);
@ -194,8 +176,7 @@ struct SemiNCAInfo {
NumToNode.push_back(BB); NumToNode.push_back(BB);
constexpr bool Direction = IsReverse != IsPostDom; // XOR. constexpr bool Direction = IsReverse != IsPostDom; // XOR.
for (const NodePtr Succ : for (const NodePtr Succ : getChildren<Direction>(BB, BatchUpdates)) {
ChildrenGetter<Direction>::Get(BB, BatchUpdates)) {
const auto SIT = NodeToInfo.find(Succ); const auto SIT = NodeToInfo.find(Succ);
// Don't visit nodes more than once but remember to collect // Don't visit nodes more than once but remember to collect
// ReverseChildren. // ReverseChildren.
@ -330,7 +311,7 @@ struct SemiNCAInfo {
// to CFG nodes within infinite loops. // to CFG nodes within infinite loops.
static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) { static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) {
assert(N && "N must be a valid node"); assert(N && "N must be a valid node");
return !ChildrenGetter<false>::Get(N, BUI).empty(); return !getChildren<false>(N, BUI).empty();
} }
static NodePtr GetEntryNode(const DomTreeT &DT) { static NodePtr GetEntryNode(const DomTreeT &DT) {
@ -748,8 +729,7 @@ struct SemiNCAInfo {
// //
// Invariant: there is an optimal path from `To` to TN with the minimum // Invariant: there is an optimal path from `To` to TN with the minimum
// depth being CurrentLevel. // depth being CurrentLevel.
for (const NodePtr Succ : for (const NodePtr Succ : getChildren<IsPostDom>(TN->getBlock(), BUI)) {
ChildrenGetter<IsPostDom>::Get(TN->getBlock(), BUI)) {
const TreeNodePtr SuccTN = DT.getNode(Succ); const TreeNodePtr SuccTN = DT.getNode(Succ);
assert(SuccTN && assert(SuccTN &&
"Unreachable successor found at reachable insertion"); "Unreachable successor found at reachable insertion");
@ -879,7 +859,7 @@ struct SemiNCAInfo {
// the DomTree about it. // the DomTree about it.
// The check is O(N), so run it only in debug configuration. // The check is O(N), so run it only in debug configuration.
auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) { auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) {
auto Successors = ChildrenGetter<IsPostDom>::Get(Of, BUI); auto Successors = getChildren<IsPostDom>(Of, BUI);
return llvm::find(Successors, SuccCandidate) != Successors.end(); return llvm::find(Successors, SuccCandidate) != Successors.end();
}; };
(void)IsSuccessor; (void)IsSuccessor;
@ -967,7 +947,7 @@ struct SemiNCAInfo {
LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN) LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN)
<< "\n"); << "\n");
auto TNB = TN->getBlock(); auto TNB = TN->getBlock();
for (const NodePtr Pred : ChildrenGetter<!IsPostDom>::Get(TNB, BUI)) { for (const NodePtr Pred : getChildren<!IsPostDom>(TNB, BUI)) {
LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n"); LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n");
if (!DT.getNode(Pred)) continue; if (!DT.getNode(Pred)) continue;