@@ -35,9 +35,13 @@ using namespace swift;
35
35
36
36
STATISTIC (NumStackPromoted, " Number of alloc_box's promoted to the stack" );
37
37
38
+ // MaxLocalApplyRecurDepth limits the recursive analysis depth while
39
+ // checking if a box can be promoted to stack. This is currently set to 4, a
40
+ // limit assumed to be sufficient to handle typical call chain of local
41
+ // functions through which a box can be passed.
38
42
static llvm::cl::opt<unsigned > MaxLocalApplyRecurDepth (
39
43
" max-local-apply-recur-depth" , llvm::cl::init(4 ),
40
- llvm::cl::desc(" Mac recursove depth for analyzing local functions" ));
44
+ llvm::cl::desc(" Max recursive depth for analyzing local functions" ));
41
45
42
46
// ===-----------------------------------------------------------------------===//
43
47
// SIL Utilities for alloc_box Promotion
@@ -280,7 +284,7 @@ static bool partialApplyEscapes(SILValue V, bool examineApply) {
280
284
return false ;
281
285
}
282
286
283
- static SILInstruction *findUnexpectedBoxUse (SILValue Box,
287
+ static SILInstruction *findUnexpectedBoxUseInDFSOrder (SILValue Box,
284
288
bool inAppliedFunction,
285
289
SmallVectorImpl<Operand *> &,
286
290
SmallPtrSetImpl<SILFunction *> &,
@@ -299,22 +303,24 @@ static bool checkLocalApplyBody(Operand *O,
299
303
if (!F || F->empty ())
300
304
return false ;
301
305
306
+ // Since this function can be called recursively while analyzing the same box,
307
+ // mark the callee as visited, so that we don't end up in a recursive cycle.
302
308
auto iter = VisitedCallees.insert (F);
303
309
if (!iter.second )
304
310
return false ;
305
311
306
312
auto calleeArg = F->getArgument (ApplySite (O->getUser ()).getCalleeArgIndex (*O));
307
- auto res =
308
- ! findUnexpectedBoxUse (calleeArg ,
309
- /* inAppliedFunction = */ true , PromotedOperands,
310
- VisitedCallees, CurrentRecurDepth + 1 );
313
+ auto res = ! findUnexpectedBoxUseInDFSOrder (calleeArg,
314
+ /* inAppliedFunction = */ true ,
315
+ PromotedOperands, VisitedCallees ,
316
+ CurrentRecurDepth + 1 );
311
317
return res;
312
318
}
313
319
314
320
// Returns true if a callee is eligible to be cloned and rewritten for
315
321
// AllocBoxToStack opt. We don't want to increase code size, so this is
316
322
// restricted only for private local functions currently.
317
- static bool isEligibleApply (ApplySite Apply) {
323
+ static bool isOptimizableApplySite (ApplySite Apply) {
318
324
auto callee = Apply.getReferencedFunctionOrNull ();
319
325
if (!callee) {
320
326
return false ;
@@ -332,21 +338,24 @@ static bool isEligibleApply(ApplySite Apply) {
332
338
if (callee->getInlineStrategy () == Inline_t::AlwaysInline)
333
339
return false ;
334
340
335
- if (callee->getLinkage () != SILLinkage::Private) {
341
+ if (callee->getLinkage () != SILLinkage::Private)
336
342
return false ;
337
- }
343
+
338
344
return true ;
339
345
}
340
346
341
347
// / Validate that the uses of a pointer to a box do not eliminate it from
342
- // / consideration for promotion to a stack element. Optionally examine the body
343
- // / of an ApplySite to see if there is an unexpected use inside.
344
- // / Return the instruction with the unexpected use if we find one.
348
+ // / consideration for promotion to a stack element. Return the instruction with
349
+ // / the unexpected use if we find one.
350
+ // / If a box has ApplySite users, we recursively examine the callees to check
351
+ // / for unexpected use of the box argument. If all the callees through which the
352
+ // / box is passed don't have any unexpected uses, `PromotedOperands` will be
353
+ // / populated with the box arguments in DFS order.
345
354
static SILInstruction *
346
- findUnexpectedBoxUse (SILValue Box, bool inAppliedFunction,
347
- SmallVectorImpl<Operand *> &PromotedOperands,
348
- SmallPtrSetImpl<SILFunction *> &VisitedCallees,
349
- unsigned CurrentRecurDepth = 0 ) {
355
+ findUnexpectedBoxUseInDFSOrder (SILValue Box, bool inAppliedFunction,
356
+ SmallVectorImpl<Operand *> &PromotedOperands,
357
+ SmallPtrSetImpl<SILFunction *> &VisitedCallees,
358
+ unsigned CurrentRecurDepth = 0 ) {
350
359
assert ((Box->getType ().is <SILBoxType>()
351
360
|| Box->getType ()
352
361
== SILType::getNativeObjectType (Box->getType ().getASTContext ()))
@@ -396,7 +405,7 @@ findUnexpectedBoxUse(SILValue Box, bool inAppliedFunction,
396
405
case ApplySiteKind::ApplyInst:
397
406
case ApplySiteKind::BeginApplyInst:
398
407
case ApplySiteKind::TryApplyInst:
399
- if (isEligibleApply (Apply) &&
408
+ if (isOptimizableApplySite (Apply) &&
400
409
checkLocalApplyBody (Op, LocalPromotedOperands, VisitedCallees,
401
410
CurrentRecurDepth)) {
402
411
LocalPromotedOperands.push_back (Op);
@@ -425,10 +434,10 @@ static bool canPromoteAllocBox(AllocBoxInst *ABI,
425
434
SmallPtrSet<SILFunction *, 8 > VisitedCallees;
426
435
// Scan all of the uses of the address of the box to see if any
427
436
// disqualifies the box from being promoted to the stack.
428
- if (auto *User = findUnexpectedBoxUse (ABI,
429
- /* inAppliedFunction = */ false ,
430
- PromotedOperands, VisitedCallees,
431
- /* CurrentRecurDepth = */ 0 )) {
437
+ if (auto *User = findUnexpectedBoxUseInDFSOrder (
438
+ ABI ,
439
+ /* inAppliedFunction = */ false , PromotedOperands, VisitedCallees,
440
+ /* CurrentRecurDepth = */ 0 )) {
432
441
(void )User;
433
442
// Otherwise, we have an unexpected use.
434
443
LLVM_DEBUG (llvm::dbgs () << " *** Failed to promote alloc_box in @"
@@ -828,8 +837,10 @@ void PromotedParamCloner::visitProjectBoxInst(ProjectBoxInst *Inst) {
828
837
829
838
// While cloning during specialization, make sure apply instructions do not have
830
839
// box arguments that need to be promoted.
831
- // This is an assertion in debug builds only. This should never be true because
832
- // we process apply callees that take promotable boxes in dfs order
840
+ // This is an assertion in debug builds only. The reason why this should never
841
+ // be true is that we have cloned our callees in DFS order meaning that any of
842
+ // our callees that had a promotable box will have already have been promoted
843
+ // away by the time this runs.
833
844
void PromotedParamCloner::checkNoPromotedBoxInApply (ApplySite Apply) {
834
845
#ifndef NDEBUG
835
846
for (auto &O : Apply.getArgumentOperands ()) {
@@ -857,10 +868,10 @@ void PromotedParamCloner::visitTryApplyInst(TryApplyInst *Inst) {
857
868
// / Specialize ApplySite by promoting the parameters indicated by
858
869
// / indices. We expect these parameters to be replaced by stack address
859
870
// / references.
860
- static SILInstruction *specializeApply (SILOptFunctionBuilder &FuncBuilder,
861
- ApplySite Apply,
862
- ArgIndexList &PromotedCalleeArgIndices,
863
- AllocBoxToStackState &pass) {
871
+ static SILInstruction *
872
+ specializeApplySite (SILOptFunctionBuilder &FuncBuilder, ApplySite Apply,
873
+ ArgIndexList &PromotedCalleeArgIndices,
874
+ AllocBoxToStackState &pass) {
864
875
auto *FRI = cast<FunctionRefInst>(Apply.getCallee ());
865
876
assert (FRI && " Expected a direct ApplySite" );
866
877
auto *F = FRI->getReferencedFunctionOrNull ();
@@ -968,7 +979,7 @@ static SILInstruction *specializeApply(SILOptFunctionBuilder &FuncBuilder,
968
979
}
969
980
}
970
981
971
- static void rewriteApplies (AllocBoxToStackState &pass) {
982
+ static void rewriteApplySites (AllocBoxToStackState &pass) {
972
983
llvm::DenseMap<ApplySite, ArgIndexList> IndexMap;
973
984
llvm::SmallVector<ApplySite, 8 > AppliesToSpecialize;
974
985
ArgIndexList Indices;
@@ -1009,7 +1020,7 @@ static void rewriteApplies(AllocBoxToStackState &pass) {
1009
1020
// Sort the indices and unique them.
1010
1021
sortUnique (Indices);
1011
1022
1012
- auto *Replacement = specializeApply (FuncBuilder, Apply, Indices, pass);
1023
+ auto *Replacement = specializeApplySite (FuncBuilder, Apply, Indices, pass);
1013
1024
assert (Apply.getKind () == ApplySite (Replacement).getKind ());
1014
1025
Apply.getInstruction ()->replaceAllUsesPairwiseWith (Replacement);
1015
1026
@@ -1027,7 +1038,7 @@ static void rewriteApplies(AllocBoxToStackState &pass) {
1027
1038
static unsigned rewritePromotedBoxes (AllocBoxToStackState &pass) {
1028
1039
// First we'll rewrite any ApplySite that we can to remove
1029
1040
// the box container pointer from the operands.
1030
- rewriteApplies (pass);
1041
+ rewriteApplySites (pass);
1031
1042
1032
1043
unsigned Count = 0 ;
1033
1044
auto rend = pass.Promotable .rend ();
0 commit comments