Skip to content

Commit 76d1551

Browse files
authored
Merge pull request #12622 from dcci/globalopt-worklist
[GlobalOpt] Switch to a worklist to avoid iterator invalidation issues.
2 parents d53f25c + 423eb79 commit 76d1551

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

lib/SILOptimizer/IPO/GlobalOpt.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ class SILGlobalOpt {
108108
bool handleTailAddr(int TailIdx, SILInstruction *I,
109109
llvm::SmallVectorImpl<StoreInst *> &TailStores);
110110

111-
void optimizeObjectAllocation(AllocRefInst *ARI);
111+
void
112+
optimizeObjectAllocation(AllocRefInst *ARI,
113+
llvm::SmallVector<SILInstruction *, 4> &toRemove);
112114
void replaceFindStringCall(ApplyInst *FindStringCall);
113115

114116
SILGlobalVariable *getVariableOfGlobalInit(SILFunction *AddrF);
@@ -1218,7 +1220,8 @@ class GlobalVariableMangler : public Mangle::ASTMangler {
12181220
/// func getarray() -> [Int] {
12191221
/// return [1, 2, 3]
12201222
/// }
1221-
void SILGlobalOpt::optimizeObjectAllocation(AllocRefInst *ARI) {
1223+
void SILGlobalOpt::optimizeObjectAllocation(
1224+
AllocRefInst *ARI, llvm::SmallVector<SILInstruction *, 4> &toRemove) {
12221225

12231226
if (ARI->isObjC())
12241227
return;
@@ -1296,14 +1299,14 @@ void SILGlobalOpt::optimizeObjectAllocation(AllocRefInst *ARI) {
12961299
assert(MemberStore);
12971300
ObjectArgs.push_back(Cloner.clone(
12981301
cast<SingleValueInstruction>(MemberStore->getSrc())));
1299-
MemberStore->eraseFromParent();
1302+
toRemove.push_back(MemberStore);
13001303
}
13011304
// Create the initializers for the tail elements.
13021305
unsigned NumBaseElements = ObjectArgs.size();
13031306
for (StoreInst *TailStore : TailStores) {
13041307
ObjectArgs.push_back(Cloner.clone(
13051308
cast<SingleValueInstruction>(TailStore->getSrc())));
1306-
TailStore->eraseFromParent();
1309+
toRemove.push_back(TailStore);
13071310
}
13081311
// Create the initializer for the object itself.
13091312
SILBuilder StaticInitBuilder(Glob);
@@ -1314,12 +1317,13 @@ void SILGlobalOpt::optimizeObjectAllocation(AllocRefInst *ARI) {
13141317
SILBuilder B(ARI);
13151318
GlobalValueInst *GVI = B.createGlobalValue(ARI->getLoc(), Glob);
13161319
B.createStrongRetain(ARI->getLoc(), GVI, B.getDefaultAtomicity());
1317-
while (!ARI->use_empty()) {
1318-
Operand *Use = *ARI->use_begin();
1320+
llvm::SmallVector<Operand *, 8> Worklist(ARI->use_begin(), ARI->use_end());
1321+
while (!Worklist.empty()) {
1322+
auto *Use = Worklist.pop_back_val();
13191323
SILInstruction *User = Use->getUser();
13201324
switch (User->getKind()) {
13211325
case SILInstructionKind::DeallocRefInst:
1322-
User->eraseFromParent();
1326+
toRemove.push_back(User);
13231327
break;
13241328
default:
13251329
Use->set(GVI);
@@ -1332,8 +1336,7 @@ void SILGlobalOpt::optimizeObjectAllocation(AllocRefInst *ARI) {
13321336
replaceFindStringCall(FindStringCall);
13331337
}
13341338

1335-
ARI->eraseFromParent();
1336-
1339+
toRemove.push_back(ARI);
13371340
HasChanged = true;
13381341
}
13391342

@@ -1456,6 +1459,7 @@ bool SILGlobalOpt::run() {
14561459
for (auto &BB : F) {
14571460
bool IsCold = ColdBlocks.isCold(&BB);
14581461
auto Iter = BB.begin();
1462+
llvm::SmallVector<SILInstruction *, 4> toRemove;
14591463
while (Iter != BB.end()) {
14601464
SILInstruction *I = &*Iter;
14611465
Iter++;
@@ -1473,10 +1477,12 @@ bool SILGlobalOpt::run() {
14731477
// for serializable functions.
14741478
// TODO: We may do the optimization _after_ serialization in the
14751479
// pass pipeline.
1476-
optimizeObjectAllocation(ARI);
1480+
optimizeObjectAllocation(ARI, toRemove);
14771481
}
14781482
}
14791483
}
1484+
for (auto *I : toRemove)
1485+
I->eraseFromParent();
14801486
}
14811487
}
14821488

test/SILOptimizer/globalopt-iter.sil

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -global-opt | %FileCheck %s
2+
3+
4+
import Builtin
5+
import Swift
6+
class B { }
7+
class E : B { }
8+
9+
// CHECK: sil @patatino : $@convention(thin) () -> () {
10+
// CHECK: bb0:
11+
// CHECK: %0 = global_value @patatinoTv_ : $B // user: %1
12+
// CHECK: strong_retain %0 : $B // id: %1
13+
// CHECK: %2 = tuple () // user: %3
14+
// CHECK: return %2 : $() // id: %3
15+
// CHECK: }
16+
17+
sil @patatino : $@convention(thin) () -> () {
18+
%1 = alloc_ref [stack] $B
19+
dealloc_ref [stack] %1 : $B
20+
%45 = tuple ()
21+
return %45 : $()
22+
}

0 commit comments

Comments
 (0)