Skip to content

Commit 13dfae7

Browse files
authored
Merge pull request #17258 from aschwaighofer/cleanup_cfg_after_noreturn_folding
2 parents a700e23 + f7a4ed8 commit 13dfae7

File tree

5 files changed

+72
-47
lines changed

5 files changed

+72
-47
lines changed

include/swift/SILOptimizer/Utils/CFG.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ void completeJointPostDominanceSet(
171171
ArrayRef<SILBasicBlock *> UserBlocks, ArrayRef<SILBasicBlock *> DefBlocks,
172172
llvm::SmallVectorImpl<SILBasicBlock *> &Completion);
173173

174+
/// \brief Remove all unreachable blocks in a function.
175+
bool removeUnreachableBlocks(SILFunction &Fn);
176+
174177
} // end namespace swift
175178

176179
#endif

lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/SIL/SILBuilder.h"
2121
#include "swift/SIL/SILUndef.h"
2222
#include "swift/SILOptimizer/Utils/Local.h"
23+
#include "swift/SILOptimizer/Utils/CFG.h"
2324
#include "swift/SILOptimizer/PassManager/Transforms.h"
2425
#include "llvm/ADT/STLExtras.h"
2526
#include "llvm/ADT/Statistic.h"
@@ -750,13 +751,16 @@ static void performNoReturnFunctionProcessing(SILFunction &Fn,
750751
SILFunctionTransform *T) {
751752
DEBUG(llvm::errs() << "*** No return function processing: " << Fn.getName()
752753
<< "\n");
753-
754+
bool Changed = false;
754755
for (auto &BB : Fn) {
755756
// Remove instructions from the basic block after a call to a noreturn
756757
// function.
757-
simplifyBlocksWithCallsToNoReturn(BB, nullptr);
758+
Changed |= simplifyBlocksWithCallsToNoReturn(BB, nullptr);
759+
}
760+
if (Changed) {
761+
removeUnreachableBlocks(Fn);
762+
T->invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
758763
}
759-
T->invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
760764
}
761765

762766
static void diagnoseUnreachable(SILFunction &Fn) {

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 4 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,6 @@ namespace {
191191
void findLoopHeaders();
192192
};
193193

194-
class RemoveUnreachable {
195-
SILFunction &Fn;
196-
llvm::SmallSet<SILBasicBlock *, 8> Visited;
197-
public:
198-
RemoveUnreachable(SILFunction &Fn) : Fn(Fn) { }
199-
void visit(SILBasicBlock *BB);
200-
bool run();
201-
};
202194
} // end anonymous namespace
203195

204196
/// Return true if there are any users of V outside the specified block.
@@ -2161,36 +2153,6 @@ bool SimplifyCFG::simplifyTermWithIdenticalDestBlocks(SILBasicBlock *BB) {
21612153
return true;
21622154
}
21632155

2164-
void RemoveUnreachable::visit(SILBasicBlock *BB) {
2165-
if (!Visited.insert(BB).second)
2166-
return;
2167-
2168-
for (auto &Succ : BB->getSuccessors())
2169-
visit(Succ);
2170-
}
2171-
2172-
bool RemoveUnreachable::run() {
2173-
bool Changed = false;
2174-
2175-
// Clear each time we run so that we can run multiple times.
2176-
Visited.clear();
2177-
2178-
// Visit all blocks reachable from the entry block of the function.
2179-
visit(&*Fn.begin());
2180-
2181-
// Remove the blocks we never reached.
2182-
for (auto It = Fn.begin(), End = Fn.end(); It != End; ) {
2183-
auto *BB = &*It++;
2184-
if (!Visited.count(BB)) {
2185-
DEBUG(llvm::dbgs() << "remove unreachable bb" << BB->getDebugID() << '\n');
2186-
removeDeadBlock(BB);
2187-
Changed = true;
2188-
}
2189-
}
2190-
2191-
return Changed;
2192-
}
2193-
21942156
/// Checks if the block contains a cond_fail as first side-effect instruction
21952157
/// and tries to move it to the predecessors (if beneficial). A sequence
21962158
///
@@ -2844,10 +2806,8 @@ bool SimplifyCFG::run() {
28442806

28452807
DEBUG(llvm::dbgs() << "### Run SimplifyCFG on " << Fn.getName() << '\n');
28462808

2847-
RemoveUnreachable RU(Fn);
2848-
28492809
// First remove any block not reachable from the entry.
2850-
bool Changed = RU.run();
2810+
bool Changed = removeUnreachableBlocks(Fn);
28512811

28522812
// Find the set of loop headers. We don't want to jump-thread through headers.
28532813
findLoopHeaders();
@@ -2860,7 +2820,7 @@ bool SimplifyCFG::run() {
28602820
if (simplifyBlocks()) {
28612821
// Simplifying other blocks might have resulted in unreachable
28622822
// loops.
2863-
RU.run();
2823+
removeUnreachableBlocks(Fn);
28642824

28652825
Changed = true;
28662826
}
@@ -2880,14 +2840,14 @@ bool SimplifyCFG::run() {
28802840
if (simplifyBlocks()) {
28812841
// Simplifying other blocks might have resulted in unreachable
28822842
// loops.
2883-
RU.run();
2843+
removeUnreachableBlocks(Fn);
28842844
Changed = true;
28852845
}
28862846

28872847
if (tailDuplicateObjCMethodCallSuccessorBlocks()) {
28882848
Changed = true;
28892849
if (simplifyBlocks())
2890-
RU.run();
2850+
removeUnreachableBlocks(Fn);
28912851
}
28922852

28932853
// Split all critical edges from non cond_br terminators.

lib/SILOptimizer/Utils/CFG.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "swift/SIL/SILArgument.h"
1616
#include "swift/SIL/SILBuilder.h"
1717
#include "swift/SILOptimizer/Utils/CFG.h"
18+
#include "swift/SILOptimizer/Utils/Local.h"
1819

1920
using namespace swift;
2021

@@ -968,3 +969,47 @@ bool swift::splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &Fn,
968969

969970
return true;
970971
}
972+
973+
namespace {
974+
class RemoveUnreachable {
975+
SILFunction &Fn;
976+
llvm::SmallSet<SILBasicBlock *, 8> Visited;
977+
public:
978+
RemoveUnreachable(SILFunction &Fn) : Fn(Fn) { }
979+
void visit(SILBasicBlock *BB);
980+
bool run();
981+
};
982+
} // end anonymous namespace
983+
984+
void RemoveUnreachable::visit(SILBasicBlock *BB) {
985+
if (!Visited.insert(BB).second)
986+
return;
987+
988+
for (auto &Succ : BB->getSuccessors())
989+
visit(Succ);
990+
}
991+
992+
bool RemoveUnreachable::run() {
993+
bool Changed = false;
994+
995+
// Clear each time we run so that we can run multiple times.
996+
Visited.clear();
997+
998+
// Visit all blocks reachable from the entry block of the function.
999+
visit(&*Fn.begin());
1000+
1001+
// Remove the blocks we never reached.
1002+
for (auto It = Fn.begin(), End = Fn.end(); It != End; ) {
1003+
auto *BB = &*It++;
1004+
if (!Visited.count(BB)) {
1005+
removeDeadBlock(BB);
1006+
Changed = true;
1007+
}
1008+
}
1009+
1010+
return Changed;
1011+
}
1012+
1013+
bool swift::removeUnreachableBlocks(SILFunction &Fn) {
1014+
return RemoveUnreachable(Fn).run();
1015+
}

test/SILOptimizer/mandatory_inlining.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,16 @@ public class A {
175175
}
176176
}
177177
}
178+
179+
// This used to crash during mandatory inlining because noreturn folding would
180+
// create sil instructions with undef in unreachable code.
181+
func dontCrash() {
182+
fatalError() // expected-note {{a call to a never-returning function}}
183+
let k = "foo" // expected-warning {{will never be executed}}
184+
switch k {
185+
case "bar":
186+
return
187+
default:
188+
fatalError("baz \(k)")
189+
}
190+
}

0 commit comments

Comments
 (0)