@@ -147,20 +147,24 @@ static EnumElementDecl *getInjectEnumCaseTo(SILValue Addr) {
147
147
}
148
148
149
149
SILInstruction *SILCombiner::visitSwitchEnumAddrInst (SwitchEnumAddrInst *SEAI) {
150
- if (SEAI->getFunction ()->hasOwnership ())
151
- return nullptr ;
150
+ SILValue Addr = SEAI->getOperand ();
152
151
153
152
// Convert switch_enum_addr -> br
154
- // if the only thing which writes to the address is an inject_enum_addr.
155
- SILValue Addr = SEAI->getOperand ();
156
- if (EnumElementDecl *EnumCase = getInjectEnumCaseTo (Addr)) {
157
- SILBasicBlock *Dest = SEAI->getCaseDestination (EnumCase);
158
- // If the only instruction which writes to Addr is an inject_enum_addr we
159
- // know that there cannot be an enum payload.
160
- assert (Dest->getNumArguments () == 0 &&
161
- " didn't expect a payload argument" );
162
- Builder.createBranch (SEAI->getLoc (), Dest);
163
- return eraseInstFromFunction (*SEAI);
153
+ //
154
+ // If the only thing which writes to the address is an inject_enum_addr. We
155
+ // only perform these optimizations when we are not in OSSA since this
156
+ // eliminates an edge from the CFG and we want SILCombine in OSSA to never do
157
+ // that, so in the future we can invalidate less.
158
+ if (!SEAI->getFunction ()->hasOwnership ()) {
159
+ if (EnumElementDecl *EnumCase = getInjectEnumCaseTo (Addr)) {
160
+ SILBasicBlock *Dest = SEAI->getCaseDestination (EnumCase);
161
+ // If the only instruction which writes to Addr is an inject_enum_addr we
162
+ // know that there cannot be an enum payload.
163
+ assert (Dest->getNumArguments () == 0 &&
164
+ " didn't expect a payload argument" );
165
+ Builder.createBranch (SEAI->getLoc (), Dest);
166
+ return eraseInstFromFunction (*SEAI);
167
+ }
164
168
}
165
169
166
170
SILType Ty = Addr->getType ();
@@ -172,15 +176,44 @@ SILInstruction *SILCombiner::visitSwitchEnumAddrInst(SwitchEnumAddrInst *SEAI) {
172
176
// ->
173
177
// %value = load %ptr
174
178
// switch_enum %value
175
- SmallVector<std::pair<EnumElementDecl*, SILBasicBlock*>, 8 > Cases;
176
- for (int i = 0 , e = SEAI->getNumCases (); i < e; ++i)
179
+ //
180
+ // If we are using ownership, we perform a load_borrow right before the new
181
+ // switch_enum and end the borrow scope right afterwards.
182
+ Builder.setCurrentDebugScope (SEAI->getDebugScope ());
183
+ SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 8 > Cases;
184
+ for (int i : range (SEAI->getNumCases ())) {
177
185
Cases.push_back (SEAI->getCase (i));
186
+ }
178
187
179
- Builder.setCurrentDebugScope (SEAI->getDebugScope ());
180
188
SILBasicBlock *Default = SEAI->hasDefault () ? SEAI->getDefaultBB () : nullptr ;
181
- LoadInst *EnumVal = Builder.createLoad (SEAI->getLoc (), Addr,
182
- LoadOwnershipQualifier::Unqualified);
183
- Builder.createSwitchEnum (SEAI->getLoc (), EnumVal, Default, Cases);
189
+ SILValue EnumVal = Builder.emitLoadBorrowOperation (SEAI->getLoc (), Addr);
190
+ auto *sei = Builder.createSwitchEnum (SEAI->getLoc (), EnumVal, Default, Cases);
191
+
192
+ if (Builder.hasOwnership ()) {
193
+ for (int i : range (sei->getNumCases ())) {
194
+ auto c = sei->getCase (i);
195
+ if (c.first ->hasAssociatedValues ()) {
196
+ auto eltType = Addr->getType ().getEnumElementType (
197
+ c.first , Builder.getModule (), Builder.getTypeExpansionContext ());
198
+ eltType = eltType.getObjectType ();
199
+ if (eltType.isTrivial (Builder.getFunction ())) {
200
+ c.second ->createPhiArgument (eltType, OwnershipKind::None);
201
+ } else {
202
+ c.second ->createPhiArgument (eltType, OwnershipKind::Guaranteed);
203
+ }
204
+ }
205
+ Builder.setInsertionPoint (c.second ->front ().getIterator ());
206
+ Builder.emitEndBorrowOperation (SEAI->getLoc (), EnumVal);
207
+ }
208
+
209
+ if (auto defaultBlock = sei->getDefaultBBOrNull ()) {
210
+ defaultBlock.get ()->createPhiArgument (EnumVal->getType (),
211
+ OwnershipKind::Guaranteed);
212
+ Builder.setInsertionPoint (defaultBlock.get ()->front ().getIterator ());
213
+ Builder.emitEndBorrowOperation (SEAI->getLoc (), EnumVal);
214
+ }
215
+ }
216
+
184
217
return eraseInstFromFunction (*SEAI);
185
218
}
186
219
0 commit comments