Skip to content

Commit e603f52

Browse files
committed
DeadCodeElimination: don't hoist destroy_value instructions
DeadCodeElimination can remove instructions including their destroys and then insert compensating destroys at a new place. This is effectively destroy-hoisting which doesn't respect deinit-barriers. Disable removing and re-creating `destroy_value` instructions. This is done by other optimizations.
1 parent 98805c9 commit e603f52

File tree

3 files changed

+46
-62
lines changed

3 files changed

+46
-62
lines changed

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,9 @@ namespace {
5151
// FIXME: Reconcile the similarities between this and
5252
// isInstructionTriviallyDead.
5353
static bool seemsUseful(SILInstruction *I) {
54-
// Even though begin_access/destroy_value/copy_value/end_lifetime have
55-
// side-effects, they can be DCE'ed if they do not have useful
56-
// dependencies/reverse dependencies
57-
if (isa<CopyValueInst>(I) ||
58-
isa<DestroyValueInst>(I) || isa<EndLifetimeInst>(I) ||
59-
isa<EndBorrowInst>(I))
54+
// Even though end_lifetime has side-effects, it can be DCE'ed if it does not
55+
// have useful dependencies/reverse dependencies
56+
if (isa<EndLifetimeInst>(I))
6057
return false;
6158

6259
if (isa<UnconditionalCheckedCastInst>(I)) {
@@ -361,16 +358,6 @@ void DCE::markLive() {
361358
}
362359
break;
363360
}
364-
case SILInstructionKind::DestroyValueInst: {
365-
auto phi = PhiValue(I.getOperand(0));
366-
// Disable DCE of phis which are lexical or may have a pointer escape.
367-
if (phi && (phi->isLexical() || findPointerEscape(phi))) {
368-
markInstructionLive(&I);
369-
}
370-
// The instruction is live only if it's operand value is also live
371-
addReverseDependency(I.getOperand(0), &I);
372-
break;
373-
}
374361
case SILInstructionKind::EndBorrowInst: {
375362
auto phi = PhiValue(lookThroughBorrowedFromDef(I.getOperand(0)));
376363
// If there is a pointer escape or phi is lexical, disable DCE.

test/SILOptimizer/dead_code_elimination_nontrivial_ossa.sil

Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,9 @@ bb2(%4 : $Error):
121121
}
122122

123123
// CHECK-LABEL: sil [ossa] @dce_deadcopy1 :
124-
// CHECK-NOT: copy_value
125-
// CHECK: destroy_value %0
124+
// CHECK: copy_value
125+
// CHECK: destroy_value %1
126+
// CHECK: destroy_value %0
126127
// CHECK-LABEL: } // end sil function 'dce_deadcopy1'
127128
sil [ossa] @dce_deadcopy1 : $@convention(thin) (@owned Klass) -> () {
128129
bb0(%0 : @owned $Klass):
@@ -134,8 +135,8 @@ bb0(%0 : @owned $Klass):
134135
}
135136

136137
// CHECK-LABEL: sil [ossa] @dce_deadcopy2 :
137-
// CHECK-NOT: copy_value
138-
// CHECK-NOT: destroy_value
138+
// CHECK: copy_value
139+
// CHECK: destroy_value
139140
// CHECK-LABEL: } // end sil function 'dce_deadcopy2'
140141
sil [ossa] @dce_deadcopy2 : $@convention(thin) (@guaranteed Klass) -> () {
141142
bb0(%0 : @guaranteed $Klass):
@@ -146,11 +147,10 @@ bb0(%0 : @guaranteed $Klass):
146147
}
147148

148149
// CHECK-LABEL: sil [ossa] @dce_deadcopy3 :
149-
// CHECK: bb0([[ARG:%.*]])
150-
// CHECK-NEXT: br bb1
151-
// CHECK: bb1:
152-
// CHECK-NEXT: [[RES:%.*]] = tuple ()
153-
// CHECK-NEXT: return [[RES]]
150+
// CHECK: bb0([[ARG:%.*]])
151+
// CHECK-NEXT: copy_value
152+
// CHECK: bb1({{.*}}):
153+
// CHECK-NEXT: destroy_value
154154
// CHECK-LABEL: } // end sil function 'dce_deadcopy3'
155155
sil [ossa] @dce_deadcopy3 : $@convention(thin) (@guaranteed Klass) -> () {
156156
bb0(%0 : @guaranteed $Klass):
@@ -164,8 +164,8 @@ bb1(%2 : @owned $Klass):
164164
}
165165

166166
// CHECK-LABEL: sil [ossa] @dce_deadcopy4 :
167-
// CHECK-NOT: copy_value
168-
// CHECK-NOT: destroy_value
167+
// CHECK: copy_value
168+
// CHECK: destroy_value
169169
// CHECK-LABEL: } // end sil function 'dce_deadcopy4'
170170
sil [ossa] @dce_deadcopy4 : $@convention(thin) (@guaranteed Klass) -> () {
171171
bb0(%0 : @guaranteed $Klass):
@@ -185,11 +185,10 @@ bb3(%2 : @owned $Klass):
185185
}
186186

187187
// CHECK-LABEL: sil [ossa] @dce_deadcopy5 :
188-
// CHECK: bb0([[ARG:%.*]])
189-
// CHECK-NEXT: br bb1
190-
// CHECK: bb1:
191-
// CHECK-NEXT: [[RES:%.*]] = tuple ()
192-
// CHECK-NEXT: return [[RES]]
188+
// CHECK: bb0([[ARG:%.*]])
189+
// CHECK-NEXT: copy_value
190+
// CHECK: bb1({{.*}}):
191+
// CHECK-NEXT: destroy_value
193192
// CHECK-LABEL: } // end sil function 'dce_deadcopy5'
194193
sil [ossa] @dce_deadcopy5 : $@convention(thin) (@guaranteed Klass) -> () {
195194
bb0(%0 : @guaranteed $Klass):
@@ -209,11 +208,10 @@ bb2:
209208
}
210209

211210
// CHECK-LABEL: sil [ossa] @dce_deadcopy6 :
212-
// CHECK: bb0([[ARG:%.*]])
213-
// CHECK-NEXT: br bb1
214-
// CHECK: bb1:
215-
// CHECK-NEXT: [[RES:%.*]] = tuple ()
216-
// CHECK-NEXT: return [[RES]]
211+
// CHECK: bb0([[ARG:%.*]])
212+
// CHECK-NEXT: copy_value
213+
// CHECK: bb5({{.*}}):
214+
// CHECK-NEXT: destroy_value
217215
// CHECK-LABEL: } // end sil function 'dce_deadcopy6'
218216
sil [ossa] @dce_deadcopy6 : $@convention(thin) (@guaranteed Klass) -> () {
219217
bb0(%0 : @guaranteed $Klass):
@@ -239,7 +237,7 @@ bb3(%2 : @owned $Klass):
239237
}
240238

241239
// CHECK-LABEL: sil [ossa] @dce_deadcopy7 :
242-
// CHECK-NOT: load [copy]
240+
// CHECK: load [copy]
243241
// CHECK-LABEL: } // end sil function 'dce_deadcopy7'
244242
sil [ossa] @dce_deadcopy7 : $@convention(thin) (@in Klass) -> () {
245243
bb0(%0 : $*Klass):
@@ -254,10 +252,9 @@ bb1(%2 : @owned $Klass):
254252
}
255253

256254
// CHECK-LABEL: sil [ossa] @dce_destructure1 :
257-
// CHECK: bb0(%0 : {{.*}})
258-
// CHECK-NEXT: destroy_value %0
259-
// CHECK-NEXT: [[RES:%.*]] = tuple ()
260-
// CHECK-NEXT: return [[RES]]
255+
// CHECK: bb0(%0 : {{.*}})
256+
// CHECK-NEXT: %1 = destructure_struct
257+
// CHECK-NEXT: destroy_value %1
261258
// CHECK-LABEL: } // end sil function 'dce_destructure1'
262259
sil [ossa] @dce_destructure1 : $@convention(thin) (@owned NonTrivialStruct) -> () {
263260
bb0(%0 : @owned $NonTrivialStruct):
@@ -280,8 +277,8 @@ bb0(%0 : @guaranteed $NonTrivialStruct):
280277
}
281278

282279
// CHECK-LABEL: sil [ossa] @dce_destructure3 :
283-
// CHECK: bb0(%0 : {{.*}})
284-
// CHECK-NOT: destructure_struct
280+
// CHECK: bb0(%0 : {{.*}})
281+
// CHECK: destructure_struct
285282
// CHECK-LABEL: } // end sil function 'dce_destructure3'
286283
sil [ossa] @dce_destructure3 : $@convention(thin) (@guaranteed NonTrivialStruct) -> () {
287284
bb0(%0 : @guaranteed $NonTrivialStruct):
@@ -297,7 +294,7 @@ bb0(%0 : @guaranteed $NonTrivialStruct):
297294
// This test shows that when we delete a dead instruction which has lifetime ending ops,
298295
// we need to insert destroys of ops to end their lifetime correctly
299296
// CHECK-LABEL: sil [ossa] @dce_insertdestroy1 :
300-
// CHECK-NOT: struct
297+
// CHECK: struct
301298
// CHECK-LABEL: } // end sil function 'dce_insertdestroy1'
302299
sil [ossa] @dce_insertdestroy1 : $@convention(thin) (@owned Klass) -> () {
303300
bb0(%0 : @owned $Klass):
@@ -314,9 +311,8 @@ bb0(%0 : @owned $Klass):
314311
// This test shows that when we delete a dead phi arg and its incoming values are live,
315312
// we need to insert destroys of the incoming values in its pred blocks.
316313
// CHECK-LABEL: sil [ossa] @dce_insertdestroy2 :
317-
// CHECK: bb1(%3 : {{.*}})
318-
// CHECK-NEXT: destroy_value %3
319-
// CHECK-NEXT: br bb3
314+
// CHECK: bb3({{.*}}):
315+
// CHECK-NEXT: destroy_value
320316
// CHECK-LABEL: } // end sil function 'dce_insertdestroy2'
321317
sil [ossa] @dce_insertdestroy2 : $@convention(thin) (@guaranteed Klass) -> @error any Error {
322318
bb0(%0 : @guaranteed $Klass):
@@ -336,7 +332,7 @@ bb3(%5 : @owned $Klass):
336332
}
337333

338334
// CHECK-LABEL: sil [ossa] @dce_multiplerevdepdests :
339-
// CHECK-NOT: destroy_value
335+
// CHECK: destroy_value
340336
// CHECK-LABEL: } // end sil function 'dce_multiplerevdepdests'
341337
sil [ossa] @dce_multiplerevdepdests : $@convention(thin) (@guaranteed Klass) -> () {
342338
bb0(%0 : @guaranteed $Klass):
@@ -396,7 +392,7 @@ bb1(%copy2 : @owned $NonTrivialStruct, %borrow2 : @guaranteed $NonTrivialStruct)
396392
}
397393

398394
// CHECK-LABEL: sil [ossa] @dce_borrowlifetime2 :
399-
// CHECK: bb1:
395+
// CHECK: bb1({{.*}}):
400396
// CHECK-LABEL: } // end sil function 'dce_borrowlifetime2'
401397
sil [ossa] @dce_borrowlifetime2 : $@convention(thin) (@guaranteed Klass) -> () {
402398
bb0(%0 : @guaranteed $Klass):
@@ -415,7 +411,7 @@ bb1(%copy2 : @owned $Klass, %borrow2 : @guaranteed $Klass):
415411
}
416412

417413
// CHECK-LABEL: sil [ossa] @dce_borrowlifetime3 :
418-
// CHECK: bb1:
414+
// CHECK: bb1({{.*}}):
419415
// CHECK-LABEL: } // end sil function 'dce_borrowlifetime3'
420416
sil [ossa] @dce_borrowlifetime3 : $@convention(thin) (@guaranteed Klass) -> () {
421417
bb0(%0 : @guaranteed $Klass):
@@ -456,7 +452,7 @@ bb2(%copy2 : @owned $Klass):
456452
}
457453

458454
// CHECK-LABEL: sil [ossa] @dce_borrowlifetime5 :
459-
// CHECK: bb1:
455+
// CHECK: bb1({{.*}}):
460456
// CHECK-LABEL: } // end sil function 'dce_borrowlifetime5'
461457
sil [ossa] @dce_borrowlifetime5 : $@convention(thin) (@guaranteed Klass) -> () {
462458
bb0(%0 : @guaranteed $Klass):
@@ -621,7 +617,7 @@ bb3(%newborrow : @guaranteed $NonTrivialStruct, %newowned1 : @owned $NonTrivialS
621617
}
622618

623619
// CHECK-LABEL: sil [ossa] @dce_deadterm1 :
624-
// CHECK-NOT: switch_enum
620+
// CHECK: switch_enum
625621
// CHECK-LABEL: } // end sil function 'dce_deadterm1'
626622
sil [ossa] @dce_deadterm1 : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
627623
bb0(%0 : @owned $FakeOptional<Builtin.NativeObject>):
@@ -644,8 +640,8 @@ bb3:
644640
}
645641

646642
// CHECK-LABEL: sil [ossa] @dce_deadterm2 :
647-
// CHECK-NOT: load [copy]
648-
// CHECK-NOT: switch_enum
643+
// CHECK: load [copy]
644+
// CHECK: switch_enum
649645
// CHECK-LABEL: } // end sil function 'dce_deadterm2'
650646
sil [ossa] @dce_deadterm2 : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
651647
bb0(%0 : @owned $FakeOptional<Builtin.NativeObject>):
@@ -710,7 +706,7 @@ bb4(%3 : @owned $Klass):
710706
}
711707

712708
// CHECK-LABEL: sil [ossa] @looping_borrow : $@convention(thin) () -> () {
713-
// CHECK-NOT: destroy_value
709+
// CHECK: destroy_value
714710
// CHECK-LABEL: } // end sil function 'looping_borrow'
715711
sil [ossa] @looping_borrow : $@convention(thin) () -> () {
716712
entry:
@@ -854,7 +850,7 @@ exit(%outer_lifetime_3 : @guaranteed $Klass, %inner_lifetime_2 : @guaranteed $Kl
854850
}
855851

856852
// CHECK-LABEL: sil [ossa] @reborrow_guaranteed_phi2 : {{.*}} {
857-
// CHECK-NOT: switch_enum
853+
// CHECK: switch_enum
858854
// CHECK-LABEL: } // end sil function 'reborrow_guaranteed_phi2'
859855
sil [ossa] @reborrow_guaranteed_phi2 : $@convention(thin) (@owned EitherNoneOrAnyObject) -> () {
860856
entry(%0 : @owned $EitherNoneOrAnyObject):
@@ -1281,7 +1277,7 @@ bb2(%phi1 : @guaranteed $NonTrivialStruct, %phi2 : @guaranteed $NonTrivialStruct
12811277
}
12821278

12831279
// CHECK-LABEL: sil [ossa] @dce_deadterm4 :
1284-
// CHECK-NOT: switch_enum
1280+
// CHECK: switch_enum
12851281
// CHECK-LABEL: } // end sil function 'dce_deadterm4'
12861282
sil [ossa] @dce_deadterm4 : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
12871283
bb0(%0 : @owned $FakeOptional<Builtin.NativeObject>):
@@ -1316,8 +1312,8 @@ bb6:
13161312
}
13171313

13181314
// CHECK-LABEL: sil [ossa] @dce_deadterm5 :
1319-
// CHECK: switch_enum
1320-
// CHECK-NOT: switch_enum
1315+
// CHECK: switch_enum
1316+
// CHECK: switch_enum
13211317
// CHECK-LABEL: } // end sil function 'dce_deadterm5'
13221318
sil [ossa] @dce_deadterm5 : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
13231319
bb0(%0 : @owned $FakeOptional<Builtin.NativeObject>):
@@ -1353,7 +1349,7 @@ bb6:
13531349
}
13541350

13551351
// CHECK-LABEL: sil [ossa] @dce_deadforwarding :
1356-
// CHECK-NOT: cond_br
1352+
// CHECK: cond_br
13571353
// CHECK-LABEL: } // end sil function 'dce_deadforwarding'
13581354
sil [ossa] @dce_deadforwarding : $@convention(thin) (@guaranteed Klass) -> () {
13591355
bb0(%0 : @guaranteed $Klass):

test/SILOptimizer/dead_code_elimination_ossa.sil

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ bb0(%0 : $*Container):
310310
// CHECK-LABEL: sil [ossa] @nested_destructure_tuple :
311311
// CHECK: bb0(%0 : @owned $(String, (Int, Int, String))):
312312
// CHECK-NEXT: (%1, %2) = destructure_tuple %0 : $(String, (Int, Int, String))
313-
// CHECK-NEXT: destroy_value %2
313+
// CHECK-NEXT: (%3, %4, %5) = destructure_tuple %2
314+
// CHECK-NEXT: destroy_value %5
314315
// CHECK-NEXT: return %1
315316
// CHECK: } // end sil function 'nested_destructure_tuple'
316317
sil [ossa] @nested_destructure_tuple : $@convention(thin) (@owned (String, (Int, Int, String))) -> @owned String {

0 commit comments

Comments
 (0)