Skip to content

Commit f833bdb

Browse files
committed
Enable Mem2Reg of lexical enum values in multiple blocks
1 parent 3d75abc commit f833bdb

File tree

3 files changed

+46
-54
lines changed

3 files changed

+46
-54
lines changed

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 43 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,13 @@ class LiveValues {
195195
return LiveValues::forOwned({stored, move});
196196
}
197197

198+
static LiveValues forValues(SILValue stored, SILValue lexical) {
199+
if (stored->getOwnershipKind() == OwnershipKind::Guaranteed) {
200+
return LiveValues::forGuaranteed({stored, lexical});
201+
}
202+
return LiveValues::forOwned({stored, lexical});
203+
}
204+
198205
static LiveValues toReplace(AllocStackInst *asi, SILValue replacement) {
199206
if (replacement->getOwnershipKind() == OwnershipKind::Guaranteed) {
200207
return LiveValues::forGuaranteed(Guaranteed::toReplace(asi, replacement));
@@ -715,6 +722,27 @@ static bool canEndLexicalLifetime(LiveValues values) {
715722
return values.canEndLexicalLifetime();
716723
}
717724

725+
static SILValue getLexicalValueForStore(SILInstruction *inst,
726+
AllocStackInst *asi) {
727+
assert(isa<StoreInst>(inst) || isa<StoreBorrowInst>(inst));
728+
729+
SILValue stored = inst->getOperand(CopyLikeInstruction::Src);
730+
LLVM_DEBUG(llvm::dbgs() << "*** Found Store def " << stored);
731+
732+
if (!lexicalLifetimeEnsured(asi)) {
733+
return SILValue();
734+
}
735+
if (isa<StoreBorrowInst>(inst)) {
736+
if (isGuaranteedLexicalValue(stored)) {
737+
return SILValue();
738+
}
739+
auto borrow = cast<BeginBorrowInst>(inst->getNextInstruction());
740+
return borrow;
741+
}
742+
auto move = cast<MoveValueInst>(inst->getNextInstruction());
743+
return move;
744+
}
745+
718746
/// Begin a lexical borrow scope for the value stored into the provided
719747
/// StoreInst after that instruction.
720748
///
@@ -1233,27 +1261,9 @@ StackAllocationPromoter::getLiveOutValues(BlockSetVector &phiBlocks,
12331261
BlockToInstMap::iterator it = initializationPoints.find(domBlock);
12341262
if (it != initializationPoints.end()) {
12351263
auto *inst = it->second;
1236-
assert(isa<StoreInst>(inst) || isa<StoreBorrowInst>(inst));
1237-
1238-
SILValue stored = inst->getOperand(CopyLikeInstruction::Src);
1239-
LLVM_DEBUG(llvm::dbgs() << "*** Found Store def " << stored);
1240-
1241-
if (!lexicalLifetimeEnsured(asi)) {
1242-
auto values = LiveValues::forOwned(stored, {});
1243-
return values;
1244-
}
1245-
if (isa<StoreBorrowInst>(inst)) {
1246-
if (isGuaranteedLexicalValue(stored)) {
1247-
auto values = LiveValues::forGuaranteed(stored, {});
1248-
return values;
1249-
}
1250-
auto borrow = cast<BeginBorrowInst>(inst->getNextInstruction());
1251-
auto values = LiveValues::forGuaranteed(stored, borrow);
1252-
return values;
1253-
}
1254-
auto move = cast<MoveValueInst>(inst->getNextInstruction());
1255-
auto values = LiveValues::forOwned(stored, move);
1256-
return values;
1264+
auto stored = inst->getOperand(CopyLikeInstruction::Src);
1265+
auto lexical = getLexicalValueForStore(inst, asi);
1266+
return LiveValues::forValues(stored, lexical);
12571267
}
12581268

12591269
// If there is a Phi definition in this block:
@@ -1806,8 +1816,13 @@ void StackAllocationPromoter::run() {
18061816
if (asi->getType().isOrHasEnum()) {
18071817
for (auto it : initializationPoints) {
18081818
auto *si = it.second;
1809-
auto src = si->getOperand(0);
1810-
valuesToComplete.push_back(src);
1819+
auto stored = si->getOperand(CopyLikeInstruction::Src);
1820+
valuesToComplete.push_back(stored);
1821+
if (lexicalLifetimeEnsured(asi)) {
1822+
if (auto lexical = getLexicalValueForStore(si, asi)) {
1823+
valuesToComplete.push_back(lexical);
1824+
}
1825+
}
18111826
}
18121827
}
18131828

@@ -1817,8 +1832,12 @@ void StackAllocationPromoter::run() {
18171832
// Now, complete lifetimes!
18181833
OSSALifetimeCompletion completion(function, domInfo);
18191834

1835+
// We may have incomplete lifetimes for enum locations on trivial paths.
1836+
// After promoting them, complete lifetime here.
18201837
for (auto it : valuesToComplete) {
1821-
completion.completeOSSALifetime(it);
1838+
// Set forceBoundaryCompletion as true so that we complete at boundary for
1839+
// lexical values as well.
1840+
completion.completeOSSALifetime(it, /* forceBoundaryCompletion */ true);
18221841
}
18231842
}
18241843

@@ -2119,33 +2138,6 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
21192138
<< *alloc);
21202139
deleter.forceDeleteWithUsers(alloc);
21212140
return true;
2122-
} else {
2123-
auto enableOptimizationForEnum = [](AllocStackInst *asi) {
2124-
if (asi->isLexical()) {
2125-
return false;
2126-
}
2127-
for (auto *use : asi->getUses()) {
2128-
auto *user = use->getUser();
2129-
if (!isa<StoreInst>(user) && !isa<StoreBorrowInst>(user)) {
2130-
continue;
2131-
}
2132-
auto stored = user->getOperand(CopyLikeInstruction::Src);
2133-
if (stored->isLexical()) {
2134-
return false;
2135-
}
2136-
}
2137-
return true;
2138-
};
2139-
// For stack locs of enum type that are lexical or with lexical stored
2140-
// values, we require that all uses are in the same block. This is because
2141-
// we can have incomplete lifetime of enum typed addresses, and on
2142-
// converting to value form this causes verification error. For all other
2143-
// stack locs of enum type, we use the lifetime completion utility to fix
2144-
// the lifetime. But when we have a lexical value, the utility can complete
2145-
// lifetimes on dead end blocks only.
2146-
if (f.hasOwnership() && alloc->getType().isOrHasEnum() &&
2147-
!enableOptimizationForEnum(alloc))
2148-
return false;
21492141
}
21502142

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

test/SILOptimizer/mem2reg_lifetime_nontrivial.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ enum KlassOptional {
10611061
sil @return_optional_or_error : $@convention(thin) () -> (@owned KlassOptional, @error Error)
10621062

10631063
// CHECK-LABEL: sil [ossa] @test_deadphi4 :
1064-
// CHECK: alloc_stack
1064+
// CHECK-NOT: alloc_stack
10651065
// CHECK-LABEL: } // end sil function 'test_deadphi4'
10661066
sil [ossa] @test_deadphi4 : $@convention(thin) (@owned KlassOptional) -> () {
10671067
bb0(%0 : @owned $KlassOptional):

test/SILOptimizer/mem2reg_ossa.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ bb7:
516516
}
517517

518518
// CHECK-LABEL: sil [ossa] @test_optional_in_multiple_blocks_lexical :
519-
// CHECK: alloc_stack
519+
// CHECK-NOT: alloc_stack
520520
// CHECK: } // end sil function 'test_optional_in_multiple_blocks_lexical'
521521
sil [ossa] @test_optional_in_multiple_blocks_lexical : $@convention(method) (@guaranteed Optional<Klass>) -> () {
522522
bb0(%0 : @guaranteed $Optional<Klass>):
@@ -542,7 +542,7 @@ bb7:
542542
}
543543

544544
// CHECK-LABEL: sil [ossa] @test_optional_in_multiple_blocks_lexical_storedvalue :
545-
// CHECK: alloc_stack
545+
// CHECK-NOT: alloc_stack
546546
// CHECK: } // end sil function 'test_optional_in_multiple_blocks_lexical_storedvalue'
547547
sil [ossa] @test_optional_in_multiple_blocks_lexical_storedvalue : $@convention(method) (@owned Optional<Klass>) -> () {
548548
bb0(%0 : @owned $Optional<Klass>):

0 commit comments

Comments
 (0)