Skip to content

Commit 4ca6b31

Browse files
committed
SILCombine: remove dead casts and end_cow_mutation instructions which are only destroyed.
If the only use of an upcast, unchecked_ref_cast or end_cow_mutation is a destroy/release, just destroy the operand and remove the cast/end_cow_mutation.
1 parent e3ac98c commit 4ca6b31

File tree

4 files changed

+89
-38
lines changed

4 files changed

+89
-38
lines changed

lib/SILOptimizer/Analysis/SimplifyInstruction.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ namespace {
6262
SILValue visitUncheckedBitwiseCastInst(UncheckedBitwiseCastInst *UBCI);
6363
SILValue
6464
visitUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *UTBCI);
65+
SILValue visitEndCOWMutationInst(EndCOWMutationInst *ECM);
6566
SILValue visitThinFunctionToPointerInst(ThinFunctionToPointerInst *TFTPI);
6667
SILValue visitPointerToThinFunctionInst(PointerToThinFunctionInst *PTTFI);
6768
SILValue visitBeginAccessInst(BeginAccessInst *BAI);
@@ -329,6 +330,21 @@ visitUnconditionalCheckedCastInst(UnconditionalCheckedCastInst *UCCI) {
329330
return SILValue();
330331
}
331332

333+
/// If the only use of a cast is a destroy, just destroy the cast operand.
334+
static SILValue simplifyDeadCast(SingleValueInstruction *Cast) {
335+
for (Operand *op : Cast->getUses()) {
336+
switch (op->getUser()->getKind()) {
337+
case SILInstructionKind::DestroyValueInst:
338+
case SILInstructionKind::StrongReleaseInst:
339+
case SILInstructionKind::StrongRetainInst:
340+
break;
341+
default:
342+
return SILValue();
343+
}
344+
}
345+
return Cast->getOperand(0);
346+
}
347+
332348
SILValue
333349
InstSimplifier::
334350
visitUncheckedRefCastInst(UncheckedRefCastInst *OPRI) {
@@ -351,7 +367,8 @@ visitUncheckedRefCastInst(UncheckedRefCastInst *OPRI) {
351367
if (OPRI->getOperand()->getType() == OPRI->getType())
352368
return OPRI->getOperand();
353369

354-
return SILValue();
370+
// (destroy_value (unchecked_ref_cast x)) -> destroy_value x
371+
return simplifyDeadCast(OPRI);
355372
}
356373

357374
SILValue
@@ -375,7 +392,8 @@ SILValue InstSimplifier::visitUpcastInst(UpcastInst *UI) {
375392
if (URCI->getOperand()->getType() == UI->getType())
376393
return URCI->getOperand();
377394

378-
return SILValue();
395+
// (destroy_value (upcast x)) -> destroy_value x
396+
return simplifyDeadCast(UI);
379397
}
380398

381399
#define LOADABLE_REF_STORAGE(Name, ...) \
@@ -410,6 +428,11 @@ visitUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *UTBCI) {
410428
return SILValue();
411429
}
412430

431+
SILValue InstSimplifier::visitEndCOWMutationInst(EndCOWMutationInst *ECM) {
432+
// (destroy_value (end_cow_mutation x)) -> destroy_value x
433+
return simplifyDeadCast(ECM);
434+
}
435+
413436
SILValue
414437
InstSimplifier::
415438
visitUncheckedBitwiseCastInst(UncheckedBitwiseCastInst *UBCI) {

test/IRGen/upcast.sil

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22

33
// Make sure that we are able to lower upcast addresses.
44

5-
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @upcast_test(%T6upcast1DC** nocapture dereferenceable({{.*}}) %0) {{.*}} {
5+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %T6upcast1CC* @upcast_test(%T6upcast1DC** nocapture dereferenceable({{.*}}) %0) {{.*}} {
66
// CHECK: entry:
7-
// CHECK-NEXT: bitcast %T6upcast1DC** {{%[0-0]+}} to %T6upcast1CC**
8-
// CHECK-NEXT: ret void
7+
// CHECK-NEXT: [[A:%[0-9]+]] = bitcast %T6upcast1DC** {{%[0-0]+}} to %T6upcast1CC**
8+
// CHECK-NEXT: [[C:%[0-9]+]] = load %T6upcast1CC*, %T6upcast1CC** [[A]]
9+
// CHECK-NEXT: ret %T6upcast1CC* [[C]]
910

1011
class C {}
1112
sil_vtable C {}
1213
class D : C {}
1314
sil_vtable D {}
1415

15-
sil @upcast_test : $@convention(thin) (@inout D) -> () {
16+
sil @upcast_test : $@convention(thin) (@inout D) -> C {
1617
bb0(%0 : $*D):
1718
%1 = upcast %0 : $*D to $*C
18-
%33 = tuple()
19-
return %33 : $()
19+
%2 = load %1 : $*C
20+
return %2 : $C
2021
}

test/SILOptimizer/cse.sil

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -617,21 +617,18 @@ bb0(%0 : $FakeOptional):
617617
class C {}
618618
class D : C { }
619619

620-
// CHECK-LABEL: sil @test1cse : $@convention(thin) (C) -> () {
621-
// CHECK: unchecked_ref_cast
620+
// CHECK-LABEL: sil @test1cse
621+
// CHECK: [[C:%[0-9]+]] = unchecked_ref_cast
622622
// CHECK-NOT: unchecked_ref_cast
623-
// CHECK: strong_release
624-
// CHECK: strong_release
625-
// CHECK: return
626-
sil @test1cse : $@convention(thin) (C) -> () {
623+
// CHECK: [[T:%[0-9]+]] = tuple ([[C]] : $Builtin.NativeObject, [[C]] : $Builtin.NativeObject)
624+
// CHECK: return [[T]]
625+
sil @test1cse : $@convention(thin) (C) -> (Builtin.NativeObject, Builtin.NativeObject) {
627626
bb0(%0 : $C):
628627
strong_retain %0 : $C
629628
%1 = unchecked_ref_cast %0 : $C to $Builtin.NativeObject
630629
%2 = unchecked_ref_cast %0 : $C to $Builtin.NativeObject
631-
strong_release %1 : $Builtin.NativeObject
632-
strong_release %2 : $Builtin.NativeObject
633-
%5 = tuple()
634-
return %5 : $()
630+
%5 = tuple(%1 : $Builtin.NativeObject, %2 : $Builtin.NativeObject)
631+
return %5 : $(Builtin.NativeObject, Builtin.NativeObject)
635632
}
636633

637634
// CHECK-LABEL: sil @test2cse : $@convention(thin) (C) -> () {
@@ -704,23 +701,20 @@ bb0(%0 : $*Builtin.Int8):
704701
}
705702

706703
// CHECK-LABEL: sil @cse_unchecked_ref_cast
707-
// CHECK: unchecked_ref_cast
704+
// CHECK: [[C:%[0-9]+]] = unchecked_ref_cast
708705
// CHECK-NOT: unchecked_ref_cast
709-
// CHECK: strong_release
710-
// CHECK: strong_release
711-
// CHECK: return
712-
sil @cse_unchecked_ref_cast : $@convention(thin) (@owned B, Builtin.Int1) -> () {
706+
// CHECK: [[T:%[0-9]+]] = tuple ([[C]] : $Builtin.NativeObject, [[C]] : $Builtin.NativeObject)
707+
// CHECK: return [[T]]
708+
sil @cse_unchecked_ref_cast : $@convention(thin) (@owned B, Builtin.Int1) -> (Builtin.NativeObject, Builtin.NativeObject) {
713709
bb0(%0: $B, %1: $Builtin.Int1):
714710
%5 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject
715-
strong_release %5 : $Builtin.NativeObject
716711
cond_br %1, bb1, bb2
717712
bb1:
718713
br bb2
719714
bb2:
720715
%21 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject
721-
strong_release %21 : $Builtin.NativeObject
722-
%32 = tuple ()
723-
return %32 : $()
716+
%32 = tuple(%5 : $Builtin.NativeObject, %21 : $Builtin.NativeObject)
717+
return %32 : $(Builtin.NativeObject, Builtin.NativeObject)
724718
}
725719

726720
// CHECK-LABEL: sil @cse_raw_pointer_to_ref

test/SILOptimizer/sil_combine.sil

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,44 @@ bb0(%0 : $C3):
809809
return %2 : $C1
810810
}
811811

812+
// CHECK-LABEL: sil @dead_upcast
813+
// CHECK: bb0
814+
// CHECK-NEXT: strong_retain %0
815+
// CHECK-NEXT: strong_release %0
816+
// CHECK-NEXT: return
817+
sil @dead_upcast : $@convention(thin) (C2) -> C2 {
818+
bb0(%0 : $C2):
819+
%1 = upcast %0 : $C2 to $C1
820+
strong_retain %1 : $C1
821+
strong_release %0 : $C2
822+
return %0 : $C2
823+
}
824+
825+
// CHECK-LABEL: sil @dead_unchecked_ref_cast
826+
// CHECK: bb0
827+
// CHECK-NEXT: strong_retain %0
828+
// CHECK-NEXT: strong_release %0
829+
// CHECK-NEXT: return
830+
sil @dead_unchecked_ref_cast : $@convention(thin) (C1) -> C1 {
831+
bb0(%0 : $C1):
832+
%1 = unchecked_ref_cast %0 : $C1 to $C2
833+
strong_retain %1 : $C2
834+
strong_release %0 : $C1
835+
return %0 : $C1
836+
}
837+
838+
// CHECK-LABEL: sil @dead_end_cow_mutation
839+
// CHECK: bb0
840+
// CHECK-NEXT: strong_retain %0
841+
// CHECK-NEXT: strong_release %0
842+
// CHECK-NEXT: return
843+
sil @dead_end_cow_mutation : $@convention(thin) (C1) -> C1 {
844+
bb0(%0 : $C1):
845+
%1 = end_cow_mutation %0 : $C1
846+
strong_retain %1 : $C1
847+
strong_release %0 : $C1
848+
return %0 : $C1
849+
}
812850

813851
struct XS {
814852
var m: Int
@@ -2294,14 +2332,13 @@ bb0(%0 : $B, %1 : $@sil_unowned B, %2 : $AnyObject, %3: $@sil_unmanaged AnyObjec
22942332
// CHECK-NOT: open_existential_ref
22952333
// CHECK: unchecked_ref_cast [[Ref]]
22962334

2297-
sil @collapse_existential_pack_unpack_unchecked_ref_cast : $@convention(thin) (MyClass) -> () {
2335+
sil @collapse_existential_pack_unpack_unchecked_ref_cast : $@convention(thin) (MyClass) -> Builtin.NativeObject {
22982336
bb0(%0: $MyClass):
22992337
%1 = init_existential_ref %0 : $MyClass : $MyClass, $AnyObject
23002338
%2 = open_existential_ref %1 : $AnyObject to $@opened("2CAE06CE-5F10-11E4-AF13-C82A1428F987") AnyObject
23012339
%3 = unchecked_ref_cast %2 : $@opened("2CAE06CE-5F10-11E4-AF13-C82A1428F987") AnyObject to $Builtin.NativeObject
23022340
strong_retain %3: $Builtin.NativeObject
2303-
%5 = tuple ()
2304-
return %5 : $()
2341+
return %3 : $Builtin.NativeObject
23052342
}
23062343

23072344
// CHECK-LABEL: sil @collapse_existential_pack_unpack_ref_to_raw_pointer
@@ -2531,15 +2568,12 @@ sil @alloc_ref_dynamic_with_metatype_genneric : $<T where T : B>() -> () {
25312568
// CHECK-NOT: alloc_ref_dynamic
25322569
// CHECK-NEXT: [[R:%[0-9]+]] = alloc_ref $E
25332570
// CHECK-NEXT: [[C:%[0-9]+]] = upcast [[R]] : $E to $B
2534-
// CHECK-NEXT: strong_release [[C]]
2535-
// CHECK: return
2536-
sil @alloc_ref_dynamic_with_upcast_metatype : $() -> () {
2571+
// CHECK-NEXT: return [[C]]
2572+
sil @alloc_ref_dynamic_with_upcast_metatype : $() -> B {
25372573
%1 = metatype $@thick E.Type
25382574
%2 = upcast %1 : $@thick E.Type to $@thick B.Type
25392575
%3 = alloc_ref_dynamic %2 : $@thick B.Type, $B
2540-
strong_release %3 : $B
2541-
%4 = tuple()
2542-
return %4 : $()
2576+
return %3 : $B
25432577
}
25442578

25452579
// CHECK-LABEL: @alloc_ref_dynamic_after_successful_checked_cast_br
@@ -2570,8 +2604,7 @@ bb3 (%10: $Builtin.Int32):
25702604
// CHECK: bb1
25712605
// CHECK-NOT: alloc_ref_dynamic
25722606
// CHECK: [[R:%[0-9]+]] = alloc_ref $E
2573-
// CHECK-NEXT: [[C:%[0-9]+]] = upcast [[R]] : $E to $B
2574-
// CHECK-NEXT: strong_release [[C]]
2607+
// CHECK-NEXT: strong_release [[R]]
25752608
sil @alloc_ref_dynamic_upcast_after_successful_checked_cast_br : $(@thick B.Type) -> Builtin.Int32 {
25762609
bb0(%1 : $@thick B.Type):
25772610
checked_cast_br [exact] %1 : $@thick B.Type to E.Type, bb1, bb2

0 commit comments

Comments
 (0)