@@ -44,35 +44,46 @@ static llvm::cl::opt<bool>
44
44
45
45
SILInstruction*
46
46
SILCombiner::visitAllocExistentialBoxInst (AllocExistentialBoxInst *AEBI) {
47
- if (AEBI->getFunction ()->hasOwnership ())
48
- return nullptr ;
49
-
50
47
// Optimize away the pattern below that happens when exceptions are created
51
48
// and in some cases, due to inlining, are not needed.
52
49
//
53
50
// %6 = alloc_existential_box $Error, $ColorError
51
+ // %6a = project_existential_box %6
54
52
// %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
59
63
SILValue boxedValue =
60
64
getConcreteValueOfExistentialBox (AEBI, /* ignoreUser*/ nullptr );
61
65
if (!boxedValue)
62
66
return nullptr ;
63
67
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
65
69
// 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
+ }
73
83
}
74
84
}
75
- if (!singleRelease)
85
+
86
+ if (!singleDestroy)
76
87
return nullptr ;
77
88
78
89
// Release the value that was stored into the existential box. The box
@@ -85,7 +96,7 @@ SILCombiner::visitAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
85
96
// store %value to %addr
86
97
// retain_value %value // must insert the release after this retain
87
98
// strong_release %box
88
- Builder.setInsertionPoint (singleRelease );
99
+ Builder.setInsertionPoint (singleDestroy );
89
100
Builder.emitDestroyValueOperation (AEBI->getLoc (), boxedValue);
90
101
91
102
eraseInstIncludingUsers (AEBI);
0 commit comments