@@ -57,16 +57,35 @@ namespace {
57
57
// / consistent non-ossa vs ossa code rather than an intermediate state.
58
58
struct OwnershipModelEliminatorVisitor
59
59
: SILInstructionVisitor<OwnershipModelEliminatorVisitor, bool > {
60
- SILBuilder &builder;
61
60
SmallVector<SILInstruction *, 8 > trackingList;
62
61
SmallBlotSetVector<SILInstruction *, 8 > instructionsToSimplify;
62
+
63
+ // / Points at either a user passed in SILBuilderContext or points at
64
+ // / builderCtxStorage.
65
+ SILBuilderContext builderCtx;
66
+
63
67
SILOpenedArchetypesTracker openedArchetypesTracker;
64
68
65
- OwnershipModelEliminatorVisitor (SILBuilder &newBuilder)
66
- : builder(newBuilder),
67
- openedArchetypesTracker (&newBuilder.getFunction()) {
68
- newBuilder.setTrackingList (&trackingList);
69
- newBuilder.setOpenedArchetypesTracker (&openedArchetypesTracker);
69
+ // / Construct an OME visitor for eliminating ownership from \p fn.
70
+ OwnershipModelEliminatorVisitor (SILFunction &fn)
71
+ : trackingList(), instructionsToSimplify(),
72
+ builderCtx (fn.getModule(), &trackingList),
73
+ openedArchetypesTracker(&fn) {
74
+ builderCtx.setOpenedArchetypesTracker (&openedArchetypesTracker);
75
+ }
76
+
77
+ // / A "syntactic" high level function that combines our insertPt with a
78
+ // / builder ctx.
79
+ // /
80
+ // / Since this is syntactic and we assume that our caller is passing in a
81
+ // / lambda that if we inline will be eliminated, we mark this function always
82
+ // / inline.
83
+ template <typename ResultTy>
84
+ ResultTy LLVM_ATTRIBUTE_ALWAYS_INLINE
85
+ withBuilder (SILInstruction *insertPt,
86
+ llvm::function_ref<ResultTy(SILBuilder &, SILLocation)> visitor) {
87
+ SILBuilderWithScope builder (insertPt, builderCtx);
88
+ return visitor (builder, insertPt->getLoc ());
70
89
}
71
90
72
91
void drainTrackingList () {
@@ -83,8 +102,6 @@ struct OwnershipModelEliminatorVisitor
83
102
// Add any elements to the tracking list that we currently have in the
84
103
// tracking list that we haven't added yet.
85
104
drainTrackingList ();
86
- builder.setInsertionPoint (instToVisit);
87
- builder.setCurrentDebugScope (instToVisit->getDebugScope ());
88
105
}
89
106
90
107
void eraseInstruction (SILInstruction *i) {
@@ -137,10 +154,12 @@ struct OwnershipModelEliminatorVisitor
137
154
// We lower this to unchecked_bitwise_cast losing our assumption of layout
138
155
// compatibility.
139
156
bool visitUncheckedValueCastInst (UncheckedValueCastInst *uvci) {
140
- auto *newVal = builder.createUncheckedBitwiseCast (
141
- uvci->getLoc (), uvci->getOperand (), uvci->getType ());
142
- eraseInstructionAndRAUW (uvci, newVal);
143
- return true ;
157
+ return withBuilder<bool >(uvci, [&](SILBuilder &b, SILLocation loc) {
158
+ auto *newVal = b.createUncheckedBitwiseCast (loc, uvci->getOperand (),
159
+ uvci->getType ());
160
+ eraseInstructionAndRAUW (uvci, newVal);
161
+ return true ;
162
+ });
144
163
}
145
164
146
165
void splitDestructure (SILInstruction *destructure,
@@ -157,8 +176,10 @@ bool OwnershipModelEliminatorVisitor::visitLoadInst(LoadInst *li) {
157
176
if (qualifier == LoadOwnershipQualifier::Unqualified)
158
177
return false ;
159
178
160
- SILValue result = builder.emitLoadValueOperation (
161
- li->getLoc (), li->getOperand (), li->getOwnershipQualifier ());
179
+ auto result = withBuilder<SILValue>(li, [&](SILBuilder &b, SILLocation loc) {
180
+ return b.emitLoadValueOperation (loc, li->getOperand (),
181
+ li->getOwnershipQualifier ());
182
+ });
162
183
163
184
// Then remove the qualified load and use the unqualified load as the def of
164
185
// all of LI's uses.
@@ -174,8 +195,10 @@ bool OwnershipModelEliminatorVisitor::visitStoreInst(StoreInst *si) {
174
195
if (qualifier == StoreOwnershipQualifier::Unqualified)
175
196
return false ;
176
197
177
- builder.emitStoreValueOperation (si->getLoc (), si->getSrc (), si->getDest (),
178
- si->getOwnershipQualifier ());
198
+ withBuilder<void >(si, [&](SILBuilder &b, SILLocation loc) {
199
+ b.emitStoreValueOperation (loc, si->getSrc (), si->getDest (),
200
+ si->getOwnershipQualifier ());
201
+ });
179
202
180
203
// Then remove the qualified store.
181
204
eraseInstruction (si);
@@ -184,8 +207,10 @@ bool OwnershipModelEliminatorVisitor::visitStoreInst(StoreInst *si) {
184
207
185
208
bool OwnershipModelEliminatorVisitor::visitStoreBorrowInst (
186
209
StoreBorrowInst *si) {
187
- builder.emitStoreValueOperation (si->getLoc (), si->getSrc (), si->getDest (),
188
- StoreOwnershipQualifier::Init);
210
+ withBuilder<void >(si, [&](SILBuilder &b, SILLocation loc) {
211
+ b.emitStoreValueOperation (loc, si->getSrc (), si->getDest (),
212
+ StoreOwnershipQualifier::Unqualified);
213
+ });
189
214
190
215
// Then remove the qualified store.
191
216
eraseInstruction (si);
@@ -194,23 +219,28 @@ bool OwnershipModelEliminatorVisitor::visitStoreBorrowInst(
194
219
195
220
bool OwnershipModelEliminatorVisitor::visitLoadBorrowInst (LoadBorrowInst *lbi) {
196
221
// Break down the load borrow into an unqualified load.
197
- auto *unqualifiedLoad = builder.createLoad (
198
- lbi->getLoc (), lbi->getOperand (), LoadOwnershipQualifier::Unqualified);
222
+ auto newLoad =
223
+ withBuilder<SILValue>(lbi, [&](SILBuilder &b, SILLocation loc) {
224
+ return b.createLoad (loc, lbi->getOperand (),
225
+ LoadOwnershipQualifier::Unqualified);
226
+ });
199
227
200
228
// Then remove the qualified load and use the unqualified load as the def of
201
229
// all of LI's uses.
202
- eraseInstructionAndRAUW (lbi, unqualifiedLoad );
230
+ eraseInstructionAndRAUW (lbi, newLoad );
203
231
return true ;
204
232
}
205
233
206
234
bool OwnershipModelEliminatorVisitor::visitCopyValueInst (CopyValueInst *cvi) {
207
235
// A copy_value of an address-only type cannot be replaced.
208
- if (cvi->getType ().isAddressOnly (builder. getFunction ()))
236
+ if (cvi->getType ().isAddressOnly (*cvi-> getFunction ()))
209
237
return false ;
210
238
211
239
// Now that we have set the unqualified ownership flag, destroy value
212
240
// operation will delegate to the appropriate strong_release, etc.
213
- builder.emitCopyValueOperation (cvi->getLoc (), cvi->getOperand ());
241
+ withBuilder<void >(cvi, [&](SILBuilder &b, SILLocation loc) {
242
+ b.emitCopyValueOperation (loc, cvi->getOperand ());
243
+ });
214
244
eraseInstructionAndRAUW (cvi, cvi->getOperand ());
215
245
return true ;
216
246
}
@@ -219,7 +249,9 @@ bool OwnershipModelEliminatorVisitor::visitUnmanagedRetainValueInst(
219
249
UnmanagedRetainValueInst *urvi) {
220
250
// Now that we have set the unqualified ownership flag, destroy value
221
251
// operation will delegate to the appropriate strong_release, etc.
222
- builder.emitCopyValueOperation (urvi->getLoc (), urvi->getOperand ());
252
+ withBuilder<void >(urvi, [&](SILBuilder &b, SILLocation loc) {
253
+ b.emitCopyValueOperation (loc, urvi->getOperand ());
254
+ });
223
255
eraseInstruction (urvi);
224
256
return true ;
225
257
}
@@ -228,7 +260,9 @@ bool OwnershipModelEliminatorVisitor::visitUnmanagedReleaseValueInst(
228
260
UnmanagedReleaseValueInst *urvi) {
229
261
// Now that we have set the unqualified ownership flag, destroy value
230
262
// operation will delegate to the appropriate strong_release, etc.
231
- builder.emitDestroyValueOperation (urvi->getLoc (), urvi->getOperand ());
263
+ withBuilder<void >(urvi, [&](SILBuilder &b, SILLocation loc) {
264
+ b.emitDestroyValueOperation (loc, urvi->getOperand ());
265
+ });
232
266
eraseInstruction (urvi);
233
267
return true ;
234
268
}
@@ -237,21 +271,24 @@ bool OwnershipModelEliminatorVisitor::visitUnmanagedAutoreleaseValueInst(
237
271
UnmanagedAutoreleaseValueInst *UAVI) {
238
272
// Now that we have set the unqualified ownership flag, destroy value
239
273
// operation will delegate to the appropriate strong_release, etc.
240
- builder.createAutoreleaseValue (UAVI->getLoc (), UAVI->getOperand (),
241
- UAVI->getAtomicity ());
274
+ withBuilder<void >(UAVI, [&](SILBuilder &b, SILLocation loc) {
275
+ b.createAutoreleaseValue (loc, UAVI->getOperand (), UAVI->getAtomicity ());
276
+ });
242
277
eraseInstruction (UAVI);
243
278
return true ;
244
279
}
245
280
246
281
bool OwnershipModelEliminatorVisitor::visitDestroyValueInst (
247
282
DestroyValueInst *dvi) {
248
283
// A destroy_value of an address-only type cannot be replaced.
249
- if (dvi->getOperand ()->getType ().isAddressOnly (builder. getFunction ()))
284
+ if (dvi->getOperand ()->getType ().isAddressOnly (*dvi-> getFunction ()))
250
285
return false ;
251
286
252
287
// Now that we have set the unqualified ownership flag, destroy value
253
288
// operation will delegate to the appropriate strong_release, etc.
254
- builder.emitDestroyValueOperation (dvi->getLoc (), dvi->getOperand ());
289
+ withBuilder<void >(dvi, [&](SILBuilder &b, SILLocation loc) {
290
+ b.emitDestroyValueOperation (loc, dvi->getOperand ());
291
+ });
255
292
eraseInstruction (dvi);
256
293
return true ;
257
294
}
@@ -310,7 +347,8 @@ void OwnershipModelEliminatorVisitor::splitDestructure(
310
347
311
348
llvm::SmallVector<Projection, 8 > projections;
312
349
Projection::getFirstLevelProjections (
313
- opType, M, builder.getTypeExpansionContext (), projections);
350
+ opType, M, TypeExpansionContext (*destructureInst->getFunction ()),
351
+ projections);
314
352
assert (projections.size () == destructureInst->getNumResults ());
315
353
316
354
auto destructureResults = destructureInst->getResults ();
@@ -324,8 +362,10 @@ void OwnershipModelEliminatorVisitor::splitDestructure(
324
362
325
363
// Otherwise, create a projection.
326
364
const auto &proj = projections[index];
327
- SingleValueInstruction *projInst =
328
- proj.createObjectProjection (builder, loc, destructureOperand).get ();
365
+ auto *projInst = withBuilder<SingleValueInstruction *>(
366
+ destructureInst, [&](SILBuilder &b, SILLocation loc) {
367
+ return proj.createObjectProjection (b, loc, destructureOperand).get ();
368
+ });
329
369
330
370
// First RAUW Result with ProjInst. This ensures that we have a complete IR
331
371
// before we perform any simplifications.
@@ -362,8 +402,7 @@ static bool stripOwnership(SILFunction &func) {
362
402
363
403
bool madeChange = false ;
364
404
SmallVector<SILInstruction *, 32 > createdInsts;
365
- SILBuilder builder (func);
366
- OwnershipModelEliminatorVisitor visitor (builder);
405
+ OwnershipModelEliminatorVisitor visitor (func);
367
406
368
407
for (auto &block : func) {
369
408
// Change all arguments to have OwnershipKind::None.
@@ -382,9 +421,16 @@ static bool stripOwnership(SILFunction &func) {
382
421
}
383
422
}
384
423
385
- // Once we have finished processing all instructions, we should not be
386
- // consistently in non-ossa form. Now go through any instructions and simplify
387
- // using inst simplify.
424
+ // Once we have finished processing all instructions, we should be
425
+ // consistently in non-ossa form meaning that it is now safe for us to invoke
426
+ // utilities that assume that they are in a consistent ossa or non-ossa form
427
+ // such as inst simplify. Now go through any instructions and simplify using
428
+ // inst simplify!
429
+ //
430
+ // DISCUSSION: We want our utilities to be able to assume if f.hasOwnership()
431
+ // is false then the utility is allowed to assume the function the utility is
432
+ // invoked within is in non-ossa form structurally (e.x.: non-ossa does not
433
+ // have arguments on the default result of checked_cast_br).
388
434
while (!visitor.instructionsToSimplify .empty ()) {
389
435
auto value = visitor.instructionsToSimplify .pop_back_val ();
390
436
if (!value.hasValue ())
0 commit comments