Index: lib/Analysis/InlineCost.cpp =================================================================== --- lib/Analysis/InlineCost.cpp +++ lib/Analysis/InlineCost.cpp @@ -970,7 +970,17 @@ // through it and see the function target. This happens not infrequently // during devirtualization and so we want to give it a hefty bonus for // inlining, but cap that bonus in the event that inlining wouldn't pan - // out. Pretend to inline the function, with a custom threshold. + // out. + + // First, check if the function has AlwaysInline attribute and give a huge + // bonus if that is the case. + if (F->hasFnAttribute(Attribute::AlwaysInline)) { + Cost -= InlineConstants::LastCallToStaticBonus; + return Base::visitCallSite(CS); + } + + // Otherwise, pretend to inline the function, with a custom threshold and give + // a bonus based on this threshold and the cost of inlining F. auto IndirectCallParams = Params; IndirectCallParams.DefaultThreshold = InlineConstants::IndirectCallThreshold; CallAnalyzer CA(TTI, GetAssumptionCache, GetBFI, PSI, *F, CS, Index: test/Transforms/Inline/inline-indirect-always.ll =================================================================== --- /dev/null +++ test/Transforms/Inline/inline-indirect-always.ll @@ -0,0 +1,32 @@ +; RUN: opt -S -inline -inline-threshold=0 < %s | FileCheck %s +declare void @ext(); + +define void @foo() #1 { + call void @ext(); + ret void +} + +define void @bar(void ()* %fptr) { + call void %fptr(); + call void @ext(); + call void @ext(); + call void @ext(); + call void @ext(); + call void @ext(); + call void @ext(); + call void @ext(); + call void @ext(); + call void @ext(); + call void @ext(); + call void @ext(); + ret void +} +; CHECK-LABEL: @baz +define void @baz() { +; CHECK-NOT: call void @bar + call void @bar(void ()* @foo) +; CHECK: ret + ret void +} + +attributes #1 = { alwaysinline }