@@ -213,6 +213,8 @@ class SILPerformanceInliner {
213213
214214 bool isAutoDiffLinearMapWithControlFlow (FullApplySite AI);
215215
216+ bool isTupleWithAllocsOrPartialApplies (SILValue retVal);
217+
216218 bool isProfitableToInline (
217219 FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
218220 int &NumCallerBlocks,
@@ -319,14 +321,8 @@ bool SILPerformanceInliner::isAutoDiffLinearMapWithControlFlow(
319321 // Extract a member from a struct/tuple/enum.
320322 val = pi->getOperand (0 );
321323 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;
330326 continue ;
331327 }
332328 return false ;
@@ -367,6 +363,29 @@ bool SILPerformanceInliner::isAutoDiffLinearMapWithControlFlow(
367363 return false ;
368364}
369365
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+
370389bool SILPerformanceInliner::isProfitableToInline (
371390 FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
372391 int &NumCallerBlocks,
@@ -483,6 +502,9 @@ bool SILPerformanceInliner::isProfitableToInline(
483502 if (def && (isa<FunctionRefInst>(def) || isa<PartialApplyInst>(def)))
484503 BlockW.updateBenefit (Benefit, RemovedClosureBenefit);
485504 else if (isAutoDiffLinearMapWithControlFlow (FAI)) {
505+ // TODO: Do we need to tweak inlining benefits given to pullbacks
506+ // (with and without control-flow)?
507+
486508 // For linear maps in Swift Autodiff, callees may be passed as an
487509 // argument, however, they may be hidden behind a branch-tracing
488510 // enum (tracing execution flow of the original function).
@@ -587,7 +609,7 @@ bool SILPerformanceInliner::isProfitableToInline(
587609 // Inlining functions which return an allocated object or partial_apply
588610 // most likely has a benefit in the caller, because e.g. it can enable
589611 // de-virtualization.
590- if (isa<AllocationInst>(retVal) || isa<PartialApplyInst>(retVal)) {
612+ if (isa<AllocationInst>(retVal) || isa<PartialApplyInst>(retVal) || isTupleWithAllocsOrPartialApplies (retVal) ) {
591613 BlockW.updateBenefit (Benefit, RemovedCallBenefit + 10 );
592614 returnsAllocation = true ;
593615 }
0 commit comments