@@ -213,6 +213,8 @@ class SILPerformanceInliner {
213
213
214
214
bool isAutoDiffLinearMapWithControlFlow (FullApplySite AI);
215
215
216
+ bool isTupleWithAllocsOrPartialApplies (SILValue retVal);
217
+
216
218
bool isProfitableToInline (
217
219
FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
218
220
int &NumCallerBlocks,
@@ -319,14 +321,8 @@ bool SILPerformanceInliner::isAutoDiffLinearMapWithControlFlow(
319
321
// Extract a member from a struct/tuple/enum.
320
322
val = pi->getOperand (0 );
321
323
continue ;
322
- } else if (auto ti = dyn_cast<ThinToThickFunctionInst>(inst)) {
323
- val = ti->getOperand ();
324
- continue ;
325
- } else if (auto cfi = dyn_cast<ConvertFunctionInst>(inst)) {
326
- val = cfi->getOperand ();
327
- continue ;
328
- } else if (auto cvt = dyn_cast<ConvertEscapeToNoEscapeInst>(inst)) {
329
- val = cvt->getOperand ();
324
+ } else if (auto base = stripFunctionConversions (inst)) {
325
+ val = base;
330
326
continue ;
331
327
}
332
328
return false ;
@@ -367,6 +363,29 @@ bool SILPerformanceInliner::isAutoDiffLinearMapWithControlFlow(
367
363
return false ;
368
364
}
369
365
366
+ // Checks if the given value is a tuple containing allocated objects
367
+ // or partial applies.
368
+ //
369
+ // Returns true if the number of allocated objects or partial applies is
370
+ // greater than 0, and false otherwise.
371
+ //
372
+ // Returns false if the value is not a tuple.
373
+ bool SILPerformanceInliner::isTupleWithAllocsOrPartialApplies (SILValue val) {
374
+ if (auto *ti = dyn_cast<TupleInst>(val)) {
375
+ for (auto i : range (ti->getNumOperands ())) {
376
+ SILValue val = ti->getOperand (i);
377
+
378
+ if (auto base = stripFunctionConversions (val))
379
+ val = base;
380
+
381
+ if (isa<AllocationInst>(val) || isa<PartialApplyInst>(val))
382
+ return true ;
383
+ }
384
+ }
385
+
386
+ return false ;
387
+ }
388
+
370
389
bool SILPerformanceInliner::isProfitableToInline (
371
390
FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
372
391
int &NumCallerBlocks,
@@ -483,6 +502,9 @@ bool SILPerformanceInliner::isProfitableToInline(
483
502
if (def && (isa<FunctionRefInst>(def) || isa<PartialApplyInst>(def)))
484
503
BlockW.updateBenefit (Benefit, RemovedClosureBenefit);
485
504
else if (isAutoDiffLinearMapWithControlFlow (FAI)) {
505
+ // TODO: Do we need to tweak inlining benefits given to pullbacks
506
+ // (with and without control-flow)?
507
+
486
508
// For linear maps in Swift Autodiff, callees may be passed as an
487
509
// argument, however, they may be hidden behind a branch-tracing
488
510
// enum (tracing execution flow of the original function).
@@ -587,7 +609,7 @@ bool SILPerformanceInliner::isProfitableToInline(
587
609
// Inlining functions which return an allocated object or partial_apply
588
610
// most likely has a benefit in the caller, because e.g. it can enable
589
611
// de-virtualization.
590
- if (isa<AllocationInst>(retVal) || isa<PartialApplyInst>(retVal)) {
612
+ if (isa<AllocationInst>(retVal) || isa<PartialApplyInst>(retVal) || isTupleWithAllocsOrPartialApplies (retVal) ) {
591
613
BlockW.updateBenefit (Benefit, RemovedCallBenefit + 10 );
592
614
returnsAllocation = true ;
593
615
}
0 commit comments