Skip to content

Commit 9d6e6dc

Browse files
committed
[semantic-sil] Update capture promotion for moving mark_uninitialized onto alloc_box instead of project_box and move the fixup pass behind it.
rdar://31521023
1 parent aa76c2a commit 9d6e6dc

File tree

3 files changed

+27
-56
lines changed

3 files changed

+27
-56
lines changed

lib/SILOptimizer/IPO/CapturePromotion.cpp

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -991,18 +991,7 @@ static bool isProjectBoxNonEscapingUse(ProjectBoxInst *PBI,
991991
EscapeMutationScanningState &State) {
992992
DEBUG(llvm::dbgs() << " Found project box: " << *PBI);
993993

994-
// Check for mutations of the address component.
995-
SILValue Addr = PBI;
996-
997-
// If the AllocBox is used by a mark_uninitialized, scan the MUI for
998-
// interesting uses.
999-
if (Addr->hasOneUse()) {
1000-
SILInstruction *SingleAddrUser = Addr->use_begin()->getUser();
1001-
if (isa<MarkUninitializedInst>(SingleAddrUser))
1002-
Addr = SILValue(SingleAddrUser);
1003-
}
1004-
1005-
for (Operand *AddrOp : Addr->getUses()) {
994+
for (Operand *AddrOp : PBI->getUses()) {
1006995
if (!isNonEscapingUse(AddrOp, State)) {
1007996
DEBUG(llvm::dbgs() << " FAIL! Has escaping user of addr:"
1008997
<< *AddrOp->getUser());
@@ -1015,11 +1004,13 @@ static bool isProjectBoxNonEscapingUse(ProjectBoxInst *PBI,
10151004

10161005
static bool scanUsesForEscapesAndMutations(Operand *Op,
10171006
EscapeMutationScanningState &State) {
1018-
if (auto *PAI = dyn_cast<PartialApplyInst>(Op->getUser())) {
1007+
SILInstruction *User = Op->getUser();
1008+
1009+
if (auto *PAI = dyn_cast<PartialApplyInst>(User)) {
10191010
return isPartialApplyNonEscapingUser(Op, PAI, State);
10201011
}
10211012

1022-
if (auto *PBI = dyn_cast<ProjectBoxInst>(Op->getUser())) {
1013+
if (auto *PBI = dyn_cast<ProjectBoxInst>(User)) {
10231014
// It is assumed in later code that we will only have 1 project_box. This
10241015
// can be seen since there is no code for reasoning about multiple
10251016
// boxes. Just put in the restriction so we are consistent.
@@ -1029,20 +1020,16 @@ static bool scanUsesForEscapesAndMutations(Operand *Op,
10291020
return isProjectBoxNonEscapingUse(PBI, State);
10301021
}
10311022

1032-
// Given a top level copy value use, check all of its user operands as if
1033-
// they were apart of the use list of the base operand.
1034-
//
1035-
// This is because even though we are copying the box, a copy of the box is
1036-
// just a retain + bitwise copy of the pointer. This has nothing to do with
1037-
// whether or not the address escapes in some way.
1023+
// Given a top level copy value use or mark_uninitialized, check all of its
1024+
// user operands as if they were apart of the use list of the base operand.
10381025
//
10391026
// This is a separate code path from the non escaping user visitor check since
10401027
// we want to be more conservative around non-top level copies (i.e. a copy
10411028
// derived from a projection like instruction). In fact such a thing may not
10421029
// even make any sense!
1043-
if (auto *CVI = dyn_cast<CopyValueInst>(Op->getUser())) {
1044-
return all_of(CVI->getUses(), [&State](Operand *CopyOp) -> bool {
1045-
return scanUsesForEscapesAndMutations(CopyOp, State);
1030+
if (isa<CopyValueInst>(User) || isa<MarkUninitializedInst>(User)) {
1031+
return all_of(User->getUses(), [&State](Operand *UserOp) -> bool {
1032+
return scanUsesForEscapesAndMutations(UserOp, State);
10461033
});
10471034
}
10481035

@@ -1171,36 +1158,18 @@ static SILValue getOrCreateProjectBoxHelper(SILValue PartialOperand) {
11711158
return B.createProjectBox(CVI->getLoc(), CVI, 0);
11721159
}
11731160

1174-
// Otherwise, handle the alloc_box case.
1175-
auto *ABI = cast<AllocBoxInst>(PartialOperand);
1176-
// Load and copy from the address value, passing the result as an argument
1177-
// to the new closure.
1178-
//
1179-
// *NOTE* This code assumes that we only have one project box user. We
1180-
// enforce this with the assert below.
1181-
assert(count_if(ABI->getUses(), [](Operand *Op) -> bool {
1182-
return isa<ProjectBoxInst>(Op->getUser());
1183-
}) == 1);
1184-
1185-
// If the address is marked uninitialized, load through the mark, so
1186-
// that DI can reason about it.
1187-
for (Operand *BoxValueUse : ABI->getUses()) {
1188-
auto *PBI = dyn_cast<ProjectBoxInst>(BoxValueUse->getUser());
1189-
if (!PBI)
1190-
continue;
1191-
1192-
auto *OptIter = PBI->getSingleUse();
1193-
if (!OptIter)
1194-
continue;
1195-
1196-
if (!isa<MarkUninitializedInst>(OptIter->getUser()))
1197-
continue;
1198-
1199-
return OptIter->getUser();
1161+
// Otherwise, handle the alloc_box case. If we have a mark_uninitialized on
1162+
// the box, we create the project value through that.
1163+
SILInstruction *Box = cast<AllocBoxInst>(PartialOperand);
1164+
if (auto *Op = Box->getSingleUse()) {
1165+
if (auto *MUI = dyn_cast<MarkUninitializedInst>(Op->getUser())) {
1166+
Box = MUI;
1167+
}
12001168
}
12011169

1202-
// Otherwise, just return a project_box.
1203-
return getOrCreateProjectBox(ABI, 0);
1170+
// Just return a project_box.
1171+
SILBuilder B(std::next(Box->getIterator()));
1172+
return B.createProjectBox(Box->getLoc(), Box, 0);
12041173
}
12051174

12061175
/// \brief Given a partial_apply instruction and a set of promotable indices,

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ static void addOwnershipModelEliminatorPipeline(SILPassPipelinePlan &P) {
7474
static void addMandatoryOptPipeline(SILPassPipelinePlan &P,
7575
const SILOptions &Options) {
7676
P.startPipeline("Guaranteed Passes");
77-
P.addMarkUninitializedFixup();
7877
if (Options.EnableMandatorySemanticARCOpts) {
7978
P.addSemanticARCOpts();
8079
}
8180
P.addDiagnoseStaticExclusivity();
8281
P.addCapturePromotion();
82+
P.addMarkUninitializedFixup();
8383
P.addAllocBoxToStack();
8484
P.addNoReturnFolding();
8585
P.addOwnershipModelEliminator();

test/SILOptimizer/capture_promotion_ownership.sil

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ sil @dummy_func : $@convention(thin) (Int, Int, Int) -> Int
3434
sil @test_capture_promotion : $@convention(thin) () -> @owned @callee_owned () -> Int {
3535
bb0:
3636
// CHECK: [[BOX1:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <Foo>
37+
// CHECK: [[MARKED_BOX1:%.*]] = mark_uninitialized [var] [[BOX1]]
3738
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <Foo>
38-
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Foo>, 0
39+
%1ab = mark_uninitialized [var] %1 : $<τ_0_0> { var τ_0_0 } <Foo>
40+
%1a = project_box %1ab : $<τ_0_0> { var τ_0_0 } <Foo>, 0
3941
%2 = function_ref @foo_allocating_init : $@convention(thin) (@thick Foo.Type) -> @owned Foo
4042
%3 = metatype $@thick Foo.Type
4143
%4 = apply %2(%3) : $@convention(thin) (@thick Foo.Type) -> @owned Foo
@@ -58,7 +60,7 @@ bb0:
5860
%15 = apply %12(%14, %13) : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
5961
store %15 to [trivial] %11a : $*Int
6062

61-
// CHECK: [[BOX1_COPY:%.*]] = copy_value [[BOX1]]
63+
// CHECK: [[BOX1_COPY:%.*]] = copy_value [[MARKED_BOX1]]
6264
// CHECK: [[BOX1_COPY_PB:%.*]] = project_box [[BOX1_COPY]]
6365
// CHECK: [[BOX2_COPY:%.*]] = copy_value [[BOX2]]
6466
// CHECK: [[BOX2_COPY_PB:%.*]] = project_box [[BOX2_COPY]]
@@ -87,14 +89,14 @@ bb0:
8789
// CHECK-NEXT: {{.*}} = partial_apply [[CLOSURE_PROMOTE]]([[LOADFOO]], [[LOADBAZ]], [[LOADINT]])
8890

8991
%17 = function_ref @closure0 : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Foo>, @owned <τ_0_0> { var τ_0_0 } <Baz>, @owned <τ_0_0> { var τ_0_0 } <Int>) -> Int
90-
%18 = copy_value %1 : $<τ_0_0> { var τ_0_0 } <Foo>
92+
%18 = copy_value %1ab : $<τ_0_0> { var τ_0_0 } <Foo>
9193
%19 = copy_value %6 : $<τ_0_0> { var τ_0_0 } <Baz>
9294
%20 = copy_value %11 : $<τ_0_0> { var τ_0_0 } <Int>
9395
%21 = partial_apply %17(%18, %19, %20) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Foo>, @owned <τ_0_0> { var τ_0_0 } <Baz>, @owned <τ_0_0> { var τ_0_0 } <Int>) -> Int
9496

9597
destroy_value %11 : $<τ_0_0> { var τ_0_0 } <Int>
9698
destroy_value %6 : $<τ_0_0> { var τ_0_0 } <Baz>
97-
destroy_value %1 : $<τ_0_0> { var τ_0_0 } <Foo>
99+
destroy_value %1ab : $<τ_0_0> { var τ_0_0 } <Foo>
98100

99101
return %21 : $@callee_owned () -> Int
100102
}

0 commit comments

Comments
 (0)