Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -968,6 +968,9 @@ def fexperimental_new_pass_manager : Flag<["-"], "fexperimental-new-pass-manager">, Group, Flags<[CC1Option]>, HelpText<"Enables an experimental new pass manager in LLVM.">; +def fexperimental_new_pass_manager_EQ : Joined<["-"], "fexperimental-new-pass-manager=">, + Group, Flags<[CC1Option]>, + HelpText<"Enables an experimental new pass manager in LLVM.">, Values<"on,off,debug">; def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group; def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group; def finstrument_functions : Flag<["-"], "finstrument-functions">, Group, Flags<[CC1Option]>, Index: clang/include/clang/Frontend/CodeGenOptions.h =================================================================== --- clang/include/clang/Frontend/CodeGenOptions.h +++ clang/include/clang/Frontend/CodeGenOptions.h @@ -89,6 +89,12 @@ Embed_Marker // Embed a marker as a placeholder for bitcode. }; + enum NewPassManagerKind { + NewPM_Off, // Use the legacy pass manager. + NewPM_On, // Use the new pass manager. + NewPM_Debug, // Use the new pass manager and print debug information. + }; + /// The code model to use (-mcmodel). std::string CodeModel; Index: clang/include/clang/Frontend/CodeGenOptions.def =================================================================== --- clang/include/clang/Frontend/CodeGenOptions.def +++ clang/include/clang/Frontend/CodeGenOptions.def @@ -55,8 +55,7 @@ ///< frontend. CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0 -CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental - ///< pass manager. +ENUM_CODEGENOPT(ExperimentalNewPassManager, NewPassManagerKind, 2, NewPM_Off) ///< The new, experimental pass manager. CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -879,7 +879,9 @@ PB.registerLoopAnalyses(LAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - ModulePassManager MPM; + const bool DebugLogging = CodeGenOpts.getExperimentalNewPassManager() == + CodeGenOptions::NewPM_Debug; + ModulePassManager MPM(DebugLogging); if (!CodeGenOpts.DisableLLVMPasses) { bool IsThinLTO = CodeGenOpts.EmitSummaryIndex; @@ -897,12 +899,12 @@ PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts); if (IsThinLTO) { - MPM = PB.buildThinLTOPreLinkDefaultPipeline(Level); + MPM = PB.buildThinLTOPreLinkDefaultPipeline(Level, DebugLogging); MPM.addPass(NameAnonGlobalPass()); } else if (IsLTO) { - MPM = PB.buildLTOPreLinkDefaultPipeline(Level); + MPM = PB.buildLTOPreLinkDefaultPipeline(Level, DebugLogging); } else { - MPM = PB.buildPerModuleDefaultPipeline(Level); + MPM = PB.buildPerModuleDefaultPipeline(Level, DebugLogging); } } } @@ -1059,7 +1061,8 @@ Conf.CGOptLevel = getCGOptLevel(CGOpts); initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); Conf.SampleProfile = std::move(SampleProfile); - Conf.UseNewPM = CGOpts.ExperimentalNewPassManager; + Conf.UseNewPM = + CGOpts.getExperimentalNewPassManager() != CodeGenOptions::NewPM_Off; switch (Action) { case Backend_EmitNothing: Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) { @@ -1126,7 +1129,7 @@ EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M); - if (CGOpts.ExperimentalNewPassManager) + if (CGOpts.getExperimentalNewPassManager() != CodeGenOptions::NewPM_Off) AsmHelper.EmitAssemblyWithNewPassManager(Action, std::move(OS)); else AsmHelper.EmitAssembly(Action, std::move(OS)); Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -3793,7 +3793,8 @@ InlineArg->render(Args, CmdArgs); Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager, - options::OPT_fno_experimental_new_pass_manager); + options::OPT_fno_experimental_new_pass_manager, + options::OPT_fexperimental_new_pass_manager_EQ); ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind); Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -472,9 +472,23 @@ } } - Opts.ExperimentalNewPassManager = Args.hasFlag( - OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager, - /* Default */ false); + if (Args.hasFlag(OPT_fexperimental_new_pass_manager, + OPT_fno_experimental_new_pass_manager, false)) + Opts.setExperimentalNewPassManager(CodeGenOptions::NewPM_On); + else + Opts.setExperimentalNewPassManager(CodeGenOptions::NewPM_Off); + + if (Arg *A = Args.getLastArg(OPT_fexperimental_new_pass_manager_EQ)) { + StringRef Name = A->getValue(); + if (Name == "on") + Opts.setExperimentalNewPassManager(CodeGenOptions::NewPM_On); + else if (Name == "off") + Opts.setExperimentalNewPassManager(CodeGenOptions::NewPM_Off); + else if (Name == "debug") + Opts.setExperimentalNewPassManager(CodeGenOptions::NewPM_Debug); + else + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + } if (Arg *A = Args.getLastArg(OPT_fveclib)) { StringRef Name = A->getValue(); Index: clang/test/CodeGen/lto-newpm-pipeline.c =================================================================== --- /dev/null +++ clang/test/CodeGen/lto-newpm-pipeline.c @@ -0,0 +1,26 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang -target x86_64-unknown-linux-gnu -c -o /dev/null -fexperimental-new-pass-manager=debug -flto=full -O0 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-FULL-O0 +// RUN: %clang -target x86_64-unknown-linux-gnu -c -o /dev/null -fexperimental-new-pass-manager=debug -flto=full -O2 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-FULL-O2 +// RUN: %clang -target x86_64-unknown-linux-gnu -c -o /dev/null -fexperimental-new-pass-manager=debug -flto=thin -O0 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-THIN-O0 +// RUN: %clang -target x86_64-unknown-linux-gnu -c -o /dev/null -fexperimental-new-pass-manager=debug -flto=thin -O2 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-THIN-O2 + +// CHECK-FULL-O0: Running pass: AlwaysInlinerPass +// CHECK-FULL-O0-NEXT: Running pass: BitcodeWriterPass + +// CHECK-THIN-O0: Running pass: AlwaysInlinerPass +// CHECK-THIN-O0-NEXT: Running pass: NameAnonGlobalPass +// CHECK-THIN-O0-NEXT: Running pass: ThinLTOBitcodeWriterPass + +// CHECK-FULL-O2: Running pass: GlobalOptPass +// CHECK-FULL-O2: Running pass: BitcodeWriterPass + +// CHECK-THIN-O2: Running pass: GlobalOptPass +// CHECK-THIN-O2: Running pass: NameAnonGlobalPass +// CHECK-THIN-O2-NEXT: Running pass: ThinLTOBitcodeWriterPass + +void Foo() {} Index: llvm/include/llvm/Option/ArgList.h =================================================================== --- llvm/include/llvm/Option/ArgList.h +++ llvm/include/llvm/Option/ArgList.h @@ -306,9 +306,13 @@ bool Default = true) const; /// AddLastArg - Render only the last argument match \p Id0, if present. - void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; - void AddLastArg(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const; + template + void AddLastArg(ArgStringList &Output, OptSpecifiers ...Ids) const { + if (Arg *A = getLastArg(Ids...)) { + A->claim(); + A->render(*this, Output); + } + } /// AddAllArgsExcept - Render all arguments matching any of the given ids /// and not matching any of the excluded ids. Index: llvm/lib/Option/ArgList.cpp =================================================================== --- llvm/lib/Option/ArgList.cpp +++ llvm/lib/Option/ArgList.cpp @@ -95,21 +95,6 @@ return std::vector(Values.begin(), Values.end()); } -void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const { - if (Arg *A = getLastArg(Id)) { - A->claim(); - A->render(*this, Output); - } -} - -void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const { - if (Arg *A = getLastArg(Id0, Id1)) { - A->claim(); - A->render(*this, Output); - } -} - void ArgList::AddAllArgsExcept(ArgStringList &Output, ArrayRef Ids, ArrayRef ExcludeIds) const {