@@ -145,200 +145,12 @@ STATISTIC(NumCopiesGenerated, "number of copy_value instructions created");
145
145
STATISTIC (NumDestroysGenerated, " number of destroy_value instructions created" );
146
146
STATISTIC (NumUnknownUsers, " number of functions with unknown users" );
147
147
148
- // ===----------------------------------------------------------------------===//
149
- // Ownership Abstraction.
150
- //
151
- // FIXME: These helpers are only defined in this pass for prototyping. After
152
- // bootstrapping, they should be moved to a central ownership API (shared by
153
- // SILOwnershipVerifier, etc.).
154
- //
155
- // Categories of owned value users. (U1-U2 apply to any value, O3-O5 only apply
156
- // to owned values).
157
- //
158
- // U1. Use the value instantaneously (copy_value, @guaranteed).
159
- //
160
- // U2. Escape the nontrivial contents of the value (ref_to_unowned,
161
- // unchecked_trivial_bitcast).
162
- //
163
- // O3. Propagate the value without consuming it (mark_dependence, begin_borrow).
164
- //
165
- // O4. Consume the value immediately (store, destroy, @owned, destructure).
166
- //
167
- // O5. Consume the value indirectly via a move (tuple, struct).
168
- // ===---------------------------------------------------------------------===//
169
-
170
- // TODO: Figure out how to handle these cases if possible.
171
- static bool isUnknownUse (Operand *use) {
172
- switch (use->getUser ()->getKind ()) {
173
- default :
174
- return false ;
175
- // FIXME: (Category O3) mark_dependence requires recursion to find all
176
- // uses. It should be replaced by begin/end dependence.
177
- case SILInstructionKind::MarkDependenceInst: // Dependent
178
- // FIXME: (Category O3) ref_tail_addr should require a borrow because it
179
- // doesn't rely on fix_lifetime like other escaping instructions.
180
- case SILInstructionKind::RefTailAddrInst:
181
- // FIXME: (Category O3) dynamic_method_br seems to capture self, presumably
182
- // propagating lifetime. This should probably borrow self, then be treated
183
- // like mark_dependence.
184
- case SILInstructionKind::DynamicMethodBranchInst:
185
- // FIXME: (Category O3) The ownership verifier says project_box can accept an
186
- // owned value as a normal use, but it projects the address. That's either an
187
- // ownership bug or a special case.
188
- case SILInstructionKind::ProjectBoxInst:
189
- case SILInstructionKind::ProjectExistentialBoxInst:
190
- // FIXME: (Category O3) The ownership verifier says open_existential_box can
191
- // accept an owned value as a normal use, but it projects an address.
192
- case SILInstructionKind::OpenExistentialBoxInst:
193
- // Unmanaged operations hopefully don't apply to the same value as CopyValue?
194
- case SILInstructionKind::UnmanagedRetainValueInst:
195
- case SILInstructionKind::UnmanagedReleaseValueInst:
196
- case SILInstructionKind::UnmanagedAutoreleaseValueInst:
197
- return true ;
198
- }
199
- }
200
-
201
- // / Return true if the given owned operand is consumed by the given call.
202
- static bool isAppliedArgConsumed (ApplySite apply, Operand *oper) {
203
- ParameterConvention paramConv;
204
- if (oper->get () == apply.getCallee ()) {
205
- assert (oper->getOperandNumber () == 0
206
- && " function can't be passed to itself" );
207
- paramConv = apply.getSubstCalleeType ()->getCalleeConvention ();
208
- } else {
209
- unsigned argIndex = apply.getCalleeArgIndex (*oper);
210
- paramConv = apply.getSubstCalleeConv ()
211
- .getParamInfoForSILArg (argIndex)
212
- .getConvention ();
213
- }
214
- return isConsumedParameter (paramConv);
215
- }
216
-
217
- // / Return true if the given builtin consumes its operand.
218
- static bool isBuiltinArgConsumed (BuiltinInst *BI) {
219
- const BuiltinInfo &Builtin = BI->getBuiltinInfo ();
220
- switch (Builtin.ID ) {
221
- default :
222
- llvm_unreachable (" Unexpected Builtin with owned value operand." );
223
- // Extend lifetime without consuming.
224
- case BuiltinValueKind::ErrorInMain:
225
- case BuiltinValueKind::UnexpectedError:
226
- case BuiltinValueKind::WillThrow:
227
- return false ;
228
- // UnsafeGuaranteed moves the value, which will later be destroyed.
229
- case BuiltinValueKind::UnsafeGuaranteed:
230
- return true ;
231
- }
232
- }
233
-
234
- // / Return true if the given operand is consumed by its user.
235
- // /
236
- // / TODO: Review the semantics of operations that extend the lifetime *without*
237
- // / propagating the value. Ideally, that never happens without borrowing first.
238
- static bool isConsuming (Operand *use) {
239
- auto *user = use->getUser ();
240
- if (isa<ApplySite>(user))
241
- return isAppliedArgConsumed (ApplySite (user), use);
242
-
243
- if (auto *BI = dyn_cast<BuiltinInst>(user))
244
- return isBuiltinArgConsumed (BI);
245
-
246
- switch (user->getKind ()) {
247
- default :
248
- llvm::dbgs () << *user;
249
- llvm_unreachable (" Unexpected use of a loadable owned value." );
250
-
251
- // Consume the value.
252
- case SILInstructionKind::AutoreleaseValueInst:
253
- case SILInstructionKind::DeallocBoxInst:
254
- case SILInstructionKind::DeallocExistentialBoxInst:
255
- case SILInstructionKind::DeallocRefInst:
256
- case SILInstructionKind::DeinitExistentialValueInst:
257
- case SILInstructionKind::DestroyValueInst:
258
- case SILInstructionKind::EndLifetimeInst:
259
- case SILInstructionKind::InitExistentialRefInst:
260
- case SILInstructionKind::InitExistentialValueInst:
261
- case SILInstructionKind::KeyPathInst:
262
- case SILInstructionKind::ReleaseValueInst:
263
- case SILInstructionKind::ReleaseValueAddrInst:
264
- case SILInstructionKind::StoreInst:
265
- case SILInstructionKind::StrongReleaseInst:
266
- case SILInstructionKind::UnownedReleaseInst:
267
- case SILInstructionKind::UnconditionalCheckedCastValueInst:
268
- return true ;
269
-
270
- // Terminators must consume their owned values.
271
- case SILInstructionKind::BranchInst:
272
- case SILInstructionKind::CheckedCastBranchInst:
273
- case SILInstructionKind::CheckedCastValueBranchInst:
274
- case SILInstructionKind::CondBranchInst:
275
- case SILInstructionKind::ReturnInst:
276
- case SILInstructionKind::ThrowInst:
277
- return true ;
278
-
279
- case SILInstructionKind::DeallocPartialRefInst:
280
- return cast<DeallocPartialRefInst>(user)->getInstance () == use->get ();
281
-
282
- // Move the value.
283
- case SILInstructionKind::TupleInst:
284
- case SILInstructionKind::StructInst:
285
- case SILInstructionKind::ObjectInst:
286
- case SILInstructionKind::EnumInst:
287
- case SILInstructionKind::OpenExistentialRefInst:
288
- case SILInstructionKind::UpcastInst:
289
- case SILInstructionKind::UncheckedRefCastInst:
290
- case SILInstructionKind::ConvertFunctionInst:
291
- case SILInstructionKind::RefToBridgeObjectInst:
292
- case SILInstructionKind::BridgeObjectToRefInst:
293
- case SILInstructionKind::UnconditionalCheckedCastInst:
294
- case SILInstructionKind::MarkUninitializedInst:
295
- case SILInstructionKind::UncheckedEnumDataInst:
296
- case SILInstructionKind::DestructureStructInst:
297
- case SILInstructionKind::DestructureTupleInst:
298
- return true ;
299
-
300
- // BeginBorrow should already be skipped.
301
- // EndBorrow extends the lifetime like a normal use.
302
- case SILInstructionKind::EndBorrowInst:
303
- return false ;
304
-
305
- // Extend the lifetime without borrowing, propagating, or destroying it.
306
- case SILInstructionKind::BridgeObjectToWordInst:
307
- case SILInstructionKind::ClassMethodInst:
308
- case SILInstructionKind::CopyBlockInst:
309
- case SILInstructionKind::CopyValueInst:
310
- case SILInstructionKind::DebugValueInst:
311
- case SILInstructionKind::ExistentialMetatypeInst:
312
- case SILInstructionKind::FixLifetimeInst:
313
- case SILInstructionKind::SelectEnumInst:
314
- case SILInstructionKind::SetDeallocatingInst:
315
- case SILInstructionKind::StoreWeakInst:
316
- case SILInstructionKind::ValueMetatypeInst:
317
- return false ;
318
-
319
- // Escape the value. The lifetime must already be enforced via something like
320
- // fix_lifetime.
321
- case SILInstructionKind::RefToRawPointerInst:
322
- case SILInstructionKind::RefToUnmanagedInst:
323
- case SILInstructionKind::RefToUnownedInst:
324
- case SILInstructionKind::UncheckedBitwiseCastInst:
325
- case SILInstructionKind::UncheckedTrivialBitCastInst:
326
- return false ;
327
-
328
- // Dynamic dispatch without capturing self.
329
- case SILInstructionKind::ObjCMethodInst:
330
- case SILInstructionKind::ObjCSuperMethodInst:
331
- case SILInstructionKind::SuperMethodInst:
332
- case SILInstructionKind::WitnessMethodInst:
333
- return false ;
334
- }
335
- }
336
-
337
148
// ===----------------------------------------------------------------------===//
338
149
// CopyPropagationState: shared state for the pass's analysis and transforms.
339
150
// ===----------------------------------------------------------------------===//
340
151
341
152
namespace {
153
+
342
154
// / LiveWithin blocks have at least one use and/or def within the block, but are
343
155
// / not LiveOut.
344
156
// /
@@ -357,9 +169,10 @@ class LivenessInfo {
357
169
// used value is consumed. (Non-consuming uses within a block that is already
358
170
// known to be live are uninteresting.)
359
171
DenseMap<SILInstruction *, bool > users;
172
+
360
173
// Original points in the CFG where the current value was consumed or
361
174
// destroyed.
362
- typedef SmallSetVector<SILBasicBlock *, 8 > BlockSetVec ;
175
+ using BlockSetVec = SmallSetVector<SILBasicBlock *, 8 >;
363
176
BlockSetVec originalDestroyBlocks;
364
177
365
178
public:
@@ -409,7 +222,7 @@ class LivenessInfo {
409
222
//
410
223
// This call cannot be allowed to destroy %val.
411
224
void recordUser (Operand *use) {
412
- bool consume = isConsuming ( use);
225
+ bool consume = use-> isConsumingUse ( );
413
226
auto iterAndSuccess = users.try_emplace (use->getUser (), consume);
414
227
if (!iterAndSuccess.second )
415
228
iterAndSuccess.first ->second &= consume;
@@ -468,7 +281,7 @@ class DestroyInfo {
468
281
469
282
// / This pass' shared state.
470
283
struct CopyPropagationState {
471
- SILFunction *F ;
284
+ SILFunction *func ;
472
285
473
286
// Per-function invalidation state.
474
287
unsigned invalidation;
@@ -483,7 +296,7 @@ struct CopyPropagationState {
483
296
DestroyInfo destroys;
484
297
485
298
CopyPropagationState (SILFunction *F)
486
- : F (F), invalidation(SILAnalysis::InvalidationKind::Nothing) {}
299
+ : func (F), invalidation(SILAnalysis::InvalidationKind::Nothing) {}
487
300
488
301
bool isValueOwned () const {
489
302
return currDef.getOwnershipKind () == ValueOwnershipKind::Owned;
@@ -600,27 +413,23 @@ static bool computeLiveness(CopyPropagationState &pass) {
600
413
for (Operand *use : value->getUses ()) {
601
414
auto *user = use->getUser ();
602
415
603
- // Bailout if we cannot yet determine the ownership of a use.
604
- if (isUnknownUse (use)) {
605
- LLVM_DEBUG (llvm::dbgs () << " Unknown owned value user: " ; user->dump ());
606
- ++NumUnknownUsers;
607
- return false ;
608
- }
609
416
// Recurse through copies.
610
417
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
611
418
defUseWorkList.insert (copy);
612
419
continue ;
613
420
}
421
+
614
422
// An entire borrow scope is considered a single use that occurs at the
615
423
// point of the end_borrow.
616
- if (auto *BBI = dyn_cast<BeginBorrowInst>(user)) {
617
- for (Operand *use : BBI ->getUses ()) {
424
+ if (auto *bbi = dyn_cast<BeginBorrowInst>(user)) {
425
+ for (Operand *use : bbi ->getUses ()) {
618
426
if (isa<EndBorrowInst>(use->getUser ()))
619
427
computeUseLiveness (use, pass);
620
428
}
621
429
continue ;
622
430
}
623
- if (isConsuming (use)) {
431
+
432
+ if (use->isConsumingUse ()) {
624
433
pass.liveness .recordOriginalDestroy (use);
625
434
// Destroying a values does not force liveness.
626
435
if (isa<DestroyValueInst>(user))
@@ -649,13 +458,14 @@ static void insertDestroyOnCFGEdge(SILBasicBlock *predBB, SILBasicBlock *succBB,
649
458
if (destroyBB != succBB)
650
459
pass.markInvalid (SILAnalysis::InvalidationKind::Branches);
651
460
652
- SILBuilderWithScope B (destroyBB->begin ());
653
- auto *DI = B.createDestroyValue (succBB->begin ()->getLoc (), pass.currDef );
461
+ SILBuilderWithScope builder (destroyBB->begin ());
462
+ auto *di =
463
+ builder.createDestroyValue (succBB->begin ()->getLoc (), pass.currDef );
654
464
655
- pass.destroys .recordFinalDestroy (DI );
465
+ pass.destroys .recordFinalDestroy (di );
656
466
657
467
++NumDestroysGenerated;
658
- LLVM_DEBUG (llvm::dbgs () << " Destroy on edge " ; DI ->dump ());
468
+ LLVM_DEBUG (llvm::dbgs () << " Destroy on edge " ; di ->dump ());
659
469
660
470
pass.markInvalid (SILAnalysis::InvalidationKind::Instructions);
661
471
}
@@ -665,11 +475,11 @@ static void insertDestroyOnCFGEdge(SILBasicBlock *predBB, SILBasicBlock *succBB,
665
475
// / Create a final destroy, immediately after `pos`.
666
476
static void insertDestroyAtInst (SILBasicBlock::iterator pos,
667
477
CopyPropagationState &pass) {
668
- SILBuilderWithScope B (pos);
669
- auto *DI = B .createDestroyValue ((*pos).getLoc (), pass.currDef );
670
- pass.destroys .recordFinalDestroy (DI );
478
+ SILBuilderWithScope builder (pos);
479
+ auto *di = builder .createDestroyValue ((*pos).getLoc (), pass.currDef );
480
+ pass.destroys .recordFinalDestroy (di );
671
481
++NumDestroysGenerated;
672
- LLVM_DEBUG (llvm::dbgs () << " Destroy at last use " ; DI ->dump ());
482
+ LLVM_DEBUG (llvm::dbgs () << " Destroy at last use " ; di ->dump ());
673
483
pass.markInvalid (SILAnalysis::InvalidationKind::Instructions);
674
484
}
675
485
@@ -679,9 +489,9 @@ static void insertDestroyAtInst(SILBasicBlock::iterator pos,
679
489
static void findOrInsertDestroyInBlock (SILBasicBlock *bb,
680
490
CopyPropagationState &pass) {
681
491
auto *defInst = pass.currDef ->getDefiningInstruction ();
682
- auto I = bb->getTerminator ()->getIterator ();
492
+ auto instIter = bb->getTerminator ()->getIterator ();
683
493
while (true ) {
684
- auto *inst = &*I ;
494
+ auto *inst = &*instIter ;
685
495
Optional<bool > isConsumingResult = pass.liveness .isConsumingUser (inst);
686
496
if (isConsumingResult.hasValue ()) {
687
497
if (isConsumingResult.getValue ()) {
@@ -691,20 +501,20 @@ static void findOrInsertDestroyInBlock(SILBasicBlock *bb,
691
501
}
692
502
// Insert a destroy after this non-consuming use.
693
503
assert (inst != bb->getTerminator () && " Terminator must consume operand." );
694
- insertDestroyAtInst (std::next (I ), pass);
504
+ insertDestroyAtInst (std::next (instIter ), pass);
695
505
break ;
696
506
}
697
507
// This is not a potential last user. Keep scanning.
698
508
// If the original destroy is reached, this is a dead live range. Insert a
699
509
// destroy immediately after the def.
700
- if (I == bb->begin ()) {
510
+ if (instIter == bb->begin ()) {
701
511
assert (cast<SILArgument>(pass.currDef )->getParent () == bb);
702
- insertDestroyAtInst (I , pass);
512
+ insertDestroyAtInst (instIter , pass);
703
513
break ;
704
514
}
705
- --I ;
706
- if (&*I == defInst) {
707
- insertDestroyAtInst (std::next (I ), pass);
515
+ --instIter ;
516
+ if (&*instIter == defInst) {
517
+ insertDestroyAtInst (std::next (instIter ), pass);
708
518
break ;
709
519
}
710
520
}
@@ -799,6 +609,7 @@ static void rewriteCopies(CopyPropagationState &pass) {
799
609
defUseWorklist.insert (copy);
800
610
return ;
801
611
}
612
+
802
613
if (auto *destroy = dyn_cast<DestroyValueInst>(user)) {
803
614
// If this destroy was marked as a final destroy, ignore it; otherwise,
804
615
// delete it.
@@ -809,8 +620,9 @@ static void rewriteCopies(CopyPropagationState &pass) {
809
620
}
810
621
return ;
811
622
}
623
+
812
624
// Nonconsuming uses do not need copies and cannot be marked as destroys.
813
- if (!isConsuming ( use))
625
+ if (!use-> isConsumingUse ( ))
814
626
return ;
815
627
816
628
// If this use was marked as a final destroy *and* this is the first
@@ -862,6 +674,7 @@ static SILValue stripCopies(SILValue v) {
862
674
v = srcCopy->getOperand ();
863
675
continue ;
864
676
}
677
+
865
678
return v;
866
679
}
867
680
}
@@ -885,12 +698,13 @@ void CopyPropagation::run() {
885
698
// Step 1. Find all copied defs.
886
699
CopyPropagationState pass (getFunction ());
887
700
SmallSetVector<SILValue, 16 > copiedDefs;
888
- for (auto &BB : *pass.F ) {
889
- for (auto &I : BB ) {
890
- if (auto *copy = dyn_cast<CopyValueInst>(&I ))
701
+ for (auto &bb : *pass.func ) {
702
+ for (auto &i : bb ) {
703
+ if (auto *copy = dyn_cast<CopyValueInst>(&i ))
891
704
copiedDefs.insert (stripCopies (copy));
892
705
}
893
706
}
707
+
894
708
for (auto &def : copiedDefs) {
895
709
pass.resetDef (def);
896
710
// Step 2: computeLiveness
0 commit comments