Skip to content

Commit dc57d6b

Browse files
committed
Disable Mem2Reg in ossa for alloc_stack [dynamic_lifetime]
With such alloc_stack we can pass over-consumed values to a proactively added phi. Even though such a SIL does not have issues at runtime, they raise an ownership verification error.
1 parent 42863d4 commit dc57d6b

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,12 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
11231123
LLVM_DEBUG(llvm::dbgs() << "*** Memory to register looking at: " << *alloc);
11241124
++NumAllocStackFound;
11251125

1126+
// In OSSA, don't do Mem2Reg on non-trivial alloc_stack with dynamic_lifetime.
1127+
if (alloc->hasDynamicLifetime() && f.hasOwnership() &&
1128+
!alloc->getType().isTrivial(f)) {
1129+
return false;
1130+
}
1131+
11261132
// Don't handle captured AllocStacks.
11271133
bool inSingleBlock = false;
11281134
if (isCaptured(alloc, inSingleBlock)) {

test/SILOptimizer/mem2reg_ossa_nontrivial.sil

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public enum FakeOptional<T> {
4343
sil [ossa] @get_nontrivialstruct : $@convention(thin) () -> @owned NonTrivialStruct
4444
sil [ossa] @get_nontrivialenum : $@convention(thin) () -> @owned NonTrivialEnum
4545
sil [ossa] @get_optionalnontrivialstruct : $@convention(thin) () -> @owned FakeOptional<NonTrivialStruct>
46+
sil [ossa] @take_nontrivialstruct : $@convention(thin) (@owned NonTrivialStruct) -> ()
4647

4748
///////////
4849
// Tests //
@@ -773,6 +774,93 @@ bbret(%new : @owned $Klass):
773774
return %new : $Klass
774775
}
775776

777+
// CHECK-LABEL: sil [ossa] @test_dynamiclifetime1 :
778+
// CHECK: alloc_stack [dynamic_lifetime]
779+
// CHECK-LABEL: } // end sil function 'test_dynamiclifetime1'
780+
sil [ossa] @test_dynamiclifetime1 : $@convention(thin) () -> () {
781+
bb0:
782+
%2 = alloc_stack $Builtin.Int1
783+
%3 = alloc_stack [dynamic_lifetime] $NonTrivialStruct
784+
%4 = integer_literal $Builtin.Int1, 0
785+
store %4 to [trivial] %2 : $*Builtin.Int1
786+
cond_br undef, bb1, bb2
787+
788+
bb1:
789+
br bb3
790+
791+
bb2:
792+
%func = function_ref @get_nontrivialstruct : $@convention(thin) () -> @owned NonTrivialStruct
793+
%val = apply %func() : $@convention(thin) () -> @owned NonTrivialStruct
794+
%27 = integer_literal $Builtin.Int1, -1
795+
store %27 to [trivial] %2 : $*Builtin.Int1
796+
store %val to [init] %3 : $*NonTrivialStruct
797+
br bb3
798+
799+
bb3:
800+
%32 = load [trivial] %2 : $*Builtin.Int1
801+
cond_br %32, bb4, bb5
802+
803+
bb4:
804+
%34 = load [take] %3 : $*NonTrivialStruct
805+
destroy_value %34 : $NonTrivialStruct
806+
br bb6
807+
808+
bb5:
809+
br bb6
810+
811+
bb6:
812+
dealloc_stack %3 : $*NonTrivialStruct
813+
dealloc_stack %2 : $*Builtin.Int1
814+
%res = tuple ()
815+
return %res : $()
816+
}
817+
818+
// CHECK-LABEL: sil [ossa] @test_dynamiclifetime2 :
819+
// CHECK: alloc_stack [dynamic_lifetime]
820+
// CHECK-LABEL: } // end sil function 'test_dynamiclifetime2'
821+
sil [ossa] @test_dynamiclifetime2 : $@convention(thin) () -> () {
822+
bb0:
823+
%2 = alloc_stack $Builtin.Int1
824+
%3 = alloc_stack [dynamic_lifetime] $NonTrivialStruct
825+
%4 = integer_literal $Builtin.Int1, 0
826+
store %4 to [trivial] %2 : $*Builtin.Int1
827+
%func1 = function_ref @get_nontrivialstruct : $@convention(thin) () -> @owned NonTrivialStruct
828+
%val1 = apply %func1() : $@convention(thin) () -> @owned NonTrivialStruct
829+
store %val1 to [init] %3 : $*NonTrivialStruct
830+
%ld1 = load [take] %3 : $*NonTrivialStruct
831+
%func2 = function_ref @take_nontrivialstruct : $@convention(thin) (@owned NonTrivialStruct) -> ()
832+
apply %func2(%ld1) : $@convention(thin) (@owned NonTrivialStruct) -> ()
833+
cond_br undef, bb1, bb2
834+
835+
bb1:
836+
br bb3
837+
838+
bb2:
839+
%val = apply %func1() : $@convention(thin) () -> @owned NonTrivialStruct
840+
%27 = integer_literal $Builtin.Int1, -1
841+
store %27 to [trivial] %2 : $*Builtin.Int1
842+
store %val to [init] %3 : $*NonTrivialStruct
843+
br bb3
844+
845+
bb3:
846+
%32 = load [trivial] %2 : $*Builtin.Int1
847+
cond_br %32, bb4, bb5
848+
849+
bb4:
850+
%ld2 = load [take] %3 : $*NonTrivialStruct
851+
destroy_value %ld2 : $NonTrivialStruct
852+
br bb6
853+
854+
bb5:
855+
br bb6
856+
857+
bb6:
858+
dealloc_stack %3 : $*NonTrivialStruct
859+
dealloc_stack %2 : $*Builtin.Int1
860+
%res = tuple ()
861+
return %res : $()
862+
}
863+
776864
// CHECK-LABEL: sil [ossa] @test_deadphi1 :
777865
// CHECK-NOT: alloc_stack
778866
// CHECK-LABEL: } // end sil function 'test_deadphi1'

0 commit comments

Comments
 (0)