Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -157,6 +157,11 @@ HelpText<"Disable implicit builtin knowledge of math functions">; } +def newpm_passes_EQ : Joined<["-"], "newpm-passes=">, + HelpText<"Pass pipeline description for new PM">; +def newpm_aa_pipeline_EQ : Joined<["-"], "newpm-aa-pipeline=">, + HelpText<"Alias analysis pipeline for the new PM">; + def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">, HelpText<"Don't run LLVM optimization passes">; def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">, Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -107,6 +107,20 @@ /// Enable additional debugging information. std::string DebugPass; + /// Pass description string for the new pass manager. + /// This is primarily for experimentation while bringing up the new pass + /// manager. It will completely replace the middle-end pipeline and so + /// will interact with options that require modifying the optimization + /// pipeline (e.g. sanitizers). + std::string NewPMPasses; + + /// Alias analysis pipeline for the new pass manager. + /// This is primarily for experimentation while bringing up the new pass + /// manager. It will completely replace the middle-end pipeline and so + /// will interact with options that require modifying the optimization + /// pipeline (e.g. sanitizers). + std::string NewPMAAPipeline; + /// The string to embed in debug information as the current working directory. std::string DebugCompilationDir; Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -31,6 +31,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/ModuleSummaryIndexObjectFile.h" +#include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/TargetRegistry.h" @@ -315,6 +316,11 @@ if (CodeGenOpts.DisableLLVMPasses) return; + // If we are going to parse a new PM pass pipeline, don't add any old PM + // passes here. + if (!CodeGenOpts.NewPMPasses.empty()) + return; + unsigned OptLevel = CodeGenOpts.OptimizationLevel; CodeGenOptions::InliningMethod Inlining = CodeGenOpts.getInlining(); @@ -744,6 +750,49 @@ // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); + if (!CodeGenOpts.NewPMPasses.empty()) { + // Use the new PM for the middle end. + // Note that we still run the old PM manager later because they contain + // e.g. the passes for printing out a BC or LL file (e.g. for -flto). + // But there is nothing else run except for the printing passes so this + // doesn't affect the actual optimization. + + // This is a really low-level internal developer option. + // Use report_fatal_error if anything goes wrong. + + PassBuilder PB(TM.get()); + AAManager AA; + if (!PB.parseAAPipeline(AA, CodeGenOpts.NewPMAAPipeline)) + report_fatal_error("Unable to parse AA pipeline description: " + + CodeGenOpts.NewPMAAPipeline); + + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + + // Register the AA manager first so that our version is the one used. + FAM.registerPass([&] { return std::move(AA); }); + + // 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; + MPM.addPass(VerifierPass()); + + // Now, add all the passes we've been requested to. + if (!PB.parsePassPipeline(MPM, CodeGenOpts.NewPMPasses)) + report_fatal_error("unable to parse pass pipeline description: " + + CodeGenOpts.NewPMPasses); + + MPM.addPass(VerifierPass()); + MPM.run(*TheModule, MAM); + } + // Run passes. For now we do all passes at once, but eventually we // would like to have the option of streaming code generation. Index: lib/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -12,6 +12,7 @@ MC ObjCARCOpts Object + Passes ProfileData ScalarOpts Support Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -840,6 +840,11 @@ Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue( Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags); + if (Arg *A = Args.getLastArg(OPT_newpm_passes_EQ)) + Opts.NewPMPasses = A->getValue(); + if (Arg *A = Args.getLastArg(OPT_newpm_aa_pipeline_EQ)) + Opts.NewPMAAPipeline = A->getValue(); + return Success; } Index: test/CodeGen/newpm-passes.c =================================================================== --- /dev/null +++ test/CodeGen/newpm-passes.c @@ -0,0 +1,26 @@ +// Check that passes get run. + +// RUN: %clang_cc1 %s -emit-llvm -o /dev/null -newpm-passes=mem2reg,aa-eval 2>&1 | FileCheck %s --check-prefix=NO-AA + +// NO-AA: ===== Alias Analysis Evaluator Report ===== +// NO-AA: 0 must alias responses + +// RUN: %clang_cc1 %s -emit-llvm -o /dev/null -newpm-passes=mem2reg,aa-eval -newpm-aa-pipeline=basic-aa 2>&1 | FileCheck %s --check-prefix=WITH-AA + +// WITH-AA: ===== Alias Analysis Evaluator Report ===== +// WITH-AA: 1 must alias responses + + +// The actual output with -flto or -emit-llvm is generated by running a +// pass in the old PM. Verify that that we still get output. + +// RUN: %clang -flto -c %s -o - -Xclang -newpm-passes=mem2reg 2>&1 | opt -S | FileCheck %s --check-prefix=OUTPUT-IS-GENERATED +// RUN: %clang -emit-llvm -S %s -o - -Xclang -newpm-passes=mem2reg 2>&1 | FileCheck %s --check-prefix=OUTPUT-IS-GENERATED + +// OUTPUT-IS-GENERATED: @foo + +int foo(int *x) { + int *y = x + 1; + int *z = y - 1; + return *x + *z; +}