Skip to content

Commit 6226fa7

Browse files
committed
[MemAccessUtils] Regard end/abort_apply as use.
Unique storage use visitor was not previously considering end_apply and abort_apply as uses of an address even when the begin_apply took that address as an argument. They are uses of it though because the address may be stored into the coroutine's frame and used when the second partial function is invoked.
1 parent e134ad7 commit 6226fa7

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,6 +1948,29 @@ bool UniqueStorageUseVisitor::findUses(UniqueStorageUseVisitor &visitor) {
19481948
return visitAccessStorageUses(gather, visitor.storage, visitor.function);
19491949
}
19501950

1951+
static bool
1952+
visitApplyOperand(Operand *use, UniqueStorageUseVisitor &visitor,
1953+
bool (UniqueStorageUseVisitor::*visit)(Operand *)) {
1954+
auto *user = use->getUser();
1955+
if (auto *bai = dyn_cast<BeginApplyInst>(user)) {
1956+
if (!(visitor.*visit)(use))
1957+
return false;
1958+
SmallVector<Operand *, 2> endApplyUses;
1959+
SmallVector<Operand *, 2> abortApplyUses;
1960+
bai->getCoroutineEndPoints(endApplyUses, abortApplyUses);
1961+
for (auto *endApplyUse : endApplyUses) {
1962+
if (!(visitor.*visit)(endApplyUse))
1963+
return false;
1964+
}
1965+
for (auto *abortApplyUse : abortApplyUses) {
1966+
if (!(visitor.*visit)(abortApplyUse))
1967+
return false;
1968+
}
1969+
return true;
1970+
}
1971+
return (visitor.*visit)(use);
1972+
}
1973+
19511974
bool GatherUniqueStorageUses::visitUse(Operand *use, AccessUseType useTy) {
19521975
unsigned operIdx = use->getOperandNumber();
19531976
auto *user = use->getUser();
@@ -1960,16 +1983,19 @@ bool GatherUniqueStorageUses::visitUse(Operand *use, AccessUseType useTy) {
19601983
case SILArgumentConvention::Indirect_Inout:
19611984
case SILArgumentConvention::Indirect_InoutAliasable:
19621985
case SILArgumentConvention::Indirect_Out:
1963-
return visitor.visitStore(use);
1986+
return visitApplyOperand(use, visitor,
1987+
&UniqueStorageUseVisitor::visitStore);
19641988
case SILArgumentConvention::Indirect_In_Guaranteed:
19651989
case SILArgumentConvention::Indirect_In:
19661990
case SILArgumentConvention::Indirect_In_Constant:
1967-
return visitor.visitLoad(use);
1991+
return visitApplyOperand(use, visitor,
1992+
&UniqueStorageUseVisitor::visitLoad);
19681993
case SILArgumentConvention::Direct_Unowned:
19691994
case SILArgumentConvention::Direct_Owned:
19701995
case SILArgumentConvention::Direct_Guaranteed:
19711996
// most likely an escape of a box
1972-
return visitor.visitUnknownUse(use);
1997+
return visitApplyOperand(use, visitor,
1998+
&UniqueStorageUseVisitor::visitUnknownUse);
19731999
}
19742000
}
19752001
switch (user->getKind()) {

test/SILOptimizer/hoist_destroy_addr.sil

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ sil @f_out : $@convention(thin) <T> () -> @out T
5959
sil @f_bool : $@convention(thin) () -> Builtin.Int1
6060
sil [ossa] @take_trivial_struct : $@convention(thin) (TrivialStruct) -> ()
6161
sil [ossa] @get_change_out : $@convention(thin) () -> @out Change
62+
sil [ossa] @coro : $@yield_once @convention(thin) (@inout X) -> @yields ()
6263

6364
// CHECK-LABEL: sil [ossa] @test_simple
6465
// CHECK: bb0(%0 : $*S):
@@ -346,6 +347,24 @@ entry(%in_addr : $*X):
346347
return %retval : $X
347348
}
348349

350+
// If a begin_apply uses the address, the end_appy and abort_apply should be
351+
// regarded as uses too. Don't hoist over them.
352+
//
353+
// CHECK-LABEL: sil [ossa] @nohoist_over_end_apply_use : {{.*}} {
354+
// CHECK: end_apply
355+
// CHECK: destroy_addr
356+
// CHECK: tuple
357+
// CHECK-LABEL: } // end sil function 'nohoist_over_end_apply_use'
358+
sil [ossa] @nohoist_over_end_apply_use : $@convention(thin) (@inout X, @owned X) -> () {
359+
entry(%addr : $*X, %instance : @owned $X):
360+
%coro = function_ref @coro : $@yield_once @convention(thin) (@inout X) -> @yields ()
361+
(%empty, %continuation) = begin_apply %coro(%addr) : $@yield_once @convention(thin) (@inout X) -> @yields ()
362+
end_apply %continuation
363+
%retval = tuple ()
364+
store %instance to [assign] %addr : $*X
365+
return %retval : $()
366+
}
367+
349368
// Fold destroy_addr and a load [copy] into a load [take] even when that
350369
// load [take] is guarded by an access scope.
351370
//

0 commit comments

Comments
 (0)