@@ -109,20 +109,21 @@ static bool addLastRelease(SILValue V, SILBasicBlock *BB,
109
109
// Find the final releases of the alloc_box along any given path.
110
110
// These can include paths from a release back to the alloc_box in a
111
111
// loop.
112
- static bool getFinalReleases (AllocBoxInst *ABI,
113
- llvm::SmallVectorImpl<SILInstruction*> &Releases) {
112
+ static bool
113
+ getFinalReleases (SILValue Box,
114
+ llvm::SmallVectorImpl<SILInstruction *> &Releases) {
114
115
llvm::SmallPtrSet<SILBasicBlock*, 16 > LiveIn;
115
116
llvm::SmallPtrSet<SILBasicBlock*, 16 > UseBlocks;
116
117
117
- auto *DefBB = ABI-> getParent ();
118
+ auto *DefBB = Box-> getParentBlock ();
118
119
119
120
auto seenRelease = false ;
120
121
SILInstruction *OneRelease = nullptr ;
121
122
122
123
// We'll treat this like a liveness problem where the alloc_box is
123
124
// the def. Each block that has a use of the owning pointer has the
124
125
// value live-in unless it is the block with the alloc_box.
125
- llvm::SmallVector<Operand *, 32 > Worklist (ABI ->use_begin (), ABI ->use_end ());
126
+ llvm::SmallVector<Operand *, 32 > Worklist (Box ->use_begin (), Box ->use_end ());
126
127
while (!Worklist.empty ()) {
127
128
auto *Op = Worklist.pop_back_val ();
128
129
auto *User = Op->getUser ();
@@ -137,12 +138,10 @@ static bool getFinalReleases(AllocBoxInst *ABI,
137
138
// Also keep track of the blocks with uses.
138
139
UseBlocks.insert (BB);
139
140
140
- // If we have a copy value, add its uses to the work list and continue.
141
- //
142
- // We are actually performing multiple operations here. We are eliminating
143
- // copies of the box and the box itself.
144
- if (auto *CVI = dyn_cast<CopyValueInst>(User)) {
145
- std::copy (CVI->use_begin (), CVI->use_end (), std::back_inserter (Worklist));
141
+ // If we have a copy value or a mark_uninitialized, add its uses to the work
142
+ // list and continue.
143
+ if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
144
+ copy (User->getUses (), std::back_inserter (Worklist));
146
145
continue ;
147
146
}
148
147
@@ -171,7 +170,7 @@ static bool getFinalReleases(AllocBoxInst *ABI,
171
170
// release/dealloc.
172
171
for (auto *BB : UseBlocks)
173
172
if (!successorHasLiveIn (BB, LiveIn))
174
- if (!addLastRelease (ABI , BB, Releases))
173
+ if (!addLastRelease (Box , BB, Releases))
175
174
return false ;
176
175
177
176
return true ;
@@ -213,9 +212,8 @@ static bool partialApplyEscapes(SILValue V, bool examineApply) {
213
212
// If we have a copy_value, the copy value does not cause an escape, but its
214
213
// uses might do so... so add the copy_value's uses to the worklist and
215
214
// continue.
216
- if (auto *Copy = dyn_cast<CopyValueInst>(User)) {
217
- std::copy (Copy->use_begin (), Copy->use_end (),
218
- std::back_inserter (Worklist));
215
+ if (isa<CopyValueInst>(User)) {
216
+ copy (User->getUses (), std::back_inserter (Worklist));
219
217
continue ;
220
218
}
221
219
@@ -353,11 +351,9 @@ static bool checkPartialApplyBody(Operand *O) {
353
351
PromotedOperands);
354
352
}
355
353
356
-
357
- // / findUnexpectedBoxUse - Validate that the uses of a pointer to a
358
- // / box do not eliminate it from consideration for promotion to a
359
- // / stack element. Optionally examine the body of partial_apply
360
- // / to see if there is an unexpected use inside. Return the
354
+ // / Validate that the uses of a pointer to a box do not eliminate it from
355
+ // / consideration for promotion to a stack element. Optionally examine the body
356
+ // / of partial_apply to see if there is an unexpected use inside. Return the
361
357
// / instruction with the unexpected use if we find one.
362
358
static SILInstruction* findUnexpectedBoxUse (SILValue Box,
363
359
bool examinePartialApply,
@@ -386,9 +382,10 @@ static SILInstruction* findUnexpectedBoxUse(SILValue Box,
386
382
(!inAppliedFunction && isa<DeallocBoxInst>(User)))
387
383
continue ;
388
384
389
- // If we have a copy_value, visit the users of the copy_value.
390
- if (auto *CVI = dyn_cast<CopyValueInst>(User)) {
391
- std::copy (CVI->use_begin (), CVI->use_end (), std::back_inserter (Worklist));
385
+ // If our user instruction is a copy_value or a marked_uninitialized, visit
386
+ // the users recursively.
387
+ if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
388
+ copy (User->getUses (), std::back_inserter (Worklist));
392
389
continue ;
393
390
}
394
391
@@ -432,19 +429,20 @@ static bool canPromoteAllocBox(AllocBoxInst *ABI,
432
429
return true ;
433
430
}
434
431
435
- static void replaceProjectBoxUsers (AllocBoxInst *ABI, AllocStackInst *ASI) {
436
- llvm::SmallVector<Operand *, 8 > Worklist (ABI->use_begin (), ABI->use_end ());
432
+ static void replaceProjectBoxUsers (SILValue HeapBox, SILValue StackBox) {
433
+ llvm::SmallVector<Operand *, 8 > Worklist (HeapBox->use_begin (),
434
+ HeapBox->use_end ());
437
435
while (!Worklist.empty ()) {
438
436
auto *Op = Worklist.pop_back_val ();
439
437
if (auto *PBI = dyn_cast<ProjectBoxInst>(Op->getUser ())) {
440
- PBI->replaceAllUsesWith (ASI );
438
+ PBI->replaceAllUsesWith (StackBox );
441
439
continue ;
442
440
}
443
441
444
442
auto *CVI = dyn_cast<CopyValueInst>(Op->getUser ());
445
443
if (!CVI)
446
444
continue ;
447
- std:: copy (CVI->use_begin (), CVI-> use_end (), std::back_inserter (Worklist));
445
+ copy (CVI->getUses (), std::back_inserter (Worklist));
448
446
}
449
447
}
450
448
@@ -453,36 +451,40 @@ static void replaceProjectBoxUsers(AllocBoxInst *ABI, AllocStackInst *ASI) {
453
451
static bool rewriteAllocBoxAsAllocStack (AllocBoxInst *ABI) {
454
452
DEBUG (llvm::dbgs () << " *** Promoting alloc_box to stack: " << *ABI);
455
453
454
+ SILValue HeapBox = ABI;
455
+ Optional<MarkUninitializedInst::Kind> Kind;
456
+ if (HeapBox->hasOneUse ()) {
457
+ auto *User = HeapBox->getSingleUse ()->getUser ();
458
+ if (auto *MUI = dyn_cast<MarkUninitializedInst>(User)) {
459
+ HeapBox = MUI;
460
+ Kind = MUI->getKind ();
461
+ }
462
+ }
463
+
456
464
llvm::SmallVector<SILInstruction *, 4 > FinalReleases;
457
- if (!getFinalReleases (ABI , FinalReleases))
465
+ if (!getFinalReleases (HeapBox , FinalReleases))
458
466
return false ;
459
467
460
468
// Promote this alloc_box to an alloc_stack. Insert the alloc_stack
461
469
// at the beginning of the function.
462
- SILBuilder BuildAlloc (ABI);
463
- BuildAlloc .setCurrentDebugScope (ABI->getDebugScope ());
470
+ SILBuilder Builder (ABI);
471
+ Builder .setCurrentDebugScope (ABI->getDebugScope ());
464
472
assert (ABI->getBoxType ()->getLayout ()->getFields ().size () == 1
465
473
&& " rewriting multi-field box not implemented" );
466
- auto *ASI = BuildAlloc.createAllocStack (ABI->getLoc (),
467
- ABI->getBoxType ()->getFieldType (ABI->getModule (), 0 ),
468
- ABI->getVarInfo ());
474
+ auto *ASI = Builder.createAllocStack (
475
+ ABI->getLoc (), ABI->getBoxType ()->getFieldType (ABI->getModule (), 0 ),
476
+ ABI->getVarInfo ());
477
+
478
+ // Transfer a mark_uninitialized if we have one.
479
+ SILValue StackBox = ASI;
480
+ if (Kind) {
481
+ StackBox =
482
+ Builder.createMarkUninitialized (ASI->getLoc (), ASI, Kind.getValue ());
483
+ }
469
484
470
485
// Replace all uses of the address of the box's contained value with
471
486
// the address of the stack location.
472
- replaceProjectBoxUsers (ABI, ASI);
473
-
474
- // Check to see if the alloc_box was used by a mark_uninitialized instruction.
475
- // If so, any uses of the pointer result need to keep using the MUI, not the
476
- // alloc_stack directly. If we don't do this, DI will miss the uses.
477
- SILValue PointerResult = ASI;
478
- for (auto UI : ASI->getUses ()) {
479
- if (auto *MUI = dyn_cast<MarkUninitializedInst>(UI->getUser ())) {
480
- assert (ASI->hasOneUse () &&
481
- " alloc_stack used by mark_uninitialized, but not exclusively!" );
482
- PointerResult = MUI;
483
- break ;
484
- }
485
- }
487
+ replaceProjectBoxUsers (HeapBox, StackBox);
486
488
487
489
assert (ABI->getBoxType ()->getLayout ()->getFields ().size () == 1
488
490
&& " promoting multi-field box not implemented" );
@@ -495,7 +497,7 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
495
497
if (!isa<DeallocBoxInst>(LastRelease)&& !Lowering.isTrivial ()) {
496
498
// For non-trivial types, insert destroys for each final release-like
497
499
// instruction we found that isn't an explicit dealloc_box.
498
- Builder.emitDestroyAddrAndFold (Loc, PointerResult );
500
+ Builder.emitDestroyAddrAndFold (Loc, StackBox );
499
501
}
500
502
Builder.createDeallocStack (Loc, ASI);
501
503
}
@@ -509,10 +511,10 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
509
511
while (!Worklist.empty ()) {
510
512
auto *User = Worklist.pop_back_val ();
511
513
512
- if (isa<CopyValueInst>(User)) {
513
- std::transform (
514
- User-> use_begin (), User->use_end (), std::back_inserter (Worklist),
515
- [](Operand *Op) -> SILInstruction * { return Op->getUser (); });
514
+ // Look through any mark_uninitialized, copy_values.
515
+ if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
516
+ transform ( User->getUses (), std::back_inserter (Worklist),
517
+ [](Operand *Op) -> SILInstruction * { return Op->getUser (); });
516
518
User->replaceAllUsesWith (
517
519
SILUndef::get (User->getType (), User->getModule ()));
518
520
User->eraseFromParent ();
0 commit comments