Skip to content

Commit aef79d0

Browse files
authored
Merge pull request #19103 from atrick/cpf-bug
Fix a bug in CopyForwarding. Bailout during destoy hoisting.
2 parents aa34eb2 + f764b8b commit aef79d0

File tree

2 files changed

+54
-15
lines changed

2 files changed

+54
-15
lines changed

lib/SILOptimizer/Transforms/CopyForwarding.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,8 +1200,19 @@ bool CopyForwarding::hoistDestroy(SILInstruction *DestroyPoint,
12001200

12011201
// If DestroyPoint is a block terminator, we must hoist.
12021202
bool MustHoist = (DestroyPoint == BB->getTerminator());
1203+
// If we haven't seen anything significant, avoid useless hoisting.
1204+
bool ShouldHoist = MustHoist;
1205+
1206+
auto tryToInsertHoistedDestroyAfter = [&](SILInstruction *afterInst) {
1207+
if (!ShouldHoist)
1208+
return false;
1209+
LLVM_DEBUG(llvm::dbgs() << " Hoisting to Use:" << *afterInst);
1210+
SILBuilderWithScope(std::next(afterInst->getIterator()), afterInst)
1211+
.createDestroyAddr(DestroyLoc, CurrentDef);
1212+
HasChanged = true;
1213+
return true;
1214+
};
12031215

1204-
bool IsWorthHoisting = MustHoist;
12051216
auto SI = DestroyPoint->getIterator(), SE = BB->begin();
12061217
while (SI != SE) {
12071218
--SI;
@@ -1219,10 +1230,10 @@ bool CopyForwarding::hoistDestroy(SILInstruction *DestroyPoint,
12191230
// destroy_addr CurrentDef
12201231
LLVM_DEBUG(llvm::dbgs() << " Cannot hoist above stored value use:"
12211232
<< *Inst);
1222-
return false;
1233+
return tryToInsertHoistedDestroyAfter(Inst);
12231234
}
1224-
if (!IsWorthHoisting && isa<ApplyInst>(Inst))
1225-
IsWorthHoisting = true;
1235+
if (!ShouldHoist && isa<ApplyInst>(Inst))
1236+
ShouldHoist = true;
12261237
continue;
12271238
}
12281239
if (auto *CopyInst = dyn_cast<CopyAddrInst>(Inst)) {
@@ -1233,19 +1244,15 @@ bool CopyForwarding::hoistDestroy(SILInstruction *DestroyPoint,
12331244
return true;
12341245
}
12351246
}
1236-
// We reached a user of CurrentDef. If we haven't seen anything significant,
1237-
// avoid useless hoisting.
1238-
if (!IsWorthHoisting)
1239-
return false;
1240-
1241-
LLVM_DEBUG(llvm::dbgs() << " Hoisting to Use:" << *Inst);
1242-
SILBuilderWithScope(std::next(SI), Inst)
1243-
.createDestroyAddr(DestroyLoc, CurrentDef);
1244-
HasChanged = true;
1245-
return true;
1247+
return tryToInsertHoistedDestroyAfter(Inst);
12461248
}
1247-
if (!DoGlobalHoisting)
1249+
if (!DoGlobalHoisting) {
1250+
// If DoGlobalHoisting is set, then we should never mark a DeadInBlock, so
1251+
// MustHoist should be false.
1252+
assert(!MustHoist &&
1253+
"Cannot hoist above a terminator with global hoisting disabled.");
12481254
return false;
1255+
}
12491256
DeadInBlocks.insert(BB);
12501257
return true;
12511258
}

test/SILOptimizer/copyforward.sil

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,3 +883,35 @@ bb0(%0 : $*AClass, %1 : $AClass):
883883
%999 = tuple ()
884884
return %999 : $()
885885
}
886+
887+
// <rdar://problem/43888666> [SR-8526]: Memory leak after switch in release configuration
888+
// CHECK-LABEL: sil @testGlobalHoistToStoredValue : $@convention(thin) (@owned AClass, @inout AClass) -> () {
889+
// CHECK: bb0(%0 : $AClass, %1 : $*AClass):
890+
// CHECK-NEXT: [[LOCAL:%.*]] = alloc_stack $AClass
891+
// CHECK-NEXT: store %0 to [[LOCAL]] : $*AClass
892+
// CHECK-NEXT: copy_addr [[LOCAL]] to %1 : $*AClass
893+
// CHECK-NEXT: retain_value %0 : $AClass
894+
// CHECK-NEXT: store %0 to %1 : $*AClass
895+
// CHECK-NEXT: destroy_addr [[LOCAL]] : $*AClass
896+
// CHECK-NEXT: br bb1
897+
// CHECK: bb1:
898+
// CHECK-NEXT: dealloc_stack [[LOCAL]] : $*AClass
899+
// CHECK-NEXT: release_value %0 : $AClass
900+
// CHECK-NEXT: tuple ()
901+
// CHECK-NEXT: return
902+
// CHECK-LABEL: } // end sil function 'testGlobalHoistToStoredValue'
903+
sil @testGlobalHoistToStoredValue : $@convention(thin) (@owned AClass, @inout AClass) -> () {
904+
bb0(%obj : $AClass, %ptr : $*AClass ):
905+
%local = alloc_stack $AClass
906+
store %obj to %local : $*AClass
907+
copy_addr %local to %ptr : $*AClass
908+
retain_value %obj : $AClass
909+
store %obj to %ptr : $*AClass
910+
br bb1
911+
bb1:
912+
destroy_addr %local : $*AClass
913+
dealloc_stack %local : $*AClass
914+
release_value %obj : $AClass
915+
%v = tuple ()
916+
return %v : $()
917+
}

0 commit comments

Comments
 (0)