Skip to content

Commit 4beadfe

Browse files
authored
Merge pull request #41744 from eeckstein/fix-mem2reg
SILMem2Reg: fix a problem with leaking enum values
2 parents bfac01f + a62a5ca commit 4beadfe

File tree

5 files changed

+63
-3
lines changed

5 files changed

+63
-3
lines changed

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,14 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
17571757
b.createDeallocStack(next->getLoc(), alloc);
17581758
}
17591759
return true;
1760+
} else {
1761+
// For enums we require that all uses are in the same block.
1762+
// Otherwise there could be a switch_enum of an optional where the none-case
1763+
// does not have a destroy of the enum value.
1764+
// After transforming such an alloc_stack, the value would leak in the none-
1765+
// case block.
1766+
if (f.hasOwnership() && alloc->getType().isOrHasEnum())
1767+
return false;
17601768
}
17611769

17621770
LLVM_DEBUG(llvm::dbgs() << "*** Need to insert BB arguments for " << *alloc);

test/SILOptimizer/mem2reg_lifetime.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1328,9 +1328,9 @@ entry(%either : @owned $E):
13281328
%addr = alloc_stack [lexical] $E
13291329
store %either to [init] %addr : $*E
13301330
%either2 = load [take] %addr : $*E
1331+
dealloc_stack %addr : $*E
13311332
switch_enum %either2 : $E, case #E.one!enumelt: one
13321333
one(%instance : @owned $C):
1333-
dealloc_stack %addr : $*E
13341334
return %instance : $C
13351335
}
13361336

test/SILOptimizer/mem2reg_lifetime_nontrivial.sil

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,8 @@ enum KlassOptional {
11011101
sil @return_optional_or_error : $@convention(thin) () -> (@owned KlassOptional, @error Error)
11021102

11031103
// CHECK-LABEL: sil [ossa] @test_deadphi4 :
1104-
// CHECK-NOT: alloc_stack
1104+
// mem2reg cannot optimize an enum location which spans over multiple blocks.
1105+
// CHECK: alloc_stack
11051106
// CHECK-LABEL: } // end sil function 'test_deadphi4'
11061107
sil [ossa] @test_deadphi4 : $@convention(thin) (@owned KlassOptional) -> () {
11071108
bb0(%0 : @owned $KlassOptional):

test/SILOptimizer/mem2reg_ossa.sil

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,3 +488,53 @@ bb0:
488488
dealloc_stack %1 : $*((), ())
489489
return %16 : $((), ())
490490
}
491+
492+
// CHECK-LABEL: sil [ossa] @dont_optimize_optional_in_multiple_blocks :
493+
// CHECK: alloc_stack
494+
// CHECK: } // end sil function 'dont_optimize_optional_in_multiple_blocks'
495+
sil [ossa] @dont_optimize_optional_in_multiple_blocks : $@convention(method) (@guaranteed Optional<Klass>) -> () {
496+
bb0(%0 : @guaranteed $Optional<Klass>):
497+
%1 = copy_value %0 : $Optional<Klass>
498+
%32 = alloc_stack $Optional<Klass>
499+
store %1 to [init] %32 : $*Optional<Klass>
500+
switch_enum %0 : $Optional<Klass>, case #Optional.some!enumelt: bb6, case #Optional.none!enumelt: bb5
501+
502+
bb5:
503+
dealloc_stack %32 : $*Optional<Klass>
504+
br bb7
505+
506+
bb6(%50 : @guaranteed $Klass):
507+
%53 = load [take] %32 : $*Optional<Klass>
508+
destroy_value %53 : $Optional<Klass>
509+
dealloc_stack %32 : $*Optional<Klass>
510+
br bb7
511+
512+
bb7:
513+
%r = tuple ()
514+
return %r : $()
515+
}
516+
517+
// CHECK-LABEL: sil [ossa] @optimize_optional_in_single_block :
518+
// CHECK-NOT: alloc_stack
519+
// CHECK: } // end sil function 'optimize_optional_in_single_block'
520+
sil [ossa] @optimize_optional_in_single_block : $@convention(method) (@guaranteed Optional<Klass>) -> () {
521+
bb0(%0 : @guaranteed $Optional<Klass>):
522+
switch_enum %0 : $Optional<Klass>, case #Optional.some!enumelt: bb6, case #Optional.none!enumelt: bb5
523+
524+
bb5:
525+
br bb7
526+
527+
bb6(%50 : @guaranteed $Klass):
528+
%32 = alloc_stack $Optional<Klass>
529+
%1 = copy_value %0 : $Optional<Klass>
530+
store %1 to [init] %32 : $*Optional<Klass>
531+
%53 = load [take] %32 : $*Optional<Klass>
532+
destroy_value %53 : $Optional<Klass>
533+
dealloc_stack %32 : $*Optional<Klass>
534+
br bb7
535+
536+
bb7:
537+
%r = tuple ()
538+
return %r : $()
539+
}
540+

test/SILOptimizer/mem2reg_ossa_nontrivial.sil

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,8 @@ enum KlassOptional {
10211021
sil @return_optional_or_error : $@convention(thin) () -> (@owned KlassOptional, @error Error)
10221022

10231023
// CHECK-LABEL: sil [ossa] @test_deadphi4 :
1024-
// CHECK-NOT: alloc_stack
1024+
// mem2reg cannot optimize an enum location which spans over multiple blocks.
1025+
// CHECK: alloc_stack
10251026
// CHECK-LABEL: } // end sil function 'test_deadphi4'
10261027
sil [ossa] @test_deadphi4 : $@convention(thin) (@owned KlassOptional) -> () {
10271028
bb0(%0 : @owned $KlassOptional):

0 commit comments

Comments
 (0)