Skip to content

Commit 7c293d8

Browse files
committed
TempRValueOpt: fix the handling of begin_access
Consider the related end_access instructions as uses to correctly mark the end of the lifetime of the temporary. This fixes a miscompile in case there is a modification of the copy-source between an begin_access and end_access.
1 parent d569031 commit 7c293d8

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

lib/SILOptimizer/Transforms/TempRValueElimination.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,24 @@ collectLoads(Operand *addressUse, CopyAddrInst *originalCopy,
153153
LLVM_DEBUG(llvm::dbgs()
154154
<< " Temp use may write/destroy its source" << *user);
155155
return false;
156-
case SILInstructionKind::BeginAccessInst:
157-
return cast<BeginAccessInst>(user)->getAccessKind() == SILAccessKind::Read;
158-
156+
case SILInstructionKind::BeginAccessInst: {
157+
auto *beginAccess = cast<BeginAccessInst>(user);
158+
if (beginAccess->getAccessKind() != SILAccessKind::Read)
159+
return false;
160+
// We don't have to recursively call collectLoads for the beginAccess
161+
// result, because a SILAccessKind::Read already guarantees that there are
162+
// no writes to the beginAccess result address (or any projection from it).
163+
// But we have to register the end-accesses as loads to correctly mark the
164+
// end-of-lifetime of the temporary object.
165+
for (Operand *accessUse : beginAccess->getUses()) {
166+
if (auto *endAccess = dyn_cast<EndAccessInst>(accessUse->getUser())) {
167+
if (endAccess->getParent() != block)
168+
return false;
169+
loadInsts.insert(endAccess);
170+
}
171+
}
172+
return true;
173+
}
159174
case SILInstructionKind::MarkDependenceInst: {
160175
auto mdi = cast<MarkDependenceInst>(user);
161176
// If the user is the base operand of the MarkDependenceInst we can return

test/SILOptimizer/temp_rvalue_opt_ossa.sil

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,27 @@ bb0(%0 : $*Klass):
759759
return %9999 : $()
760760
}
761761

762+
763+
// CHECK-LABEL: sil [ossa] @dont_optimize_with_modify_inside_access
764+
// CHECK: [[STK:%[0-9]+]] = alloc_stack $Klass
765+
// CHECK: copy_addr %0 to [initialization] [[STK]]
766+
// CHECK: begin_access [read] [static] [[STK]]
767+
// CHECK-LABEL: } // end sil function 'dont_optimize_with_modify_inside_access'
768+
sil [ossa] @dont_optimize_with_modify_inside_access : $@convention(thin) (@inout Klass, @owned Klass) -> () {
769+
bb0(%0 : $*Klass, %1 : @owned $Klass):
770+
%stack = alloc_stack $Klass
771+
copy_addr %0 to [initialization] %stack : $*Klass
772+
%f = function_ref @inguaranteed_user_without_result : $@convention(thin) (@in_guaranteed Klass) -> ()
773+
%access = begin_access [read] [static] %stack : $*Klass
774+
store %1 to [assign] %0 : $*Klass // This store prevents the optimization
775+
%call = apply %f(%access) : $@convention(thin) (@in_guaranteed Klass) -> ()
776+
end_access %access : $*Klass
777+
destroy_addr %stack : $*Klass
778+
dealloc_stack %stack : $*Klass
779+
%9999 = tuple()
780+
return %9999 : $()
781+
}
782+
762783
/////////////////
763784
// Store Tests //
764785
/////////////////

0 commit comments

Comments
 (0)