Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
//===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the DomTreeUpdater class, which provides a uniform way
|
|
|
|
// to update dominator tree related data structures.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/IR/DomTreeUpdater.h"
|
|
|
|
#include "llvm/Analysis/PostDominators.h"
|
|
|
|
#include "llvm/IR/Dominators.h"
|
|
|
|
#include "llvm/Support/GenericDomTree.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <functional>
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
|
|
|
bool DomTreeUpdater::isUpdateValid(
|
|
|
|
const DominatorTree::UpdateType Update) const {
|
|
|
|
const auto *From = Update.getFrom();
|
|
|
|
const auto *To = Update.getTo();
|
|
|
|
const auto Kind = Update.getKind();
|
|
|
|
|
|
|
|
// Discard updates by inspecting the current state of successors of From.
|
|
|
|
// Since isUpdateValid() must be called *after* the Terminator of From is
|
|
|
|
// altered we can determine if the update is unnecessary for batch updates
|
|
|
|
// or invalid for a single update.
|
|
|
|
const bool HasEdge = llvm::any_of(
|
|
|
|
successors(From), [To](const BasicBlock *B) { return B == To; });
|
|
|
|
|
|
|
|
// If the IR does not match the update,
|
|
|
|
// 1. In batch updates, this update is unnecessary.
|
|
|
|
// 2. When called by insertEdge*()/deleteEdge*(), this update is invalid.
|
|
|
|
// Edge does not exist in IR.
|
|
|
|
if (Kind == DominatorTree::Insert && !HasEdge)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Edge exists in IR.
|
|
|
|
if (Kind == DominatorTree::Delete && HasEdge)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DomTreeUpdater::isSelfDominance(
|
|
|
|
const DominatorTree::UpdateType Update) const {
|
|
|
|
// Won't affect DomTree and PostDomTree.
|
|
|
|
return Update.getFrom() == Update.getTo();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DomTreeUpdater::applyLazyUpdate(DominatorTree::UpdateKind Kind,
|
|
|
|
BasicBlock *From, BasicBlock *To) {
|
2018-07-13 22:41:15 +08:00
|
|
|
assert((DT || PDT) &&
|
|
|
|
"Call applyLazyUpdate() when both DT and PDT are nullptrs.");
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
assert(Strategy == DomTreeUpdater::UpdateStrategy::Lazy &&
|
|
|
|
"Call applyLazyUpdate() with Eager strategy error");
|
|
|
|
// Analyze pending updates to determine if the update is unnecessary.
|
|
|
|
const DominatorTree::UpdateType Update = {Kind, From, To};
|
|
|
|
const DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
|
|
|
|
? DominatorTree::Insert
|
|
|
|
: DominatorTree::Delete,
|
|
|
|
From, To};
|
|
|
|
// Only check duplicates in updates that are not applied by both trees.
|
|
|
|
auto I =
|
|
|
|
PendUpdates.begin() + std::max(PendDTUpdateIndex, PendPDTUpdateIndex);
|
|
|
|
const auto E = PendUpdates.end();
|
|
|
|
|
|
|
|
assert(I <= E && "Iterator out of range.");
|
|
|
|
|
|
|
|
for (; I != E; ++I) {
|
|
|
|
if (Update == *I)
|
|
|
|
return false; // Discard duplicate updates.
|
|
|
|
|
|
|
|
if (Invert == *I) {
|
|
|
|
// Update and Invert are both valid (equivalent to a no-op). Remove
|
|
|
|
// Invert from PendUpdates and discard the Update.
|
|
|
|
PendUpdates.erase(I);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PendUpdates.push_back(Update); // Save the valid update.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::applyDomTreeUpdates() {
|
|
|
|
// No pending DomTreeUpdates.
|
|
|
|
if (Strategy != UpdateStrategy::Lazy || !DT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Only apply updates not are applied by DomTree.
|
|
|
|
if (hasPendingDomTreeUpdates()) {
|
|
|
|
const auto I = PendUpdates.begin() + PendDTUpdateIndex;
|
|
|
|
const auto E = PendUpdates.end();
|
|
|
|
assert(I < E && "Iterator range invalid; there should be DomTree updates.");
|
|
|
|
DT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
|
|
|
|
PendDTUpdateIndex = PendUpdates.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::flush() {
|
|
|
|
applyDomTreeUpdates();
|
|
|
|
applyPostDomTreeUpdates();
|
|
|
|
dropOutOfDateUpdates();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::applyPostDomTreeUpdates() {
|
|
|
|
// No pending PostDomTreeUpdates.
|
|
|
|
if (Strategy != UpdateStrategy::Lazy || !PDT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Only apply updates not are applied by PostDomTree.
|
|
|
|
if (hasPendingPostDomTreeUpdates()) {
|
|
|
|
const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
|
|
|
|
const auto E = PendUpdates.end();
|
|
|
|
assert(I < E &&
|
|
|
|
"Iterator range invalid; there should be PostDomTree updates.");
|
|
|
|
PDT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
|
|
|
|
PendPDTUpdateIndex = PendUpdates.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::tryFlushDeletedBB() {
|
|
|
|
if (!hasPendingUpdates())
|
|
|
|
forceFlushDeletedBB();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DomTreeUpdater::forceFlushDeletedBB() {
|
|
|
|
if (DeletedBBs.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (auto *BB : DeletedBBs) {
|
2018-07-25 14:18:33 +08:00
|
|
|
// After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy,
|
|
|
|
// validateDeleteBB() removes all instructions of DelBB and adds an
|
|
|
|
// UnreachableInst as its terminator. So we check whether the BasicBlock to
|
|
|
|
// delete only has an UnreachableInst inside.
|
|
|
|
assert(BB->getInstList().size() == 1 &&
|
|
|
|
isa<UnreachableInst>(BB->getTerminator()) &&
|
|
|
|
"DelBB has been modified while awaiting deletion.");
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
BB->removeFromParent();
|
|
|
|
eraseDelBBNode(BB);
|
|
|
|
delete BB;
|
|
|
|
}
|
|
|
|
DeletedBBs.clear();
|
|
|
|
Callbacks.clear();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-03 14:51:35 +08:00
|
|
|
void DomTreeUpdater::recalculate(Function &F) {
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
|
|
|
|
if (Strategy == UpdateStrategy::Eager) {
|
|
|
|
if (DT)
|
|
|
|
DT->recalculate(F);
|
|
|
|
if (PDT)
|
|
|
|
PDT->recalculate(F);
|
2018-08-03 14:51:35 +08:00
|
|
|
return;
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
}
|
|
|
|
|
2018-08-03 14:51:35 +08:00
|
|
|
// There is little performance gain if we pend the recalculation under
|
|
|
|
// Lazy UpdateStrategy so we recalculate available trees immediately.
|
|
|
|
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
// Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes.
|
|
|
|
IsRecalculatingDomTree = IsRecalculatingPostDomTree = true;
|
|
|
|
|
|
|
|
// Because all trees are going to be up-to-date after recalculation,
|
|
|
|
// flush awaiting deleted BasicBlocks.
|
2018-08-03 14:51:35 +08:00
|
|
|
forceFlushDeletedBB();
|
|
|
|
if (DT)
|
|
|
|
DT->recalculate(F);
|
|
|
|
if (PDT)
|
|
|
|
PDT->recalculate(F);
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
|
|
|
|
// Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
|
|
|
|
IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
|
2018-08-03 14:51:35 +08:00
|
|
|
PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size();
|
|
|
|
dropOutOfDateUpdates();
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DomTreeUpdater::hasPendingUpdates() const {
|
|
|
|
return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DomTreeUpdater::hasPendingDomTreeUpdates() const {
|
|
|
|
if (!DT)
|
|
|
|
return false;
|
|
|
|
return PendUpdates.size() != PendDTUpdateIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const {
|
|
|
|
if (!PDT)
|
|
|
|
return false;
|
|
|
|
return PendUpdates.size() != PendPDTUpdateIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const {
|
|
|
|
if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
|
|
|
|
return false;
|
|
|
|
return DeletedBBs.count(DelBB) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The DT and PDT require the nodes related to updates
|
|
|
|
// are not deleted when update functions are called.
|
|
|
|
// So BasicBlock deletions must be pended when the
|
|
|
|
// UpdateStrategy is Lazy. When the UpdateStrategy is
|
|
|
|
// Eager, the BasicBlock will be deleted immediately.
|
|
|
|
void DomTreeUpdater::deleteBB(BasicBlock *DelBB) {
|
|
|
|
validateDeleteBB(DelBB);
|
|
|
|
if (Strategy == UpdateStrategy::Lazy) {
|
|
|
|
DeletedBBs.insert(DelBB);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DelBB->removeFromParent();
|
|
|
|
eraseDelBBNode(DelBB);
|
|
|
|
delete DelBB;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::callbackDeleteBB(
|
|
|
|
BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback) {
|
|
|
|
validateDeleteBB(DelBB);
|
|
|
|
if (Strategy == UpdateStrategy::Lazy) {
|
|
|
|
Callbacks.push_back(CallBackOnDeletion(DelBB, Callback));
|
|
|
|
DeletedBBs.insert(DelBB);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DelBB->removeFromParent();
|
|
|
|
eraseDelBBNode(DelBB);
|
|
|
|
Callback(DelBB);
|
|
|
|
delete DelBB;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::eraseDelBBNode(BasicBlock *DelBB) {
|
|
|
|
if (DT && !IsRecalculatingDomTree)
|
|
|
|
if (DT->getNode(DelBB))
|
|
|
|
DT->eraseNode(DelBB);
|
|
|
|
|
|
|
|
if (PDT && !IsRecalculatingPostDomTree)
|
|
|
|
if (PDT->getNode(DelBB))
|
|
|
|
PDT->eraseNode(DelBB);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) {
|
|
|
|
assert(DelBB && "Invalid push_back of nullptr DelBB.");
|
|
|
|
assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
|
|
|
|
// DelBB is unreachable and all its instructions are dead.
|
|
|
|
while (!DelBB->empty()) {
|
|
|
|
Instruction &I = DelBB->back();
|
|
|
|
// Replace used instructions with an arbitrary value (undef).
|
|
|
|
if (!I.use_empty())
|
|
|
|
I.replaceAllUsesWith(llvm::UndefValue::get(I.getType()));
|
|
|
|
DelBB->getInstList().pop_back();
|
|
|
|
}
|
|
|
|
// Make sure DelBB has a valid terminator instruction. As long as DelBB is a
|
|
|
|
// Child of Function F it must contain valid IR.
|
|
|
|
new UnreachableInst(DelBB->getContext(), DelBB);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates,
|
|
|
|
bool ForceRemoveDuplicates) {
|
2018-07-13 12:02:13 +08:00
|
|
|
if (!DT && !PDT)
|
|
|
|
return;
|
|
|
|
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
if (Strategy == UpdateStrategy::Lazy || ForceRemoveDuplicates) {
|
|
|
|
SmallVector<DominatorTree::UpdateType, 8> Seen;
|
|
|
|
for (const auto U : Updates)
|
|
|
|
// For Lazy UpdateStrategy, avoid duplicates to applyLazyUpdate() to save
|
|
|
|
// on analysis.
|
|
|
|
if (llvm::none_of(
|
|
|
|
Seen,
|
|
|
|
[U](const DominatorTree::UpdateType S) { return S == U; }) &&
|
|
|
|
isUpdateValid(U) && !isSelfDominance(U)) {
|
|
|
|
Seen.push_back(U);
|
|
|
|
if (Strategy == UpdateStrategy::Lazy)
|
|
|
|
applyLazyUpdate(U.getKind(), U.getFrom(), U.getTo());
|
|
|
|
}
|
|
|
|
if (Strategy == UpdateStrategy::Lazy)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (DT)
|
|
|
|
DT->applyUpdates(Seen);
|
|
|
|
if (PDT)
|
|
|
|
PDT->applyUpdates(Seen);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DT)
|
|
|
|
DT->applyUpdates(Updates);
|
|
|
|
if (PDT)
|
|
|
|
PDT->applyUpdates(Updates);
|
|
|
|
}
|
|
|
|
|
|
|
|
DominatorTree &DomTreeUpdater::getDomTree() {
|
|
|
|
assert(DT && "Invalid acquisition of a null DomTree");
|
|
|
|
applyDomTreeUpdates();
|
|
|
|
dropOutOfDateUpdates();
|
|
|
|
return *DT;
|
|
|
|
}
|
|
|
|
|
|
|
|
PostDominatorTree &DomTreeUpdater::getPostDomTree() {
|
|
|
|
assert(PDT && "Invalid acquisition of a null PostDomTree");
|
|
|
|
applyPostDomTreeUpdates();
|
|
|
|
dropOutOfDateUpdates();
|
|
|
|
return *PDT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::insertEdge(BasicBlock *From, BasicBlock *To) {
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
assert(isUpdateValid({DominatorTree::Insert, From, To}) &&
|
|
|
|
"Inserted edge does not appear in the CFG");
|
|
|
|
#endif
|
|
|
|
|
2018-07-13 12:02:13 +08:00
|
|
|
if (!DT && !PDT)
|
|
|
|
return;
|
|
|
|
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
// Won't affect DomTree and PostDomTree; discard update.
|
|
|
|
if (From == To)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Strategy == UpdateStrategy::Eager) {
|
|
|
|
if (DT)
|
|
|
|
DT->insertEdge(From, To);
|
|
|
|
if (PDT)
|
|
|
|
PDT->insertEdge(From, To);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
applyLazyUpdate(DominatorTree::Insert, From, To);
|
|
|
|
}
|
|
|
|
|
2018-07-13 12:02:13 +08:00
|
|
|
void DomTreeUpdater::insertEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
if (From == To)
|
2018-07-13 12:02:13 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!DT && !PDT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!isUpdateValid({DominatorTree::Insert, From, To}))
|
|
|
|
return;
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
|
|
|
|
if (Strategy == UpdateStrategy::Eager) {
|
|
|
|
if (DT)
|
|
|
|
DT->insertEdge(From, To);
|
|
|
|
if (PDT)
|
|
|
|
PDT->insertEdge(From, To);
|
2018-07-13 12:02:13 +08:00
|
|
|
return;
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
applyLazyUpdate(DominatorTree::Insert, From, To);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::deleteEdge(BasicBlock *From, BasicBlock *To) {
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
assert(isUpdateValid({DominatorTree::Delete, From, To}) &&
|
|
|
|
"Deleted edge still exists in the CFG!");
|
|
|
|
#endif
|
|
|
|
|
2018-07-13 12:02:13 +08:00
|
|
|
if (!DT && !PDT)
|
|
|
|
return;
|
|
|
|
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
// Won't affect DomTree and PostDomTree; discard update.
|
|
|
|
if (From == To)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Strategy == UpdateStrategy::Eager) {
|
|
|
|
if (DT)
|
|
|
|
DT->deleteEdge(From, To);
|
|
|
|
if (PDT)
|
|
|
|
PDT->deleteEdge(From, To);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
applyLazyUpdate(DominatorTree::Delete, From, To);
|
|
|
|
}
|
|
|
|
|
2018-07-13 12:02:13 +08:00
|
|
|
void DomTreeUpdater::deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
if (From == To)
|
2018-07-13 12:02:13 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!DT && !PDT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!isUpdateValid({DominatorTree::Delete, From, To}))
|
|
|
|
return;
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
|
|
|
|
if (Strategy == UpdateStrategy::Eager) {
|
|
|
|
if (DT)
|
|
|
|
DT->deleteEdge(From, To);
|
|
|
|
if (PDT)
|
|
|
|
PDT->deleteEdge(From, To);
|
2018-07-13 12:02:13 +08:00
|
|
|
return;
|
Reappl "[Dominators] Add the DomTreeUpdater class"
Summary:
This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]].
This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process.
—Prior to the patch—
- Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily.
- DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated.
- Functions receiving DT/DDT need to branch a lot which is currently necessary.
- Functions using both DomTree and PostDomTree need to call the update function separately on both trees.
- People need to construct an additional DeferredDominance class to use functions only receiving DDT.
—After the patch—
Patch by Chijun Sima <simachijun@gmail.com>.
Reviewers: kuhar, brzycki, dmgreen, grosser, davide
Reviewed By: kuhar, brzycki
Author: NutshellySima
Subscribers: vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D48383
llvm-svn: 336163
2018-07-03 10:06:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
applyLazyUpdate(DominatorTree::Delete, From, To);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomTreeUpdater::dropOutOfDateUpdates() {
|
|
|
|
if (Strategy == DomTreeUpdater::UpdateStrategy::Eager)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tryFlushDeletedBB();
|
|
|
|
|
|
|
|
// Drop all updates applied by both trees.
|
|
|
|
if (!DT)
|
|
|
|
PendDTUpdateIndex = PendUpdates.size();
|
|
|
|
if (!PDT)
|
|
|
|
PendPDTUpdateIndex = PendUpdates.size();
|
|
|
|
|
|
|
|
const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex);
|
|
|
|
const auto B = PendUpdates.begin();
|
|
|
|
const auto E = PendUpdates.begin() + dropIndex;
|
|
|
|
assert(B <= E && "Iterator out of range.");
|
|
|
|
PendUpdates.erase(B, E);
|
|
|
|
// Calculate current index.
|
|
|
|
PendDTUpdateIndex -= dropIndex;
|
|
|
|
PendPDTUpdateIndex -= dropIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
|
|
LLVM_DUMP_METHOD void DomTreeUpdater::dump() const {
|
|
|
|
raw_ostream &OS = llvm::dbgs();
|
|
|
|
|
|
|
|
OS << "Available Trees: ";
|
|
|
|
if (DT || PDT) {
|
|
|
|
if (DT)
|
|
|
|
OS << "DomTree ";
|
|
|
|
if (PDT)
|
|
|
|
OS << "PostDomTree ";
|
|
|
|
OS << "\n";
|
|
|
|
} else
|
|
|
|
OS << "None\n";
|
|
|
|
|
|
|
|
OS << "UpdateStrategy: ";
|
|
|
|
if (Strategy == UpdateStrategy::Eager) {
|
|
|
|
OS << "Eager\n";
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
OS << "Lazy\n";
|
|
|
|
int Index = 0;
|
|
|
|
|
|
|
|
auto printUpdates =
|
|
|
|
[&](ArrayRef<DominatorTree::UpdateType>::const_iterator begin,
|
|
|
|
ArrayRef<DominatorTree::UpdateType>::const_iterator end) {
|
|
|
|
if (begin == end)
|
|
|
|
OS << " None\n";
|
|
|
|
Index = 0;
|
|
|
|
for (auto It = begin, ItEnd = end; It != ItEnd; ++It) {
|
|
|
|
auto U = *It;
|
|
|
|
OS << " " << Index << " : ";
|
|
|
|
++Index;
|
|
|
|
if (U.getKind() == DominatorTree::Insert)
|
|
|
|
OS << "Insert, ";
|
|
|
|
else
|
|
|
|
OS << "Delete, ";
|
|
|
|
BasicBlock *From = U.getFrom();
|
|
|
|
if (From) {
|
|
|
|
auto S = From->getName();
|
|
|
|
if (!From->hasName())
|
|
|
|
S = "(no name)";
|
|
|
|
OS << S << "(" << From << "), ";
|
|
|
|
} else {
|
|
|
|
OS << "(badref), ";
|
|
|
|
}
|
|
|
|
BasicBlock *To = U.getTo();
|
|
|
|
if (To) {
|
|
|
|
auto S = To->getName();
|
|
|
|
if (!To->hasName())
|
|
|
|
S = "(no_name)";
|
|
|
|
OS << S << "(" << To << ")\n";
|
|
|
|
} else {
|
|
|
|
OS << "(badref)\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (DT) {
|
|
|
|
const auto I = PendUpdates.begin() + PendDTUpdateIndex;
|
|
|
|
assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
|
|
|
|
"Iterator out of range.");
|
|
|
|
OS << "Applied but not cleared DomTreeUpdates:\n";
|
|
|
|
printUpdates(PendUpdates.begin(), I);
|
|
|
|
OS << "Pending DomTreeUpdates:\n";
|
|
|
|
printUpdates(I, PendUpdates.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PDT) {
|
|
|
|
const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
|
|
|
|
assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
|
|
|
|
"Iterator out of range.");
|
|
|
|
OS << "Applied but not cleared PostDomTreeUpdates:\n";
|
|
|
|
printUpdates(PendUpdates.begin(), I);
|
|
|
|
OS << "Pending PostDomTreeUpdates:\n";
|
|
|
|
printUpdates(I, PendUpdates.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << "Pending DeletedBBs:\n";
|
|
|
|
Index = 0;
|
|
|
|
for (auto BB : DeletedBBs) {
|
|
|
|
OS << " " << Index << " : ";
|
|
|
|
++Index;
|
|
|
|
if (BB->hasName())
|
|
|
|
OS << BB->getName() << "(";
|
|
|
|
else
|
|
|
|
OS << "(no_name)(";
|
|
|
|
OS << BB << ")\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << "Pending Callbacks:\n";
|
|
|
|
Index = 0;
|
|
|
|
for (auto BB : Callbacks) {
|
|
|
|
OS << " " << Index << " : ";
|
|
|
|
++Index;
|
|
|
|
if (BB->hasName())
|
|
|
|
OS << BB->getName() << "(";
|
|
|
|
else
|
|
|
|
OS << "(no_name)(";
|
|
|
|
OS << BB << ")\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
} // namespace llvm
|