summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2010-09-09 20:32:23 +0000
committerOwen Anderson <resistor@mac.com>2010-09-09 20:32:23 +0000
commitf9a26b89f8815651048ed5518d99b484ac7c2ba0 (patch)
tree796d42a0dd32f512e44d2c5ea66174a3a5df7ff5
parentce07b5458d87d5f5ad306a1d86785537e9a3ce0c (diff)
downloadllvm-f9a26b89f8815651048ed5518d99b484ac7c2ba0.tar.gz
llvm-f9a26b89f8815651048ed5518d99b484ac7c2ba0.tar.bz2
llvm-f9a26b89f8815651048ed5518d99b484ac7c2ba0.tar.xz
What the loop unroller cares about, rather than just not unrolling loops with calls, is
not unrolling loops that contain calls that would be better off getting inlined. This mostly comes up when an interleaved devirtualization pass has devirtualized a call which the inliner will inline on a future pass. Thus, rather than blocking all loops containing calls, add a metric for "inline candidate calls" and block loops containing those instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113535 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Analysis/CodeMetrics.h8
-rw-r--r--lib/Analysis/InlineCost.cpp6
-rw-r--r--lib/Transforms/Scalar/LoopUnrollPass.cpp10
3 files changed, 18 insertions, 6 deletions
diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h
index 6ae68f36d7..1a67409ad1 100644
--- a/include/llvm/Analysis/CodeMetrics.h
+++ b/include/llvm/Analysis/CodeMetrics.h
@@ -45,6 +45,11 @@ namespace llvm {
/// NumCalls - Keep track of the number of calls to 'big' functions.
unsigned NumCalls;
+
+ /// NumInlineCandidates - Keep track of the number of calls to internal
+ /// functions with only a single caller. These are likely targets for
+ /// future inlining, likely exposed by interleaved devirtualization.
+ unsigned NumInlineCandidates;
/// NumVectorInsts - Keep track of how many instructions produce vector
/// values. The inliner is being more aggressive with inlining vector
@@ -56,7 +61,8 @@ namespace llvm {
CodeMetrics() : callsSetJmp(false), isRecursive(false),
containsIndirectBr(false), usesDynamicAlloca(false),
- NumInsts(0), NumBlocks(0), NumCalls(0), NumVectorInsts(0),
+ NumInsts(0), NumBlocks(0), NumCalls(0),
+ NumInlineCandidates(0), NumVectorInsts(0),
NumRets(0) {}
/// analyzeBasicBlock - Add information about the specified basic block
diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp
index ee2657c58e..afdf474c61 100644
--- a/lib/Analysis/InlineCost.cpp
+++ b/lib/Analysis/InlineCost.cpp
@@ -70,6 +70,12 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
// variables as volatile if they are live across a setjmp call, and they
// probably won't do this in callers.
if (const Function *F = CS.getCalledFunction()) {
+ // If a function is both internal and has a single use, then it is
+ // extremely likely to get inlined in the future (it was probably
+ // exposed by an interleaved devirtualization pass).
+ if (F->hasInternalLinkage() && F->hasOneUse())
+ ++NumInlineCandidates;
+
if (F->isDeclaration() &&
(F->getName() == "setjmp" || F->getName() == "_setjmp"))
callsSetJmp = true;
diff --git a/lib/Transforms/Scalar/LoopUnrollPass.cpp b/lib/Transforms/Scalar/LoopUnrollPass.cpp
index 7968939f11..806f63d104 100644
--- a/lib/Transforms/Scalar/LoopUnrollPass.cpp
+++ b/lib/Transforms/Scalar/LoopUnrollPass.cpp
@@ -89,7 +89,7 @@ static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) {
for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
I != E; ++I)
Metrics.analyzeBasicBlock(*I);
- NumCalls = Metrics.NumCalls;
+ NumCalls = Metrics.NumInlineCandidates;
unsigned LoopSize = Metrics.NumInsts;
@@ -151,11 +151,11 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
// Enforce the threshold.
if (CurrentThreshold != NoThreshold) {
- unsigned NumCalls;
- unsigned LoopSize = ApproximateLoopSize(L, NumCalls);
+ unsigned NumInlineCandidates;
+ unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates);
DEBUG(dbgs() << " Loop Size = " << LoopSize << "\n");
- if (NumCalls != 0) {
- DEBUG(dbgs() << " Not unrolling loop with function calls.\n");
+ if (NumInlineCandidates != 0) {
+ DEBUG(dbgs() << " Not unrolling loop with inlinable calls.\n");
return false;
}
uint64_t Size = (uint64_t)LoopSize*Count;