Skip to content

Commit 56b1f23

Browse files
committed
Re-apply dc65f70 with some changes.
The underlying type of Int varies depending on platform, so use Int32 explicitly in this test now since the data size is immaterial for the test. Also allow for very limited self recursion rather than none, which provides for a balance between performance and code bloat since inlining can remove overhead and expose other opportunities for optimization.
1 parent 6e3e83c commit 56b1f23

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

lib/SILPasses/IPO/PerformanceInliner.cpp

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

545+
// Return true if the callee does few (or no) self-recursive calls.
546+
static bool calleeHasMinimalSelfRecursion(SILFunction *Callee) {
547+
int countSelfRecursiveCalls = 0;
548+
549+
for (auto &BB : *Callee) {
550+
for (auto &I : BB) {
551+
if (auto Apply = FullApplySite::isa(&I)) {
552+
if (Apply.getCalleeFunction() == Callee)
553+
++countSelfRecursiveCalls;
554+
555+
if (countSelfRecursiveCalls > 2)
556+
return true;
557+
}
558+
}
559+
}
560+
561+
return false;
562+
}
563+
545564
// Returns the callee of an apply_inst if it is basically inlinable.
546565
SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
547566

@@ -624,6 +643,17 @@ SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
624643
Callee->getName() << ".\n");
625644
return nullptr;
626645
}
646+
647+
// Inlining self-recursive functions into other functions can result
648+
// in excessive code duplication since we run the inliner multiple
649+
// times in our pipeline, so we only do it for callees with few
650+
// self-recursive calls.
651+
if (calleeHasMinimalSelfRecursion(Callee)) {
652+
DEBUG(llvm::dbgs() << " FAIL: Callee is self-recursive in "
653+
<< Callee->getName() << ".\n");
654+
return nullptr;
655+
}
656+
627657
DEBUG(llvm::dbgs() << " Eligible callee: " <<
628658
Callee->getName() << "\n");
629659

test/SILPasses/inline_recursive.swift

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %target-swift-frontend -primary-file %s -parse-as-library -emit-sil -O | FileCheck %s
22

3-
private func recFunc(x: Int) -> Int {
3+
private func recFunc(x: Int32) -> Int32 {
44
if x > 0 {
55
return recFunc(x - 1)
66
}
@@ -9,11 +9,31 @@ private func recFunc(x: Int) -> Int {
99

1010
//CHECK-LABEL: sil {{.*}}callit
1111
// CHECK: bb0:
12-
// CHECK-NEXT: integer_literal {{.*}}, 0
12+
// CHECK-NEXT: integer_literal $Builtin.Int32, 0
1313
// CHECK-NEXT: struct
1414
// CHECK-NEXT: return
1515

16-
func callit() -> Int {
16+
func callit() -> Int32 {
1717
return recFunc(3)
1818
}
1919

20+
private func recFuncManyCalls(x: Int32) -> Int32 {
21+
if x > 4 {
22+
return recFuncManyCalls(x - 1)
23+
+ recFuncManyCalls(x - 2)
24+
+ recFuncManyCalls(x - 3)
25+
+ recFuncManyCalls(x - 4)
26+
+ recFuncManyCalls(x - 5)
27+
}
28+
return 0
29+
}
30+
31+
// CHECK-LABEL: sil hidden {{.*}}callother
32+
// CHECK: bb0:
33+
// CHECK: [[FN:%.*]] = function_ref {{.*}}recFuncManyCalls
34+
// CHECK: [[APPLY:%.*]] = apply [[FN]]
35+
// CHECK-NOT: apply
36+
// CHECK: return [[APPLY]]
37+
func callother() -> Int32 {
38+
return recFuncManyCalls(10)
39+
}

0 commit comments

Comments
 (0)