Skip to content

Commit 1c52364

Browse files
committed
[Mem2Reg] Complete single-block trivial enum cases
Add `end_lifetime` for values of non-trivial enum type which aren't destroyed in non-dead-end blocks.
1 parent 4b3588c commit 1c52364

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2097,14 +2097,33 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) {
20972097
}
20982098
}
20992099

2100-
if (!runningVals || !runningVals->isStorageValid) {
2100+
auto *function = asi->getFunction();
2101+
if (!function->hasOwnership() || !runningVals ||
2102+
!runningVals->isStorageValid ||
2103+
asi->getElementType().isTrivial(function)) {
21012104
return;
21022105
}
21032106
// There is still valid storage after visiting all instructions in this
21042107
// block which are the only instructions involving this alloc_stack.
21052108
// That can happen if:
21062109
// (1) this block is a dead-end. TODO: OSSACompleteLifetime: Complete such
21072110
// lifetimes.
2111+
// (2) a trivial case of a non-trivial enum was stored to the address
2112+
2113+
auto *deadEndBlocks = deadEndBlocksAnalysis->get(function);
2114+
2115+
if (!deadEndBlocks->isDeadEnd(parentBlock)) {
2116+
// We may have incomplete lifetimes for enum locations on trivial paths.
2117+
// After promoting them, complete lifetime here.
2118+
ASSERT(asi->getElementType().isOrHasEnum());
2119+
OSSACompleteLifetime completion(function, domInfo, *deadEndBlocks,
2120+
OSSACompleteLifetime::IgnoreTrivialVariable,
2121+
/*forceLivenessVerification=*/false,
2122+
/*nonDestroyingEnd=*/true);
2123+
completion.completeOSSALifetime(
2124+
runningVals->value.replacement(asi, nullptr),
2125+
OSSACompleteLifetime::Boundary::Liveness);
2126+
}
21082127
}
21092128

21102129
void MemoryToRegisters::collectStoredValues(AllocStackInst *asi,

test/SILOptimizer/mem2reg_ossa_nontrivial.sil

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,45 @@ x(%13 : @guaranteed $X):
16691669

16701670
exit:
16711671
destroy_addr %main_addr
1672+
dealloc_stack %temp
1673+
dealloc_stack %main_addr
1674+
%retval = tuple ()
1675+
return %retval
1676+
}
1677+
1678+
// CHECK-LABEL: sil [ossa] @end_lifetime_at_trivial_case_dealloc_stack_3 : {{.*}} {
1679+
// CHECK: bb0([[IN_ADDR:%[^,]+]] :
1680+
// CHECK: [[IN_BORROW:%[^,]+]] = load_borrow [[IN_ADDR]]
1681+
// CHECK: switch_enum [[IN_BORROW]]
1682+
// CHECK: case #Result.success!enumelt: [[INT:bb[0-9]+]]
1683+
// CHECK: [[INT]]
1684+
// CHECK: end_borrow [[IN_BORROW]]
1685+
// CHECK: [[IN_COPY:%[^,]+]] = load [copy] [[IN_ADDR]]
1686+
// CHECK: end_lifetime [[IN_COPY]]
1687+
// CHECK-LABEL: } // end sil function 'end_lifetime_at_trivial_case_dealloc_stack_3'
1688+
sil [ossa] @end_lifetime_at_trivial_case_dealloc_stack_3 : $@convention(thin) (@in_guaranteed Result<Int, X>) -> () {
1689+
entry(%in_addr : $*Result<Int, X>):
1690+
%in_borrow = load_borrow %in_addr
1691+
switch_enum %in_borrow,
1692+
case #Result.success!enumelt: int,
1693+
case #Result.failure!enumelt: x
1694+
1695+
int(%int : $Int):
1696+
end_borrow %in_borrow
1697+
%temp = alloc_stack $Result<Int, X>
1698+
%in_copy = load [copy] %in_addr
1699+
store %in_copy to [init] %temp
1700+
dealloc_stack %temp
1701+
br int2
1702+
1703+
int2:
1704+
br exit
1705+
1706+
x(%13 : @guaranteed $X):
1707+
end_borrow %in_borrow
1708+
br exit
1709+
1710+
exit:
16721711
%retval = tuple ()
16731712
return %retval
16741713
}

0 commit comments

Comments
 (0)