Skip to content

Commit 76a733e

Browse files
Merge pull request #65923 from nate-chandler/mem2reg/complete-new-enum-phi-lifetimes
[Mem2Reg] Complete new enum phi lifetimes.
2 parents 31bfa4b + 209e3df commit 76a733e

File tree

2 files changed

+125
-54
lines changed

2 files changed

+125
-54
lines changed

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ class StackAllocationPromoter {
938938

939939
private:
940940
/// Promote AllocStacks into SSA.
941-
void promoteAllocationToPhi();
941+
void promoteAllocationToPhi(BlockSetVector &livePhiBlocks);
942942

943943
/// Replace the dummy nodes with new block arguments.
944944
void addBlockArguments(BlockSetVector &phiBlocks);
@@ -1685,7 +1685,8 @@ void StackAllocationPromoter::pruneAllocStackUsage() {
16851685
LLVM_DEBUG(llvm::dbgs() << "*** Finished pruning : " << *asi);
16861686
}
16871687

1688-
void StackAllocationPromoter::promoteAllocationToPhi() {
1688+
void StackAllocationPromoter::promoteAllocationToPhi(
1689+
BlockSetVector &livePhiBlocks) {
16891690
LLVM_DEBUG(llvm::dbgs() << "*** Placing Phis for : " << *asi);
16901691

16911692
// A list of blocks that will require new Phi values.
@@ -1781,10 +1782,6 @@ void StackAllocationPromoter::promoteAllocationToPhi() {
17811782
// Replace the dummy values with new block arguments.
17821783
addBlockArguments(phiBlocks);
17831784

1784-
// The blocks which still have new phis after fixBranchesAndUses runs. These
1785-
// are not necessarily the same as phiBlocks because fixBranchesAndUses
1786-
// removes superfluous proactive phis.
1787-
BlockSetVector livePhiBlocks(asi->getFunction());
17881785
// Hook up the Phi nodes, loads, and debug_value_addr with incoming values.
17891786
fixBranchesAndUses(phiBlocks, livePhiBlocks);
17901787

@@ -1801,8 +1798,13 @@ void StackAllocationPromoter::run() {
18011798
// per block and the last store is recorded.
18021799
pruneAllocStackUsage();
18031800

1801+
// The blocks which still have new phis after fixBranchesAndUses runs. These
1802+
// are not necessarily the same as phiBlocks because fixBranchesAndUses
1803+
// removes superfluous proactive phis.
1804+
BlockSetVector livePhiBlocks(asi->getFunction());
1805+
18041806
// Replace AllocStacks with Phi-nodes.
1805-
promoteAllocationToPhi();
1807+
promoteAllocationToPhi(livePhiBlocks);
18061808

18071809
// Make sure that all of the allocations were promoted into registers.
18081810
assert(isWriteOnlyAllocation(asi) && "Non-write uses left behind");
@@ -1814,14 +1816,18 @@ void StackAllocationPromoter::run() {
18141816
// Use the lifetime completion utility to complete such lifetimes.
18151817
// First, collect the stored values to complete.
18161818
if (asi->getType().isOrHasEnum()) {
1819+
for (auto *block : livePhiBlocks) {
1820+
SILPhiArgument *argument = cast<SILPhiArgument>(
1821+
block->getArgument(block->getNumArguments() - 1));
1822+
assert(argument->isPhi());
1823+
valuesToComplete.push_back(argument);
1824+
}
18171825
for (auto it : initializationPoints) {
18181826
auto *si = it.second;
18191827
auto stored = si->getOperand(CopyLikeInstruction::Src);
18201828
valuesToComplete.push_back(stored);
1821-
if (lexicalLifetimeEnsured(asi)) {
1822-
if (auto lexical = getLexicalValueForStore(si, asi)) {
1823-
valuesToComplete.push_back(lexical);
1824-
}
1829+
if (auto lexical = getLexicalValueForStore(si, asi)) {
1830+
valuesToComplete.push_back(lexical);
18251831
}
18261832
}
18271833
}

test/SILOptimizer/mem2reg_ossa.sil

Lines changed: 108 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
11
// RUN: %target-sil-opt -enable-sil-verify-all %s -mem2reg | %FileCheck %s
22

33
import Builtin
4-
import Swift
54

65
//////////////////
76
// Declarations //
87
//////////////////
98

9+
typealias AnyObject = Builtin.AnyObject
10+
11+
struct Int64 {
12+
var _value : Builtin.Int64
13+
}
14+
15+
struct Int {
16+
var _value : Builtin.Int64
17+
}
18+
19+
struct Bool {
20+
var _value : Builtin.Int1
21+
}
22+
23+
enum FakeOptional<T> {
24+
case some(T)
25+
case none
26+
}
27+
1028
class Klass {}
1129

1230
struct SmallCodesizeStruct {
@@ -492,22 +510,22 @@ bb0:
492510
// CHECK-LABEL: sil [ossa] @test_optional_in_multiple_blocks :
493511
// CHECK-NOT: alloc_stack
494512
// CHECK: } // end sil function 'test_optional_in_multiple_blocks'
495-
sil [ossa] @test_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
513+
sil [ossa] @test_optional_in_multiple_blocks : $@convention(method) (@guaranteed FakeOptional<Klass>) -> () {
514+
bb0(%0 : @guaranteed $FakeOptional<Klass>):
515+
%1 = copy_value %0 : $FakeOptional<Klass>
516+
%32 = alloc_stack $FakeOptional<Klass>
517+
store %1 to [init] %32 : $*FakeOptional<Klass>
518+
switch_enum %0 : $FakeOptional<Klass>, case #FakeOptional.some!enumelt: bb6, case #FakeOptional.none!enumelt: bb5
501519

502520
bb5:
503-
dealloc_stack %32 : $*Optional<Klass>
521+
dealloc_stack %32 : $*FakeOptional<Klass>
504522
br bb7
505523

506524
bb6(%50 : @guaranteed $Klass):
507-
%53 = load [copy] %32 : $*Optional<Klass>
508-
destroy_value %53 : $Optional<Klass>
509-
destroy_addr %32 : $*Optional<Klass>
510-
dealloc_stack %32 : $*Optional<Klass>
525+
%53 = load [copy] %32 : $*FakeOptional<Klass>
526+
destroy_value %53 : $FakeOptional<Klass>
527+
destroy_addr %32 : $*FakeOptional<Klass>
528+
dealloc_stack %32 : $*FakeOptional<Klass>
511529
br bb7
512530

513531
bb7:
@@ -518,22 +536,22 @@ bb7:
518536
// CHECK-LABEL: sil [ossa] @test_optional_in_multiple_blocks_lexical :
519537
// CHECK-NOT: alloc_stack
520538
// CHECK: } // end sil function 'test_optional_in_multiple_blocks_lexical'
521-
sil [ossa] @test_optional_in_multiple_blocks_lexical : $@convention(method) (@guaranteed Optional<Klass>) -> () {
522-
bb0(%0 : @guaranteed $Optional<Klass>):
523-
%1 = copy_value %0 : $Optional<Klass>
524-
%32 = alloc_stack [lexical] $Optional<Klass>
525-
store %1 to [init] %32 : $*Optional<Klass>
526-
switch_enum %0 : $Optional<Klass>, case #Optional.some!enumelt: bb6, case #Optional.none!enumelt: bb5
539+
sil [ossa] @test_optional_in_multiple_blocks_lexical : $@convention(method) (@guaranteed FakeOptional<Klass>) -> () {
540+
bb0(%0 : @guaranteed $FakeOptional<Klass>):
541+
%1 = copy_value %0 : $FakeOptional<Klass>
542+
%32 = alloc_stack [lexical] $FakeOptional<Klass>
543+
store %1 to [init] %32 : $*FakeOptional<Klass>
544+
switch_enum %0 : $FakeOptional<Klass>, case #FakeOptional.some!enumelt: bb6, case #FakeOptional.none!enumelt: bb5
527545

528546
bb5:
529-
dealloc_stack %32 : $*Optional<Klass>
547+
dealloc_stack %32 : $*FakeOptional<Klass>
530548
br bb7
531549

532550
bb6(%50 : @guaranteed $Klass):
533-
%53 = load [copy] %32 : $*Optional<Klass>
534-
destroy_value %53 : $Optional<Klass>
535-
destroy_addr %32 : $*Optional<Klass>
536-
dealloc_stack %32 : $*Optional<Klass>
551+
%53 = load [copy] %32 : $*FakeOptional<Klass>
552+
destroy_value %53 : $FakeOptional<Klass>
553+
destroy_addr %32 : $*FakeOptional<Klass>
554+
dealloc_stack %32 : $*FakeOptional<Klass>
537555
br bb7
538556

539557
bb7:
@@ -544,23 +562,23 @@ bb7:
544562
// CHECK-LABEL: sil [ossa] @test_optional_in_multiple_blocks_lexical_storedvalue :
545563
// CHECK-NOT: alloc_stack
546564
// CHECK: } // end sil function 'test_optional_in_multiple_blocks_lexical_storedvalue'
547-
sil [ossa] @test_optional_in_multiple_blocks_lexical_storedvalue : $@convention(method) (@owned Optional<Klass>) -> () {
548-
bb0(%0 : @owned $Optional<Klass>):
549-
%1 = copy_value %0 : $Optional<Klass>
550-
%32 = alloc_stack $Optional<Klass>
551-
store %0 to [init] %32 : $*Optional<Klass>
552-
switch_enum %1 : $Optional<Klass>, case #Optional.some!enumelt: bb6, case #Optional.none!enumelt: bb5
565+
sil [ossa] @test_optional_in_multiple_blocks_lexical_storedvalue : $@convention(method) (@owned FakeOptional<Klass>) -> () {
566+
bb0(%0 : @owned $FakeOptional<Klass>):
567+
%1 = copy_value %0 : $FakeOptional<Klass>
568+
%32 = alloc_stack $FakeOptional<Klass>
569+
store %0 to [init] %32 : $*FakeOptional<Klass>
570+
switch_enum %1 : $FakeOptional<Klass>, case #FakeOptional.some!enumelt: bb6, case #FakeOptional.none!enumelt: bb5
553571

554572
bb5:
555-
dealloc_stack %32 : $*Optional<Klass>
573+
dealloc_stack %32 : $*FakeOptional<Klass>
556574
br bb7
557575

558576
bb6(%50 : @owned $Klass):
559-
%53 = load [copy] %32 : $*Optional<Klass>
560-
destroy_value %53 : $Optional<Klass>
577+
%53 = load [copy] %32 : $*FakeOptional<Klass>
578+
destroy_value %53 : $FakeOptional<Klass>
561579
destroy_value %50 : $Klass
562-
destroy_addr %32 : $*Optional<Klass>
563-
dealloc_stack %32 : $*Optional<Klass>
580+
destroy_addr %32 : $*FakeOptional<Klass>
581+
dealloc_stack %32 : $*FakeOptional<Klass>
564582
br bb7
565583

566584
bb7:
@@ -571,24 +589,71 @@ bb7:
571589
// CHECK-LABEL: sil [ossa] @optimize_optional_in_single_block :
572590
// CHECK-NOT: alloc_stack
573591
// CHECK: } // end sil function 'optimize_optional_in_single_block'
574-
sil [ossa] @optimize_optional_in_single_block : $@convention(method) (@guaranteed Optional<Klass>) -> () {
575-
bb0(%0 : @guaranteed $Optional<Klass>):
576-
switch_enum %0 : $Optional<Klass>, case #Optional.some!enumelt: bb6, case #Optional.none!enumelt: bb5
592+
sil [ossa] @optimize_optional_in_single_block : $@convention(method) (@guaranteed FakeOptional<Klass>) -> () {
593+
bb0(%0 : @guaranteed $FakeOptional<Klass>):
594+
switch_enum %0 : $FakeOptional<Klass>, case #FakeOptional.some!enumelt: bb6, case #FakeOptional.none!enumelt: bb5
577595

578596
bb5:
579597
br bb7
580598

581599
bb6(%50 : @guaranteed $Klass):
582-
%32 = alloc_stack $Optional<Klass>
583-
%1 = copy_value %0 : $Optional<Klass>
584-
store %1 to [init] %32 : $*Optional<Klass>
585-
%53 = load [take] %32 : $*Optional<Klass>
586-
destroy_value %53 : $Optional<Klass>
587-
dealloc_stack %32 : $*Optional<Klass>
600+
%32 = alloc_stack $FakeOptional<Klass>
601+
%1 = copy_value %0 : $FakeOptional<Klass>
602+
store %1 to [init] %32 : $*FakeOptional<Klass>
603+
%53 = load [take] %32 : $*FakeOptional<Klass>
604+
destroy_value %53 : $FakeOptional<Klass>
605+
dealloc_stack %32 : $*FakeOptional<Klass>
588606
br bb7
589607

590608
bb7:
591609
%r = tuple ()
592610
return %r : $()
593611
}
594612

613+
// CHECK-LABEL: sil [ossa] @switch_enum_out_of_new_phi_block : {{.*}} {
614+
// CHECK-NOT: alloc_stack
615+
// CHECK: } // end sil function 'switch_enum_out_of_new_phi_block'
616+
sil [ossa] @switch_enum_out_of_new_phi_block : $() -> () {
617+
entry:
618+
%addr = alloc_stack $FakeOptional<Klass>
619+
cond_br undef, store_none, agg_either
620+
621+
store_none:
622+
%none1 = enum $FakeOptional<Klass>, #FakeOptional.none!enumelt
623+
store %none1 to [init] %addr : $*FakeOptional<Klass>
624+
br switcheroo
625+
626+
agg_either:
627+
cond_br undef, agg_some, agg_none
628+
629+
agg_some:
630+
%Klass = apply undef() : $@convention(thin) () -> (@owned Klass)
631+
%some = enum $FakeOptional<Klass>, #FakeOptional.some!enumelt, %Klass : $Klass
632+
br store_maybe(%some : $FakeOptional<Klass>)
633+
634+
agg_none:
635+
%none2 = enum $FakeOptional<Klass>, #FakeOptional.none!enumelt
636+
br store_maybe(%none2 : $FakeOptional<Klass>)
637+
638+
store_maybe(%maybe : @owned $FakeOptional<Klass>):
639+
store %maybe to [init] %addr : $*FakeOptional<Klass>
640+
br switcheroo
641+
642+
switcheroo:
643+
%borrow = load_borrow %addr : $*FakeOptional<Klass>
644+
switch_enum %borrow : $FakeOptional<Klass>, case #FakeOptional.some!enumelt: bb14, case #FakeOptional.none!enumelt: bb15
645+
646+
bb14(%some_borrowed : @guaranteed $Klass):
647+
end_borrow %borrow : $FakeOptional<Klass>
648+
destroy_addr %addr : $*FakeOptional<Klass>
649+
br bb16
650+
651+
bb15:
652+
end_borrow %borrow : $FakeOptional<Klass>
653+
br bb16
654+
655+
bb16:
656+
dealloc_stack %addr : $*FakeOptional<Klass>
657+
%retval = tuple ()
658+
return %retval : $()
659+
}

0 commit comments

Comments
 (0)