Index: clang/test/CodeGen/flatten.c =================================================================== --- clang/test/CodeGen/flatten.c +++ clang/test/CodeGen/flatten.c @@ -1,9 +1,3 @@ -// UNSUPPORTED: experimental-new-pass-manager -// Currently, different code seems to be intentionally generated under the new -// PM since we alwaysinline functions and not callsites under new PM. -// Under new PM, f() will not be inlined from g() since f is not marked as -// alwaysinline. - // RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o - | FileCheck %s void f(void) {} Index: clang/test/CodeGenCXX/flatten.cpp =================================================================== --- clang/test/CodeGenCXX/flatten.cpp +++ clang/test/CodeGenCXX/flatten.cpp @@ -1,7 +1,3 @@ -// UNSUPPORTED: experimental-new-pass-manager -// See the comment for CodeGen/flatten.c on why this is unsupported with the new -// PM. - // RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++11 %s -emit-llvm -o - | FileCheck %s void f(void) {} Index: llvm/lib/Transforms/IPO/AlwaysInliner.cpp =================================================================== --- llvm/lib/Transforms/IPO/AlwaysInliner.cpp +++ llvm/lib/Transforms/IPO/AlwaysInliner.cpp @@ -54,13 +54,13 @@ if (F.isPresplitCoroutine()) continue; - if (!F.isDeclaration() && F.hasFnAttribute(Attribute::AlwaysInline) && - isInlineViable(F).isSuccess()) { + if (!F.isDeclaration() && isInlineViable(F).isSuccess()) { Calls.clear(); for (User *U : F.users()) if (auto *CB = dyn_cast(U)) - if (CB->getCalledFunction() == &F) + if (CB->getCalledFunction() == &F && + CB->hasFnAttr(Attribute::AlwaysInline)) Calls.insert(CB); for (CallBase *CB : Calls) { @@ -92,10 +92,11 @@ Changed = true; } - // Remember to try and delete this function afterward. This both avoids - // re-walking the rest of the module and avoids dealing with any iterator - // invalidation issues while deleting functions. - InlinedFunctions.push_back(&F); + if (F.hasFnAttribute(Attribute::AlwaysInline)) + // Remember to try and delete this function afterward. This both avoids + // re-walking the rest of the module and avoids dealing with any + // iterator invalidation issues while deleting functions. + InlinedFunctions.push_back(&F); } } Index: llvm/test/Transforms/Inline/always-inline.ll =================================================================== --- llvm/test/Transforms/Inline/always-inline.ll +++ llvm/test/Transforms/Inline/always-inline.ll @@ -1,14 +1,7 @@ -; RUN: opt < %s -inline-threshold=0 -always-inline -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL -; -; Ensure the threshold has no impact on these decisions. -; RUN: opt < %s -inline-threshold=20000000 -always-inline -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL -; RUN: opt < %s -inline-threshold=-20000000 -always-inline -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL -; -; The new pass manager doesn't re-use any threshold based infrastructure for -; the always inliner, but test that we get the correct result. The new PM -; always inliner also doesn't support inlining call-site alwaysinline -; annotations. It isn't clear that this is a reasonable use case for -; 'alwaysinline'. +; Ensure the threshold has no impact on these decisions. The new pass manager +; doesn't re-use any threshold based infrastructure for the always inliner, +; but test that we get the correct result. + ; RUN: opt < %s -inline-threshold=0 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK ; RUN: opt < %s -inline-threshold=20000000 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK ; RUN: opt < %s -inline-threshold=-20000000 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK @@ -145,15 +138,24 @@ ; CHECK-LABEL: @inner7( ret i32 1 } -define i32 @outer7() { -; CHECK-CALL-LABEL: @outer7( -; CHECK-CALL-NOT: call -; CHECK-CALL: ret +define i32 @outer7a() { +; CHECK-LABEL: @outer7a( +; CHECK-NOT: call +; CHECK: ret %r = call i32 @inner7() alwaysinline ret i32 %r } +define i32 @outer7b() { +; CHECK-LABEL: @outer7b( +; CHECK-NOT: call +; CHECK: ret + + %r = call i32 @inner7() #0 + ret i32 %r +} + define internal float* @inner8(float* nocapture align 128 %a) alwaysinline { ; CHECK-NOT: @inner8( ret float* %a @@ -318,3 +320,5 @@ call void @inner14() ret void } + +attributes #0 = { alwaysinline }