Skip to content

Commit 8c5fae0

Browse files
authored
Merge pull request #81499 from meg-gupta/fixdropdeinit
Fix InstructionDeleter for drop_deinit instruction
2 parents 9993d29 + 16d1ead commit 8c5fae0

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

lib/SILOptimizer/Utils/InstructionDeleter.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ static bool isScopeAffectingInstructionDead(SILInstruction *inst,
6363
return false;
6464
}
6565

66+
// Don't delete dead drop_deinit instruction. They are a marker to eliminate
67+
// user-defined deinit and we do not want to lose it.
68+
if (isa<DropDeinitInst>(inst)) {
69+
return false;
70+
}
71+
6672
for (auto result : inst->getResults()) {
6773
// If inst has any owned move-only value as a result, deleting it may
6874
// shorten that value's lifetime which is illegal according to language
@@ -268,9 +274,16 @@ void InstructionDeleter::deleteWithUses(SILInstruction *inst, bool fixLifetimes,
268274
if (fixLifetimes) {
269275
LoadInst *li = nullptr;
270276
if (operand.isConsuming()) {
271-
SILBuilderWithScope builder(inst);
272-
auto *dvi = builder.createDestroyValue(inst->getLoc(), operandValue);
273-
getCallbacks().createdNewInst(dvi);
277+
if (isa<DropDeinitInst>(operandValue)) {
278+
SILBuilderWithScope builder(inst);
279+
auto *eli = builder.createEndLifetime(inst->getLoc(), operandValue);
280+
getCallbacks().createdNewInst(eli);
281+
} else {
282+
SILBuilderWithScope builder(inst);
283+
auto *dvi =
284+
builder.createDestroyValue(inst->getLoc(), operandValue);
285+
getCallbacks().createdNewInst(dvi);
286+
}
274287
} else if ((li = dyn_cast<LoadInst>(inst)) &&
275288
li->getOwnershipQualifier() ==
276289
LoadOwnershipQualifier::Take) {

test/SILOptimizer/drop_deinit_opt.sil

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: %target-sil-opt %s -early-inline -mem2reg | %FileCheck %s
2+
3+
import Swift
4+
import Builtin
5+
6+
struct FileDescriptor : ~Copyable {
7+
@_hasStorage private var fd: Int { get set }
8+
init(_ fd: Int)
9+
deinit
10+
}
11+
12+
sil hidden [ossa] @fd_close : $@convention(thin) (Int) -> () {
13+
bb0(%0 : $Int):
14+
debug_value %0, let, name "fd", argno 1
15+
%2 = tuple ()
16+
return %2
17+
}
18+
19+
// CHECK-LABEL: sil hidden [ossa] @fd_deinit1 :
20+
// CHECK: drop_deinit
21+
// CHECK-LABEL: } // end sil function 'fd_deinit1'
22+
sil hidden [ossa] @fd_deinit1 : $@convention(method) (@owned FileDescriptor) -> () {
23+
bb0(%0 : @owned $FileDescriptor):
24+
%1 = alloc_stack $FileDescriptor, let, name "self", argno 1
25+
store %0 to [init] %1
26+
%3 = drop_deinit %1
27+
%6 = struct_element_addr %3, #FileDescriptor.fd
28+
%7 = load [trivial] %6
29+
%9 = function_ref @fd_close : $@convention(thin) (Int) -> ()
30+
%10 = apply %9(%7) : $@convention(thin) (Int) -> ()
31+
dealloc_stack %1
32+
%12 = tuple ()
33+
return %12
34+
}
35+
36+
// CHECK-LABEL: sil hidden [ossa] @fd_deinit2 :
37+
// CHECK: end_lifetime
38+
// CHECK-LABEL: } // end sil function 'fd_deinit2'
39+
sil hidden [ossa] @fd_deinit2 : $@convention(method) (@owned FileDescriptor) -> () {
40+
bb0(%0 : @owned $FileDescriptor):
41+
%3 = drop_deinit %0
42+
%6 = destructure_struct %3
43+
%9 = function_ref @fd_close : $@convention(thin) (Int) -> ()
44+
%10 = apply %9(%6) : $@convention(thin) (Int) -> ()
45+
%12 = tuple ()
46+
return %12
47+
}

0 commit comments

Comments
 (0)