| //===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// |
| /// This file is just a split of the code that logically belongs in llc.cpp but |
| /// that includes the new pass manager headers. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "NewPMDriver.h" |
| #include "llvm/Analysis/CGSCCPassManager.h" |
| #include "llvm/Analysis/TargetLibraryInfo.h" |
| #include "llvm/CodeGen/CommandFlags.h" |
| #include "llvm/CodeGen/MIRParser/MIRParser.h" |
| #include "llvm/CodeGen/MIRPrinter.h" |
| #include "llvm/CodeGen/MachineModuleInfo.h" |
| #include "llvm/CodeGen/MachinePassManager.h" |
| #include "llvm/CodeGen/TargetPassConfig.h" |
| #include "llvm/IR/DiagnosticInfo.h" |
| #include "llvm/IR/DiagnosticPrinter.h" |
| #include "llvm/IR/IRPrintingPasses.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/IR/PassManager.h" |
| #include "llvm/IR/Verifier.h" |
| #include "llvm/IRReader/IRReader.h" |
| #include "llvm/Passes/CodeGenPassBuilder.h" // TODO: Include pass headers properly. |
| #include "llvm/Passes/PassBuilder.h" |
| #include "llvm/Passes/StandardInstrumentations.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/Error.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/FormattedStream.h" |
| #include "llvm/Support/ToolOutputFile.h" |
| #include "llvm/Support/WithColor.h" |
| #include "llvm/Target/CGPassBuilderOption.h" |
| #include "llvm/Target/TargetMachine.h" |
| #include "llvm/Target/TargetOptions.h" |
| #include "llvm/Transforms/Scalar/LoopPassManager.h" |
| #include "llvm/Transforms/Utils/Cloning.h" |
| |
| namespace llvm { |
| extern cl::opt<bool> PrintPipelinePasses; |
| } // namespace llvm |
| |
| using namespace llvm; |
| |
| static cl::opt<std::string> |
| RegAlloc("regalloc-npm", |
| cl::desc("Register allocator to use for new pass manager"), |
| cl::Hidden, cl::init("default")); |
| |
| static cl::opt<bool> |
| DebugPM("debug-pass-manager", cl::Hidden, |
| cl::desc("Print pass management debugging information")); |
| |
| bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { |
| DiagnosticHandler::handleDiagnostics(DI); |
| if (DI.getKind() == llvm::DK_SrcMgr) { |
| const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI); |
| const SMDiagnostic &SMD = DISM.getSMDiag(); |
| |
| SMD.print(nullptr, errs()); |
| |
| // For testing purposes, we print the LocCookie here. |
| if (DISM.isInlineAsmDiag() && DISM.getLocCookie()) |
| WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n"; |
| |
| return true; |
| } |
| |
| if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) |
| if (!Remark->isEnabled()) |
| return true; |
| |
| DiagnosticPrinterRawOStream DP(errs()); |
| errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; |
| DI.print(DP); |
| errs() << "\n"; |
| return true; |
| } |
| |
| static llvm::ExitOnError ExitOnErr; |
| |
| static void RunPasses(bool BOS, ToolOutputFile *Out, Module *M, |
| LLVMContext &Context, SmallString<0> &Buffer, |
| ModulePassManager *MPM, ModuleAnalysisManager *MAM, |
| MachineFunctionPassManager &MFPM, |
| MachineFunctionAnalysisManager &MFAM) { |
| assert(M && "invalid input module!"); |
| |
| // Before executing passes, print the final values of the LLVM options. |
| cl::PrintOptionValues(); |
| |
| if (MPM) { |
| assert(MAM && "expect a ModuleAnalysisManager!"); |
| MPM->run(*M, *MAM); |
| } |
| |
| ExitOnErr(MFPM.run(*M, MFAM)); |
| |
| if (Context.getDiagHandlerPtr()->HasErrors) |
| exit(1); |
| |
| if (BOS) |
| Out->os() << Buffer; |
| } |
| |
| int llvm::compileModuleWithNewPM( |
| StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR, |
| std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out, |
| std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context, |
| const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline, |
| CodeGenFileType FileType) { |
| |
| if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) { |
| WithColor::warning(errs(), Arg0) |
| << "--passes cannot be used with " |
| << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n"; |
| return 1; |
| } |
| |
| LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target); |
| |
| raw_pwrite_stream *OS = &Out->os(); |
| |
| // Manually do the buffering rather than using buffer_ostream, |
| // so we can memcmp the contents in CompileTwice mode in future. |
| SmallString<0> Buffer; |
| std::unique_ptr<raw_svector_ostream> BOS; |
| if ((codegen::getFileType() != CodeGenFileType::AssemblyFile && |
| !Out->os().supportsSeeking())) { |
| BOS = std::make_unique<raw_svector_ostream>(Buffer); |
| OS = BOS.get(); |
| } |
| |
| // Fetch options from TargetPassConfig |
| CGPassBuilderOption Opt = getCGPassBuilderOption(); |
| Opt.DisableVerify = NoVerify; |
| Opt.DebugPM = DebugPM; |
| Opt.RegAlloc = RegAlloc; |
| |
| PassInstrumentationCallbacks PIC; |
| StandardInstrumentations SI(Context, Opt.DebugPM); |
| SI.registerCallbacks(PIC); |
| registerCodeGenCallback(PIC, LLVMTM); |
| |
| LoopAnalysisManager LAM; |
| FunctionAnalysisManager FAM; |
| CGSCCAnalysisManager CGAM; |
| ModuleAnalysisManager MAM; |
| PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC); |
| PB.registerModuleAnalyses(MAM); |
| PB.registerCGSCCAnalyses(CGAM); |
| PB.registerFunctionAnalyses(FAM); |
| PB.registerLoopAnalyses(LAM); |
| PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); |
| |
| FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); |
| MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); }); |
| |
| MachineFunctionAnalysisManager MFAM(FAM, MAM); |
| |
| if (!PassPipeline.empty()) { |
| // Construct a custom pass pipeline that starts after instruction |
| // selection. |
| |
| if (!MIR) { |
| WithColor::warning(errs(), Arg0) << "-passes is for .mir file only.\n"; |
| return 1; |
| } |
| |
| MachineFunctionPassManager MFPM; |
| ExitOnErr(PB.parsePassPipeline(MFPM, PassPipeline)); |
| MFPM.addPass(PrintMIRPass(*OS)); |
| MFPM.addPass(FreeMachineFunctionPass()); |
| |
| auto &MMI = MFAM.getResult<MachineModuleAnalysis>(*M); |
| if (MIR->parseMachineFunctions(*M, MMI)) |
| return 1; |
| |
| RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, nullptr, nullptr, |
| MFPM, MFAM); |
| } else { |
| ModulePassManager MPM; |
| MachineFunctionPassManager MFPM; |
| |
| ExitOnErr(LLVMTM.buildCodeGenPipeline(MPM, MFPM, MFAM, *OS, |
| DwoOut ? &DwoOut->os() : nullptr, |
| FileType, Opt, &PIC)); |
| |
| auto StartStopInfo = TargetPassConfig::getStartStopInfo(PIC); |
| assert(StartStopInfo && "Expect StartStopInfo!"); |
| // Add IR or MIR printing pass according the pass type. |
| |
| if (auto StopPassName = StartStopInfo->StopPass; !StopPassName.empty()) { |
| MFPM.addPass(PrintMIRPass(*OS)); |
| MFPM.addPass(FreeMachineFunctionPass()); |
| } |
| |
| if (PrintPipelinePasses) { |
| std::string IRPipeline; |
| raw_string_ostream IRSOS(IRPipeline); |
| MPM.printPipeline(IRSOS, [&PIC](StringRef ClassName) { |
| auto PassName = PIC.getPassNameForClassName(ClassName); |
| return PassName.empty() ? ClassName : PassName; |
| }); |
| outs() << "IR pipeline: " << IRPipeline << '\n'; |
| |
| std::string MIRPipeline; |
| raw_string_ostream MIRSOS(MIRPipeline); |
| MFPM.printPipeline(MIRSOS, [&PIC](StringRef ClassName) { |
| auto PassName = PIC.getPassNameForClassName(ClassName); |
| return PassName.empty() ? ClassName : PassName; |
| }); |
| outs() << "MIR pipeline: " << MIRPipeline << '\n'; |
| return 0; |
| } |
| |
| RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM, MFPM, |
| MFAM); |
| } |
| |
| // Declare success. |
| Out->keep(); |
| if (DwoOut) |
| DwoOut->keep(); |
| |
| return 0; |
| } |