Skip to content

Commit 2a81238

Browse files
committed
[AddrLowering] Copy for out-of-range guar stores.
When a copy_value's only use is a store, in some cases, as an optimization, creating a copy_addr can be skipped. Whether a value is such a copy_value is determined by the isStoreCopy predicate. If the operand of the copy_value is a guaranteed value and any of its guaranteed roots have live ranges which the store is outside of, skip this optimization and create the copy_addr.
1 parent 1264e6d commit 2a81238

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -361,13 +361,28 @@ static bool isStoreCopy(SILValue value) {
361361
SmallVector<SILValue, 4> roots;
362362
findGuaranteedReferenceRoots(source, /*lookThroughNestedBorrows=*/true,
363363
roots);
364-
if (llvm::any_of(roots, [](SILValue root) {
365-
// Handle forwarding phis conservatively rather than recursing.
366-
if (SILArgument::asPhi(root) && !BorrowedValue(root))
367-
return true;
368-
369-
return isa<BeginApplyInst>(root->getDefiningInstruction());
370-
})) {
364+
SSAPrunedLiveness liveness;
365+
if (llvm::any_of(roots, [&liveness, storeInst](SILValue root) {
366+
// Handle forwarding phis conservatively rather than recursing.
367+
if (SILArgument::asPhi(root) && !BorrowedValue(root))
368+
return true;
369+
370+
if (isa<BeginApplyInst>(root->getDefiningInstruction())) {
371+
return true;
372+
}
373+
liveness.initializeDef(root);
374+
auto summary = liveness.computeSimple();
375+
if (summary.addressUseKind != AddressUseKind::NonEscaping) {
376+
return true;
377+
}
378+
if (summary.innerBorrowKind != InnerBorrowKind::Contained) {
379+
return true;
380+
}
381+
if (!liveness.isWithinBoundary(storeInst)) {
382+
return true;
383+
}
384+
return false;
385+
})) {
371386
return false;
372387
}
373388
}

test/SILOptimizer/address_lowering.sil

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,29 @@ entry:
18581858
return %retval : $()
18591859
}
18601860

1861+
// CHECK-LABEL: sil [ossa] @testCopyValue1StoreExtractAfterDestroyAggregate : {{.*}} {
1862+
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] :
1863+
// CHECK: [[INSTANCE_ADDR:%[^,]+]] = alloc_stack $Pair<T>
1864+
// CHECK: [[COPY_ADDR:%[^,]+]] = alloc_stack $T
1865+
// CHECK: apply undef<T>([[INSTANCE_ADDR]])
1866+
// CHECK: [[X_ADDR:%[^,]+]] = struct_element_addr [[INSTANCE_ADDR]]{{.*}}, #Pair.x
1867+
// CHECK: copy_addr [[X_ADDR]] to [init] [[COPY_ADDR]]
1868+
// CHECK: destroy_addr [[INSTANCE_ADDR]]
1869+
// CHECK: copy_addr [take] [[COPY_ADDR]] to [[ADDR]]
1870+
// CHECK-LABEL: } // end sil function 'testCopyValue1StoreExtractAfterDestroyAggregate'
1871+
sil [ossa] @testCopyValue1StoreExtractAfterDestroyAggregate : $@convention(thin) <T> (@inout T) -> () {
1872+
entry(%addr : $*T):
1873+
%instance = apply undef<T>() : $@convention(thin) <Tee> () -> @out Pair<Tee>
1874+
%lifetime = begin_borrow %instance : $Pair<T>
1875+
%x = struct_extract %lifetime : $Pair<T>, #Pair.x
1876+
%copy = copy_value %x : $T
1877+
end_borrow %lifetime : $Pair<T>
1878+
destroy_value %instance : $Pair<T>
1879+
store %copy to [assign] %addr : $*T
1880+
%retval = tuple ()
1881+
return %retval : $()
1882+
}
1883+
18611884
// CHECK-LABEL: sil hidden [ossa] @testOpaqueYield :
18621885
// CHECK: bb0(%0 : @guaranteed $TestGeneric<T>):
18631886
// CHECK: [[REF:%.*]] = ref_element_addr %0 : $TestGeneric<T>, #TestGeneric.borrowedGeneric

0 commit comments

Comments
 (0)