Skip to content

Commit 7d5c60b

Browse files
committed
[sil-combine] Implement simple alloc_existential_box removal.
1 parent 35f941f commit 7d5c60b

File tree

1 file changed

+28
-17
lines changed

1 file changed

+28
-17
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,35 +44,46 @@ static llvm::cl::opt<bool>
4444

4545
SILInstruction*
4646
SILCombiner::visitAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
47-
if (AEBI->getFunction()->hasOwnership())
48-
return nullptr;
49-
5047
// Optimize away the pattern below that happens when exceptions are created
5148
// and in some cases, due to inlining, are not needed.
5249
//
5350
// %6 = alloc_existential_box $Error, $ColorError
51+
// %6a = project_existential_box %6
5452
// %7 = enum $VendingMachineError, #ColorError.Red
55-
// store %7 to %6#1 : $*ColorError
56-
// debug_value %6#0 : $Error
57-
// strong_release %6#0 : $Error
58-
53+
// store %7 to %6a : $*ColorError
54+
// debug_value %6 : $Error
55+
// strong_release %6 : $Error
56+
//
57+
// %6 = alloc_existential_box $Error, $ColorError
58+
// %6a = project_existential_box %6
59+
// %7 = enum $VendingMachineError, #ColorError.Red
60+
// store %7 to [init] %6a : $*ColorError
61+
// debug_value %6 : $Error
62+
// destroy_value %6 : $Error
5963
SILValue boxedValue =
6064
getConcreteValueOfExistentialBox(AEBI, /*ignoreUser*/ nullptr);
6165
if (!boxedValue)
6266
return nullptr;
6367

64-
// Check if the box is released at a single place. That's the end of its
68+
// Check if the box is destroyed at a single place. That's the end of its
6569
// lifetime.
66-
StrongReleaseInst *singleRelease = nullptr;
67-
for (Operand *use : AEBI->getUses()) {
68-
if (auto *RI = dyn_cast<StrongReleaseInst>(use->getUser())) {
69-
// If this is not the only release of the box then bail out.
70-
if (singleRelease)
71-
return nullptr;
72-
singleRelease = RI;
70+
SILInstruction *singleDestroy = nullptr;
71+
if (hasOwnership()) {
72+
if (auto *use = AEBI->getSingleConsumingUse()) {
73+
singleDestroy = dyn_cast<DestroyValueInst>(use->getUser());
74+
}
75+
} else {
76+
for (Operand *use : AEBI->getUses()) {
77+
auto *user = use->getUser();
78+
if (isa<StrongReleaseInst>(user) || isa<ReleaseValueInst>(user)) {
79+
if (singleDestroy)
80+
return nullptr;
81+
singleDestroy = user;
82+
}
7383
}
7484
}
75-
if (!singleRelease)
85+
86+
if (!singleDestroy)
7687
return nullptr;
7788

7889
// Release the value that was stored into the existential box. The box
@@ -85,7 +96,7 @@ SILCombiner::visitAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
8596
// store %value to %addr
8697
// retain_value %value // must insert the release after this retain
8798
// strong_release %box
88-
Builder.setInsertionPoint(singleRelease);
99+
Builder.setInsertionPoint(singleDestroy);
89100
Builder.emitDestroyValueOperation(AEBI->getLoc(), boxedValue);
90101

91102
eraseInstIncludingUsers(AEBI);

0 commit comments

Comments
 (0)