diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp index e5cf557d72a81..a58e475082a1d 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp @@ -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()) { diff --git a/test/SILOptimizer/sil_combine_moveonly.sil b/test/SILOptimizer/sil_combine_moveonly.sil index df42158c3c1d5..1a39bc99847b1 100644 --- a/test/SILOptimizer/sil_combine_moveonly.sil +++ b/test/SILOptimizer/sil_combine_moveonly.sil @@ -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 : $() +} +