diff options
-rw-r--r-- | llvm/lib/Transforms/IPO/Inliner.cpp | 44 | ||||
-rw-r--r-- | llvm/test/Transforms/Inline/delete-call.ll | 22 |
2 files changed, 52 insertions, 14 deletions
diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp index ea47366f47e..0243fe83276 100644 --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -32,6 +32,7 @@ using namespace llvm; STATISTIC(NumInlined, "Number of functions inlined"); +STATISTIC(NumCallsDeleted, "Number of call sites deleted, not inlined"); STATISTIC(NumDeleted, "Number of functions deleted because all callers found"); STATISTIC(NumMergedAllocas, "Number of allocas merged together"); @@ -336,23 +337,39 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) { for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi) { CallSite CS = CallSites[CSi]; + Function *Caller = CS.getCaller(); Function *Callee = CS.getCalledFunction(); - // We can only inline direct calls to non-declarations. - if (Callee == 0 || Callee->isDeclaration()) continue; + + // If this call site is dead and it is to a readonly function, we should + // just delete the call instead of trying to inline it, regardless of + // size. This happens because IPSCCP propagates the result out of the + // call and then we're left with the dead call. + if (CS.getInstruction()->use_empty() && + !CS.getInstruction()->mayHaveSideEffects()) { + DEBUG(errs() << " -> Deleting dead call: " + << *CS.getInstruction() << "\n"); + // Update the call graph by deleting the edge from Callee to Caller. + CG[Caller]->removeCallEdgeFor(CS); + CS.getInstruction()->eraseFromParent(); + ++NumCallsDeleted; + } else { + // We can only inline direct calls to non-declarations. + if (Callee == 0 || Callee->isDeclaration()) continue; - // If the policy determines that we should inline this function, - // try to do so. - if (!shouldInline(CS)) - continue; + // If the policy determines that we should inline this function, + // try to do so. + if (!shouldInline(CS)) + continue; - Function *Caller = CS.getCaller(); - // Attempt to inline the function... - if (!InlineCallIfPossible(CS, CG, TD, InlinedArrayAllocas)) - continue; + // Attempt to inline the function... + if (!InlineCallIfPossible(CS, CG, TD, InlinedArrayAllocas)) + continue; + ++NumInlined; + } - // If we inlined the last possible call site to the function, delete the - // function body now. - if (Callee->use_empty() && Callee->hasLocalLinkage() && + // If we inlined or deleted the last possible call site to the function, + // delete the function body now. + if (Callee && Callee->use_empty() && Callee->hasLocalLinkage() && // TODO: Can remove if in SCC now. !SCCFunctions.count(Callee) && @@ -391,7 +408,6 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) { } --CSi; - ++NumInlined; Changed = true; LocalChange = true; } diff --git a/llvm/test/Transforms/Inline/delete-call.ll b/llvm/test/Transforms/Inline/delete-call.ll new file mode 100644 index 00000000000..3505608b828 --- /dev/null +++ b/llvm/test/Transforms/Inline/delete-call.ll @@ -0,0 +1,22 @@ +; RUN: opt %s -S -inline -functionattrs -stats |& grep {Number of call sites deleted, not inlined} +; RUN: opt %s -S -inline -stats |& grep {Number of functions inlined} + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" +target triple = "i386-apple-darwin9.8" + +define internal i32 @test(i32 %x, i32 %y, i32 %z) nounwind { +entry: + %0 = add nsw i32 %y, %z ; <i32> [#uses=1] + %1 = mul i32 %0, %x ; <i32> [#uses=1] + %2 = mul i32 %y, %z ; <i32> [#uses=1] + %3 = add nsw i32 %1, %2 ; <i32> [#uses=1] + ret i32 %3 +} + +define i32 @test2() nounwind { +entry: + %0 = call i32 @test(i32 1, i32 2, i32 4) nounwind ; <i32> [#uses=1] + ret i32 14 +} + + |