Index: cfe/trunk/include/clang/Driver/Options.td =================================================================== --- cfe/trunk/include/clang/Driver/Options.td +++ cfe/trunk/include/clang/Driver/Options.td @@ -823,6 +823,9 @@ def finline_hint_functions: Flag<["-"], "finline-hint-functions">, Group, Flags<[CC1Option]>, HelpText<"Inline functions wich are (explicitly or implicitly) marked inline">; def finline : Flag<["-"], "finline">, Group; +def fexperimental_new_pass_manager : Flag<["-"], "fexperimental-new-pass-manager">, + Group, Flags<[CC1Option]>, + HelpText<"Enables an experimental new pass manager in LLVM.">; 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]>, @@ -1000,6 +1003,9 @@ def fno_gnu_keywords : Flag<["-"], "fno-gnu-keywords">, Group, Flags<[CC1Option]>; def fno_inline_functions : Flag<["-"], "fno-inline-functions">, Group, Flags<[CC1Option]>; def fno_inline : Flag<["-"], "fno-inline">, Group, Flags<[CC1Option]>; +def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-manager">, + Group, Flags<[CC1Option]>, + HelpText<"Disables an experimental new pass manager in LLVM.">; def fveclib : Joined<["-"], "fveclib=">, Group, Flags<[CC1Option]>, HelpText<"Use the given vector functions library">; def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group, Index: cfe/trunk/include/clang/Frontend/CodeGenOptions.def =================================================================== --- cfe/trunk/include/clang/Frontend/CodeGenOptions.def +++ cfe/trunk/include/clang/Frontend/CodeGenOptions.def @@ -52,6 +52,8 @@ CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get ///< the pristine IR generated by the ///< frontend. +CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables 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: cfe/trunk/lib/CodeGen/BackendUtil.cpp =================================================================== --- cfe/trunk/lib/CodeGen/BackendUtil.cpp +++ cfe/trunk/lib/CodeGen/BackendUtil.cpp @@ -20,20 +20,21 @@ #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Bitcode/BitcodeWriterPass.h" -#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/IR/DataLayout.h" -#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/IR/Verifier.h" #include "llvm/LTO/LTOBackend.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/ModuleSummaryIndexObjectFile.h" +#include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" @@ -114,6 +115,9 @@ void EmitAssembly(BackendAction Action, std::unique_ptr OS); + + void EmitAssemblyWithNewPassManager(BackendAction Action, + std::unique_ptr OS); }; // We need this wrapper to access LangOpts and CGOpts from extension functions @@ -709,6 +713,134 @@ } } +static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { + switch (Opts.OptimizationLevel) { + default: + llvm_unreachable("Invalid optimization level!"); + + case 1: + return PassBuilder::O1; + + case 2: + switch (Opts.OptimizeSize) { + default: + llvm_unreachable("Invalide optimization level for size!"); + + case 0: + return PassBuilder::O2; + + case 1: + return PassBuilder::Os; + + case 2: + return PassBuilder::Oz; + } + + case 3: + return PassBuilder::O3; + } +} + +/// A clean version of `EmitAssembly` that uses the new pass manager. +/// +/// Not all features are currently supported in this system, but where +/// necessary it falls back to the legacy pass manager to at least provide +/// basic functionality. +/// +/// This API is planned to have its functionality finished and then to replace +/// `EmitAssembly` at some point in the future when the default switches. +void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( + BackendAction Action, std::unique_ptr OS) { + TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); + setCommandLineOpts(); + + // The new pass manager always makes a target machine available to passes + // during construction. + CreateTargetMachine(/*MustCreateTM*/ true); + if (!TM) + // This will already be diagnosed, just bail. + return; + TheModule->setDataLayout(TM->createDataLayout()); + + PassBuilder PB(TM.get()); + + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + + // Register the AA manager first so that our version is the one used. + FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); + + // Register all the basic analyses with the managers. + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + + ModulePassManager MPM; + if (CodeGenOpts.OptimizationLevel == 0) { + // Build a minimal pipeline based on the semantics required by Clang, which + // is just that always inlining occurs. + MPM.addPass(AlwaysInlinerPass()); + } else { + // Otherwise, use the default pass pipeline. We also have to map our + // optimization levels into one of the distinct levels used to configure + // the pipeline. + PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts); + + MPM = PB.buildPerModuleDefaultPipeline(Level); + } + + // FIXME: We still use the legacy pass manager to do code generation. We + // create that pass manager here and use it as needed below. + legacy::PassManager CodeGenPasses; + bool NeedCodeGen = false; + + // Append any output we need to the pass manager. + switch (Action) { + case Backend_EmitNothing: + break; + + case Backend_EmitBC: + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + CodeGenOpts.EmitSummaryIndex, + CodeGenOpts.EmitSummaryIndex)); + break; + + case Backend_EmitLL: + MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists)); + break; + + case Backend_EmitAssembly: + case Backend_EmitMCNull: + case Backend_EmitObj: + NeedCodeGen = true; + CodeGenPasses.add( + createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); + if (!AddEmitPasses(CodeGenPasses, Action, *OS)) + // FIXME: Should we handle this error differently? + return; + break; + } + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + // Now that we have all of the passes ready, run them. + { + PrettyStackTraceString CrashInfo("Optimizer"); + MPM.run(*TheModule, MAM); + } + + // Now if needed, run the legacy PM for codegen. + if (NeedCodeGen) { + PrettyStackTraceString CrashInfo("Code generation"); + CodeGenPasses.run(*TheModule); + } +} + static void runThinLTOBackend(const CodeGenOptions &CGOpts, Module *M, std::unique_ptr OS) { // If we are performing a ThinLTO importing compile, load the function index @@ -801,7 +933,10 @@ EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M); - AsmHelper.EmitAssembly(Action, std::move(OS)); + if (CGOpts.ExperimentalNewPassManager) + AsmHelper.EmitAssemblyWithNewPassManager(Action, std::move(OS)); + else + AsmHelper.EmitAssembly(Action, std::move(OS)); // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's // DataLayout. Index: cfe/trunk/lib/Driver/Tools.cpp =================================================================== --- cfe/trunk/lib/Driver/Tools.cpp +++ cfe/trunk/lib/Driver/Tools.cpp @@ -5909,6 +5909,9 @@ options::OPT_fno_inline_functions)) InlineArg->render(Args, CmdArgs); + Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager, + options::OPT_fno_experimental_new_pass_manager); + ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind); // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and Index: cfe/trunk/lib/Frontend/CompilerInvocation.cpp =================================================================== --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp @@ -462,6 +462,10 @@ } } + Opts.ExperimentalNewPassManager = Args.hasFlag( + OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager, + /* Default */ false); + if (Arg *A = Args.getLastArg(OPT_fveclib)) { StringRef Name = A->getValue(); if (Name == "Accelerate") Index: cfe/trunk/test/CodeGen/arm64_crypto.c =================================================================== --- cfe/trunk/test/CodeGen/arm64_crypto.c +++ cfe/trunk/test/CodeGen/arm64_crypto.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-feature +neon -target-feature +crypto -ffreestanding -Os -S -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-feature +neon -target-feature +crypto -ffreestanding -fexperimental-new-pass-manager -Os -S -o - %s | FileCheck %s // REQUIRES: aarch64-registered-target #include Index: cfe/trunk/test/CodeGen/inline-optim.c =================================================================== --- cfe/trunk/test/CodeGen/inline-optim.c +++ cfe/trunk/test/CodeGen/inline-optim.c @@ -1,9 +1,13 @@ // Make sure -finline-functions family flags are behaving correctly. // RUN: %clang_cc1 -triple i686-pc-win32 -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fexperimental-new-pass-manager -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s // RUN: %clang_cc1 -triple i686-pc-win32 -O3 -fno-inline-functions -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fexperimental-new-pass-manager -O3 -fno-inline-functions -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s // RUN: %clang_cc1 -triple i686-pc-win32 -O3 -finline-hint-functions -emit-llvm %s -o - | FileCheck -check-prefix=HINT %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fexperimental-new-pass-manager -O3 -finline-hint-functions -emit-llvm %s -o - | FileCheck -check-prefix=HINT %s // RUN: %clang_cc1 -triple i686-pc-win32 -O3 -finline-functions -emit-llvm %s -o - | FileCheck -check-prefix=INLINE %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fexperimental-new-pass-manager -O3 -finline-functions -emit-llvm %s -o - | FileCheck -check-prefix=INLINE %s inline int inline_hint(int a, int b) { return(a+b); } Index: cfe/trunk/test/Driver/clang_f_opts.c =================================================================== --- cfe/trunk/test/Driver/clang_f_opts.c +++ cfe/trunk/test/Driver/clang_f_opts.c @@ -469,3 +469,11 @@ // CHECK-WCHAR2: -fshort-wchar // CHECK-WCHAR2-NOT: -fno-short-wchar // DELIMITERS: {{^ *"}} + +// RUN: %clang -### -fno-experimental-new-pass-manager -fexperimental-new-pass-manager %s 2>&1 | FileCheck --check-prefix=CHECK-PM --check-prefix=CHECK-NEW-PM %s +// RUN: %clang -### -fexperimental-new-pass-manager -fno-experimental-new-pass-manager %s 2>&1 | FileCheck --check-prefix=CHECK-PM --check-prefix=CHECK-NO-NEW-PM %s +// CHECK-PM-NOT: argument unused +// CHECK-NEW-PM: -fexperimental-new-pass-manager +// CHECK-NEW-PM-NOT: -fno-experimental-new-pass-manager +// CHECK-NO-NEW-PM: -fno-experimental-new-pass-manager +// CHECK-NO-NEW-PM-NOT: -fexperimental-new-pass-manager