diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -826,6 +826,10 @@ continue; } + // To make sure the inline cost is as accurate as possible, + // remove any dead users left by previous passes. + Callee.removeDeadConstantUsers(); + auto Advice = Advisor.getAdvice(*CB, OnlyMandatory); // Check whether we want to inline this callsite. if (!Advice->isInliningRecommended()) { diff --git a/llvm/test/Transforms/Inline/inline-cost-dead-users.ll b/llvm/test/Transforms/Inline/inline-cost-dead-users.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Inline/inline-cost-dead-users.ll @@ -0,0 +1,32 @@ +; Test to ensure that the inlining cost model isn't tripped up by dead constant users. +; In this case, the call to g via a bitcasted function pointer is canonicalized to +; a direct call to g with bitcasted arguments, leaving the original bitcast +; as a dead use of g. + +; RUN: opt < %s -instcombine -inline -pass-remarks=inline -S 2>&1 \ +; RUN: | FileCheck %s + +; Inline costs of f and g should be the same. + +; CHECK: 'f' inlined into 'h' with (cost=[[EXPECTED_COST:.+]], threshold={{.+}}) +; CHECK: 'g' inlined into 'h' with (cost=[[EXPECTED_COST]], threshold={{.+}}) + +%0 = type { i64, i64, i64 } +%1 = type { i64, i64, i64 } + +define internal void @f(%0* align 8 %a) unnamed_addr { +start: + ret void +} + +define internal void @g(%0* align 8 %a) unnamed_addr { +start: + ret void +} + +define void @h(%0* align 8 %a, %1* align 8 %b) unnamed_addr { +start: + call void @f(%0* align 8 %a) + call void bitcast (void (%0*)* @g to void (%1*)*)(%1* align 8 %b) + ret void +} diff --git a/llvm/test/Transforms/Inline/last-callsite.ll b/llvm/test/Transforms/Inline/last-callsite.ll --- a/llvm/test/Transforms/Inline/last-callsite.ll +++ b/llvm/test/Transforms/Inline/last-callsite.ll @@ -260,10 +260,10 @@ ; constant expression cannot be inlined because the constant expression forms ; a second use. If this part starts failing we need to use more complex ; constant expressions to reference a particular function with them. - %sink = alloca i1 - store volatile i1 icmp ne (i64 ptrtoint (void (i1)* @test4_g to i64), i64 ptrtoint(void (i1)* @test4_g to i64)), i1* %sink + %sink = alloca i64 + store volatile i64 mul (i64 ptrtoint (void (i1)* @test4_g to i64), i64 ptrtoint(void (i1)* @test4_g to i64)), i64* %sink call void @test4_g(i1 true) -; CHECK: store volatile i1 false +; CHECK: store volatile i64 mul (i64 ptrtoint (void (i1)* @test4_g to i64), i64 ptrtoint (void (i1)* @test4_g to i64)), i64* %sink ; CHECK: call void @test4_g(i1 true) ret void