Skip to content

Commit b9c5c41

Browse files
committed
[OSSACanOwned] Copy for guaranteed final consume.
Because discovery of defs walks into reborrows and borrowed-from instructions, copies may be processed whose underlying value is a guaranteed value (namely, a reborrow or a borrowed-from instruction). The last consume of such a copy is a final consume, but even so, a copy is still necessary: the original value is guaranteed and can't serve as an operand to an instruction which requries an owned value. rdar://139842132
1 parent aea53a1 commit b9c5c41

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,7 +1169,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
11691169
//
11701170
// Return true if the operand can use the current definition. Return false if
11711171
// it requires a copy.
1172-
auto visitUse = [&](Operand *use) {
1172+
auto visitUse = [&](Operand *use, Def def) {
11731173
auto *user = use->getUser();
11741174
// The current def can always be used for a copy_value.
11751175
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
@@ -1204,6 +1204,11 @@ void CanonicalizeOSSALifetime::rewriteCopies(
12041204
return false;
12051205
}
12061206

1207+
// This is a final consume, but a copy will still be necessary if the
1208+
// original value is guaranteed.
1209+
if (def.getOriginalValue()->getOwnershipKind() == OwnershipKind::Guaranteed)
1210+
return false;
1211+
12071212
return true;
12081213
};
12091214

@@ -1222,7 +1227,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
12221227
for (auto useIter = value->use_begin(), endIter = value->use_end();
12231228
useIter != endIter;) {
12241229
Operand *use = *useIter++;
1225-
if (!visitUse(use)) {
1230+
if (!visitUse(use, def)) {
12261231
copyLiveUse(use, getCallbacks());
12271232
}
12281233
}
@@ -1236,7 +1241,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
12361241
for (auto useIter = srcCopy->use_begin();
12371242
useIter != srcCopy->use_end();) {
12381243
Operand *use = *useIter++;
1239-
if (!visitUse(use)) {
1244+
if (!visitUse(use, def)) {
12401245
if (!reusedCopyOp && srcCopy->getParent() == use->getParentBlock()) {
12411246
reusedCopyOp = use;
12421247
} else {

test/SILOptimizer/canonicalize_ossa_lifetime_unit.sil

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,3 +789,32 @@ entry(%c : @owned $C):
789789
specify_test "canonicalize_ossa_lifetime true false true %c"
790790
unreachable
791791
}
792+
793+
// CHECK-LABEL: begin running test {{.*}} on consume_copy_of_borrowed_from
794+
// CHECK-LABEL: sil [ossa] @consume_copy_of_borrowed_from : {{.*}} {
795+
// The copy can't be eliminated because its root is a guaranteed value.
796+
// CHECK: copy_value
797+
// CHECK-LABEL: } // end sil function 'consume_copy_of_borrowed_from'
798+
// CHECK-LABEL: end running test {{.*}} on consume_copy_of_borrowed_from
799+
sil [ossa] @consume_copy_of_borrowed_from : $@convention(thin) (@owned C) -> () {
800+
bb0(%instance : @owned $C):
801+
%borrow = begin_borrow %instance : $C
802+
br bb1(%instance : $C, %borrow : $C)
803+
804+
bb1(%instance2 : @owned $C, %reborrowed : @reborrow $C):
805+
specify_test "canonicalize_ossa_lifetime true false true %instance2"
806+
%reborrow = borrowed %reborrowed : $C from (%instance2 : $C)
807+
cond_br undef, bb2, bb3
808+
809+
bb2:
810+
end_borrow %reborrow : $C
811+
destroy_value %instance2 : $C
812+
%retval = tuple ()
813+
return %retval : $()
814+
815+
bb3:
816+
%copy = copy_value %reborrow : $C
817+
%takeC = function_ref @takeC : $@convention(thin) (@owned C) -> ()
818+
apply %takeC(%copy) : $@convention(thin) (@owned C) -> ()
819+
unreachable
820+
}

0 commit comments

Comments
 (0)