aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2010-04-16 16:01:18 +0000
committerDan Gohman <gohman@apple.com>2010-04-16 16:01:18 +0000
commitb391bb8947e9703e4803d50f24df6caaa8bb0cc9 (patch)
treeb0cba8da285159033f107ca19aa36b3008735770
parentea25b48af33be42e19236d8eac26bd42b45bcc1b (diff)
Disable inlining of recursive calls. It can complicate tailcallelim and
dependent analyses, and increase code size, so doing it profitably would require more complex heuristics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101471 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/InlineCost.cpp7
-rw-r--r--test/Transforms/Inline/tail-recursion.ll29
2 files changed, 36 insertions, 0 deletions
diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp
index 6650a680f1..b3ce42c859 100644
--- a/lib/Analysis/InlineCost.cpp
+++ b/lib/Analysis/InlineCost.cpp
@@ -263,6 +263,13 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
CS.isNoInline())
return llvm::InlineCost::getNever();
+ // Don't inline directly recursive calls, for now. Inlining a directly
+ // recursive call is effectively unrolling a loop, so it calls for different
+ // heuristics, which aren't implemented yet. Until then, err on the
+ // conservative side.
+ if (Callee == Caller)
+ return llvm::InlineCost::getNever();
+
// InlineCost - This value measures how good of an inline candidate this call
// site is to inline. A lower inline cost make is more likely for the call to
// be inlined. This value may go negative.
diff --git a/test/Transforms/Inline/tail-recursion.ll b/test/Transforms/Inline/tail-recursion.ll
new file mode 100644
index 0000000000..146bed4cd0
--- /dev/null
+++ b/test/Transforms/Inline/tail-recursion.ll
@@ -0,0 +1,29 @@
+; RUN: opt -inline -tailcallelim -indvars -loop-deletion -S < %s | FileCheck %s
+
+; Inline shouldn't inline foo into itself because it's a tailcallelim
+; candidate. Tailcallelim should convert the call into a loop. Indvars
+; should calculate the exit value, making the loop dead. Loop deletion
+; should delete the loop.
+; PR6842
+
+; CHECK: define i32 @bar() nounwind {
+; CHECK-NEXT: ret i32 10000
+; CHECK-NEXT: }
+
+define internal i32 @foo(i32 %x) nounwind {
+ %i = add i32 %x, 1 ; <i32> [#uses=3]
+ %a = icmp slt i32 %i, 10000 ; <i1> [#uses=1]
+ br i1 %a, label %more, label %done
+
+done: ; preds = %0
+ ret i32 %i
+
+more: ; preds = %0
+ %z = tail call i32 @foo(i32 %i) ; <i32> [#uses=1]
+ ret i32 %z
+}
+
+define i32 @bar() nounwind {
+ %z = call i32 @foo(i32 0) ; <i32> [#uses=1]
+ ret i32 %z
+}