Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit a57b9df

Browse files
committed
[JumpThreading] Preservation of DT and LVI across the pass
Summary: See D37528 for a previous (non-deferred) version of this patch and its description. Preserves dominance in a deferred manner using a new class DeferredDominance. This reduces the performance impact of updating the DominatorTree at every edge insertion and deletion. A user may call DDT->flush() within JumpThreading for an up-to-date DT. This patch currently has one flush() at the end of runImpl() to ensure DT is preserved across the pass. LVI is also preserved to help subsequent passes such as CorrelatedValuePropagation. LVI is simpler to maintain and is done immediately (not deferred). The code to perform the preversation was minimally altered and simply marked as preserved for the PassManager to be informed. This extends the analysis available to JumpThreading for future enhancements such as threading across loop headers. Reviewers: dberlin, kuhar, sebpop Reviewed By: kuhar, sebpop Subscribers: mgorny, dmgreen, kuba, rnk, rsmith, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D40146 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@322401 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e2b0a2a commit a57b9df

File tree

15 files changed

+1308
-99
lines changed

15 files changed

+1308
-99
lines changed

include/llvm/IR/Dominators.h

+84
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,90 @@ class DominatorTreeWrapperPass : public FunctionPass {
290290
void print(raw_ostream &OS, const Module *M = nullptr) const override;
291291
};
292292

293+
//===-------------------------------------
294+
/// \brief Class to defer updates to a DominatorTree.
295+
///
296+
/// Definition: Applying updates to every edge insertion and deletion is
297+
/// expensive and not necessary. When one needs the DominatorTree for analysis
298+
/// they can request a flush() to perform a larger batch update. This has the
299+
/// advantage of the DominatorTree inspecting the set of updates to find
300+
/// duplicates or unnecessary subtree updates.
301+
///
302+
/// The scope of DeferredDominance operates at a Function level.
303+
///
304+
/// It is not necessary for the user to scrub the updates for duplicates or
305+
/// updates that point to the same block (Delete, BB_A, BB_A). Performance
306+
/// can be gained if the caller attempts to batch updates before submitting
307+
/// to applyUpdates(ArrayRef) in cases where duplicate edge requests will
308+
/// occur.
309+
///
310+
/// It is required for the state of the LLVM IR to be applied *before*
311+
/// submitting updates. The update routines must analyze the current state
312+
/// between a pair of (From, To) basic blocks to determine if the update
313+
/// needs to be queued.
314+
/// Example (good):
315+
/// TerminatorInstructionBB->removeFromParent();
316+
/// DDT->deleteEdge(BB, Successor);
317+
/// Example (bad):
318+
/// DDT->deleteEdge(BB, Successor);
319+
/// TerminatorInstructionBB->removeFromParent();
320+
class DeferredDominance {
321+
public:
322+
DeferredDominance(DominatorTree &DT_) : DT(DT_) {}
323+
324+
/// \brief Queues multiple updates and discards duplicates.
325+
void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates);
326+
327+
/// \brief Helper method for a single edge insertion. It's almost always
328+
/// better to batch updates and call applyUpdates to quickly remove duplicate
329+
/// edges. This is best used when there is only a single insertion needed to
330+
/// update Dominators.
331+
void insertEdge(BasicBlock *From, BasicBlock *To);
332+
333+
/// \brief Helper method for a single edge deletion. It's almost always better
334+
/// to batch updates and call applyUpdates to quickly remove duplicate edges.
335+
/// This is best used when there is only a single deletion needed to update
336+
/// Dominators.
337+
void deleteEdge(BasicBlock *From, BasicBlock *To);
338+
339+
/// \brief Delays the deletion of a basic block until a flush() event.
340+
void deleteBB(BasicBlock *DelBB);
341+
342+
/// \brief Returns true if DelBB is awaiting deletion at a flush() event.
343+
bool pendingDeletedBB(BasicBlock *DelBB);
344+
345+
/// \brief Flushes all pending updates and block deletions. Returns a
346+
/// correct DominatorTree reference to be used by the caller for analysis.
347+
DominatorTree &flush();
348+
349+
/// \brief Drops all internal state and forces a (slow) recalculation of the
350+
/// DominatorTree based on the current state of the LLVM IR in F. This should
351+
/// only be used in corner cases such as the Entry block of F being deleted.
352+
void recalculate(Function &F);
353+
354+
/// \brief Debug method to help view the state of pending updates.
355+
LLVM_DUMP_METHOD void dump() const;
356+
357+
private:
358+
DominatorTree &DT;
359+
SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
360+
SmallPtrSet<BasicBlock *, 8> DeletedBBs;
361+
362+
/// Apply an update (Kind, From, To) to the internal queued updates. The
363+
/// update is only added when determined to be necessary. Checks for
364+
/// self-domination, unnecessary updates, duplicate requests, and balanced
365+
/// pairs of requests are all performed. Returns true if the update is
366+
/// queued and false if it is discarded.
367+
bool applyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
368+
BasicBlock *To);
369+
370+
/// Performs all pending basic block deletions. We have to defer the deletion
371+
/// of these blocks until after the DominatorTree updates are applied. The
372+
/// internal workings of the DominatorTree code expect every update's From
373+
/// and To blocks to exist and to be a member of the same Function.
374+
bool flushDelBB();
375+
};
376+
293377
} // end namespace llvm
294378

295379
#endif // LLVM_IR_DOMINATORS_H

include/llvm/Transforms/Scalar/JumpThreading.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class BinaryOperator;
3434
class BranchInst;
3535
class CmpInst;
3636
class Constant;
37+
class DeferredDominance;
3738
class Function;
3839
class Instruction;
3940
class IntrinsicInst;
@@ -77,6 +78,7 @@ class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> {
7778
TargetLibraryInfo *TLI;
7879
LazyValueInfo *LVI;
7980
AliasAnalysis *AA;
81+
DeferredDominance *DDT;
8082
std::unique_ptr<BlockFrequencyInfo> BFI;
8183
std::unique_ptr<BranchProbabilityInfo> BPI;
8284
bool HasProfileData = false;
@@ -107,8 +109,8 @@ class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> {
107109

108110
// Glue for old PM.
109111
bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_,
110-
AliasAnalysis *AA_, bool HasProfileData_,
111-
std::unique_ptr<BlockFrequencyInfo> BFI_,
112+
AliasAnalysis *AA_, DeferredDominance *DDT_,
113+
bool HasProfileData_, std::unique_ptr<BlockFrequencyInfo> BFI_,
112114
std::unique_ptr<BranchProbabilityInfo> BPI_);
113115

114116
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);

include/llvm/Transforms/Utils/BasicBlockUtils.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace llvm {
2727

2828
class BlockFrequencyInfo;
2929
class BranchProbabilityInfo;
30+
class DeferredDominance;
3031
class DominatorTree;
3132
class Function;
3233
class Instruction;
@@ -38,7 +39,7 @@ class TargetLibraryInfo;
3839
class Value;
3940

4041
/// Delete the specified block, which must have no predecessors.
41-
void DeleteDeadBlock(BasicBlock *BB);
42+
void DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT = nullptr);
4243

4344
/// We know that BB has one predecessor. If there are any single-entry PHI nodes
4445
/// in it, fold them away. This handles the case when all entries to the PHI

include/llvm/Transforms/Utils/Local.h

+13-7
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ struct SimplifyCFGOptions {
117117
/// conditions and indirectbr addresses this might make dead if
118118
/// DeleteDeadConditions is true.
119119
bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false,
120-
const TargetLibraryInfo *TLI = nullptr);
120+
const TargetLibraryInfo *TLI = nullptr,
121+
DeferredDominance *DDT = nullptr);
121122

122123
//===----------------------------------------------------------------------===//
123124
// Local dead code elimination.
@@ -171,18 +172,21 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB,
171172
///
172173
/// .. and delete the predecessor corresponding to the '1', this will attempt to
173174
/// recursively fold the 'and' to 0.
174-
void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred);
175+
void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
176+
DeferredDominance *DDT = nullptr);
175177

176178
/// BB is a block with one predecessor and its predecessor is known to have one
177179
/// successor (BB!). Eliminate the edge between them, moving the instructions in
178180
/// the predecessor into BB. This deletes the predecessor block.
179-
void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr);
181+
void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr,
182+
DeferredDominance *DDT = nullptr);
180183

181184
/// BB is known to contain an unconditional branch, and contains no instructions
182185
/// other than PHI nodes, potential debug intrinsics and the branch. If
183186
/// possible, eliminate BB by rewriting all the predecessors to branch to the
184187
/// successor block and return true. If we can't transform, return false.
185-
bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB);
188+
bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
189+
DeferredDominance *DDT = nullptr);
186190

187191
/// Check for and eliminate duplicate PHI nodes in this block. This doesn't try
188192
/// to be clever about PHI nodes which differ only in the order of the incoming
@@ -385,7 +389,8 @@ unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB);
385389
/// Insert an unreachable instruction before the specified
386390
/// instruction, making it and the rest of the code in the block dead.
387391
unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap,
388-
bool PreserveLCSSA = false);
392+
bool PreserveLCSSA = false,
393+
DeferredDominance *DDT = nullptr);
389394

390395
/// Convert the CallInst to InvokeInst with the specified unwind edge basic
391396
/// block. This also splits the basic block where CI is located, because
@@ -400,12 +405,13 @@ BasicBlock *changeToInvokeAndSplitBasicBlock(CallInst *CI,
400405
///
401406
/// \param BB Block whose terminator will be replaced. Its terminator must
402407
/// have an unwind successor.
403-
void removeUnwindEdge(BasicBlock *BB);
408+
void removeUnwindEdge(BasicBlock *BB, DeferredDominance *DDT = nullptr);
404409

405410
/// Remove all blocks that can not be reached from the function's entry.
406411
///
407412
/// Returns true if any basic block was removed.
408-
bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr);
413+
bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr,
414+
DeferredDominance *DDT = nullptr);
409415

410416
/// Combine the metadata of two instructions so that K can replace J
411417
///

lib/IR/Dominators.cpp

+188
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/ADT/DepthFirstIterator.h"
1919
#include "llvm/ADT/SmallPtrSet.h"
2020
#include "llvm/IR/CFG.h"
21+
#include "llvm/IR/Constants.h"
2122
#include "llvm/IR/Instructions.h"
2223
#include "llvm/IR/PassManager.h"
2324
#include "llvm/Support/CommandLine.h"
@@ -389,3 +390,190 @@ void DominatorTreeWrapperPass::print(raw_ostream &OS, const Module *) const {
389390
DT.print(OS);
390391
}
391392

393+
//===----------------------------------------------------------------------===//
394+
// DeferredDominance Implementation
395+
//===----------------------------------------------------------------------===//
396+
//
397+
// The implementation details of the DeferredDominance class which allows
398+
// one to queue updates to a DominatorTree.
399+
//
400+
//===----------------------------------------------------------------------===//
401+
402+
/// \brief Queues multiple updates and discards duplicates.
403+
void DeferredDominance::applyUpdates(
404+
ArrayRef<DominatorTree::UpdateType> Updates) {
405+
SmallVector<DominatorTree::UpdateType, 8> Seen;
406+
for (auto U : Updates)
407+
// Avoid duplicates to applyUpdate() to save on analysis.
408+
if (std::none_of(Seen.begin(), Seen.end(),
409+
[U](DominatorTree::UpdateType S) { return S == U; })) {
410+
Seen.push_back(U);
411+
applyUpdate(U.getKind(), U.getFrom(), U.getTo());
412+
}
413+
}
414+
415+
/// \brief Helper method for a single edge insertion. It's almost always better
416+
/// to batch updates and call applyUpdates to quickly remove duplicate edges.
417+
/// This is best used when there is only a single insertion needed to update
418+
/// Dominators.
419+
void DeferredDominance::insertEdge(BasicBlock *From, BasicBlock *To) {
420+
applyUpdate(DominatorTree::Insert, From, To);
421+
}
422+
423+
/// \brief Helper method for a single edge deletion. It's almost always better
424+
/// to batch updates and call applyUpdates to quickly remove duplicate edges.
425+
/// This is best used when there is only a single deletion needed to update
426+
/// Dominators.
427+
void DeferredDominance::deleteEdge(BasicBlock *From, BasicBlock *To) {
428+
applyUpdate(DominatorTree::Delete, From, To);
429+
}
430+
431+
/// \brief Delays the deletion of a basic block until a flush() event.
432+
void DeferredDominance::deleteBB(BasicBlock *DelBB) {
433+
assert(DelBB && "Invalid push_back of nullptr DelBB.");
434+
assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
435+
// DelBB is unreachable and all its instructions are dead.
436+
while (!DelBB->empty()) {
437+
Instruction &I = DelBB->back();
438+
// Replace used instructions with an arbitrary value (undef).
439+
if (!I.use_empty())
440+
I.replaceAllUsesWith(llvm::UndefValue::get(I.getType()));
441+
DelBB->getInstList().pop_back();
442+
}
443+
// Make sure DelBB has a valid terminator instruction. As long as DelBB is a
444+
// Child of Function F it must contain valid IR.
445+
new UnreachableInst(DelBB->getContext(), DelBB);
446+
DeletedBBs.insert(DelBB);
447+
}
448+
449+
/// \brief Returns true if DelBB is awaiting deletion at a flush() event.
450+
bool DeferredDominance::pendingDeletedBB(BasicBlock *DelBB) {
451+
if (DeletedBBs.empty())
452+
return false;
453+
return DeletedBBs.count(DelBB) != 0;
454+
}
455+
456+
/// \brief Flushes all pending updates and block deletions. Returns a
457+
/// correct DominatorTree reference to be used by the caller for analysis.
458+
DominatorTree &DeferredDominance::flush() {
459+
// Updates to DT must happen before blocks are deleted below. Otherwise the
460+
// DT traversal will encounter badref blocks and assert.
461+
if (!PendUpdates.empty()) {
462+
DT.applyUpdates(PendUpdates);
463+
PendUpdates.clear();
464+
}
465+
flushDelBB();
466+
return DT;
467+
}
468+
469+
/// \brief Drops all internal state and forces a (slow) recalculation of the
470+
/// DominatorTree based on the current state of the LLVM IR in F. This should
471+
/// only be used in corner cases such as the Entry block of F being deleted.
472+
void DeferredDominance::recalculate(Function &F) {
473+
// flushDelBB must be flushed before the recalculation. The state of the IR
474+
// must be consistent before the DT traversal algorithm determines the
475+
// actual DT.
476+
if (flushDelBB() || !PendUpdates.empty()) {
477+
DT.recalculate(F);
478+
PendUpdates.clear();
479+
}
480+
}
481+
482+
/// \brief Debug method to help view the state of pending updates.
483+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
484+
LLVM_DUMP_METHOD void DeferredDominance::dump() const {
485+
raw_ostream &OS = llvm::dbgs();
486+
OS << "PendUpdates:\n";
487+
int I = 0;
488+
for (auto U : PendUpdates) {
489+
OS << " " << I << " : ";
490+
++I;
491+
if (U.getKind() == DominatorTree::Insert)
492+
OS << "Insert, ";
493+
else
494+
OS << "Delete, ";
495+
BasicBlock *From = U.getFrom();
496+
if (From) {
497+
auto S = From->getName();
498+
if (!From->hasName())
499+
S = "(no name)";
500+
OS << S << "(" << From << "), ";
501+
} else {
502+
OS << "(badref), ";
503+
}
504+
BasicBlock *To = U.getTo();
505+
if (To) {
506+
auto S = To->getName();
507+
if (!To->hasName())
508+
S = "(no_name)";
509+
OS << S << "(" << To << ")\n";
510+
} else {
511+
OS << "(badref)\n";
512+
}
513+
}
514+
OS << "DeletedBBs:\n";
515+
I = 0;
516+
for (auto BB : DeletedBBs) {
517+
OS << " " << I << " : ";
518+
++I;
519+
if (BB->hasName())
520+
OS << BB->getName() << "(";
521+
else
522+
OS << "(no_name)(";
523+
OS << BB << ")\n";
524+
}
525+
}
526+
#endif
527+
528+
/// Apply an update (Kind, From, To) to the internal queued updates. The
529+
/// update is only added when determined to be necessary. Checks for
530+
/// self-domination, unnecessary updates, duplicate requests, and balanced
531+
/// pairs of requests are all performed. Returns true if the update is
532+
/// queued and false if it is discarded.
533+
bool DeferredDominance::applyUpdate(DominatorTree::UpdateKind Kind,
534+
BasicBlock *From, BasicBlock *To) {
535+
if (From == To)
536+
return false; // Cannot dominate self; discard update.
537+
538+
// Discard updates by inspecting the current state of successors of From.
539+
// Since applyUpdate() must be called *after* the Terminator of From is
540+
// altered we can determine if the update is unnecessary.
541+
bool HasEdge = std::any_of(succ_begin(From), succ_end(From),
542+
[To](BasicBlock *B) { return B == To; });
543+
if (Kind == DominatorTree::Insert && !HasEdge)
544+
return false; // Unnecessary Insert: edge does not exist in IR.
545+
if (Kind == DominatorTree::Delete && HasEdge)
546+
return false; // Unnecessary Delete: edge still exists in IR.
547+
548+
// Analyze pending updates to determine if the update is unnecessary.
549+
DominatorTree::UpdateType Update = {Kind, From, To};
550+
DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
551+
? DominatorTree::Insert
552+
: DominatorTree::Delete,
553+
From, To};
554+
for (auto I = PendUpdates.begin(), E = PendUpdates.end(); I != E; ++I) {
555+
if (Update == *I)
556+
return false; // Discard duplicate updates.
557+
if (Invert == *I) {
558+
// Update and Invert are both valid (equivalent to a no-op). Remove
559+
// Invert from PendUpdates and discard the Update.
560+
PendUpdates.erase(I);
561+
return false;
562+
}
563+
}
564+
PendUpdates.push_back(Update); // Save the valid update.
565+
return true;
566+
}
567+
568+
/// Performs all pending basic block deletions. We have to defer the deletion
569+
/// of these blocks until after the DominatorTree updates are applied. The
570+
/// internal workings of the DominatorTree code expect every update's From
571+
/// and To blocks to exist and to be a member of the same Function.
572+
bool DeferredDominance::flushDelBB() {
573+
if (DeletedBBs.empty())
574+
return false;
575+
for (auto *BB : DeletedBBs)
576+
BB->eraseFromParent();
577+
DeletedBBs.clear();
578+
return true;
579+
}

0 commit comments

Comments
 (0)