Skip to content

Commit 6310dfc

Browse files
committed
TempRValueOpt: fix the handling of load [take]
load [take] was not considered as a use and it was not detected if it's in a different basic block. This fixes a miscompile in case there is a modification of the copy-source before a load [take]. rdar://problem/69757314
1 parent 7c293d8 commit 6310dfc

File tree

2 files changed

+36
-35
lines changed

2 files changed

+36
-35
lines changed

lib/SILOptimizer/Transforms/TempRValueElimination.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ collectLoads(Operand *addressUse, CopyAddrInst *originalCopy,
241241
case SILInstructionKind::UncheckedAddrCastInst:
242242
return collectLoadsFromProjection(cast<SingleValueInstruction>(user),
243243
originalCopy, loadInsts);
244-
case SILInstructionKind::LoadInst:
244+
245+
case SILInstructionKind::LoadInst: {
245246
// Loads are the end of the data flow chain. The users of the load can't
246247
// access the temporary storage.
247248
//
@@ -251,14 +252,17 @@ collectLoads(Operand *addressUse, CopyAddrInst *originalCopy,
251252
// function. So if we have such a load [take], we /must/ have a
252253
// reinitialization or an alloc_stack that does not fit the pattern we are
253254
// expecting from SILGen. Be conservative and return false.
254-
if (auto *li = dyn_cast<LoadInst>(user)) {
255-
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Take) {
256-
return false;
257-
}
255+
auto *li = cast<LoadInst>(user);
256+
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Take &&
257+
// Only accept load [take] if it takes the whole temporary object.
258+
// load [take] from a projection would destroy only a part of the
259+
// temporary and we don't handle this.
260+
address != originalCopy->getDest()) {
261+
return false;
258262
}
259263
loadInsts.insert(user);
260264
return true;
261-
265+
}
262266
case SILInstructionKind::LoadBorrowInst:
263267
loadInsts.insert(user);
264268
return true;
@@ -432,15 +436,6 @@ bool TempRValueOptPass::tryOptimizeCopyIntoTemp(CopyAddrInst *copyInst) {
432436
if (isa<DestroyAddrInst>(user) || isa<DeallocStackInst>(user))
433437
continue;
434438

435-
// Same for load [take] on the top level temp object. SILGen always takes
436-
// whole values from temporaries. If we have load [take] on projections from
437-
// our base, we fail since those would be re-initializations.
438-
if (auto *li = dyn_cast<LoadInst>(user)) {
439-
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Take) {
440-
continue;
441-
}
442-
}
443-
444439
if (!collectLoads(useOper, copyInst, loadInsts))
445440
return false;
446441
}

test/SILOptimizer/temp_rvalue_opt_ossa.sil

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,22 @@ bb0(%0 : $*B, %1 : $*GS<B>):
128128
return %9999 : $()
129129
}
130130

131+
// CHECK-LABEL: sil [ossa] @store_before_load_take
132+
// CHECK: [[STK:%[0-9]+]] = alloc_stack
133+
// CHECK: copy_addr [take] %0 to [initialization] [[STK]]
134+
// CHECK: store
135+
// CHECK: load [take] [[STK]]
136+
// CHECK: return
137+
// CHECK: } // end sil function 'store_before_load_take'
138+
sil [ossa] @store_before_load_take : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
139+
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
140+
%stk = alloc_stack $Builtin.NativeObject
141+
copy_addr [take] %0 to [initialization] %stk : $*Builtin.NativeObject
142+
store %1 to [init] %0 : $*Builtin.NativeObject
143+
%obj = load [take] %stk : $*Builtin.NativeObject
144+
dealloc_stack %stk : $*Builtin.NativeObject
145+
return %obj : $Builtin.NativeObject
146+
}
131147
// CHECK-LABEL: sil [ossa] @load_in_wrong_block
132148
// CHECK: bb0(%0 : $*GS<B>):
133149
// CHECK-NEXT: alloc_stack
@@ -693,38 +709,28 @@ bb0(%0 : @owned $GS<Builtin.NativeObject>):
693709
return %obj : $GS<Builtin.NativeObject>
694710
}
695711

696-
// CHECK-LABEL: sil [ossa] @hoist_load_copy_to_src_copy_addr_site_two_takes : $@convention(thin) (@in GS<Builtin.NativeObject>) -> @owned GS<Builtin.NativeObject> {
697-
// CHECK: bb0([[ARG:%.*]] :
698-
// CHECK: [[COPY_1:%.*]] = load [copy] [[ARG]]
699-
// CHECK: [[COPY_2:%.*]] = load [copy] [[ARG]]
700-
// CHECK: destroy_addr [[ARG]]
701-
// CHECK: cond_br undef, bb1, bb2
702-
//
712+
// CHECK-LABEL: sil [ossa] @dont_optimize_with_load_in_different_block
713+
// CHECK: [[STK:%[0-9]+]] = alloc_stack
714+
// CHECK: copy_addr %0 to [initialization] [[STK]]
703715
// CHECK: bb1:
704-
// CHECK: destroy_value [[COPY_1]]
705-
// CHECK: br bb3([[COPY_2]] :
706-
//
716+
// CHECK: load [take] [[STK]]
707717
// CHECK: bb2:
708-
// CHECK: destroy_value [[COPY_2]]
709-
// CHECK: br bb3([[COPY_1]] :
710-
//
711-
// CHECK: bb3([[RESULT:%.*]] : @owned
712-
// CHECK: apply {{%.*}}([[RESULT]])
713-
// CHECK: return [[RESULT]]
714-
// CHECK: } // end sil function 'hoist_load_copy_to_src_copy_addr_site_two_takes'
715-
sil [ossa] @hoist_load_copy_to_src_copy_addr_site_two_takes : $@convention(thin) (@in GS<Builtin.NativeObject>) -> @owned GS<Builtin.NativeObject> {
716-
bb0(%0 : $*GS<Builtin.NativeObject>):
718+
// CHECK: copy_addr %1 to %0
719+
// CHECK: load [take] [[STK]]
720+
// CHECK: } // end sil function 'dont_optimize_with_load_in_different_block'
721+
sil [ossa] @dont_optimize_with_load_in_different_block : $@convention(thin) (@inout GS<Builtin.NativeObject>, @in_guaranteed GS<Builtin.NativeObject>) -> @owned GS<Builtin.NativeObject> {
722+
bb0(%0 : $*GS<Builtin.NativeObject>, %1 : $*GS<Builtin.NativeObject>):
717723
%f = function_ref @use_gsbase_builtinnativeobject : $@convention(thin) (@guaranteed GS<Builtin.NativeObject>) -> ()
718724
%stk = alloc_stack $GS<Builtin.NativeObject>
719725
copy_addr %0 to [initialization] %stk : $*GS<Builtin.NativeObject>
720-
destroy_addr %0 : $*GS<Builtin.NativeObject>
721726
cond_br undef, bb1, bb2
722727

723728
bb1:
724729
%obj = load [take] %stk : $*GS<Builtin.NativeObject>
725730
br bb3(%obj : $GS<Builtin.NativeObject>)
726731

727732
bb2:
733+
copy_addr %1 to %0 : $*GS<Builtin.NativeObject>
728734
%obj2 = load [take] %stk : $*GS<Builtin.NativeObject>
729735
br bb3(%obj2 : $GS<Builtin.NativeObject>)
730736

0 commit comments

Comments
 (0)