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 @@ -333,6 +333,9 @@ LLVM_DEBUG(dbgs() << "Skipping inlining due to history: " << F.getName() << " -> " << Callee.getName() << "\n"); setInlineRemark(*CB, "recursive"); + // Set noinline so that we don't forget this decision across CGSCC + // iterations. + CB->setIsNoInline(); continue; } diff --git a/llvm/test/Transforms/Inline/inline-history-noinline.ll b/llvm/test/Transforms/Inline/inline-history-noinline.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Inline/inline-history-noinline.ll @@ -0,0 +1,32 @@ +; RUN: opt -passes=inline -S < %s | FileCheck %s + +; This will inline @f1 into @a, causing two new calls to @f2, which will get inlined for two calls to @f1. +; The inline history should stop recursive inlining here, and make sure to mark the inlined calls as noinline so we don't repeat the inlining later on when @a gets inlined into @b. + +define internal void @f1(ptr %p) { + call void %p(ptr @f1) + ret void +} + +define internal void @f2(ptr %p) { + call void %p(ptr @f2) + call void %p(ptr @f2) + ret void +} + +define void @b() { +; CHECK-LABEL: define void @b() { +; CHECK-NEXT: call void @f1(ptr @f2) #[[NOINLINE:[0-9]+]] +; CHECK-NEXT: call void @f1(ptr @f2) #[[NOINLINE]] +; CHECK-NEXT: ret void +; + call void @a() + ret void +} + +define internal void @a() { + call void @f1(ptr @f2) + ret void +} + +; CHECK: [[NOINLINE]] = { noinline }