Skip to content

Commit d154dfd

Browse files
authored
Merge pull request #64204 from eeckstein/fix-dce
SILOptimizer: fix a stack overflow in DCE
2 parents d346ca4 + 1c844ed commit d154dfd

File tree

6 files changed

+52
-34
lines changed

6 files changed

+52
-34
lines changed

include/swift/SIL/SILBasicBlock.h

-11
Original file line numberDiff line numberDiff line change
@@ -427,11 +427,6 @@ public SwiftObjectHeader {
427427
return getTerminator()->getSingleSuccessorBlock();
428428
}
429429

430-
/// Returns true if \p BB is a successor of this block.
431-
bool isSuccessorBlock(SILBasicBlock *Block) const {
432-
return getTerminator()->isSuccessorBlock(Block);
433-
}
434-
435430
using SuccessorBlockListTy = TermInst::SuccessorBlockListTy;
436431
using ConstSuccessorBlockListTy = TermInst::ConstSuccessorBlockListTy;
437432

@@ -459,12 +454,6 @@ public SwiftObjectHeader {
459454
return {pred_begin(), pred_end()};
460455
}
461456

462-
bool isPredecessorBlock(SILBasicBlock *BB) const {
463-
return any_of(
464-
getPredecessorBlocks(),
465-
[&BB](const SILBasicBlock *PredBB) -> bool { return BB == PredBB; });
466-
}
467-
468457
SILBasicBlock *getSinglePredecessorBlock() {
469458
if (pred_empty() || std::next(pred_begin()) != pred_end())
470459
return nullptr;

include/swift/SIL/SILInstruction.h

-8
Original file line numberDiff line numberDiff line change
@@ -8940,14 +8940,6 @@ class TermInst : public NonValueInstruction {
89408940
return const_cast<TermInst *>(this)->getSingleSuccessorBlock();
89418941
}
89428942

8943-
/// Returns true if \p BB is a successor of this block.
8944-
bool isSuccessorBlock(SILBasicBlock *BB) const {
8945-
auto Range = getSuccessorBlocks();
8946-
return any_of(Range, [&BB](const SILBasicBlock *SuccBB) -> bool {
8947-
return BB == SuccBB;
8948-
});
8949-
}
8950-
89518943
using SuccessorBlockArgumentListTy =
89528944
TransformRange<ConstSuccessorListTy, function_ref<ArrayRef<SILArgument *>(
89538945
const SILSuccessor &)>>;

lib/SIL/Verifier/SILVerifier.cpp

+27-12
Original file line numberDiff line numberDiff line change
@@ -6289,18 +6289,6 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
62896289
}
62906290

62916291
void visitSILBasicBlock(SILBasicBlock *BB) {
6292-
// Make sure that each of the successors/predecessors of this basic block
6293-
// have this basic block in its predecessor/successor list.
6294-
for (const auto *SuccBB : BB->getSuccessorBlocks()) {
6295-
require(SuccBB->isPredecessorBlock(BB),
6296-
"Must be a predecessor of each successor.");
6297-
}
6298-
6299-
for (const SILBasicBlock *PredBB : BB->getPredecessorBlocks()) {
6300-
require(PredBB->isSuccessorBlock(BB),
6301-
"Must be a successor of each predecessor.");
6302-
}
6303-
63046292
SILInstructionVisitor::visitSILBasicBlock(BB);
63056293
verifyDebugScopeHoles(BB);
63066294
}
@@ -6331,6 +6319,33 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
63316319
continue;
63326320
visitSILBasicBlock(&BB);
63336321
}
6322+
6323+
verifyPredecessorSucessorStructure(F);
6324+
}
6325+
6326+
// Make sure that each of the successors/predecessors of a basic block
6327+
// have this basic block in its predecessor/successor list.
6328+
void verifyPredecessorSucessorStructure(SILFunction *f) {
6329+
using PredSuccPair = std::pair<SILBasicBlock *, SILBasicBlock *>;
6330+
llvm::DenseSet<PredSuccPair> foundSuccessors;
6331+
llvm::DenseSet<PredSuccPair> foundPredecessors;
6332+
6333+
for (auto &block : *f) {
6334+
for (SILBasicBlock *succ : block.getSuccessorBlocks()) {
6335+
foundSuccessors.insert({&block, succ});
6336+
}
6337+
for (SILBasicBlock *pred : block.getPredecessorBlocks()) {
6338+
foundPredecessors.insert({pred, &block});
6339+
}
6340+
}
6341+
for (PredSuccPair predSucc : foundSuccessors) {
6342+
require(foundPredecessors.contains(predSucc),
6343+
"block is not predecessor of its successor");
6344+
}
6345+
for (PredSuccPair predSucc : foundPredecessors) {
6346+
require(foundSuccessors.contains(predSucc),
6347+
"block is not successor of its predecessor");
6348+
}
63346349
}
63356350

63366351
void visitSILFunction(SILFunction *F) {

lib/SILOptimizer/Analysis/LoopRegionAnalysis.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,12 @@ void LoopRegionFunctionInfo::verify() {
218218

219219
// If R and OtherR are blocks, then OtherR should be a successor of the
220220
// real block.
221-
if (R->isBlock() && OtherR->isBlock())
222-
assert(R->getBlock()->isSuccessorBlock(OtherR->getBlock()) &&
221+
if (R->isBlock() && OtherR->isBlock()) {
222+
auto succs = R->getBlock()->getSuccessors();
223+
assert(std::find(succs.begin(), succs.end(), OtherR->getBlock()) != succs.end() &&
223224
"Expected either R was not a block or OtherR was a CFG level "
224225
"successor of R.");
226+
}
225227
}
226228
}
227229
#endif

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ void DCE::markInstructionLive(SILInstruction *Inst) {
215215

216216
LLVM_DEBUG(llvm::dbgs() << "Marking as live: " << *Inst);
217217

218-
markControllingTerminatorsLive(Inst->getParent());
219218
Worklist.push_back(Inst);
220219
}
221220

@@ -450,6 +449,8 @@ void DCE::propagateLiveBlockArgument(SILArgument *Arg) {
450449
// Given an instruction which is considered live, propagate that liveness
451450
// back to the instructions that produce values it consumes.
452451
void DCE::propagateLiveness(SILInstruction *I) {
452+
markControllingTerminatorsLive(I->getParent());
453+
453454
if (!isa<TermInst>(I)) {
454455
for (auto &O : I->getAllOperands())
455456
markValueLive(O.get());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %gyb %s > %t/main.swift
3+
// RUN: %target-swift-frontend -O -parse-as-library -sil-verify-none -emit-sil %t/main.swift -o /dev/null
4+
5+
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
6+
// REQUIRES: long_test
7+
8+
// Check that the compiler does not crash in DCE due to a stack overflow.
9+
// rdar://106198943
10+
11+
public func test(_ a: Int) -> Int {
12+
switch (a) {
13+
% for i in range(32000):
14+
case ${i}: return ${i % 7}
15+
% end
16+
default: return -1
17+
}
18+
}
19+

0 commit comments

Comments
 (0)