Skip to content

Commit c5efe9a

Browse files
Merge pull request #40764 from nate-chandler/copy-propagation/shrink-borrow-scope/dont-hoist-over-any-applies
[ShrinkBorrowScope] Don't hoist over any applies.
2 parents 2b5857b + 3ba8a93 commit c5efe9a

File tree

4 files changed

+123
-71
lines changed

4 files changed

+123
-71
lines changed

lib/SILOptimizer/Utils/ShrinkBorrowScope.cpp

Lines changed: 6 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ class ShrinkBorrowScope {
5151
/// which is itself a deinit barrier.
5252
SmallPtrSet<SILBasicBlock *, 8> barredBlocks;
5353

54-
llvm::SmallDenseMap<ApplySite, size_t> transitiveUsesPerApplySite;
55-
5654
// The list of blocks to look for new points at which to insert end_borrows
5755
// in. A block must not be processed if all of its successors have not yet
5856
// been. For that reason, it is necessary to allow the same block to be
@@ -136,48 +134,16 @@ class ShrinkBorrowScope {
136134
}
137135
}
138136

139-
size_t usesInApply(ApplySite apply) {
140-
if (auto count = transitiveUsesPerApplySite.lookup(apply))
141-
return count;
142-
return 0;
143-
}
144-
145137
bool canHoistOverInstruction(SILInstruction *instruction) {
146138
return tryHoistOverInstruction(instruction, /*rewrite=*/false);
147139
}
148140

149141
bool tryHoistOverInstruction(SILInstruction *instruction, bool rewrite = true) {
142+
if (instruction == introducer) {
143+
return false;
144+
}
150145
if (users.contains(instruction)) {
151-
if (auto apply = ApplySite::isa(instruction)) {
152-
SmallVector<int, 2> rewritableArgumentIndices;
153-
auto count = apply.getNumArguments();
154-
for (unsigned index = 0; index < count; ++index) {
155-
auto argument = apply.getArgument(index);
156-
if (canReplaceValueWithBorrowedValue(argument)) {
157-
rewritableArgumentIndices.push_back(index);
158-
}
159-
}
160-
if (rewritableArgumentIndices.size() != usesInApply(apply)) {
161-
return false;
162-
}
163-
if (rewrite) {
164-
// We can rewrite all the arguments which are transitive uses of the
165-
// borrow.
166-
for (auto index : rewritableArgumentIndices) {
167-
auto argument = apply.getArgument(index);
168-
auto borrowee = introducer->getOperand();
169-
if (auto *cvi = dyn_cast<CopyValueInst>(argument)) {
170-
cvi->setOperand(borrowee);
171-
modifiedCopyValueInsts.push_back(cvi);
172-
madeChange = true;
173-
} else {
174-
apply.setArgument(index, borrowee);
175-
madeChange = true;
176-
}
177-
}
178-
}
179-
return true;
180-
} else if (auto *bbi = dyn_cast<BeginBorrowInst>(instruction)) {
146+
if (auto *bbi = dyn_cast<BeginBorrowInst>(instruction)) {
181147
if (bbi->isLexical() &&
182148
canReplaceValueWithBorrowedValue(bbi->getOperand())) {
183149
if (rewrite) {
@@ -234,9 +200,6 @@ bool ShrinkBorrowScope::populateUsers() {
234200
for (auto *use : uses) {
235201
auto *user = use->getUser();
236202
users.insert(user);
237-
if (auto apply = ApplySite::isa(user)) {
238-
++transitiveUsesPerApplySite[apply];
239-
}
240203
}
241204
return true;
242205
}
@@ -298,20 +261,12 @@ void ShrinkBorrowScope::findBarriers() {
298261
// At that time, it was checked that this block (along with all that
299262
// successor's other predecessors) had a terminator over which the borrow
300263
// scope could be shrunk. Shrink it now.
301-
#ifndef NDEBUG
302-
bool hoisted =
303-
#endif
304-
tryHoistOverInstruction(block->getTerminator());
305-
#ifndef NDEBUG
264+
bool hoisted = tryHoistOverInstruction(block->getTerminator());
306265
assert(hoisted);
307-
#endif
266+
(void)hoisted;
308267
}
309268
SILInstruction *barrier = nullptr;
310269
while ((instruction = instruction->getPreviousInstruction())) {
311-
if (instruction == introducer) {
312-
barrier = instruction;
313-
break;
314-
}
315270
if (!tryHoistOverInstruction(instruction)) {
316271
barrier = instruction;
317272
break;

test/SILOptimizer/copy_propagation_borrow.sil

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,11 @@ bb3:
394394
// CHECK: [[ALLOC:%.*]] = alloc_ref $C
395395
// CHECK-NEXT: [[B1:%.*]] = begin_borrow [[ALLOC]]
396396
// CHECK-NOT: copy
397+
// CHECK: [[B2:%.*]] = begin_borrow [[ALLOC]]
397398
// CHECK-NOT: copy
398399
// CHECK: end_borrow [[B1]] : $C
399-
// CHECK: apply %0([[ALLOC]]) : $@convention(thin) (@guaranteed C) -> ()
400+
// CHECK: apply %0([[B2]]) : $@convention(thin) (@guaranteed C) -> ()
401+
// CHECK: end_borrow [[B2]] : $C
400402
// CHECK-NEXT: return [[ALLOC]] : $C
401403
// CHECK-LABEL: } // end sil function 'testInterleavedBorrow'
402404
sil [ossa] @testInterleavedBorrow : $@convention(thin) () -> @owned C {
@@ -426,11 +428,14 @@ bb0:
426428
// CHECK: [[B1:%.*]] = begin_borrow [[ALLOC]]
427429
// CHECK: apply %{{.*}}([[B1]]) : $@convention(thin) (@guaranteed C) -> ()
428430
// CHECK-NEXT: end_borrow [[B1]] : $C
431+
// CHECK-NEXT: [[B2:%.*]] = begin_borrow [[ALLOC]]
429432
// CHECK-NEXT: cond_br undef, bb1, bb2
430433
// CHECK: bb1:
431-
// CHECK: apply %{{.*}}([[ALLOC]]) : $@convention(thin) (@guaranteed C) -> ()
434+
// CHECK: apply %{{.*}}([[B2]]) : $@convention(thin) (@guaranteed C) -> ()
435+
// CHECK-NEXT: end_borrow [[B2]] : $C
432436
// CHECK-NEXT: br bb3
433437
// CHECK: bb2:
438+
// CHECK-NEXT: end_borrow [[B2]] : $C
434439
// CHECK-NEXT: br bb3
435440
// CHECK: bb3:
436441
// CHECK-NEXT: return [[ALLOC]] : $C

test/SILOptimizer/shrink_borrow_scope.sil

Lines changed: 108 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ sil [ossa] @synchronization_point : $@convention(thin) () -> ()
4444
// Hoist over br.
4545
// CHECK-LABEL: sil [ossa] @hoist_over_branch_1 : {{.*}} {
4646
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
47+
// CHECK: [[LIFETIME:%[^,]]] = begin_borrow [[INSTANCE]]
4748
// CHECK: [[CALLEE_GUARANTEED:%[^,]+]] = function_ref @callee_guaranteed
48-
// CHECK: {{%[^,]+}} = apply [[CALLEE_GUARANTEED]]([[INSTANCE]])
49+
// CHECK: {{%[^,]+}} = apply [[CALLEE_GUARANTEED]]([[LIFETIME]])
50+
// CHECK: end_borrow [[LIFETIME]]
4951
// CHECK: br [[EXIT:bb[0-9]+]]
5052
// CHECK: [[EXIT]]:
5153
// CHECK: return [[INSTANCE]]
@@ -64,8 +66,10 @@ bl1:
6466
// Hoist over cond_br.
6567
// CHECK-LABEL: sil [ossa] @hoist_over_branch_2 : {{.*}} {
6668
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
69+
// CHECK: [[LIFETIME:%[^,]]] = begin_borrow [[INSTANCE]]
6770
// CHECK: [[CALLEE_GUARANTEED:%[^,]+]] = function_ref @callee_guaranteed
68-
// CHECK: {{%[^,]+}} = apply [[CALLEE_GUARANTEED]]([[INSTANCE]])
71+
// CHECK: {{%[^,]+}} = apply [[CALLEE_GUARANTEED]]([[LIFETIME]])
72+
// CHECK: end_borrow [[LIFETIME]]
6973
// CHECK: cond_br undef, [[BL1:bb[0-9]+]], [[BL2:bb[0-9]+]]
7074
// CHECK: [[BL1]]:
7175
// CHECK: br [[EXIT:bb[0-9]+]]
@@ -93,8 +97,10 @@ exit:
9397
// Hoist over two brs.
9498
// CHECK-LABEL: sil [ossa] @hoist_over_branch_3 : {{.*}} {
9599
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
100+
// CHECK: [[LIFETIME:%[^,]]] = begin_borrow [[INSTANCE]]
96101
// CHECK: [[CALLEE_GUARANTEED:%[^,]+]] = function_ref @callee_guaranteed
97-
// CHECK: {{%[^,]+}} = apply [[CALLEE_GUARANTEED]]([[INSTANCE]])
102+
// CHECK: {{%[^,]+}} = apply [[CALLEE_GUARANTEED]]([[LIFETIME]])
103+
// CHECK: end_borrow [[LIFETIME]]
98104
// CHECK: cond_br undef, [[BL1:bb[0-9]+]], [[BL2:bb[0-9]+]]
99105
// CHECK: [[BL1]]:
100106
// CHECK: br [[EXIT:bb[0-9]+]]
@@ -121,12 +127,15 @@ exit:
121127
// Don't hoist over 1 / 2 brs.
122128
// CHECK-LABEL: sil [ossa] @hoist_over_branch_4 : {{.*}} {
123129
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
130+
// CHECK: [[LIFETIME:%[^,]]] = begin_borrow [[INSTANCE]]
124131
// CHECK: cond_br undef, [[BL1:bb[0-9]+]], [[BL2:bb[0-9]+]]
125132
// CHECK: [[BL1]]:
126133
// CHECK: [[CALLEE_GUARANTEED:%[^,]+]] = function_ref @callee_guaranteed
127-
// CHECK: {{%[^,]+}} = apply [[CALLEE_GUARANTEED]]([[INSTANCE]])
134+
// CHECK: {{%[^,]+}} = apply [[CALLEE_GUARANTEED]]([[LIFETIME]])
135+
// CHECK: end_borrow [[LIFETIME]]
128136
// CHECK: br [[EXIT:bb[0-9]+]]
129137
// CHECK: [[BL2]]:
138+
// CHECK: end_borrow [[LIFETIME]]
130139
// CHECK: br [[EXIT]]
131140
// CHECK: [[EXIT]]:
132141
// CHECK: return [[INSTANCE]]
@@ -149,8 +158,10 @@ exit:
149158
// Hoist over switch_enum destinations.
150159
// CHECK-LABEL: sil [ossa] @hoist_over_branch_5 : {{.*}} {
151160
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C, [[CASE:%[^,]+]] : $OneOfThree):
161+
// CHECK: [[LIFETIME:%[^,]]] = begin_borrow [[INSTANCE]]
152162
// CHECK: [[CALLEE_GUARANTEED:%[^,]+]] = function_ref @callee_guaranteed
153-
// CHECK: {{%[0-9]+}} = apply [[CALLEE_GUARANTEED]]([[INSTANCE]])
163+
// CHECK: {{%[0-9]+}} = apply [[CALLEE_GUARANTEED]]([[LIFETIME]])
164+
// CHECK: end_borrow [[LIFETIME]]
154165
// CHECK: switch_enum [[CASE]] : $OneOfThree, case #OneOfThree.one!enumelt: [[ONE_DEST:bb[0-9]+]], case #OneOfThree.two!enumelt: [[TWO_DEST:bb[0-9]+]], case #OneOfThree.three!enumelt: [[THREE_DEST:bb[0-9]+]]
155166
// CHECK: [[ONE_DEST]]:
156167
// CHECK: br [[EXIT:bb[0-9]+]]
@@ -590,11 +601,15 @@ entry(%instance : @guaranteed $C):
590601
return %result : $()
591602
}
592603

593-
// Hoist over an apply that uses a copy of the borrow.
594-
// CHECK-LABEL: sil [ossa] @hoist_over_apply_at_copy : {{.*}} {
595-
// CHECK-NOT: copy_value
596-
// CHECK-LABEL: // end sil function 'hoist_over_apply_at_copy'
597-
sil [ossa] @hoist_over_apply_at_copy : $@convention(thin) (@owned C) -> () {
604+
// Don't hoist over an apply that uses a copy of the borrow.
605+
// CHECK-LABEL: sil [ossa] @dont_hoist_over_apply_at_copy : {{.*}} {
606+
// CHECK: begin_borrow
607+
// CHECK: copy_value
608+
// CHECK: apply
609+
// CHECK: end_borrow
610+
// CHECK: destroy_value
611+
// CHECK-LABEL: } // end sil function 'dont_hoist_over_apply_at_copy'
612+
sil [ossa] @dont_hoist_over_apply_at_copy : $@convention(thin) (@owned C) -> () {
598613
entry(%instance : @owned $C):
599614
%synchronization_point = function_ref @synchronization_point : $@convention(thin) () -> ()
600615
%callee_owned = function_ref @callee_owned : $@convention(thin) (@owned C) -> ()
@@ -612,13 +627,13 @@ entry(%instance : @owned $C):
612627
return %result : $()
613628
}
614629

615-
// Hoist over an apply that uses the borrow.
630+
// Don't hoist over an apply that uses the borrow.
616631
// CHECK-LABEL: sil [ossa] @hoist_over_apply_at_borrow : {{.*}} {
617632
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
618633
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[INSTANCE]]
634+
// CHECK: apply {{%[^,]+}}([[LIFETIME]])
619635
// CHECK: end_borrow [[LIFETIME]]
620-
// CHECK: apply {{%[^,]+}}([[INSTANCE]])
621-
// CHECK-LABEL: // end sil function 'hoist_over_apply_at_borrow'
636+
// CHECK-LABEL: } // end sil function 'hoist_over_apply_at_borrow'
622637
sil [ossa] @hoist_over_apply_at_borrow : $@convention(thin) (@owned C) -> () {
623638
entry(%instance : @owned $C):
624639
%lifetime = begin_borrow %instance : $C
@@ -645,7 +660,7 @@ entry(%instance : @owned $C):
645660
// CHECK: [[COPY:%[^,]+]] = copy_value [[LIFETIME]]
646661
// CHECK: end_borrow [[LIFETIME]]
647662
// CHECK: begin_borrow [[COPY]]
648-
// CHECK-LABEL: // end sil function 'hoist_over_borrow_of_copy'
663+
// CHECK-LABEL: } // end sil function 'hoist_over_borrow_of_copy'
649664
sil [ossa] @hoist_over_borrow_of_copy : $@convention(thin) (@owned C) -> () {
650665
entry(%instance : @owned $C):
651666
%lifetime_1 = begin_borrow %instance : $C
@@ -695,11 +710,18 @@ entry(%instance : @owned $C):
695710
return %result : $()
696711
}
697712

698-
// CHECK-LABEL: sil [ossa] @hoist_over_try_apply_at_borrow : {{.*}} {
713+
// CHECK-LABEL: sil [ossa] @dont_hoist_over_try_apply_at_borrow : {{.*}} {
699714
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
700-
// CHECK-NEXT: try_apply undef([[INSTANCE]]) : $@convention(thin) (@guaranteed C) -> @error Error, normal bb1, error bb2
701-
// CHECK-LABEL: } // end sil function 'hoist_over_try_apply_at_borrow'
702-
sil [ossa] @hoist_over_try_apply_at_borrow : $@convention(thin) (@owned C) -> @error Error {
715+
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[INSTANCE]]
716+
// CHECK: try_apply undef([[LIFETIME]]) : {{.*}}, normal [[GOOD:bb[0-9]+]], error [[BAD:bb[0-9]+]]
717+
// CHECK: [[GOOD]]
718+
// CHECK: end_borrow [[LIFETIME]]
719+
// CHECK: destroy_value [[INSTANCE]]
720+
// CHECK: [[BAD]]
721+
// CHECK: end_borrow [[LIFETIME]]
722+
// CHECK: destroy_value [[INSTANCE]]
723+
// CHECK-LABEL: } // end sil function 'dont_hoist_over_try_apply_at_borrow'
724+
sil [ossa] @dont_hoist_over_try_apply_at_borrow : $@convention(thin) (@owned C) -> @error Error {
703725
bb0(%instance : @owned $C):
704726
%lifetime = begin_borrow %instance : $C
705727
try_apply undef(%lifetime) : $@convention(thin) (@guaranteed C) -> @error Error, normal good, error bad
@@ -716,6 +738,74 @@ bad(%15 : @owned $Error):
716738
throw %15 : $Error
717739
}
718740

741+
// CHECK-LABEL: sil [ossa] @dont_hoist_over_try_apply_barrier : {{.*}} {
742+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
743+
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[INSTANCE]]
744+
// CHECK: try_apply undef() : {{.*}}, normal [[GOOD:bb[0-9]+]], error [[BAD:bb[0-9]+]]
745+
// CHECK: [[GOOD]]([[REGISTER_3:%[^,]+]] : $()):
746+
// CHECK: end_borrow [[LIFETIME]]
747+
// CHECK: destroy_value [[INSTANCE]]
748+
// CHECK: [[BAD]]([[ERROR:%[^,]+]] : @owned $Error):
749+
// CHECK: end_borrow [[LIFETIME]]
750+
// CHECK: destroy_value [[INSTANCE]]
751+
// CHECK: throw [[ERROR]]
752+
// CHECK-LABEL: } // end sil function 'dont_hoist_over_try_apply_barrier'
753+
sil [ossa] @dont_hoist_over_try_apply_barrier : $@convention(thin) (@owned C) -> @error Error {
754+
bb0(%instance : @owned $C):
755+
%lifetime = begin_borrow %instance : $C
756+
%_ = apply undef(%lifetime) : $@convention(thin) (@guaranteed C) -> ()
757+
try_apply undef() : $@convention(thin) () -> @error Error, normal good, error bad
758+
759+
good(%8 : $()):
760+
end_borrow %lifetime : $C
761+
destroy_value %instance : $C
762+
%13 = tuple ()
763+
return %13 : $()
764+
765+
bad(%15 : @owned $Error):
766+
end_borrow %lifetime : $C
767+
destroy_value %instance : $C
768+
throw %15 : $Error
769+
}
770+
771+
// Hoist up to two parallel barrier applies from a block with two predecessors.
772+
//
773+
// CHECK-LABEL: sil [ossa] @hoist_up_to_two_barrier_applies : $@convention(thin) (@owned C) -> () {
774+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
775+
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INSTANCE]]
776+
// CHECK: cond_br undef, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]]
777+
// CHECK: [[LEFT]]:
778+
// CHECK: [[REGISTER_3:%[^,]+]] = apply undef()
779+
// CHECK: end_borrow [[LIFETIME]]
780+
// CHECK: br [[EXIT:bb[0-9]+]]
781+
// CHECK: [[RIGHT]]:
782+
// CHECK: [[REGISTER_6:%[^,]+]] = apply undef()
783+
// CHECK: end_borrow [[LIFETIME]]
784+
// CHECK: br [[EXIT]]
785+
// CHECK: [[EXIT]]:
786+
// CHECK: destroy_value [[INSTANCE]]
787+
// CHECK-LABEL: } // end sil function 'hoist_up_to_two_barrier_applies'
788+
sil [ossa] @hoist_up_to_two_barrier_applies : $@convention(thin) (@owned C) -> () {
789+
entry(%instance : @owned $C):
790+
%lifetime = begin_borrow [lexical] %instance : $C
791+
%_ = apply undef(%lifetime) : $@convention(thin) (@guaranteed C) -> ()
792+
cond_br undef, left, right
793+
794+
left:
795+
%result_left = apply undef() : $@convention(thin) () -> ()
796+
br exit
797+
798+
right:
799+
%result_right = apply undef() : $@convention(thin) () -> ()
800+
br exit
801+
802+
exit:
803+
end_borrow %lifetime : $C
804+
destroy_value %instance : $C
805+
%retval = tuple ()
806+
return %retval : $()
807+
}
808+
719809
// =============================================================================
720810
// instruction tests }}
721811
// =============================================================================

test/SILOptimizer/shrink_borrow_scope.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %target-swift-frontend -c -O -enable-copy-propagation=true -enable-lexical-lifetimes=true -sil-verify-all -Xllvm -sil-print-final-ossa-module %s | %FileCheck %s
22

3+
// REQUIRES: rdar87255563
4+
35
// =============================================================================
46
// = DECLARATIONS {{
57
// =============================================================================

0 commit comments

Comments
 (0)