Skip to content

Commit 041ecba

Browse files
committed
Canonicalize single value forwarding insts that only have debug_value and destroy_value uses.
E.x.: ``` %1 = unchecked_ref_cast %0 destroy_value %1 -> destroy_value %0 ``` I am doing this only in non-Raw SIL to ensure that I do not disturb the mandatory passes.
1 parent 291b75f commit 041ecba

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed

lib/SILOptimizer/Utils/CanonicalizeInstruction.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,35 @@ eliminateSimpleBorrows(BeginBorrowInst *bbi, CanonicalizeInstruction &pass) {
522522
return killInstruction(bbi, next, pass);
523523
}
524524

525+
/// Delete any result having forwarding instruction that only has destroy_value
526+
/// and debug_value uses.
527+
static SILBasicBlock::iterator
528+
eliminateUnneededForwardingUnarySingleValueInst(SingleValueInstruction *inst,
529+
CanonicalizeInstruction &pass) {
530+
auto next = std::next(inst->getIterator());
531+
532+
for (auto *use : getNonDebugUses(inst))
533+
if (!isa<DestroyValueInst>(use->getUser()))
534+
return next;
535+
deleteAllDebugUses(inst);
536+
SILValue op = inst->getOperand(0);
537+
inst->replaceAllUsesWith(op);
538+
pass.notifyHasNewUsers(op);
539+
return killInstruction(inst, next, pass);
540+
}
541+
542+
static Optional<SILBasicBlock::iterator>
543+
tryEliminateUnneededForwardingInst(SILInstruction *i,
544+
CanonicalizeInstruction &pass) {
545+
assert(isa<OwnershipForwardingInst>(i) &&
546+
"Must be an ownership forwarding inst");
547+
if (auto *svi = dyn_cast<SingleValueInstruction>(i))
548+
if (svi->getNumOperands() == 1)
549+
return eliminateUnneededForwardingUnarySingleValueInst(svi, pass);
550+
551+
return None;
552+
}
553+
525554
//===----------------------------------------------------------------------===//
526555
// Top-Level Entry Point
527556
//===----------------------------------------------------------------------===//
@@ -545,6 +574,16 @@ CanonicalizeInstruction::canonicalize(SILInstruction *inst) {
545574
if (auto *bbi = dyn_cast<BeginBorrowInst>(inst))
546575
return eliminateSimpleBorrows(bbi, *this);
547576

577+
// If we have ownership and are not in raw SIL, eliminate unneeded forwarding
578+
// insts. We don't do this in raw SIL as not to disturb the codegen read by
579+
// diagnostics.
580+
auto *fn = inst->getFunction();
581+
if (fn->hasOwnership() && fn->getModule().getStage() != SILStage::Raw) {
582+
if (isa<OwnershipForwardingInst>(inst))
583+
if (auto newNext = tryEliminateUnneededForwardingInst(inst, *this))
584+
return *newNext;
585+
}
586+
548587
// Skip ahead.
549588
return std::next(inst->getIterator());
550589
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all -mandatory-combine -sil-mandatory-combine-enable-canon-and-simple-dce %s | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
7+
// Trivial declarations
8+
9+
struct MyInt {
10+
var value: Builtin.Int64
11+
}
12+
13+
// Generic declarations
14+
15+
protocol Addable {
16+
static var an: Self { get }
17+
}
18+
19+
// Class declarations
20+
21+
class Klass {
22+
init()
23+
deinit
24+
}
25+
26+
class SubKlass : Klass {}
27+
28+
sil @use_klass_unowned : $@convention(thin) (Klass) -> ()
29+
30+
// Existential declarations
31+
32+
protocol Proto {
33+
static var an: Proto { get }
34+
}
35+
36+
// Trivial support
37+
38+
sil @first_of_three_ints : $@convention(thin) (MyInt, MyInt, MyInt) -> MyInt
39+
40+
sil @constant_zero : $@convention(thin) () -> MyInt
41+
42+
sil @identity_int : $@convention(thin) (MyInt) -> MyInt
43+
44+
// Generic support
45+
46+
sil @first_of_three_addables : $@convention(thin) <A where A : Addable> (@in_guaranteed A, @guaranteed <τ_0_0 where τ_0_0 : Addable> { var τ_0_0 } <A>, @guaranteed <τ_0_0 where τ_0_0 : Addable> { var τ_0_0 } <A>) -> @
47+
out A
48+
49+
// Class support
50+
51+
sil [exact_self_class] @klass_alloc_init : $@convention(method) (@thick Klass.Type) -> @owned Klass
52+
53+
// Klass.init()
54+
sil @klass_init : $@convention(method) (@owned Klass) -> @owned Klass
55+
// Klass.deinit
56+
sil @klass_deinit : $@convention(method) (@guaranteed Klass) -> @owned Builtin.NativeObject
57+
58+
// Klass.__deallocating_deinit
59+
sil @klass_dealloc_deinit : $@convention(method) (@owned Klass) -> ()
60+
61+
sil_vtable Klass {
62+
#Klass.init!allocator: (Klass.Type) -> () -> Klass : @klass_alloc_init
63+
#Klass.deinit!deallocator: @klass_dealloc_deinit
64+
}
65+
66+
sil @first_of_three_klasses : $@convention(thin) (@guaranteed Klass, @guaranteed Klass, @guaranteed Klass) -> @owned Klass
67+
68+
sil @use_klass_guaranteed : $@convention(thin) (@guaranteed Klass) -> ()
69+
70+
// Existential support
71+
72+
sil @first_of_three_protos : $@convention(thin) (@in_guaranteed Proto, @guaranteed { var Proto }, @guaranteed { var Proto }) -> @out Proto
73+
74+
sil @get_proto : $@convention(thin) () -> @out Proto
75+
76+
// Mixed support
77+
78+
sil @proto_from_proto_and_myint : $@convention(thin) (@in_guaranteed Proto, MyInt) -> @out Proto
79+
80+
sil @myint_from_myint_and_proto : $@convention(thin) (MyInt, @guaranteed { var Proto }) -> MyInt
81+
82+
sil @myint_from_proto_and_myint : $@convention(thin) (@guaranteed { var Proto }, MyInt) -> MyInt
83+
84+
// Enum support
85+
86+
enum FakeOptional<T> {
87+
case none
88+
case some(T)
89+
}
90+
91+
sil @use_fakeoptional_klass_guaranteed : $@convention(thin) (@guaranteed FakeOptional<Klass>) -> ()
92+
93+
///////////
94+
// Tests //
95+
///////////
96+
97+
// CHECK-LABEL: sil [ossa] @testUnneededDestroyOfForwardingInst : $@convention(thin) (@owned Klass) -> () {
98+
// CHECK-NOT: unchecked_ref_cast
99+
// CHECK: } // end sil function 'testUnneededDestroyOfForwardingInst'
100+
sil [ossa] @testUnneededDestroyOfForwardingInst : $@convention(thin) (@owned Klass) -> () {
101+
bb0(%0 : @owned $Klass):
102+
%1 = unchecked_ref_cast %0 : $Klass to $Builtin.NativeObject
103+
destroy_value %1 : $Builtin.NativeObject
104+
%9999 = tuple()
105+
return %9999 : $()
106+
}

0 commit comments

Comments
 (0)