Index: llvm/lib/Transforms/IPO/AlwaysInliner.cpp =================================================================== --- llvm/lib/Transforms/IPO/AlwaysInliner.cpp +++ llvm/lib/Transforms/IPO/AlwaysInliner.cpp @@ -59,7 +59,7 @@ for (User *U : F.users()) if (auto *CB = dyn_cast(U)) - if (CB->getCalledFunction() == &F && + if (CB->getCalledFunction() == &F && !CB->isNoInline() && CB->hasFnAttr(Attribute::AlwaysInline)) Calls.insert(CB); @@ -207,6 +207,9 @@ if (Callee->isDeclaration()) return InlineCost::getNever("no definition"); + if (CB.isNoInline()) + return InlineCost::getNever("noinline call site attribute"); + if (!CB.hasFnAttr(Attribute::AlwaysInline)) return InlineCost::getNever("no alwaysinline attribute"); Index: llvm/test/Transforms/Inline/always-inline.ll =================================================================== --- llvm/test/Transforms/Inline/always-inline.ll +++ llvm/test/Transforms/Inline/always-inline.ll @@ -314,3 +314,42 @@ call void @inner14() ret void } + +define internal i32 @inner15() { +; CHECK: @inner15( + ret i32 1 +} + +define i32 @outer15() { +; CHECK-LABEL: @outer15( +; CHECK: call + + %r = call i32 @inner15() noinline + ret i32 %r +} + +define internal i32 @inner16() alwaysinline { +; CHECK: @inner16( + ret i32 1 +} + +define i32 @outer16() { +; CHECK-LABEL: @outer16( +; CHECK: call + + %r = call i32 @inner16() noinline + ret i32 %r +} + +define i32 @inner17() alwaysinline { +; CHECK: @inner17( + ret i32 1 +} + +define i32 @outer17() { +; CHECK-LABEL: @outer17( +; CHECK: call + + %r = call i32 @inner17() noinline + ret i32 %r +}