From c89dcd80194beb56b7c9db3e70f606309d33028a Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Mon, 4 Sep 2023 23:17:10 -0700 Subject: [PATCH] Fix handling of none value stores to non-trivial enums in Mem2Reg We allow none values to be stored to a non-trivial enum. For such store_borrow, `LiveValues::forValues` used an Owned storage type, but endLexicalLifetime expected Guaranteed storage type, leading to a compiler crash. For store_borrow, use the LiveValues::forGuaranteed and for store use LiveValues::forOwned to avoid this. Fixes rdar://114390472 --- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 11 +--- test/SILOptimizer/mem2reg_ossa_nontrivial.sil | 66 +++++++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 1f441327879a7..629f50d88f3e6 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -203,13 +203,6 @@ class LiveValues { return LiveValues::forOwned({stored, move}); } - static LiveValues forValues(SILValue stored, SILValue lexical) { - if (stored->getOwnershipKind() == OwnershipKind::Guaranteed) { - return LiveValues::forGuaranteed({stored, lexical}); - } - return LiveValues::forOwned({stored, lexical}); - } - static LiveValues toReplace(AllocStackInst *asi, SILValue replacement) { if (replacement->getOwnershipKind() == OwnershipKind::Guaranteed) { return LiveValues::forGuaranteed(Guaranteed::toReplace(asi, replacement)); @@ -1290,7 +1283,9 @@ StackAllocationPromoter::getLiveOutValues(BasicBlockSetVector &phiBlocks, auto *inst = it->second; auto stored = inst->getOperand(CopyLikeInstruction::Src); auto lexical = getLexicalValueForStore(inst, asi); - return LiveValues::forValues(stored, lexical); + return isa(inst) + ? LiveValues::forGuaranteed(stored, lexical) + : LiveValues::forOwned(stored, lexical); } // If there is a Phi definition in this block: diff --git a/test/SILOptimizer/mem2reg_ossa_nontrivial.sil b/test/SILOptimizer/mem2reg_ossa_nontrivial.sil index 62cc04ad1d56e..471b100c50d47 100644 --- a/test/SILOptimizer/mem2reg_ossa_nontrivial.sil +++ b/test/SILOptimizer/mem2reg_ossa_nontrivial.sil @@ -1227,3 +1227,69 @@ entry(%instance : @owned $AnyObject): %82 = tuple () return %82 : $() } + +// CHECK-LABEL: sil [ossa] @test_enum_store_borrow_none : +// CHECK: alloc_stack +// CHECK-NOT: alloc_stack +// CHECK: dealloc_stack +// CHECK-LABEL: } // end sil function 'test_enum_store_borrow_none' +sil [ossa] @test_enum_store_borrow_none : $@convention(thin) () -> () { +bb0: + %1 = alloc_stack [lexical] $FakeOptional + %none = enum $FakeOptional, #FakeOptional.none!enumelt + %2 = store_borrow %none to %1 : $*FakeOptional + %3 = alloc_stack $FakeOptional + %4 = load [copy] %2 : $*FakeOptional + store %4 to [init] %3 : $*FakeOptional + switch_enum_addr %3 : $*FakeOptional, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2 + +bb1: + %7 = unchecked_take_enum_data_addr %3 : $*FakeOptional, #FakeOptional.some!enumelt + %8 = load [take] %7 : $*Klass + destroy_value %8 : $Klass + dealloc_stack %3 : $*FakeOptional + br bb3 + +bb2: + dealloc_stack %3 : $*FakeOptional + br bb3 + +bb3: + end_borrow %2 : $*FakeOptional + dealloc_stack %1 : $*FakeOptional + %t = tuple () + return %t : $() +} + +// CHECK-LABEL: sil [ossa] @test_enum_store_none : +// CHECK: alloc_stack +// CHECK-NOT: alloc_stack +// CHECK: dealloc_stack +// CHECK-LABEL: } // end sil function 'test_enum_store_none' +sil [ossa] @test_enum_store_none : $@convention(thin) () -> () { +bb0: + %1 = alloc_stack [lexical] $FakeOptional + %none = enum $FakeOptional, #FakeOptional.none!enumelt + store %none to [init] %1 : $*FakeOptional + %3 = alloc_stack $FakeOptional + %4 = load [copy] %1 : $*FakeOptional + store %4 to [init] %3 : $*FakeOptional + switch_enum_addr %3 : $*FakeOptional, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2 + +bb1: + %7 = unchecked_take_enum_data_addr %3 : $*FakeOptional, #FakeOptional.some!enumelt + %8 = load [take] %7 : $*Klass + destroy_value %8 : $Klass + dealloc_stack %3 : $*FakeOptional + br bb3 + +bb2: + dealloc_stack %3 : $*FakeOptional + br bb3 + +bb3: + destroy_addr %1 : $*FakeOptional + dealloc_stack %1 : $*FakeOptional + %t = tuple () + return %t : $() +}