forked from OSchip/llvm-project
[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:
parent
0b161def6c
commit
e22de4e46d
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue