Skip to content

Commit 21973e0

Browse files
committed
[semantic-sil] Update allocbox-to-stack for the mark_uninitialized begin on the alloc_box instead of the project_box.
This also moves the eliminator pass behind alloc box to stack. rdar://31521023
1 parent 9d6e6dc commit 21973e0

File tree

4 files changed

+79
-78
lines changed

4 files changed

+79
-78
lines changed

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ static void addMandatoryOptPipeline(SILPassPipelinePlan &P,
7979
}
8080
P.addDiagnoseStaticExclusivity();
8181
P.addCapturePromotion();
82-
P.addMarkUninitializedFixup();
8382
P.addAllocBoxToStack();
83+
P.addMarkUninitializedFixup();
8484
P.addNoReturnFolding();
8585
P.addOwnershipModelEliminator();
8686
P.addDefiniteInitialization();

lib/SILOptimizer/Transforms/AllocBoxToStack.cpp

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -109,20 +109,21 @@ static bool addLastRelease(SILValue V, SILBasicBlock *BB,
109109
// Find the final releases of the alloc_box along any given path.
110110
// These can include paths from a release back to the alloc_box in a
111111
// loop.
112-
static bool getFinalReleases(AllocBoxInst *ABI,
113-
llvm::SmallVectorImpl<SILInstruction*> &Releases) {
112+
static bool
113+
getFinalReleases(SILValue Box,
114+
llvm::SmallVectorImpl<SILInstruction *> &Releases) {
114115
llvm::SmallPtrSet<SILBasicBlock*, 16> LiveIn;
115116
llvm::SmallPtrSet<SILBasicBlock*, 16> UseBlocks;
116117

117-
auto *DefBB = ABI->getParent();
118+
auto *DefBB = Box->getParentBlock();
118119

119120
auto seenRelease = false;
120121
SILInstruction *OneRelease = nullptr;
121122

122123
// We'll treat this like a liveness problem where the alloc_box is
123124
// the def. Each block that has a use of the owning pointer has the
124125
// 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());
126127
while (!Worklist.empty()) {
127128
auto *Op = Worklist.pop_back_val();
128129
auto *User = Op->getUser();
@@ -137,12 +138,10 @@ static bool getFinalReleases(AllocBoxInst *ABI,
137138
// Also keep track of the blocks with uses.
138139
UseBlocks.insert(BB);
139140

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));
146145
continue;
147146
}
148147

@@ -171,7 +170,7 @@ static bool getFinalReleases(AllocBoxInst *ABI,
171170
// release/dealloc.
172171
for (auto *BB : UseBlocks)
173172
if (!successorHasLiveIn(BB, LiveIn))
174-
if (!addLastRelease(ABI, BB, Releases))
173+
if (!addLastRelease(Box, BB, Releases))
175174
return false;
176175

177176
return true;
@@ -213,9 +212,8 @@ static bool partialApplyEscapes(SILValue V, bool examineApply) {
213212
// If we have a copy_value, the copy value does not cause an escape, but its
214213
// uses might do so... so add the copy_value's uses to the worklist and
215214
// 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));
219217
continue;
220218
}
221219

@@ -353,11 +351,9 @@ static bool checkPartialApplyBody(Operand *O) {
353351
PromotedOperands);
354352
}
355353

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
361357
/// instruction with the unexpected use if we find one.
362358
static SILInstruction* findUnexpectedBoxUse(SILValue Box,
363359
bool examinePartialApply,
@@ -386,9 +382,10 @@ static SILInstruction* findUnexpectedBoxUse(SILValue Box,
386382
(!inAppliedFunction && isa<DeallocBoxInst>(User)))
387383
continue;
388384

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));
392389
continue;
393390
}
394391

@@ -432,19 +429,20 @@ static bool canPromoteAllocBox(AllocBoxInst *ABI,
432429
return true;
433430
}
434431

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());
437435
while (!Worklist.empty()) {
438436
auto *Op = Worklist.pop_back_val();
439437
if (auto *PBI = dyn_cast<ProjectBoxInst>(Op->getUser())) {
440-
PBI->replaceAllUsesWith(ASI);
438+
PBI->replaceAllUsesWith(StackBox);
441439
continue;
442440
}
443441

444442
auto *CVI = dyn_cast<CopyValueInst>(Op->getUser());
445443
if (!CVI)
446444
continue;
447-
std::copy(CVI->use_begin(), CVI->use_end(), std::back_inserter(Worklist));
445+
copy(CVI->getUses(), std::back_inserter(Worklist));
448446
}
449447
}
450448

@@ -453,36 +451,40 @@ static void replaceProjectBoxUsers(AllocBoxInst *ABI, AllocStackInst *ASI) {
453451
static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
454452
DEBUG(llvm::dbgs() << "*** Promoting alloc_box to stack: " << *ABI);
455453

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+
456464
llvm::SmallVector<SILInstruction *, 4> FinalReleases;
457-
if (!getFinalReleases(ABI, FinalReleases))
465+
if (!getFinalReleases(HeapBox, FinalReleases))
458466
return false;
459467

460468
// Promote this alloc_box to an alloc_stack. Insert the alloc_stack
461469
// at the beginning of the function.
462-
SILBuilder BuildAlloc(ABI);
463-
BuildAlloc.setCurrentDebugScope(ABI->getDebugScope());
470+
SILBuilder Builder(ABI);
471+
Builder.setCurrentDebugScope(ABI->getDebugScope());
464472
assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
465473
&& "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+
}
469484

470485
// Replace all uses of the address of the box's contained value with
471486
// 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);
486488

487489
assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
488490
&& "promoting multi-field box not implemented");
@@ -495,7 +497,7 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
495497
if (!isa<DeallocBoxInst>(LastRelease)&& !Lowering.isTrivial()) {
496498
// For non-trivial types, insert destroys for each final release-like
497499
// instruction we found that isn't an explicit dealloc_box.
498-
Builder.emitDestroyAddrAndFold(Loc, PointerResult);
500+
Builder.emitDestroyAddrAndFold(Loc, StackBox);
499501
}
500502
Builder.createDeallocStack(Loc, ASI);
501503
}
@@ -509,10 +511,10 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
509511
while (!Worklist.empty()) {
510512
auto *User = Worklist.pop_back_val();
511513

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(); });
516518
User->replaceAllUsesWith(
517519
SILUndef::get(User->getType(), User->getModule()));
518520
User->eraseFromParent();

test/SILOptimizer/allocbox_to_stack.sil

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ bb0:
6868
sil @multi_strong_release : $() -> Int {
6969
bb0:
7070
%1 = alloc_box ${ var Int }
71-
%1a = project_box %1 : ${ var Int }, 0
72-
%2 = mark_uninitialized [rootself] %1a : $*Int
71+
%1a = mark_uninitialized [rootself] %1 : ${ var Int }
72+
%2 = project_box %1a : ${ var Int }, 0
7373
%3 = load %2 : $*Int
74-
%x = strong_retain %1 : ${ var Int }
75-
%y = strong_release %1 : ${ var Int }
74+
%x = strong_retain %1a : ${ var Int }
75+
%y = strong_release %1a : ${ var Int }
7676
%b = br bb1
7777
bb1:
7878

79-
%4 = strong_release %1 : ${ var Int }
79+
%4 = strong_release %1a : ${ var Int }
8080
%5 = return %3 : $Int
8181

8282
// CHECK: %0 = alloc_stack
@@ -318,9 +318,9 @@ extension Int : My_Incrementable { }
318318
sil @test_mui : $@convention(thin) (Builtin.Int1) -> () {
319319
bb0(%0 : $Builtin.Int1):
320320
%2 = alloc_box ${ var SomeClass }
321-
%2a = project_box %2 : ${ var SomeClass }, 0
321+
%2a = mark_uninitialized [var] %2 : ${ var SomeClass }
322+
%3 = project_box %2a : ${ var SomeClass }, 0
322323
// CHECK: [[STACK:%[0-9]+]] = alloc_stack
323-
%3 = mark_uninitialized [var] %2a : $*SomeClass
324324
// CHECK: [[MUI:%[0-9]+]] = mark_uninitialized
325325
cond_br %0, bb1, bb3
326326

@@ -335,7 +335,7 @@ bb1:
335335
strong_retain %12 : $SomeClass
336336
%14 = apply %11(%12) : $@convention(thin) (@owned SomeClass) -> ()
337337

338-
strong_release %2 : ${ var SomeClass }
338+
strong_release %2a : ${ var SomeClass }
339339
// CHECK: destroy_addr [[MUI]]
340340
// CHECK-NEXT: dealloc_stack [[STACK]]
341341
br bb2
@@ -347,7 +347,7 @@ bb2:
347347
return %17 : $()
348348

349349
bb3:
350-
strong_release %2 : ${ var SomeClass }
350+
strong_release %2a : ${ var SomeClass }
351351
// CHECK: destroy_addr [[MUI]]
352352
// CHECK-NEXT: dealloc_stack [[STACK]]
353353
br bb2
@@ -715,8 +715,8 @@ sil hidden @try_apply_during_chaining_init : $@convention(method) (Int, @owned T
715715
// %1 // user: %7
716716
bb0(%0 : $Int, %1 : $ThrowDerivedClass):
717717
%2 = alloc_box ${ var ThrowDerivedClass }, let, name "self"
718-
%3 = project_box %2 : ${ var ThrowDerivedClass }, 0
719-
%4 = mark_uninitialized [delegatingself] %3 : $*ThrowDerivedClass
718+
%3 = mark_uninitialized [delegatingself] %2 : ${ var ThrowDerivedClass }
719+
%4 = project_box %3 : ${ var ThrowDerivedClass }, 0
720720
store %1 to %4 : $*ThrowDerivedClass
721721
%8 = load %4 : $*ThrowDerivedClass
722722
%9 = function_ref @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error)
@@ -732,7 +732,7 @@ bb2(%14 : $ThrowDerivedClass): // Preds: bb1
732732
store %14 to %4 : $*ThrowDerivedClass
733733
%16 = load %4 : $*ThrowDerivedClass
734734
strong_retain %16 : $ThrowDerivedClass
735-
strong_release %2 : ${ var ThrowDerivedClass }
735+
strong_release %3 : ${ var ThrowDerivedClass }
736736
return %16 : $ThrowDerivedClass
737737

738738
// %20 // user: %22
@@ -746,7 +746,7 @@ bb4(%23 : $Error): // Preds: bb1
746746

747747
// %25 // user: %27
748748
bb5(%25 : $Error): // Preds: bb4 bb3
749-
strong_release %2 : ${ var ThrowDerivedClass }
749+
strong_release %3 : ${ var ThrowDerivedClass }
750750
throw %25 : $Error
751751
}
752752

@@ -1029,4 +1029,3 @@ bb3:
10291029
unreachable
10301030

10311031
}
1032-

test/SILOptimizer/allocbox_to_stack_ownership.sil

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ bb0:
6969
sil @multi_destroy_value : $@convention(thin) () -> Int {
7070
bb0:
7171
%1 = alloc_box ${ var Int }
72-
%1a = project_box %1 : ${ var Int }, 0
73-
%2 = mark_uninitialized [rootself] %1a : $*Int
72+
%1a = mark_uninitialized [rootself] %1 : ${ var Int }
73+
%2 = project_box %1a : ${ var Int }, 0
7474
%3 = load [trivial] %2 : $*Int
75-
%x = copy_value %1 : ${ var Int }
76-
destroy_value %1 : ${ var Int }
75+
%x = copy_value %1a : ${ var Int }
76+
destroy_value %1a : ${ var Int }
7777
br bb1
7878

7979
bb1:
@@ -314,9 +314,9 @@ extension Int : My_Incrementable { }
314314
sil @test_mui : $@convention(thin) (Builtin.Int1) -> () {
315315
bb0(%0 : @trivial $Builtin.Int1):
316316
%2 = alloc_box ${ var SomeClass }
317-
%2a = project_box %2 : ${ var SomeClass }, 0
317+
%2a = mark_uninitialized [var] %2 : ${ var SomeClass }
318+
%3 = project_box %2a : ${ var SomeClass }, 0
318319
// CHECK: [[STACK:%[0-9]+]] = alloc_stack
319-
%3 = mark_uninitialized [var] %2a : $*SomeClass
320320
// CHECK: [[MUI:%[0-9]+]] = mark_uninitialized
321321
cond_br %0, bb1, bb3
322322

@@ -330,7 +330,7 @@ bb1:
330330
%12 = load [copy] %3 : $*SomeClass
331331
%14 = apply %11(%12) : $@convention(thin) (@owned SomeClass) -> ()
332332

333-
destroy_value %2 : ${ var SomeClass }
333+
destroy_value %2a : ${ var SomeClass }
334334
// CHECK: destroy_addr [[MUI]]
335335
// CHECK-NEXT: dealloc_stack [[STACK]]
336336
br bb2
@@ -342,7 +342,7 @@ bb2:
342342
return %17 : $()
343343

344344
bb3:
345-
destroy_value %2 : ${ var SomeClass }
345+
destroy_value %2a : ${ var SomeClass }
346346
// CHECK: destroy_addr [[MUI]]
347347
// CHECK-NEXT: dealloc_stack [[STACK]]
348348
br bb2
@@ -711,8 +711,8 @@ sil hidden @try_apply_during_chaining_init : $@convention(method) (Int, @owned T
711711
// %1 // user: %7
712712
bb0(%0 : @trivial $Int, %1 : @owned $ThrowDerivedClass):
713713
%2 = alloc_box ${ var ThrowDerivedClass }, let, name "self"
714-
%3 = project_box %2 : ${ var ThrowDerivedClass }, 0
715-
%4 = mark_uninitialized [delegatingself] %3 : $*ThrowDerivedClass
714+
%3 = mark_uninitialized [delegatingself] %2 : ${ var ThrowDerivedClass }
715+
%4 = project_box %3 : ${ var ThrowDerivedClass }, 0
716716
store %1 to [init] %4 : $*ThrowDerivedClass
717717
%8 = load [take] %4 : $*ThrowDerivedClass
718718
%9 = function_ref @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error)
@@ -727,7 +727,7 @@ bb1(%12 : @trivial $Int): // Preds: bb0
727727
bb2(%14 : @owned $ThrowDerivedClass): // Preds: bb1
728728
store %14 to [init] %4 : $*ThrowDerivedClass
729729
%16 = load [copy] %4 : $*ThrowDerivedClass
730-
destroy_value %2 : ${ var ThrowDerivedClass }
730+
destroy_value %3 : ${ var ThrowDerivedClass }
731731
return %16 : $ThrowDerivedClass
732732

733733
// %20 // user: %22
@@ -741,7 +741,7 @@ bb4(%23 : @owned $Error): // Preds: bb1
741741

742742
// %25 // user: %27
743743
bb5(%25 : @owned $Error): // Preds: bb4 bb3
744-
destroy_value %2 : ${ var ThrowDerivedClass }
744+
destroy_value %3 : ${ var ThrowDerivedClass }
745745
throw %25 : $Error
746746
}
747747

0 commit comments

Comments
 (0)