Skip to content

Commit 546039f

Browse files
authored
Merge pull request #34820 from gottesmm/simple-lifetime-join
[semantic-arc-opts] Let the simple lifetime join optimization handle certain copies with forwarding insts.
2 parents 110dff5 + 5a2d63d commit 546039f

File tree

2 files changed

+48
-14
lines changed

2 files changed

+48
-14
lines changed

lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -289,23 +289,21 @@ bool SemanticARCOptVisitor::eliminateDeadLiveRangeCopyValue(
289289
static bool canSafelyJoinSimpleRange(SILValue cviOperand,
290290
DestroyValueInst *cviOperandDestroy,
291291
CopyValueInst *cvi) {
292-
// We only handle cases where our copy_value has a single consuming use that
293-
// is not a forwarding use. We need to use the LiveRange functionality to
294-
// guarantee correctness in the presence of forwarding uses.
295-
//
296-
// NOTE: This use may be any type of consuming use and may not be a
297-
// destroy_value.
292+
// We only handle cases where our copy_value has a single lifetime ending
293+
// use. We are not working with live ranges here so we do can treat forwarding
294+
// insts like any other value.
298295
auto *cviConsumer = cvi->getSingleConsumingUse();
299-
if (!cviConsumer || isOwnedForwardingUse(cviConsumer)) {
296+
if (!cviConsumer) {
300297
return false;
301298
}
302299

303300
// Ok, we may be able to eliminate this. The main thing we need to be careful
304-
// of here is that if the destroy_value is /after/ the consuming use of the
305-
// operand of copy_value, we may have normal uses of the copy_value's operand
306-
// that would become use-after-frees since we would be shrinking the lifetime
307-
// of the object potentially. Consider the following SIL:
301+
// of here is that if the lifetime of %0 ends /after/ the lifetime of
302+
// %1. Otherwise we would be shrinking the lifetime of the object
303+
// potentially. Consider the following SIL that we would miscompile in such a
304+
// case.
308305
//
306+
// // potential_miscompile.sil
309307
// %0 = ...
310308
// %1 = copy_value %0
311309
// apply %cviConsumer(%1)

test/SILOptimizer/semantic-arc-opts.sil

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ struct StructWithEnumWithIndirectCaseField {
9090
var field : EnumWithIndirectCase
9191
}
9292

93+
sil @get_fakeoptional_nativeobject : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject>
94+
9395
///////////
9496
// Tests //
9597
///////////
@@ -1747,10 +1749,8 @@ bb1:
17471749
return %9999 : $()
17481750
}
17491751

1750-
// Forwarding case. We need LiveRanges for this.
1751-
//
17521752
// CHECK-LABEL: sil [ossa] @donot_join_simple_liveranges_in_same_block_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
1753-
// CHECK: copy_value
1753+
// CHECK-NOT: copy_value
17541754
// CHECK: } // end sil function 'donot_join_simple_liveranges_in_same_block_2'
17551755
sil [ossa] @donot_join_simple_liveranges_in_same_block_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
17561756
bb0(%0 : @owned $Builtin.NativeObject):
@@ -2832,3 +2832,39 @@ bb1:
28322832
bb2:
28332833
unreachable
28342834
}
2835+
2836+
// Make sure we leave only one copy in bb2 and no destroys
2837+
//
2838+
// CHECK-LABEL: sil [ossa] @join_test_with_forwarding_inst : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject> {
2839+
// CHECK: bb2:
2840+
// CHECK: copy_value
2841+
// CHECK-NOT: destroy_value
2842+
// CHECK-NOT: copy_value
2843+
// CHECK: br bb3(
2844+
// CHECK: } // end sil function 'join_test_with_forwarding_inst'
2845+
sil [ossa] @join_test_with_forwarding_inst : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject> {
2846+
bb0:
2847+
%allocStack = alloc_stack $Builtin.NativeObject
2848+
%0 = function_ref @get_fakeoptional_nativeobject : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject>
2849+
%1 = apply %0() : $@convention(thin) () -> @owned FakeOptional<Builtin.NativeObject>
2850+
cond_br undef, bb1, bb2
2851+
2852+
bb1:
2853+
destroy_value %1 : $FakeOptional<Builtin.NativeObject>
2854+
%2 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
2855+
br bb3(%2 : $FakeOptional<Builtin.NativeObject>)
2856+
2857+
bb2:
2858+
%3 = unchecked_enum_data %1 : $FakeOptional<Builtin.NativeObject>, #FakeOptional.some!enumelt
2859+
%4 = copy_value %3 : $Builtin.NativeObject
2860+
store %3 to [init] %allocStack : $*Builtin.NativeObject
2861+
%4c = copy_value %4 : $Builtin.NativeObject
2862+
destroy_value %4 : $Builtin.NativeObject
2863+
%5 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.some!enumelt, %4c : $Builtin.NativeObject
2864+
destroy_addr %allocStack : $*Builtin.NativeObject
2865+
br bb3(%5 : $FakeOptional<Builtin.NativeObject>)
2866+
2867+
bb3(%result : @owned $FakeOptional<Builtin.NativeObject>):
2868+
dealloc_stack %allocStack : $*Builtin.NativeObject
2869+
return %result : $FakeOptional<Builtin.NativeObject>
2870+
}

0 commit comments

Comments
 (0)