Skip to content

Commit ca29d53

Browse files
Merge pull request #66716 from nate-chandler/rdar110913116
[SILOptimizer] Don't optimize move-only lifetimes.
2 parents 4e5ff2c + 5d7aa84 commit ca29d53

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,11 @@ bool hoistDestroys(SILValue root, bool ignoreDeinitBarriers,
870870
BasicCalleeAnalysis *calleeAnalysis) {
871871
LLVM_DEBUG(llvm::dbgs() << "Performing destroy hoisting on " << root);
872872

873+
// Don't canonicalize the lifetimes of addresses of move-only type.
874+
// According to language rules, they are fixed.
875+
if (root->getType().isMoveOnly())
876+
return false;
877+
873878
SILFunction *function = root->getFunction();
874879
if (!function)
875880
return false;

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,12 @@ void CanonicalizeOSSALifetime::rewriteLifetimes() {
11571157
bool CanonicalizeOSSALifetime::canonicalizeValueLifetime(SILValue def) {
11581158
LivenessState livenessState(*this, def);
11591159

1160+
// Don't canonicalize the lifetimes of values of move-only type. According to
1161+
// language rules, they are fixed.
1162+
if (def->getType().isMoveOnly()) {
1163+
return false;
1164+
}
1165+
11601166
// Step 1: Compute liveness.
11611167
if (!computeLiveness()) {
11621168
LLVM_DEBUG(llvm::dbgs() << "Failed to compute liveness boundary!\n");

test/SILOptimizer/canonicalize_ossa_lifetime_unit.sil

+46
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ sil @getOwned : $@convention(thin) () -> @owned C
55
sil @barrier : $@convention(thin) () -> ()
66
struct S {}
77

8+
@_moveOnly struct MoS {}
9+
@_moveOnly struct MoE {}
10+
811
// When access scopes are respected, the lifetime which previously extended
912
// beyond the access scope still extends beyond it.
1013
// CHECK-LABEL: begin running test 1 of 2 on retract_value_lifetime_into_access_scope_when_access_scopes_not_respected: canonicalize-ossa-lifetime with: true, false, true, @trace
@@ -134,3 +137,46 @@ exit(%phi : @owned $C, %typhi : $S):
134137
%retval = tuple ()
135138
return %retval : $()
136139
}
140+
141+
sil @empty : $@convention(thin) () -> () {
142+
[global: ]
143+
bb0:
144+
%0 = tuple ()
145+
return %0 : $()
146+
}
147+
148+
// Even though the apply of %empty is not a deinit barrier, verify that the
149+
// destroy is not hoisted, because MoS is move-only.
150+
// CHECK-LABEL: begin running test {{.*}} on dont_move_destroy_value_of_moveonly_struct: canonicalize-ossa-lifetime with: true, false, true, @argument
151+
// CHECK-LABEL: sil [ossa] @dont_move_destroy_value_of_moveonly_struct : {{.*}} {
152+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
153+
// CHECK: apply
154+
// CHECK: destroy_value [[INSTANCE]]
155+
// CHECK-LABEL: } // end sil function 'dont_move_destroy_value_of_moveonly_struct'
156+
// CHECK-LABEL: end running test {{.*}} on dont_move_destroy_value_of_moveonly_struct: canonicalize-ossa-lifetime with: true, false, true, @argument
157+
sil [ossa] @dont_move_destroy_value_of_moveonly_struct : $@convention(thin) (@owned MoS) -> () {
158+
entry(%instance : @owned $MoS):
159+
test_specification "canonicalize-ossa-lifetime true false true @argument"
160+
%empty = function_ref @empty : $@convention(thin) () -> ()
161+
apply %empty() : $@convention(thin) () -> ()
162+
destroy_value %instance : $MoS
163+
%retval = tuple ()
164+
return %retval : $()
165+
}
166+
167+
// CHECK-LABEL: begin running test {{.*}} on dont_move_destroy_value_of_moveonly_enum: canonicalize-ossa-lifetime with: true, false, true, @argument
168+
// CHECK-LABEL: sil [ossa] @dont_move_destroy_value_of_moveonly_enum : {{.*}} {
169+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
170+
// CHECK: apply
171+
// CHECK: destroy_value [[INSTANCE]]
172+
// CHECK-LABEL: } // end sil function 'dont_move_destroy_value_of_moveonly_enum'
173+
// CHECK-LABEL: end running test {{.*}} on dont_move_destroy_value_of_moveonly_enum: canonicalize-ossa-lifetime with: true, false, true, @argument
174+
sil [ossa] @dont_move_destroy_value_of_moveonly_enum : $@convention(thin) (@owned MoE) -> () {
175+
entry(%instance : @owned $MoE):
176+
test_specification "canonicalize-ossa-lifetime true false true @argument"
177+
%empty = function_ref @empty : $@convention(thin) () -> ()
178+
apply %empty() : $@convention(thin) () -> ()
179+
destroy_value %instance : $MoE
180+
%retval = tuple ()
181+
return %retval : $()
182+
}

test/SILOptimizer/hoist_destroy_addr.sil

+34
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ struct STXXITXXII {
7979
var i: I
8080
}
8181

82+
@_moveOnly struct MoS {}
83+
@_moveOnly struct MoE {}
84+
8285
sil @unknown : $@convention(thin) () -> ()
8386
sil @use_S : $@convention(thin) (@in_guaranteed S) -> ()
8487

@@ -1145,3 +1148,34 @@ entry(%addr : $*X):
11451148
%retval = tuple ()
11461149
return %retval : $()
11471150
}
1151+
1152+
// Even though the apply of %empty is not a deinit barrier (c.f.
1153+
// hoist_over_apply_of_non_barrier_fn), verify that the destroy_addr is not
1154+
// hoisted, because MoS is move-only.
1155+
// CHECK-LABEL: sil [ossa] @dont_move_destroy_addr_of_moveonly_struct : {{.*}} {
1156+
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] :
1157+
// CHECK: apply
1158+
// CHECK: destroy_addr [[ADDR]]
1159+
// CHECK-LABEL: } // end sil function 'dont_move_destroy_addr_of_moveonly_struct'
1160+
sil [ossa] @dont_move_destroy_addr_of_moveonly_struct : $@convention(thin) (@in MoS) -> () {
1161+
entry(%addr : $*MoS):
1162+
%empty = function_ref @empty : $@convention(thin) () -> ()
1163+
apply %empty() : $@convention(thin) () -> ()
1164+
destroy_addr %addr : $*MoS
1165+
%retval = tuple ()
1166+
return %retval : $()
1167+
}
1168+
1169+
// CHECK-LABEL: sil [ossa] @dont_move_destroy_addr_of_moveonly_enum : {{.*}} {
1170+
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] :
1171+
// CHECK: apply
1172+
// CHECK: destroy_addr [[ADDR]]
1173+
// CHECK-LABEL: } // end sil function 'dont_move_destroy_addr_of_moveonly_enum'
1174+
sil [ossa] @dont_move_destroy_addr_of_moveonly_enum : $@convention(thin) (@in MoE) -> () {
1175+
entry(%addr : $*MoE):
1176+
%empty = function_ref @empty : $@convention(thin) () -> ()
1177+
apply %empty() : $@convention(thin) () -> ()
1178+
destroy_addr %addr : $*MoE
1179+
%retval = tuple ()
1180+
return %retval : $()
1181+
}

0 commit comments

Comments
 (0)