From: David Blaikie Date: Fri, 9 Jun 2017 03:29:20 +0000 (+0000) Subject: Inliner: Don't touch indirect calls X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d38ff399246e4986e8864c391cc6b0b566de782c;p=llvm Inliner: Don't touch indirect calls Other comments/implications are that this isn't intended behavior (nor perserved/reimplemented in the new inliner) & complicates fixing the 'inlining' of trivially dead calls without consulting the cost function first. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305052 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index 673d3af0ab5..c0dfeede05c 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -519,6 +519,10 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG, Function *Caller = CS.getCaller(); Function *Callee = CS.getCalledFunction(); + // We can only inline direct calls to non-declarations. + if (!Callee || 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 @@ -531,10 +535,6 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG, CS.getInstruction()->eraseFromParent(); ++NumCallsDeleted; } else { - // We can only inline direct calls to non-declarations. - if (!Callee || Callee->isDeclaration()) - continue; - // If this call site was obtained by inlining another function, verify // that the include path for the function did not include the callee // itself. If so, we'd be recursively inlining the same function, diff --git a/test/Transforms/Inline/basictest.ll b/test/Transforms/Inline/basictest.ll index b98644cd2dd..f34ed084113 100644 --- a/test/Transforms/Inline/basictest.ll +++ b/test/Transforms/Inline/basictest.ll @@ -91,3 +91,27 @@ define i32 @test() { ret i32 %e ; CHECK: } } + +; Inliner shouldn't delete calls it can't inline, even if they're trivially dead +; CHECK-LABEL: @outer4( +define void @outer4(void ()* %inner4) { +entry: +; CHECK: call void %inner4() + call void %inner4() nounwind readnone + ret void +} + +declare void @inner5_inner() + +define void @inner5(void ()* %x) { + call void %x() nounwind readnone + ret void +} + +; Inliner shouldn't delete calls it can't inline, even if they're trivially dead and temporarily indirect +; CHECK-LABEL: @outer5( +define void @outer5() { +; CHECK: call void @inner5_inner( + call void @inner5(void ()* @inner5_inner) + ret void +}