Skip to content

Commit de58e79

Browse files
committed
[ownership] When RAUWing an unowned value with a owned/guaranteed value only insert unchecked_ownership_conversion for terminator uses.
Already, we allow for owned/guaranteed values to be passed to values with unowned ownership. This just cleans up the SIL a bit. That being said, we still need unchecked_ownership_conversion for the terminator case since any owned/guaranteed's value (ignoreing function parameters) will end before the return meaning that we need some way of escaping it.
1 parent 2abd7e8 commit de58e79

File tree

3 files changed

+53
-16
lines changed

3 files changed

+53
-16
lines changed

lib/SILOptimizer/Utils/OwnershipOptUtils.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -608,14 +608,19 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
608608
// value, we need to ensure that the guaranteed value is live at all use
609609
// points of the unowned value. If so, just replace and continue.
610610
//
611-
// TODO: Implement this.
611+
// TODO: Implement this for more interesting cases.
612+
if (isa<SILFunctionArgument>(newValue))
613+
return replaceAllUsesAndErase(oldValue, newValue, callbacks);
612614

613615
// Otherwise, we need to lifetime extend the borrow over all of the use
614-
// points. To do so, we copy the value, borrow it, insert an unchecked
615-
// ownership conversion to unowned at oldValue and then RAUW.
616+
// points. To do so, we copy the value, borrow it, and insert an unchecked
617+
// ownership conversion to unowned at all uses that are terminator uses.
618+
//
619+
// We need to insert the conversion since if we have a non-argument
620+
// guaranteed value since its scope will end before the terminator so we
621+
// need to convert the value to unowned early.
616622
//
617-
// We need to insert the conversion to ensure that we do not violate
618-
// ownership propagation rules of forwarding insts.
623+
// TODO: Do we need a separate array here?
619624
SmallVector<Operand *, 8> oldValueUses(oldValue->getUses());
620625
for (auto *use : oldValueUses) {
621626
if (auto *ti = dyn_cast<TermInst>(use->getUser())) {
@@ -628,14 +633,12 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
628633
}
629634
}
630635
}
636+
631637
auto extender = getLifetimeExtender();
632638
SILValue borrow =
633639
extender.createPlusZeroBorrow(newValue, oldValue->getUses());
634640
SILBuilderWithScope builder(oldValue);
635-
auto *newInst = builder.createUncheckedOwnershipConversion(
636-
oldValue->getLoc(), borrow, OwnershipKind::Unowned);
637-
callbacks.createdNewInst(newInst);
638-
return replaceAllUsesAndErase(oldValue, newInst, callbacks);
641+
return replaceAllUsesAndErase(oldValue, borrow, callbacks);
639642
}
640643
case OwnershipKind::Owned: {
641644
// If we have an unowned value that we want to replace with an owned value,
@@ -646,13 +649,15 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
646649

647650
// Otherwise, insert a copy of the owned value and lifetime extend that over
648651
// all uses of the value and then RAUW.
652+
//
653+
// NOTE: For terminator uses, we funnel the use through an
654+
// unchecked_ownership_conversion to ensure that we can end the lifetime of
655+
// our owned/guaranteed value before the terminator.
649656
SmallVector<Operand *, 8> oldValueUses(oldValue->getUses());
650657
for (auto *use : oldValueUses) {
651658
if (auto *ti = dyn_cast<TermInst>(use->getUser())) {
652659
if (ti->isFunctionExiting()) {
653660
SILBuilderWithScope builder(ti);
654-
// We insert this to ensure that we can extend our owned value's
655-
// lifetime to before the function end point.
656661
auto *newInst = builder.createUncheckedOwnershipConversion(
657662
ti->getLoc(), use->get(), OwnershipKind::Unowned);
658663
callbacks.createdNewInst(newInst);
@@ -663,10 +668,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
663668
auto extender = getLifetimeExtender();
664669
SILValue copy = extender.createPlusZeroCopy(newValue, oldValue->getUses());
665670
SILBuilderWithScope builder(oldValue);
666-
auto *newInst = builder.createUncheckedOwnershipConversion(
667-
oldValue->getLoc(), copy, OwnershipKind::Unowned);
668-
callbacks.createdNewInst(newInst);
669-
auto result = replaceAllUsesAndErase(oldValue, newInst, callbacks);
671+
auto result = replaceAllUsesAndErase(oldValue, copy, callbacks);
670672
return result;
671673
}
672674
}

test/SILOptimizer/ossa_rauw_tests.sil

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,40 @@ bb0(%0 : @guaranteed $Klass):
318318
return %3 : $(Klass, Klass)
319319
}
320320

321+
// CHECK-LABEL: sil [ossa] @unowned_to_guaranteed_rauw_2a : $@convention(thin) (@guaranteed Builtin.NativeObject) -> (Klass, Klass) {
322+
// CHECK: bb0(
323+
// CHECK-NEXT: unchecked_ref_cast
324+
// CHECK-NEXT: tuple
325+
// CHECK-NEXT: return
326+
// CHECK: } // end sil function 'unowned_to_guaranteed_rauw_2a'
327+
sil [ossa] @unowned_to_guaranteed_rauw_2a : $@convention(thin) (@guaranteed Builtin.NativeObject) -> (Klass, Klass) {
328+
bb0(%0 : @guaranteed $Builtin.NativeObject):
329+
%0a = unchecked_ref_cast %0 : $Builtin.NativeObject to $Klass
330+
%1 = unchecked_bitwise_cast %0a : $Klass to $SubKlass
331+
%2 = unchecked_bitwise_cast %1 : $SubKlass to $Klass
332+
%3 = tuple(%2 : $Klass, %2 : $Klass)
333+
return %3 : $(Klass, Klass)
334+
}
335+
336+
// We need the unchecked_ownership_conversion since our base value is
337+
// guaranteed, not a function argument, and our user is a function exiting
338+
// terminator.
339+
//
340+
// CHECK-LABEL: sil [ossa] @unowned_to_guaranteed_rauw_2b : $@convention(thin) (@guaranteed Builtin.NativeObject) -> Klass {
341+
// CHECK: bb0(
342+
// CHECK-NEXT: unchecked_ref_cast
343+
// CHECK-NEXT: unchecked_ownership_conversion
344+
// CHECK-NEXT: return
345+
// CHECK: } // end sil function 'unowned_to_guaranteed_rauw_2b'
346+
sil [ossa] @unowned_to_guaranteed_rauw_2b : $@convention(thin) (@guaranteed Builtin.NativeObject) -> Klass {
347+
bb0(%0 : @guaranteed $Builtin.NativeObject):
348+
%0a = unchecked_ref_cast %0 : $Builtin.NativeObject to $Klass
349+
%1 = unchecked_bitwise_cast %0a : $Klass to $SubKlass
350+
%2 = unchecked_bitwise_cast %1 : $SubKlass to $Klass
351+
return %2 : $Klass
352+
}
353+
354+
321355
// CHECK-LABEL: sil [ossa] @unowned_to_guaranteed_rauw_2_loop : $@convention(thin) (@guaranteed Klass) -> @owned FakeOptional<(Klass, Klass)> {
322356
// CHECK: bb0([[ARG:%.*]] : @guaranteed $Klass):
323357
// CHECK-NOT: unchecked_bitwise_cast
@@ -376,7 +410,6 @@ bbExitBlock(%result : @owned $FakeOptional<(Klass, Klass)>):
376410

377411
// CHECK-LABEL: sil [ossa] @unowned_to_guaranteed_rauw_3 : $@convention(thin) (@guaranteed Klass) -> Klass {
378412
// CHECK: bb0(
379-
// CHECK-NEXT: unchecked_ownership_conversion
380413
// CHECK-NEXT: return
381414
// CHECK: } // end sil function 'unowned_to_guaranteed_rauw_3'
382415
sil [ossa] @unowned_to_guaranteed_rauw_3 : $@convention(thin) (@guaranteed Klass) -> Klass {

test/SILOptimizer/sil_combine_ossa.sil

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,6 +2024,7 @@ bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
20242024
// CHECK-NEXT: unchecked_trivial_bit_cast
20252025
// CHECK-NEXT: unchecked_ref_cast
20262026
// CHECK-NOT: unchecked_bitwise_cast
2027+
// CHECK-NOT: unchecked_ownership_conversion
20272028
// CHECK: } // end sil function 'bitwise_combines_owned'
20282029
sil [ossa] @bitwise_combines_owned : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
20292030
bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
@@ -2050,6 +2051,7 @@ bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
20502051
// CHECK-NEXT: unchecked_trivial_bit_cast
20512052
// CHECK-NEXT: unchecked_ref_cast
20522053
// CHECK-NOT: unchecked_bitwise_cast
2054+
// CHECK-NOT: unchecked_ownership_conversion
20532055
// CHECK: } // end sil function 'bitwise_combines_guaranteed'
20542056
sil [ossa] @bitwise_combines_guaranteed : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
20552057
bb0(%0 : @guaranteed $Builtin.NativeObject, %1 : $Builtin.RawPointer):

0 commit comments

Comments
 (0)