SILCombine: don't fold unchecked_take_enum_data_addr - destroy_addr of enums with deinit

Destroying whole non-copyable enums with a deinit would wrongly trigger calling its deinit.
This commit is contained in:
Erik Eckstein
2025-10-13 19:23:14 +02:00
parent 23474f93b7
commit 66e718525b
2 changed files with 30 additions and 0 deletions

View File

@@ -1146,6 +1146,10 @@ SILInstruction *SILCombiner::visitUncheckedTakeEnumDataAddrInst(
}
if (onlyDestroys) {
// Destroying whole non-copyable enums with a deinit would wrongly trigger calling its deinit.
if (tedai->getOperand()->getType().isValueTypeWithDeinit())
return nullptr;
// The unchecked_take_enum_data_addr is dead: remove it and replace all
// destroys with a destroy of its operand.
while (!tedai->use_empty()) {

View File

@@ -185,3 +185,29 @@ bb0(%0 : @owned $S2):
return %r
}
// CHECK-LABEL: sil [ossa] @dont_fold_destroy_of_take_enum_with_deinit_ossa :
// CHECK: bb0(%0 : $*MaybeFileDescriptor):
// CHECK-NEXT: %1 = unchecked_take_enum_data_addr %0
// CHECK-NEXT: destroy_addr %1
// CHECK: } // end sil function 'dont_fold_destroy_of_take_enum_with_deinit_ossa'
sil [ossa] @dont_fold_destroy_of_take_enum_with_deinit_ossa : $@convention(thin) (@in MaybeFileDescriptor) -> () {
bb0(%0 : $*MaybeFileDescriptor):
%1 = unchecked_take_enum_data_addr %0, #MaybeFileDescriptor.some!enumelt
destroy_addr %1
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_fold_destroy_of_take_enum_with_deinit :
// CHECK: bb0(%0 : $*MaybeFileDescriptor):
// CHECK-NEXT: %1 = unchecked_take_enum_data_addr %0
// CHECK-NEXT: destroy_addr %1
// CHECK: } // end sil function 'dont_fold_destroy_of_take_enum_with_deinit'
sil @dont_fold_destroy_of_take_enum_with_deinit : $@convention(thin) (@in MaybeFileDescriptor) -> () {
bb0(%0 : $*MaybeFileDescriptor):
%1 = unchecked_take_enum_data_addr %0, #MaybeFileDescriptor.some!enumelt
destroy_addr %1
%r = tuple ()
return %r : $()
}