Skip to content

Commit 39078cf

Browse files
committed
[SSADestroyHoisting] Aliasable addr args respect deinit barriers.
Previously, all arguments using the inout convention were hoisted ignoring deinit barriers. That was incorrect because @inout_aliasable addresses are modifications but aren't exclusive. Here, that's fixed by only allowing arguments with the @inout convention to be hoisted.
1 parent 0d8866c commit 39078cf

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -821,11 +821,17 @@ void SSADestroyHoisting::run() {
821821
// Arguments enclose everything.
822822
for (auto *arg : getFunction()->getArguments()) {
823823
if (arg->getType().isAddress()) {
824-
bool isInout = cast<SILFunctionArgument>(arg)
825-
->getArgumentConvention()
826-
.isInoutConvention();
827-
changed |= hoistDestroys(arg, /*ignoreDeinitBarriers=*/
828-
isInout, remainingDestroyAddrs, deleter);
824+
auto convention = cast<SILFunctionArgument>(arg)->getArgumentConvention();
825+
// This is equivalent to writing
826+
//
827+
// convention == SILArgumentConvention::Indirect_Inout
828+
//
829+
// but communicates the rationale: in order to ignore deinit barriers, the
830+
// address must be exclusively accessed and be a modification.
831+
bool ignoreDeinitBarriers = convention.isInoutConvention() &&
832+
convention.isExclusiveIndirectParameter();
833+
changed |= hoistDestroys(arg, ignoreDeinitBarriers, remainingDestroyAddrs,
834+
deleter);
829835
}
830836
}
831837

test/SILOptimizer/hoist_destroy_addr.sil

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,21 @@ entry(%instance : @none $TrivialStruct):
255255
return %retval : $()
256256
}
257257

258+
// CHECK-LABEL: sil [ossa] @nohoist_inout_aliasable : {{.*}} {
259+
// CHECK: apply
260+
// CHECK: destroy_addr
261+
// CHECK-LABEL: } // end sil function 'nohoist_inout_aliasable'
262+
sil [ossa] @nohoist_inout_aliasable : $@convention(thin) (@inout_aliasable X) -> () {
263+
entry(%addr : $*X):
264+
%value = load [copy] %addr : $*X
265+
%unknown = function_ref @unknown : $@convention(thin) () -> ()
266+
apply %unknown() : $@convention(thin) () -> ()
267+
destroy_addr %addr : $*X
268+
store %value to [init] %addr : $*X
269+
%tuple = tuple ()
270+
return %tuple : $()
271+
}
272+
258273
// Fold destroy_addr and a load [copy] into a load [take] even when that
259274
// load [take] is guarded by an access scope.
260275
//
@@ -426,4 +441,3 @@ entry(%instance : @owned $X):
426441
dealloc_stack %addr_outer : $*X
427442
return %value : $X
428443
}
429-

0 commit comments

Comments
 (0)