summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/BackendUtil.cpp143
-rw-r--r--clang/lib/Driver/Tools.cpp3
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp4
3 files changed, 146 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 8e729f1facf..3a5fdb42d7d 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/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 @@ public:
void EmitAssembly(BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS);
+
+ void EmitAssemblyWithNewPassManager(BackendAction Action,
+ std::unique_ptr<raw_pwrite_stream> OS);
};
// We need this wrapper to access LangOpts and CGOpts from extension functions
@@ -709,6 +713,134 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
}
}
+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<raw_pwrite_stream> 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<raw_pwrite_stream> OS) {
// If we are performing a ThinLTO importing compile, load the function index
@@ -801,7 +933,10 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
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.
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index 71878aa33b6..5bab0ef4a8e 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -5909,6 +5909,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
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
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 6e5f6e57a2c..ae4417c93c2 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -462,6 +462,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
}
+ 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")
OpenPOWER on IntegriCloud