Skip to content

Commit 625e6d7

Browse files
committed
[DestroyAddrHoisting] Skip init_enum_data_addrs.
A destroy of an `init_enum_data_addr` is not equivalent to a destroy of the whole enum's address. Treat such destroys just like destroys of `struct_element_addr`s are treated: by bailing out. rdar://152431332
1 parent 5af8437 commit 625e6d7

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,20 @@ struct KnownStorageUses : UniqueStorageUseVisitor {
164164
bool visitStore(Operand *use) override { return recordUser(use->getUser()); }
165165

166166
bool visitDestroy(Operand *use) override {
167+
// An init_enum_data_addr is viewed as an "identity projection", rather than
168+
// a proper projection like a struct_element_addr. As a result, its
169+
// destroys are passed directly to visitors. But such addresses aren't
170+
// quite equivalent to the original address. Specifically, a destroy of an
171+
// init_enum_data_addr cannot in general be replaced with a destroy of the
172+
// whole enum. The latter destroy is only equivalent to the former if there
173+
// has been an `inject_enum_addr`.
174+
//
175+
// Handle a destroy of such a projection just like we handle the destroy of
176+
// a struct_element_addr: by bailing out.
177+
if (isa<InitEnumDataAddrInst>(
178+
stripAccessAndAccessStorageCasts(use->get()))) {
179+
return false;
180+
}
167181
originalDestroys.insert(use->getUser());
168182
return true;
169183
}

test/SILOptimizer/hoist_destroy_addr.sil

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,3 +1280,39 @@ bb0(%aggregate : $*NCAggregate):
12801280
%retval = tuple ()
12811281
return %retval
12821282
}
1283+
1284+
// CHECK-LABEL: sil [ossa] @nohoist_ieda : {{.*}} {
1285+
// CHECK: [[IEDA:%[^,]+]] = init_enum_data_addr
1286+
// CHECK: tuple
1287+
// CHECK-NEXT: destroy_addr [[IEDA]]
1288+
// CHECK-LABEL: } // end sil function 'nohoist_ieda'
1289+
sil [ossa] @nohoist_ieda : $@convention(thin) () -> @out TwoCases {
1290+
bb0(%out : $*TwoCases):
1291+
%ieda = init_enum_data_addr %out, #TwoCases.A!enumelt
1292+
apply undef(%ieda) : $@convention(thin) () -> @out X
1293+
%retval = tuple ()
1294+
destroy_addr %ieda
1295+
apply undef(%ieda) : $@convention(thin) () -> @out X
1296+
inject_enum_addr %out, #TwoCases.A!enumelt
1297+
return %retval
1298+
}
1299+
1300+
// CHECK-LABEL: sil [ossa] @nohoist_ieda_2 : {{.*}} {
1301+
// CHECK: [[IEDA:%[^,]+]] = init_enum_data_addr
1302+
// CHECK: tuple
1303+
// CHECK: [[CTM:%[^,]+]] = copyable_to_moveonlywrapper_addr [[IEDA]]
1304+
// CHECK: [[MTC:%[^,]+]] = moveonlywrapper_to_copyable_addr [[CTM]]
1305+
// CHECK-NEXT: destroy_addr [[MTC]]
1306+
// CHECK-LABEL: } // end sil function 'nohoist_ieda_2'
1307+
sil [ossa] @nohoist_ieda_2 : $@convention(thin) () -> @out TwoCases {
1308+
bb0(%out : $*TwoCases):
1309+
%ieda = init_enum_data_addr %out, #TwoCases.A!enumelt
1310+
apply undef(%ieda) : $@convention(thin) () -> @out X
1311+
%retval = tuple ()
1312+
%ctm = copyable_to_moveonlywrapper_addr %ieda
1313+
%mtc = moveonlywrapper_to_copyable_addr %ctm
1314+
destroy_addr %mtc
1315+
apply undef(%ieda) : $@convention(thin) () -> @out X
1316+
inject_enum_addr %out, #TwoCases.A!enumelt
1317+
return %retval
1318+
}

0 commit comments

Comments
 (0)