Skip to content

Commit 6ac8553

Browse files
authored
Merge pull request #18457 from atrick/fix-unexpected-box-use
2 parents 3121af2 + 2c74a01 commit 6ac8553

File tree

2 files changed

+52
-85
lines changed

2 files changed

+52
-85
lines changed

lib/SILOptimizer/Transforms/AllocBoxToStack.cpp

Lines changed: 21 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -63,70 +63,6 @@ static bool useCaptured(Operand *UI) {
6363
return true;
6464
}
6565

66-
/// Given an apply or partial_apply, return the direct callee or
67-
/// nullptr if this is not a direct call.
68-
static FunctionRefInst *getDirectCallee(SILInstruction *Call) {
69-
if (auto *Apply = dyn_cast<ApplyInst>(Call))
70-
return dyn_cast<FunctionRefInst>(Apply->getCallee());
71-
else
72-
return dyn_cast<FunctionRefInst>(cast<PartialApplyInst>(Call)->getCallee());
73-
}
74-
75-
/// Given an operand of a direct apply or partial_apply of a function,
76-
/// return the argument index of the parameter used in the body of the function
77-
/// to represent this operand.
78-
static size_t getArgIndexForOperand(Operand *O) {
79-
assert(isa<ApplyInst>(O->getUser())
80-
|| isa<PartialApplyInst>(O->getUser())
81-
&& "Expected apply or partial_apply!");
82-
83-
auto OperandIndex = O->getOperandNumber();
84-
assert(OperandIndex != 0 && "Operand cannot be the applied function!");
85-
86-
// The applied function is the first operand.
87-
auto ArgIndex = OperandIndex - ApplyInst::getArgumentOperandNumber();
88-
89-
if (auto *Apply = dyn_cast<ApplyInst>(O->getUser())) {
90-
assert(Apply->getSubstCalleeConv().getNumSILArguments()
91-
== Apply->getArguments().size()
92-
&& "Expected all arguments to be supplied!");
93-
(void)Apply;
94-
} else {
95-
auto *PartialApply = cast<PartialApplyInst>(O->getUser());
96-
auto fnConv = PartialApply->getSubstCalleeConv();
97-
auto ArgCount = PartialApply->getArguments().size();
98-
assert(ArgCount <= fnConv.getNumParameters());
99-
ArgIndex += (fnConv.getNumSILArguments() - ArgCount);
100-
}
101-
102-
return ArgIndex;
103-
}
104-
105-
/// Given an operand of a direct apply or partial_apply of a function,
106-
/// return the parameter used in the body of the function to represent
107-
/// this operand.
108-
static SILArgument *getParameterForOperand(SILFunction *F, Operand *O) {
109-
assert(F && !F->empty() && "Expected a function with a body!");
110-
111-
auto &Entry = F->front();
112-
size_t ArgIndex = getArgIndexForOperand(O);
113-
assert(ArgIndex >= F->getConventions().getSILArgIndexOfFirstParam());
114-
115-
return Entry.getArgument(ArgIndex);
116-
}
117-
118-
/// Return a pointer to the SILFunction called by Call if we can
119-
/// determine which function that is, and we have a body for that
120-
/// function. Otherwise return nullptr.
121-
static SILFunction *getFunctionBody(SILInstruction *Call) {
122-
if (auto *FRI = getDirectCallee(Call))
123-
if (auto *F = FRI->getReferencedFunction())
124-
if (!F->empty())
125-
return F;
126-
127-
return nullptr;
128-
}
129-
13066
//===----------------------------------------------------------------------===//
13167
// Liveness for alloc_box Promotion
13268
//===----------------------------------------------------------------------===//
@@ -269,16 +205,16 @@ static bool partialApplyEscapes(SILValue V, bool examineApply);
269205

270206
/// Could this operand to an apply escape that function by being
271207
/// stored or returned?
272-
static bool partialApplyArgumentEscapes(Operand *O) {
273-
SILFunction *F = getFunctionBody(O->getUser());
208+
static bool applyArgumentEscapes(FullApplySite Apply, Operand *O) {
209+
SILFunction *F = Apply.getReferencedFunction();
274210
// If we cannot examine the function body, assume the worst.
275-
if (!F)
211+
if (!F || F->empty())
276212
return true;
277213

278214
// Check the uses of the operand, but do not recurse down into other
279215
// apply instructions.
280-
auto Param = SILValue(getParameterForOperand(F, O));
281-
return partialApplyEscapes(Param, /* examineApply = */ false);
216+
auto calleeArg = F->getArgument(Apply.getCalleeArgIndex(*O));
217+
return partialApplyEscapes(calleeArg, /* examineApply = */ false);
282218
}
283219

284220
static bool partialApplyEscapes(SILValue V, bool examineApply) {
@@ -301,9 +237,7 @@ static bool partialApplyEscapes(SILValue V, bool examineApply) {
301237
continue;
302238
}
303239

304-
if (auto AI = dyn_cast<ApplyInst>(User)) {
305-
ApplySite Apply(AI);
306-
240+
if (auto Apply = FullApplySite::isa(User)) {
307241
// Applying a function does not cause the function to escape.
308242
if (!Apply.isArgumentOperand(*Op))
309243
continue;
@@ -315,7 +249,7 @@ static bool partialApplyEscapes(SILValue V, bool examineApply) {
315249

316250
// Optionally drill down into an apply to see if the operand is
317251
// captured in or returned from the apply.
318-
if (examineApply && !partialApplyArgumentEscapes(Op))
252+
if (examineApply && !applyArgumentEscapes(Apply, Op))
319253
continue;
320254
}
321255

@@ -349,16 +283,16 @@ static SILInstruction *findUnexpectedBoxUse(SILValue Box,
349283
/// disqualify it from being promoted to a stack location. Return
350284
/// true if this partial apply will not block our promoting the box.
351285
static bool checkPartialApplyBody(Operand *O) {
352-
SILFunction *F = getFunctionBody(O->getUser());
286+
SILFunction *F = ApplySite(O->getUser()).getReferencedFunction();
353287
// If we cannot examine the function body, assume the worst.
354-
if (!F)
288+
if (!F || F->empty())
355289
return false;
356290

357291
// We don't actually use these because we're not recursively
358292
// rewriting the partial applies we find.
359293
llvm::SmallVector<Operand *, 1> PromotedOperands;
360-
auto Param = SILValue(getParameterForOperand(F, O));
361-
return !findUnexpectedBoxUse(Param, /* examinePartialApply = */ false,
294+
auto calleeArg = F->getArgument(ApplySite(O->getUser()).getCalleeArgIndex(*O));
295+
return !findUnexpectedBoxUse(calleeArg, /* examinePartialApply = */ false,
362296
/* inAppliedFunction = */ true,
363297
PromotedOperands);
364298
}
@@ -802,7 +736,7 @@ void PromotedParamCloner::visitProjectBoxInst(ProjectBoxInst *Inst) {
802736
/// references.
803737
static PartialApplyInst *
804738
specializePartialApply(PartialApplyInst *PartialApply,
805-
ArgIndexList &PromotedArgIndices,
739+
ArgIndexList &PromotedCalleeArgIndices,
806740
AllocBoxToStackState &pass) {
807741
auto *FRI = cast<FunctionRefInst>(PartialApply->getCallee());
808742
assert(FRI && "Expected a direct partial_apply!");
@@ -813,7 +747,8 @@ specializePartialApply(PartialApplyInst *PartialApply,
813747
if (PartialApply->getFunction()->isSerialized())
814748
Serialized = IsSerializable;
815749

816-
std::string ClonedName = getClonedName(F, Serialized, PromotedArgIndices);
750+
std::string ClonedName =
751+
getClonedName(F, Serialized, PromotedCalleeArgIndices);
817752

818753
auto &M = PartialApply->getModule();
819754

@@ -823,7 +758,8 @@ specializePartialApply(PartialApplyInst *PartialApply,
823758
ClonedFn = PrevFn;
824759
} else {
825760
// Clone the function the existing partial_apply references.
826-
PromotedParamCloner Cloner(F, Serialized, PromotedArgIndices, ClonedName);
761+
PromotedParamCloner Cloner(F, Serialized, PromotedCalleeArgIndices,
762+
ClonedName);
827763
Cloner.populateCloned();
828764
ClonedFn = Cloner.getCloned();
829765
pass.T->notifyAddFunction(ClonedFn, F);
@@ -836,8 +772,8 @@ specializePartialApply(PartialApplyInst *PartialApply,
836772

837773
// Promote the arguments that need promotion.
838774
for (auto &O : PartialApply->getArgumentOperands()) {
839-
auto ArgIndex = getArgIndexForOperand(&O);
840-
if (!count(PromotedArgIndices, ArgIndex)) {
775+
auto CalleeArgIndex = ApplySite(O.getUser()).getCalleeArgIndex(O);
776+
if (!count(PromotedCalleeArgIndices, CalleeArgIndex)) {
841777
Args.push_back(O.get());
842778
continue;
843779
}
@@ -886,18 +822,18 @@ static void rewritePartialApplies(AllocBoxToStackState &pass) {
886822
// Build a map from partial_apply to the indices of the operands
887823
// that will be promoted in our rewritten version.
888824
for (auto *O : pass.PromotedOperands) {
889-
auto ArgIndexNumber = getArgIndexForOperand(O);
825+
auto CalleeArgIndexNumber = ApplySite(O->getUser()).getCalleeArgIndex(*O);
890826

891827
Indices.clear();
892-
Indices.push_back(ArgIndexNumber);
828+
Indices.push_back(CalleeArgIndexNumber);
893829

894830
auto *PartialApply = cast<PartialApplyInst>(O->getUser());
895831
llvm::DenseMap<PartialApplyInst *, ArgIndexList>::iterator It;
896832
bool Inserted;
897833
std::tie(It, Inserted) = IndexMap.insert(std::make_pair(PartialApply,
898834
Indices));
899835
if (!Inserted)
900-
It->second.push_back(ArgIndexNumber);
836+
It->second.push_back(CalleeArgIndexNumber);
901837
}
902838

903839
// Clone the referenced function of each partial_apply, removing the

test/SILOptimizer/allocbox_to_stack.sil

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,3 +1029,34 @@ bb3:
10291029
unreachable
10301030

10311031
}
1032+
1033+
// Verify the case in which a box used by a partial apply which is then used by a try_apply.
1034+
//
1035+
// <rdar://problem/42815224> Swift CI: 2. Swift Source Compatibility Suite (master): Kitura project fails with compiler crash
1036+
// CHECK-LABEL: sil @testPAUsedByTryApplyClosure : $@convention(thin) (@guaranteed { var Int }) -> () {
1037+
// CHECK-LABEL: } // end sil function 'testPAUsedByTryApplyClosure'
1038+
sil @testPAUsedByTryApplyClosure : $@convention(thin) (@guaranteed { var Int }) -> () {
1039+
bb0(%0: ${ var Int }):
1040+
%v = tuple ()
1041+
return %v : $()
1042+
}
1043+
1044+
// CHECK-LABEL: sil private @testPAUsedByTryApply : $@convention(method) (@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error Error) -> () {
1045+
// CHECK-LABEL: } // end sil function 'testPAUsedByTryApply'
1046+
sil private @testPAUsedByTryApply : $@convention(method) (@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error Error) -> () {
1047+
bb0(%0: $@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error Error):
1048+
%box = alloc_box ${ var Int }, var
1049+
%closure = function_ref @testPAUsedByTryApplyClosure : $@convention(thin) (@guaranteed { var Int }) -> ()
1050+
%pa = partial_apply [callee_guaranteed] %closure(%box) : $@convention(thin) (@guaranteed { var Int }) -> ()
1051+
try_apply %0(%pa) : $@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error Error, normal bb2, error bb3
1052+
1053+
bb2(%result : $()):
1054+
br bb4
1055+
1056+
bb3(%error : $Error):
1057+
br bb4
1058+
1059+
bb4:
1060+
%v = tuple ()
1061+
return %v : $()
1062+
}

0 commit comments

Comments
 (0)