The inliner was choosing to not consider call sites
authorChris Lattner <sabre@nondot.org>
Thu, 22 Apr 2010 23:37:35 +0000 (23:37 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 22 Apr 2010 23:37:35 +0000 (23:37 +0000)
that appear in the SCC as a result of inlining as candidates
for inlining.  Change this so that it *does* consider call
sites that change from being indirect to being direct as a
result of inlining.  This allows it to completely
"devirtualize" the testcase.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@102146 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Transforms/Utils/Cloning.h
lib/Transforms/IPO/Inliner.cpp
lib/Transforms/Utils/InlineFunction.cpp
test/Transforms/Inline/indirect_resolve.ll

index 4b6025b6be72c12386a05ffc02abaf901ef41891..a9dc95b4a81b384b87c3a1b509ccad5e9f245649 100644 (file)
@@ -174,10 +174,15 @@ public:
   /// StaticAllocas - InlineFunction fills this in with all static allocas that
   /// get copied into the caller.
   SmallVector<AllocaInst*, 4> StaticAllocas;
-  
+
+  /// DevirtualizedCalls - InlineFunction fills this in with callsites that were
+  /// inlined from the callee that went from being indirect calls to direct
+  /// calls due to inlining.  This is only filled in if CG is non-null.
+  SmallVector<Instruction*, 2> DevirtualizedCalls;
   
   void reset() {
     StaticAllocas.clear();
+    DevirtualizedCalls.clear();
   }
 };
   
index 19b65e8e1f96619d2f159e89455b51541283a76d..1de7b0753d20427dc6704e2c985ba8943b899f8e 100644 (file)
@@ -383,11 +383,17 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) {
         if (!shouldInline(CS))
           continue;
 
-        // Attempt to inline the function...
+        // Attempt to inline the function.
         if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas))
           continue;
         ++NumInlined;
 
+        // If inlining this function devirtualized any call sites, throw them
+        // onto our worklist to process.  They are useful inline candidates.
+        for (unsigned i = 0, e = InlineInfo.DevirtualizedCalls.size();
+             i != e; ++i)
+          CallSites.push_back(CallSite(InlineInfo.DevirtualizedCalls[i]));
+        
         // Update the cached cost info with the inlined call.
         growCachedCostInfo(Caller, Callee);
       }
index 5629a38709b4f0b5f72ce4db7a68dc6c63f2a5ea..a913d157e24a907931b06fb6defdf4c2180fa388 100644 (file)
@@ -170,7 +170,8 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
 static void UpdateCallGraphAfterInlining(CallSite CS,
                                          Function::iterator FirstNewBlock,
                                        DenseMap<const Value*, Value*> &ValueMap,
-                                         CallGraph &CG) {
+                                         InlineFunctionInfo &IFI) {
+  CallGraph &CG = *IFI.CG;
   const Function *Caller = CS.getInstruction()->getParent()->getParent();
   const Function *Callee = CS.getCalledFunction();
   CallGraphNode *CalleeNode = CG[Callee];
@@ -210,6 +211,10 @@ static void UpdateCallGraphAfterInlining(CallSite CS,
       if (Function *F = CallSite(NewCall).getCalledFunction()) {
         // Indirect call site resolved to direct call.
         CallerNode->addCalledFunction(CallSite::get(NewCall), CG[F]);
+        
+        // Remember that this callsite got devirtualized for the client of
+        // InlineFunction.
+        IFI.DevirtualizedCalls.push_back(NewCall);
         continue;
       }
     
@@ -362,7 +367,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI) {
 
     // Update the callgraph if requested.
     if (IFI.CG)
-      UpdateCallGraphAfterInlining(CS, FirstNewBlock, ValueMap, *IFI.CG);
+      UpdateCallGraphAfterInlining(CS, FirstNewBlock, ValueMap, IFI);
   }
 
   // If there are any alloca instructions in the block that used to be the entry
index 76182e2fe4f666bd8914d6d52e5424196323fd35..eb4f9bc0583e2c6aca6e8ef7713823d562d2da3b 100644 (file)
@@ -1,7 +1,7 @@
-; RUN: opt < %s -inline | llvm-dis
+; RUN: opt < %s -inline -S | FileCheck %s
 ; PR4834
 
-define i32 @main() {
+define i32 @test1() {
   %funcall1_ = call fastcc i32 ()* ()* @f1()
   %executecommandptr1_ = call i32 %funcall1_()
   ret i32 %executecommandptr1_
@@ -14,3 +14,31 @@ define internal fastcc i32 ()* @f1() nounwind readnone {
 define internal i32 @f2() nounwind readnone {
   ret i32 1
 }
+
+; CHECK: @test1()
+; CHECK-NEXT: ret i32 1
+
+
+
+
+
+declare i8* @f1a(i8*) ssp align 2
+
+define internal i32 @f2a(i8* %t) inlinehint ssp {
+entry:
+  ret i32 41
+}
+
+define internal i32 @f3a(i32 (i8*)* %__f) ssp {
+entry:
+  %A = call i32 %__f(i8* undef)
+  ret i32 %A
+}
+
+define i32 @test2(i8* %this) ssp align 2 {
+  %X = call i32 @f3a(i32 (i8*)* @f2a) ssp
+  ret i32 %X
+}
+
+; CHECK: @test2
+; CHECK-NEXT: ret i32 41
\ No newline at end of file