Skip to content

Commit 15be37b

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 dac9dd7 commit 15be37b

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
@@ -1170,7 +1170,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
11701170
//
11711171
// Return true if the operand can use the current definition. Return false if
11721172
// it requires a copy.
1173-
auto visitUse = [&](Operand *use) {
1173+
auto visitUse = [&](Operand *use, Def def) {
11741174
auto *user = use->getUser();
11751175
// The current def can always be used for a copy_value.
11761176
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
@@ -1205,6 +1205,11 @@ void CanonicalizeOSSALifetime::rewriteCopies(
12051205
return false;
12061206
}
12071207

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

@@ -1223,7 +1228,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
12231228
for (auto useIter = value->use_begin(), endIter = value->use_end();
12241229
useIter != endIter;) {
12251230
Operand *use = *useIter++;
1226-
if (!visitUse(use)) {
1231+
if (!visitUse(use, def)) {
12271232
copyLiveUse(use, getCallbacks());
12281233
}
12291234
}
@@ -1237,7 +1242,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
12371242
for (auto useIter = srcCopy->use_begin();
12381243
useIter != srcCopy->use_end();) {
12391244
Operand *use = *useIter++;
1240-
if (!visitUse(use)) {
1245+
if (!visitUse(use, def)) {
12411246
if (!reusedCopyOp && srcCopy->getParent() == use->getParentBlock()) {
12421247
reusedCopyOp = use;
12431248
} 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)