[DomTree] Extend update API to allow a post CFG view.

Extend the `applyUpdates` in DominatorTree to allow a post CFG view,
different from the current CFG.
This patch implements the functionality of updating an already up to
date DT, to the desired PostCFGView.
Combining a set of updates towards an up to date DT and a PostCFGView is
not yet supported.

Differential Revision: https://reviews.llvm.org/D85472
This commit is contained in:
Alina Sbirlea 2020-02-26 13:33:02 -08:00
parent bd670142b0
commit d3e372ea8f
5 changed files with 89 additions and 30 deletions

View File

@ -66,9 +66,11 @@ extern template void DeleteEdge<BBPostDomTree>(BBPostDomTree &DT,
BasicBlock *To);
extern template void ApplyUpdates<BBDomTree>(BBDomTree &DT,
BBDomTreeGraphDiff &);
BBDomTreeGraphDiff &,
BBDomTreeGraphDiff *);
extern template void ApplyUpdates<BBPostDomTree>(BBPostDomTree &DT,
BBPostDomTreeGraphDiff &);
BBPostDomTreeGraphDiff &,
BBPostDomTreeGraphDiff *);
extern template bool Verify<BBDomTree>(const BBDomTree &DT,
BBDomTree::VerificationLevel VL);

View File

@ -213,7 +213,9 @@ void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
template <typename DomTreeT>
void ApplyUpdates(DomTreeT &DT,
GraphDiff<typename DomTreeT::NodePtr,
DomTreeT::IsPostDominator> &PreViewCFG);
DomTreeT::IsPostDominator> &PreViewCFG,
GraphDiff<typename DomTreeT::NodePtr,
DomTreeT::IsPostDominator> *PostViewCFG);
template <typename DomTreeT>
bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL);
@ -543,7 +545,30 @@ protected:
void applyUpdates(ArrayRef<UpdateType> Updates) {
GraphDiff<NodePtr, IsPostDominator> PreViewCFG(
Updates, /*ReverseApplyUpdates=*/true);
DomTreeBuilder::ApplyUpdates(*this, PreViewCFG);
DomTreeBuilder::ApplyUpdates(*this, PreViewCFG, nullptr);
}
/// \param Updates An unordered sequence of updates to perform. The current
/// CFG and the reverse of these updates provides the pre-view of the CFG.
/// \param PostViewUpdates An unordered sequence of update to perform in order
/// to obtain a post-view of the CFG. The DT will be updates assuming the
/// obtained PostViewCFG is the desired end state.
void applyUpdates(ArrayRef<UpdateType> Updates,
ArrayRef<UpdateType> PostViewUpdates) {
// GraphDiff<NodePtr, IsPostDom> *PostViewCFG = nullptr) {
if (Updates.empty()) {
GraphDiff<NodePtr, IsPostDom> PostViewCFG(PostViewUpdates);
DomTreeBuilder::ApplyUpdates(*this, PostViewCFG, &PostViewCFG);
} else {
// TODO:
// PreViewCFG needs to merge Updates and PostViewCFG. The updates in
// Updates need to be reversed, and match the direction in PostViewCFG.
// Normally, a PostViewCFG is created without reversing updates, so one
// of the internal vectors needs reversing in order to do the
// legalization of the merged vector of updates.
llvm_unreachable("Currently unsupported to update given a set of "
"updates towards a PostView");
}
}
/// Inform the dominator tree about a CFG edge insertion and update the tree.

View File

@ -79,14 +79,15 @@ struct SemiNCAInfo {
using UpdateKind = typename DomTreeT::UpdateKind;
struct BatchUpdateInfo {
// Note: Updates inside PreViewCFG are aleady legalized.
BatchUpdateInfo(GraphDiffT &PreViewCFG)
: PreViewCFG(PreViewCFG),
BatchUpdateInfo(GraphDiffT &PreViewCFG, GraphDiffT *PostViewCFG = nullptr)
: PreViewCFG(PreViewCFG), PostViewCFG(PostViewCFG),
NumLegalized(PreViewCFG.getNumLegalizedUpdates()) {}
// Remembers if the whole tree was recalculated at some point during the
// current batch update.
bool IsRecalculated = false;
GraphDiffT &PreViewCFG;
GraphDiffT *PostViewCFG;
const size_t NumLegalized;
};
@ -560,12 +561,21 @@ struct SemiNCAInfo {
auto *Parent = DT.Parent;
DT.reset();
DT.Parent = Parent;
SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree,
// there's no point doing it incrementally.
// If the update is using the actual CFG, BUI is null. If it's using a view,
// BUI is non-null and the PreCFGView is used. When calculating from
// scratch, make the PreViewCFG equal to the PostCFGView, so Post is used.
BatchUpdatePtr PostViewBUI = nullptr;
if (BUI && BUI->PostViewCFG) {
BUI->PreViewCFG = *BUI->PostViewCFG;
PostViewBUI = BUI;
}
// This is rebuilding the whole tree, not incrementally, but PostViewBUI is
// used in case the caller needs a DT update with a CFGView.
SemiNCAInfo SNCA(PostViewBUI);
// Step #0: Number blocks in depth-first order and initialize variables used
// in later stages of the algorithm.
DT.Roots = FindRoots(DT, nullptr);
DT.Roots = FindRoots(DT, PostViewBUI);
SNCA.doFullDFSWalk(DT, AlwaysDescend);
SNCA.runSemiNCA(DT);
@ -1139,7 +1149,10 @@ struct SemiNCAInfo {
//===--------------------- DomTree Batch Updater --------------------------===
//~~
static void ApplyUpdates(DomTreeT &DT, GraphDiffT &PreViewCFG) {
static void ApplyUpdates(DomTreeT &DT, GraphDiffT &PreViewCFG,
GraphDiffT *PostViewCFG) {
// Note: the PostViewCFG is only used when computing from scratch. It's data
// should already included in the PreViewCFG for incremental updates.
const size_t NumUpdates = PreViewCFG.getNumLegalizedUpdates();
if (NumUpdates == 0)
return;
@ -1148,14 +1161,22 @@ struct SemiNCAInfo {
// machinery.
if (NumUpdates == 1) {
UpdateT Update = PreViewCFG.popUpdateForIncrementalUpdates();
if (Update.getKind() == UpdateKind::Insert)
InsertEdge(DT, /*BUI=*/nullptr, Update.getFrom(), Update.getTo());
else
DeleteEdge(DT, /*BUI=*/nullptr, Update.getFrom(), Update.getTo());
if (!PostViewCFG) {
if (Update.getKind() == UpdateKind::Insert)
InsertEdge(DT, /*BUI=*/nullptr, Update.getFrom(), Update.getTo());
else
DeleteEdge(DT, /*BUI=*/nullptr, Update.getFrom(), Update.getTo());
} else {
BatchUpdateInfo BUI(*PostViewCFG, PostViewCFG);
if (Update.getKind() == UpdateKind::Insert)
InsertEdge(DT, &BUI, Update.getFrom(), Update.getTo());
else
DeleteEdge(DT, &BUI, Update.getFrom(), Update.getTo());
}
return;
}
BatchUpdateInfo BUI(PreViewCFG);
BatchUpdateInfo BUI(PreViewCFG, PostViewCFG);
// Recalculate the DominatorTree when the number of updates
// exceeds a threshold, which usually makes direct updating slower than
// recalculation. We select this threshold proportional to the
@ -1571,8 +1592,10 @@ void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
template <class DomTreeT>
void ApplyUpdates(DomTreeT &DT,
GraphDiff<typename DomTreeT::NodePtr,
DomTreeT::IsPostDominator> &PreViewCFG) {
SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, PreViewCFG);
DomTreeT::IsPostDominator> &PreViewCFG,
GraphDiff<typename DomTreeT::NodePtr,
DomTreeT::IsPostDominator> *PostViewCFG) {
SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, PreViewCFG, PostViewCFG);
}
template <class DomTreeT>

View File

@ -783,24 +783,32 @@ void MemorySSAUpdater::updateExitBlocksForClonedLoop(
void MemorySSAUpdater::applyUpdates(ArrayRef<CFGUpdate> Updates,
DominatorTree &DT) {
SmallVector<CFGUpdate, 4> DeleteUpdates;
SmallVector<CFGUpdate, 4> RevDeleteUpdates;
SmallVector<CFGUpdate, 4> InsertUpdates;
for (auto &Update : Updates) {
if (Update.getKind() == DT.Insert)
InsertUpdates.push_back({DT.Insert, Update.getFrom(), Update.getTo()});
else
else {
DeleteUpdates.push_back({DT.Delete, Update.getFrom(), Update.getTo()});
RevDeleteUpdates.push_back({DT.Insert, Update.getFrom(), Update.getTo()});
}
}
if (!DeleteUpdates.empty()) {
// Update for inserted edges: use newDT and snapshot CFG as if deletes had
// not occurred.
// FIXME: This creates a new DT, so it's more expensive to do mix
// delete/inserts vs just inserts. We can do an incremental update on the DT
// to revert deletes, than re-delete the edges. Teaching DT to do this, is
// part of a pending cleanup.
DominatorTree NewDT(DT, DeleteUpdates);
GraphDiff<BasicBlock *> GD(DeleteUpdates, /*ReverseApplyUpdates=*/true);
applyInsertUpdates(InsertUpdates, NewDT, &GD);
SmallVector<CFGUpdate, 0> Empty;
// Deletes are reversed applied, because this CFGView is pretending the
// deletes did not happen yet, hence the edges still exist.
DT.applyUpdates(Empty, RevDeleteUpdates);
// Note: the MSSA update below doesn't distinguish between a GD with
// (RevDelete,false) and (Delete, true), but this matters for the DT
// updates above; for "children" purposes they are equivalent; but the
// updates themselves convey the desired update, used inside DT only.
GraphDiff<BasicBlock *> GD(RevDeleteUpdates);
applyInsertUpdates(InsertUpdates, DT, &GD);
// Update DT to redelete edges; this matches the real CFG so we can perform
// the standard update without a postview of the CFG.
DT.applyUpdates(DeleteUpdates);
} else {
GraphDiff<BasicBlock *> GD;
applyInsertUpdates(InsertUpdates, DT, &GD);

View File

@ -90,10 +90,11 @@ template void llvm::DomTreeBuilder::DeleteEdge<DomTreeBuilder::BBPostDomTree>(
DomTreeBuilder::BBPostDomTree &DT, BasicBlock *From, BasicBlock *To);
template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBDomTree>(
DomTreeBuilder::BBDomTree &DT, DomTreeBuilder::BBDomTreeGraphDiff &);
DomTreeBuilder::BBDomTree &DT, DomTreeBuilder::BBDomTreeGraphDiff &,
DomTreeBuilder::BBDomTreeGraphDiff *);
template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBPostDomTree>(
DomTreeBuilder::BBPostDomTree &DT,
DomTreeBuilder::BBPostDomTreeGraphDiff &);
DomTreeBuilder::BBPostDomTree &DT, DomTreeBuilder::BBPostDomTreeGraphDiff &,
DomTreeBuilder::BBPostDomTreeGraphDiff *);
template bool llvm::DomTreeBuilder::Verify<DomTreeBuilder::BBDomTree>(
const DomTreeBuilder::BBDomTree &DT,