aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/IPO/Inliner.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-03-12 11:19:33 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-03-12 11:19:33 +0000
commit6c0b3ac8ea51d35bbd2565f17f1a73c3bfcb5cdf (patch)
treec2b037cd4eee85dfebfa559534cd769940752560 /lib/Transforms/IPO/Inliner.cpp
parentfc72ae613afd7ca2526bb66156bafe8b0054cb3b (diff)
downloadexternal_llvm-6c0b3ac8ea51d35bbd2565f17f1a73c3bfcb5cdf.zip
external_llvm-6c0b3ac8ea51d35bbd2565f17f1a73c3bfcb5cdf.tar.gz
external_llvm-6c0b3ac8ea51d35bbd2565f17f1a73c3bfcb5cdf.tar.bz2
When inlining a function and adding its inner call sites to the
candidate set for subsequent inlining, try to simplify the arguments to the inner call site now that inlining has been performed. The goal here is to propagate and fold constants through deeply nested call chains. Without doing this, we loose the inliner bonus that should be applied because the arguments don't match the exact pattern the cost estimator uses. Reviewed on IRC by Benjamin Kramer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152556 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/IPO/Inliner.cpp')
-rw-r--r--lib/Transforms/IPO/Inliner.cpp36
1 files changed, 35 insertions, 1 deletions
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index 1f7625d..9590df9 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -19,6 +19,7 @@
#include "llvm/IntrinsicInst.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/InlineCost.h"
+#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
#include "llvm/Transforms/Utils/Cloning.h"
@@ -327,6 +328,37 @@ static bool InlineHistoryIncludes(Function *F, int InlineHistoryID,
return false;
}
+/// \brief Simplify arguments going into a particular callsite.
+///
+/// This is important to do each time we add a callsite due to inlining so that
+/// constants and other entities which feed into inline cost estimation are
+/// properly recognized when analyzing the new callsite. Consider:
+/// void outer(int x) {
+/// if (x < 42)
+/// return inner(42 - x);
+/// ...
+/// }
+/// void inner(int x) {
+/// ...
+/// }
+///
+/// The inliner gives calls to 'outer' with a constant argument a bonus because
+/// it will delete one side of a branch. But the resulting call to 'inner'
+/// will, after inlining, also have a constant operand. We need to do just
+/// enough constant folding to expose this for callsite arguments. The rest
+/// will be taken care of after the inliner finishes running.
+static void simplifyCallSiteArguments(const TargetData *TD, CallSite CS) {
+ // FIXME: It would be nice to avoid this smallvector if RAUW doesn't
+ // invalidate operand iterators in any cases.
+ SmallVector<std::pair<Value *, Value*>, 4> SimplifiedArgs;
+ for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
+ I != E; ++I)
+ if (Instruction *Inst = dyn_cast<Instruction>(*I))
+ if (Value *SimpleArg = SimplifyInstruction(Inst, TD))
+ SimplifiedArgs.push_back(std::make_pair(Inst, SimpleArg));
+ for (unsigned Idx = 0, Size = SimplifiedArgs.size(); Idx != Size; ++Idx)
+ SimplifiedArgs[Idx].first->replaceAllUsesWith(SimplifiedArgs[Idx].second);
+}
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
CallGraph &CG = getAnalysis<CallGraph>();
@@ -455,7 +487,9 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) {
for (unsigned i = 0, e = InlineInfo.InlinedCalls.size();
i != e; ++i) {
Value *Ptr = InlineInfo.InlinedCalls[i];
- CallSites.push_back(std::make_pair(CallSite(Ptr), NewHistoryID));
+ CallSite NewCS = Ptr;
+ simplifyCallSiteArguments(TD, NewCS);
+ CallSites.push_back(std::make_pair(NewCS, NewHistoryID));
}
}