[llvm-commits] [llvm] r152556 - in /llvm/trunk: lib/Transforms/IPO/Inliner.cpp test/Transforms/Inline/inline_constprop.ll

Chandler Carruth chandlerc at gmail.com
Mon Mar 12 04:19:33 PDT 2012


Author: chandlerc
Date: Mon Mar 12 06:19:33 2012
New Revision: 152556

URL: http://llvm.org/viewvc/llvm-project?rev=152556&view=rev
Log:
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.

Modified:
    llvm/trunk/lib/Transforms/IPO/Inliner.cpp
    llvm/trunk/test/Transforms/Inline/inline_constprop.ll

Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=152556&r1=152555&r2=152556&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Mon Mar 12 06:19:33 2012
@@ -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 @@
   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 @@
           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));
           }
         }
         

Modified: llvm/trunk/test/Transforms/Inline/inline_constprop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_constprop.ll?rev=152556&r1=152555&r2=152556&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_constprop.ll (original)
+++ llvm/trunk/test/Transforms/Inline/inline_constprop.ll Mon Mar 12 06:19:33 2012
@@ -12,3 +12,78 @@
   %X = call i32 @callee1( i32 10, i32 3 )
   ret i32 %X
 }
+
+define i32 @caller2() {
+; CHECK: @caller2
+; CHECK-NOT: call void @callee2
+; CHECK: ret
+
+; We contrive to make this hard for *just* the inline pass to do in order to
+; simulate what can actually happen with large, complex functions getting
+; inlined.
+  %a = add i32 42, 0
+  %b = add i32 48, 0
+
+  %x = call i32 @callee21(i32 %a, i32 %b)
+  ret i32 %x
+}
+
+define i32 @callee21(i32 %x, i32 %y) {
+  %sub = sub i32 %y, %x
+  %result = call i32 @callee22(i32 %sub)
+  ret i32 %result
+}
+
+declare i8* @getptr()
+
+define i32 @callee22(i32 %x) {
+  %icmp = icmp ugt i32 %x, 42
+  br i1 %icmp, label %bb.true, label %bb.false
+bb.true:
+  ; This block musn't be counted in the inline cost.
+  %ptr = call i8* @getptr()
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+  load volatile i8* %ptr
+
+  ret i32 %x
+bb.false:
+  ret i32 %x
+}





More information about the llvm-commits mailing list