Skip to content

Commit dc65f70

Browse files
committed
Do not inline self-recursive functions into other functions.
Because our optimization pipeline runs the inliner multiple times, inlining self-recursive functions into other functions can result in substantial code growth, which results in more code being generated, and more compile time. This was exposed by other changes I have to remove call graph updating from the inliner (which should have resulted in NFC but didn't due to implicit deserialization).
1 parent a78567a commit dc65f70

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

lib/SILPasses/IPO/PerformanceInliner.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,16 @@ bool SILPerformanceInliner::hasInliningCycle(SILFunction *Caller,
542542
return InlinedBefore;
543543
}
544544

545+
546+
static bool calleeIsSelfRecursive(SILFunction *Callee) {
547+
for (auto &BB : *Callee)
548+
for (auto &I : BB)
549+
if (auto Apply = FullApplySite::isa(&I))
550+
if (Apply.getCalleeFunction() == Callee)
551+
return true;
552+
return false;
553+
}
554+
545555
// Returns the callee of an apply_inst if it is basically inlinable.
546556
SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
547557

@@ -624,6 +634,16 @@ SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
624634
Callee->getName() << ".\n");
625635
return nullptr;
626636
}
637+
638+
// Inlining self-recursive functions into other functions can result
639+
// in excessive code duplication since we run the inliner multiple
640+
// times in our pipeline.
641+
if (calleeIsSelfRecursive(Callee)) {
642+
DEBUG(llvm::dbgs() << " FAIL: Callee is self-recursive in " <<
643+
Callee->getName() << ".\n");
644+
return nullptr;
645+
}
646+
627647
DEBUG(llvm::dbgs() << " Eligible callee: " <<
628648
Callee->getName() << "\n");
629649

test/SILPasses/inline_recursive.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@ private func recFunc(x: Int) -> Int {
77
return 0
88
}
99

10-
//CHECK-LABEL: sil {{.*}}callit
11-
// CHECK: bb0:
12-
// CHECK-NEXT: integer_literal {{.*}}, 0
13-
// CHECK-NEXT: struct
14-
// CHECK-NEXT: return
10+
// Ensure that we do not inline self-recursive functions into other
11+
// functions since doing so can result in large code growth if we run
12+
// the inlining pass multiple times.
1513

14+
// CHECK-LABEL: sil hidden @_TF16inline_recursive6callitFT_Si
15+
// CHECK: bb0:
16+
// CHECK: [[FN:%.*]] = function_ref @_TF16inline_recursiveP33_38E63D320CFF538A1F98BBC31453B1EB7recFuncFSiSi
17+
// CHECK: [[BUILTIN_INT:%.*]] = integer_literal $Builtin.Int64, 3
18+
// CHECK: [[INT:%.*]] = struct $Int ([[BUILTIN_INT]] : $Builtin.Int64)
19+
// CHECK: [[APPLY:%.*]] = apply [[FN]]([[INT]])
20+
// CHECK: return [[APPLY]]
1621
func callit() -> Int {
1722
return recFunc(3)
1823
}
19-

0 commit comments

Comments
 (0)