From 171607afa79bf53dd2857d5a5af78c47f3415b54 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Thu, 2 Oct 2025 19:20:05 +0200 Subject: [PATCH] DeadStoreElimination: fix a corner case of storing a trivial case of a non-trivial enum Storing a trivial enum case in a non-trivial enum must be treated like a non-trivial init or assign, e.g. ``` %1 = enum $Optional, #Optional.none!enumelt store %1 to [trivial] %0 // <- cannot delete this store! store %2 to [assign] %0 ``` --- .../FunctionPasses/DeadStoreElimination.swift | 9 ++++++++- test/SILOptimizer/dead_store_elim.sil | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/DeadStoreElimination.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/DeadStoreElimination.swift index c7c4a1fa44986..ef7eb618e10f9 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/DeadStoreElimination.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/DeadStoreElimination.swift @@ -167,8 +167,15 @@ private extension StoreInst { var hasValidOwnershipForDeadStoreElimination: Bool { switch storeOwnership { - case .unqualified, .trivial: + case .unqualified: return true + case .trivial: + // Storing a trivial enum case in a non-trivial enum must be treated like a non-trivial + // init or assign, e.g. + // %1 = enum $Optional, #Optional.none!enumelt + // store %1 to [trivial] %0 // <- cannot delete this store! + // store %2 to [assign] %0 + return source.type.isTrivial(in: parentFunction) case .initialize, .assign: // In OSSA, non-trivial values cannot be dead-store eliminated because that could shrink // the lifetime of the original stored value (because it's not kept in memory anymore). diff --git a/test/SILOptimizer/dead_store_elim.sil b/test/SILOptimizer/dead_store_elim.sil index 4cd51cceba8f7..c55bc4992cc9e 100644 --- a/test/SILOptimizer/dead_store_elim.sil +++ b/test/SILOptimizer/dead_store_elim.sil @@ -1615,6 +1615,17 @@ bb0(%0 : $Int, %1 : @owned $IntAndFoo, %2 : $*IntAndFoo): return %r : $() } +// We don't support this, yet. +// Just check that we don't crash. +sil [ossa] @test_trivial_store_of_non_trivial_enum : $@convention(thin) (@owned Optional) -> @out Optional { +bb0(%0 : $*Optional, %1 : @owned $Optional): + %2 = enum $Optional, #Optional.none!enumelt + store %2 to [trivial] %0 + store %1 to [assign] %0 + %r = tuple () + return %r +} + // CHECK-LABEL: sil @test_bind_memory : // CHECK: store %0 // CHECK: end sil function 'test_bind_memory'