Skip to content

Commit dd37265

Browse files
authored
[CodeGenPrepare] Cache known-live PHIs when deleting dead PHI chains (#207191)
This patch fixes a compile-time issue in CodeGenPrepare for huge functions. `DeleteDeadPHIs` may repeatedly prove overlapping PHI chains non-dead. For very large functions, many PHIs can share the same non-dead def-use suffix, causing the same suffix to be scanned many times. Add an `KnownNonDeadPHIs` cache to `RecursivelyDeleteDeadPHINode` and `DeleteDeadPHIs`. When a chain is proven non-dead, visited PHIs are recorded so later queries can stop once they reach one of them. This reduces the pathological CodeGenPrepare case from ~30mins to ~30s.
1 parent cd85482 commit dd37265

5 files changed

Lines changed: 41 additions & 16 deletions

File tree

llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,10 @@ FoldSingleEntryPHINodes(BasicBlock *BB,
9191
/// recursively delete any operands that become dead as a result. This includes
9292
/// tracing the def-use list from the PHI to see if it is ultimately unused or
9393
/// if it reaches an unused cycle. Return true if any PHIs were deleted.
94-
LLVM_ABI bool DeleteDeadPHIs(BasicBlock *BB,
95-
const TargetLibraryInfo *TLI = nullptr,
96-
MemorySSAUpdater *MSSAU = nullptr);
94+
LLVM_ABI bool
95+
DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr,
96+
MemorySSAUpdater *MSSAU = nullptr,
97+
SmallPtrSetImpl<PHINode *> *KnownNonDeadPHIs = nullptr);
9798

9899
/// Attempts to merge a block into its predecessor, if possible. The return
99100
/// value indicates success or failure.

llvm/include/llvm/Transforms/Utils/Local.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class DataLayout;
2828
class Value;
2929
class WeakTrackingVH;
3030
class WeakVH;
31+
template <typename PtrType> class SmallPtrSetImpl;
3132
template <typename T> class SmallVectorImpl;
3233
class AAResults;
3334
class AllocaInst;
@@ -129,10 +130,10 @@ LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructionsPermissive(
129130
/// by a trivially dead instruction, delete it. If that makes any of its
130131
/// operands trivially dead, delete them too, recursively. Return true if a
131132
/// change was made.
132-
LLVM_ABI bool
133-
RecursivelyDeleteDeadPHINode(PHINode *PN,
134-
const TargetLibraryInfo *TLI = nullptr,
135-
MemorySSAUpdater *MSSAU = nullptr);
133+
LLVM_ABI bool RecursivelyDeleteDeadPHINode(
134+
PHINode *PN, const TargetLibraryInfo *TLI = nullptr,
135+
MemorySSAUpdater *MSSAU = nullptr,
136+
SmallPtrSetImpl<PHINode *> *KnownNonDeadPHIs = nullptr);
136137

137138
/// Scan the specified basic block and try to simplify any instructions in it
138139
/// and recursively delete dead instructions.

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,11 +946,12 @@ bool CodeGenPrepare::eliminateMostlyEmptyBlocks(Function &F, bool &ResetLI) {
946946

947947
ResetLI = false;
948948
bool MadeChange = false;
949+
SmallPtrSet<PHINode *, 32> KnownNonDeadPHIs;
949950
// Note that this intentionally skips the entry block.
950951
for (auto &Block : llvm::drop_begin(F)) {
951952
// Delete phi nodes that could block deleting other empty blocks.
952953
if (!DisableDeletePHIs)
953-
MadeChange |= DeleteDeadPHIs(&Block, TLInfo);
954+
MadeChange |= DeleteDeadPHIs(&Block, TLInfo, nullptr, &KnownNonDeadPHIs);
954955
}
955956

956957
for (auto &Block : llvm::drop_begin(F)) {

llvm/lib/Transforms/Utils/BasicBlockUtils.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,25 @@ bool llvm::FoldSingleEntryPHINodes(BasicBlock *BB,
212212
}
213213

214214
bool llvm::DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI,
215-
MemorySSAUpdater *MSSAU) {
215+
MemorySSAUpdater *MSSAU,
216+
SmallPtrSetImpl<PHINode *> *KnownNonDeadPHIs) {
216217
// Recursively deleting a PHI may cause multiple PHIs to be deleted
217218
// or RAUW'd undef, so use an array of WeakTrackingVH for the PHIs to delete.
218219
SmallVector<WeakTrackingVH, 8> PHIs(llvm::make_pointer_range(BB->phis()));
219220

220-
bool Changed = false;
221-
for (const auto &PHI : PHIs)
222-
if (PHINode *PN = dyn_cast_or_null<PHINode>(PHI.operator Value *()))
223-
Changed |= RecursivelyDeleteDeadPHINode(PN, TLI, MSSAU);
221+
SmallPtrSet<PHINode *, 32> LocalKnownNonDeadPHIs;
222+
if (!KnownNonDeadPHIs)
223+
KnownNonDeadPHIs = &LocalKnownNonDeadPHIs;
224224

225+
bool Changed = false;
226+
for (const auto &PHI : PHIs) {
227+
if (PHINode *PN = dyn_cast_or_null<PHINode>(PHI.operator Value *())) {
228+
bool PHIChanged = RecursivelyDeleteDeadPHINode(PN, TLI, MSSAU, KnownNonDeadPHIs);
229+
Changed |= PHIChanged;
230+
if (PHIChanged && KnownNonDeadPHIs)
231+
KnownNonDeadPHIs->clear();
232+
}
233+
}
225234
return Changed;
226235
}
227236

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -640,10 +640,12 @@ static bool areAllUsesEqual(Instruction *I) {
640640
/// either forms a cycle or is terminated by a trivially dead instruction,
641641
/// delete it. If that makes any of its operands trivially dead, delete them
642642
/// too, recursively. Return true if a change was made.
643-
bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN,
644-
const TargetLibraryInfo *TLI,
645-
llvm::MemorySSAUpdater *MSSAU) {
643+
bool llvm::RecursivelyDeleteDeadPHINode(
644+
PHINode *PN, const TargetLibraryInfo *TLI, llvm::MemorySSAUpdater *MSSAU,
645+
SmallPtrSetImpl<PHINode *> *KnownNonDeadPHIs) {
646646
SmallPtrSet<Instruction*, 4> Visited;
647+
SmallVector<PHINode *, 8> VisitedPHIs;
648+
647649
for (Instruction *I = PN; areAllUsesEqual(I) && !I->mayHaveSideEffects();
648650
I = cast<Instruction>(*I->user_begin())) {
649651
if (I->use_empty())
@@ -657,7 +659,18 @@ bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN,
657659
(void)RecursivelyDeleteTriviallyDeadInstructions(I, TLI, MSSAU);
658660
return true;
659661
}
662+
663+
if (PHINode *CurPN = dyn_cast<PHINode>(I)) {
664+
if (KnownNonDeadPHIs && KnownNonDeadPHIs->contains(CurPN))
665+
break;
666+
VisitedPHIs.push_back(CurPN);
667+
}
660668
}
669+
670+
if (KnownNonDeadPHIs)
671+
for (PHINode *VisitedPN : VisitedPHIs)
672+
KnownNonDeadPHIs->insert(VisitedPN);
673+
661674
return false;
662675
}
663676

0 commit comments

Comments
 (0)