Skip to content

Commit 2439bee

Browse files
committed
[DomTreeUpdater] Move critical edge splitting code to updater
1 parent 87c35d7 commit 2439bee

27 files changed

+267
-304
lines changed

llvm/include/llvm/Analysis/GenericDomTreeUpdater.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ class GenericDomTreeUpdater {
105105
return PendUpdates.size() != PendPDTUpdateIndex;
106106
}
107107

108+
bool hasPendingCriticalEdges() const {
109+
if (!PDT && !DT)
110+
return false;
111+
return !CriticalEdgesToSplit.empty();
112+
}
113+
108114
///@{
109115
/// \name Mutation APIs
110116
///
@@ -146,8 +152,25 @@ class GenericDomTreeUpdater {
146152
/// 2. It is illegal to submit any update that has already been submitted,
147153
/// i.e., you are supposed not to insert an existent edge or delete a
148154
/// nonexistent edge.
155+
/// 3. This kind updates are incompatible with critical edge splitting
156+
/// updates, call this method will apply all critical edge updates in
157+
/// lazy mode. It is not recommended to interleave applyUpdates and
158+
/// applyUpdatesForCriticalEdgeSplitting.
149159
void applyUpdates(ArrayRef<typename DomTreeT::UpdateType> Updates);
150160

161+
/// Apply updates that the critical edge (FromBB, ToBB) has been
162+
/// split with NewBB.
163+
///
164+
/// \note Do not use this method with regular edges.
165+
///
166+
/// \note This kind updates are incompatible with generic updates,
167+
/// call this method will submit all generic updates in lazy mode.
168+
/// It is not recommended to interleave applyUpdates and
169+
/// applyUpdatesForCriticalEdgeSplitting.
170+
void applyUpdatesForCriticalEdgeSplitting(BasicBlockT *FromBB,
171+
BasicBlockT *ToBB,
172+
BasicBlockT *NewBB);
173+
151174
/// Submit updates to all available trees. It will also
152175
/// 1. discard duplicated updates,
153176
/// 2. remove invalid updates. (Invalid updates means deletion of an edge that
@@ -197,6 +220,7 @@ class GenericDomTreeUpdater {
197220
applyDomTreeUpdates();
198221
applyPostDomTreeUpdates();
199222
dropOutOfDateUpdates();
223+
applySplitCriticalEdges();
200224
}
201225

202226
///@}
@@ -243,6 +267,35 @@ class GenericDomTreeUpdater {
243267
/// Drop all updates applied by all available trees and delete BasicBlocks if
244268
/// all available trees are up-to-date.
245269
void dropOutOfDateUpdates();
270+
271+
private:
272+
/// Helper structure used to hold all the basic blocks
273+
/// involved in the split of a critical edge.
274+
struct CriticalEdge {
275+
BasicBlockT *FromBB;
276+
BasicBlockT *ToBB;
277+
BasicBlockT *NewBB;
278+
};
279+
280+
/// Pile up all the critical edges to be split.
281+
/// The splitting of a critical edge is local and thus, it is possible
282+
/// to apply several of those changes at the same time.
283+
SmallVector<CriticalEdge, 32> CriticalEdgesToSplit;
284+
285+
/// Remember all the basic blocks that are inserted during
286+
/// edge splitting.
287+
/// Invariant: NewBBs == all the basic blocks contained in the NewBB
288+
/// field of all the elements of CriticalEdgesToSplit.
289+
/// I.e., forall elt in CriticalEdgesToSplit, it exists BB in NewBBs
290+
/// such as BB == elt.NewBB.
291+
SmallSet<BasicBlockT *, 32> NewBBs;
292+
293+
/// Apply all the recorded critical edges to the DT.
294+
/// This updates the underlying DT information in a way that uses
295+
/// the fast query path of DT as much as possible.
296+
///
297+
/// \post CriticalEdgesToSplit.empty().
298+
void applySplitCriticalEdges();
246299
};
247300

248301
} // namespace llvm

llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#ifndef LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
1717
#define LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
1818

19+
#include "llvm/ADT/SmallBitVector.h"
1920
#include "llvm/Analysis/GenericDomTreeUpdater.h"
2021
#include "llvm/Support/Debug.h"
2122
#include "llvm/Support/raw_ostream.h"
@@ -61,6 +62,9 @@ void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::applyUpdates(
6162
return;
6263

6364
if (Strategy == UpdateStrategy::Lazy) {
65+
if (!CriticalEdgesToSplit.empty())
66+
applySplitCriticalEdges();
67+
6468
PendUpdates.reserve(PendUpdates.size() + Updates.size());
6569
for (const auto &U : Updates)
6670
if (!isSelfDominance(U))
@@ -348,6 +352,123 @@ void GenericDomTreeUpdater<DerivedT, DomTreeT,
348352
PendPDTUpdateIndex -= dropIndex;
349353
}
350354

355+
template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
356+
void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::
357+
applyUpdatesForCriticalEdgeSplitting(BasicBlockT *FromBB, BasicBlockT *ToBB,
358+
BasicBlockT *NewBB) {
359+
if (!DT && !PDT)
360+
return;
361+
CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB});
362+
bool Inserted = NewBBs.insert(NewBB).second;
363+
(void)Inserted;
364+
assert(Inserted &&
365+
"A basic block inserted via edge splitting cannot appear twice");
366+
if (Strategy == UpdateStrategy::Lazy) {
367+
applyDomTreeUpdates();
368+
applyPostDomTreeUpdates();
369+
}
370+
if (Strategy == UpdateStrategy::Eager)
371+
applySplitCriticalEdges();
372+
}
373+
374+
template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
375+
void GenericDomTreeUpdater<DerivedT, DomTreeT,
376+
PostDomTreeT>::applySplitCriticalEdges() {
377+
// Bail out early if there is nothing to do.
378+
if (CriticalEdgesToSplit.empty())
379+
return;
380+
381+
// For each element in CriticalEdgesToSplit, remember whether or not element
382+
// is the new immediate domminator of its successor. The mapping is done by
383+
// index, i.e., the information for the ith element of CriticalEdgesToSplit is
384+
// the ith element of IsNewIDom.
385+
SmallBitVector IsNewIDom(CriticalEdgesToSplit.size(), true);
386+
SmallBitVector IsNewIPDom(CriticalEdgesToSplit.size(), true);
387+
size_t Idx = 0;
388+
389+
// Collect all the dominance properties info, before invalidating
390+
// the underlying DT.
391+
for (CriticalEdge &Edge : CriticalEdgesToSplit) {
392+
// Update dominator information.
393+
if (DT) {
394+
BasicBlockT *Succ = Edge.ToBB;
395+
auto *SuccDTNode = DT->getNode(Succ);
396+
397+
for (BasicBlockT *PredBB : predecessors(Succ)) {
398+
if (PredBB == Edge.NewBB)
399+
continue;
400+
// If we are in this situation:
401+
// FromBB1 FromBB2
402+
// + +
403+
// + + + +
404+
// + + + +
405+
// ... Split1 Split2 ...
406+
// + +
407+
// + +
408+
// +
409+
// Succ
410+
// Instead of checking the domiance property with Split2, we check it
411+
// with FromBB2 since Split2 is still unknown of the underlying DT
412+
// structure.
413+
if (NewBBs.count(PredBB)) {
414+
assert(pred_size(PredBB) == 1 && "A basic block resulting from a "
415+
"critical edge split has more "
416+
"than one predecessor!");
417+
PredBB = *pred_begin(PredBB);
418+
}
419+
if (!DT->dominates(SuccDTNode, DT->getNode(PredBB))) {
420+
IsNewIDom[Idx] = false;
421+
break;
422+
}
423+
}
424+
}
425+
426+
// Same as DT version but from another direction.
427+
if (PDT) {
428+
BasicBlockT *Pred = Edge.FromBB;
429+
auto *PredDTNode = PDT->getNode(Pred);
430+
for (BasicBlockT *SuccBB : successors(Pred)) {
431+
if (SuccBB == Edge.NewBB)
432+
continue;
433+
if (NewBBs.count(SuccBB)) {
434+
assert(succ_size(SuccBB) == 1 && "A basic block resulting from a "
435+
"critical edge split has more "
436+
"than one predecessor!");
437+
SuccBB = *succ_begin(SuccBB);
438+
}
439+
if (!PDT->dominates(PredDTNode, PDT->getNode(SuccBB))) {
440+
IsNewIPDom[Idx] = false;
441+
break;
442+
}
443+
}
444+
}
445+
++Idx;
446+
}
447+
448+
// Now, update DT with the collected dominance properties info.
449+
Idx = 0;
450+
for (CriticalEdge &Edge : CriticalEdgesToSplit) {
451+
if (DT) {
452+
// We know FromBB dominates NewBB.
453+
auto *NewDTNode = DT->addNewBlock(Edge.NewBB, Edge.FromBB);
454+
455+
// If all the other predecessors of "Succ" are dominated by "Succ" itself
456+
// then the new block is the new immediate dominator of "Succ". Otherwise,
457+
// the new block doesn't dominate anything.
458+
if (IsNewIDom[Idx])
459+
DT->changeImmediateDominator(DT->getNode(Edge.ToBB), NewDTNode);
460+
}
461+
if (PDT) {
462+
auto *NewPDTNode = PDT->addNewBlock(Edge.NewBB, Edge.ToBB);
463+
if (IsNewIPDom[Idx])
464+
PDT->changeImmediateDominator(PDT->getNode(Edge.FromBB), NewPDTNode);
465+
}
466+
++Idx;
467+
}
468+
NewBBs.clear();
469+
CriticalEdgesToSplit.clear();
470+
}
471+
351472
} // namespace llvm
352473

353474
#endif // LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H

llvm/include/llvm/CodeGen/MachineBasicBlock.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
namespace llvm {
3333

3434
class BasicBlock;
35+
class MachineDomTreeUpdater;
3536
class MachineFunction;
3637
class MCSymbol;
3738
class ModuleSlotTracker;
@@ -970,15 +971,17 @@ class MachineBasicBlock
970971
/// MachineLoopInfo, as applicable.
971972
MachineBasicBlock *
972973
SplitCriticalEdge(MachineBasicBlock *Succ, Pass &P,
973-
std::vector<SparseBitVector<>> *LiveInSets = nullptr) {
974-
return SplitCriticalEdge(Succ, &P, nullptr, LiveInSets);
974+
std::vector<SparseBitVector<>> *LiveInSets = nullptr,
975+
MachineDomTreeUpdater *MDTU = nullptr) {
976+
return SplitCriticalEdge(Succ, &P, nullptr, LiveInSets, MDTU);
975977
}
976978

977979
MachineBasicBlock *
978980
SplitCriticalEdge(MachineBasicBlock *Succ,
979981
MachineFunctionAnalysisManager &MFAM,
980-
std::vector<SparseBitVector<>> *LiveInSets = nullptr) {
981-
return SplitCriticalEdge(Succ, nullptr, &MFAM, LiveInSets);
982+
std::vector<SparseBitVector<>> *LiveInSets = nullptr,
983+
MachineDomTreeUpdater *MDTU = nullptr) {
984+
return SplitCriticalEdge(Succ, nullptr, &MFAM, LiveInSets, MDTU);
982985
}
983986

984987
/// Check if the edge between this block and the given successor \p
@@ -1256,10 +1259,9 @@ class MachineBasicBlock
12561259
void removePredecessor(MachineBasicBlock *Pred);
12571260

12581261
// Helper method for new pass manager migration.
1259-
MachineBasicBlock *
1260-
SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P,
1261-
MachineFunctionAnalysisManager *MFAM,
1262-
std::vector<SparseBitVector<>> *LiveInSets);
1262+
MachineBasicBlock *SplitCriticalEdge(
1263+
MachineBasicBlock *Succ, Pass *P, MachineFunctionAnalysisManager *MFAM,
1264+
std::vector<SparseBitVector<>> *LiveInSets, MachineDomTreeUpdater *MDTU);
12631265
};
12641266

12651267
raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB);
@@ -1341,6 +1343,12 @@ inline auto successors(const MachineBasicBlock *BB) { return BB->successors(); }
13411343
inline auto predecessors(const MachineBasicBlock *BB) {
13421344
return BB->predecessors();
13431345
}
1346+
inline auto succ_size(const MachineBasicBlock *BB) { return BB->succ_size(); }
1347+
inline auto pred_size(const MachineBasicBlock *BB) { return BB->pred_size(); }
1348+
inline auto succ_begin(const MachineBasicBlock *BB) { return BB->succ_begin(); }
1349+
inline auto pred_begin(const MachineBasicBlock *BB) { return BB->pred_begin(); }
1350+
inline auto succ_end(const MachineBasicBlock *BB) { return BB->succ_end(); }
1351+
inline auto pred_end(const MachineBasicBlock *BB) { return BB->pred_end(); }
13441352

13451353
/// MachineInstrSpan provides an interface to get an iteration range
13461354
/// containing the instruction it was initialized with, along with all

0 commit comments

Comments
 (0)