xref: /freebsd-src/contrib/llvm-project/llvm/tools/llc/NewPMDriver.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
17a6dacacSDimitry Andric //===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===//
27a6dacacSDimitry Andric //
37a6dacacSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47a6dacacSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
57a6dacacSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67a6dacacSDimitry Andric //
77a6dacacSDimitry Andric //===----------------------------------------------------------------------===//
87a6dacacSDimitry Andric /// \file
97a6dacacSDimitry Andric ///
107a6dacacSDimitry Andric /// This file is just a split of the code that logically belongs in llc.cpp but
117a6dacacSDimitry Andric /// that includes the new pass manager headers.
127a6dacacSDimitry Andric ///
137a6dacacSDimitry Andric //===----------------------------------------------------------------------===//
147a6dacacSDimitry Andric 
157a6dacacSDimitry Andric #include "NewPMDriver.h"
167a6dacacSDimitry Andric #include "llvm/Analysis/CGSCCPassManager.h"
177a6dacacSDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
187a6dacacSDimitry Andric #include "llvm/CodeGen/CommandFlags.h"
197a6dacacSDimitry Andric #include "llvm/CodeGen/MIRParser/MIRParser.h"
207a6dacacSDimitry Andric #include "llvm/CodeGen/MIRPrinter.h"
217a6dacacSDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
227a6dacacSDimitry Andric #include "llvm/CodeGen/MachinePassManager.h"
237a6dacacSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
247a6dacacSDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
257a6dacacSDimitry Andric #include "llvm/IR/DiagnosticPrinter.h"
267a6dacacSDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
277a6dacacSDimitry Andric #include "llvm/IR/LLVMContext.h"
287a6dacacSDimitry Andric #include "llvm/IR/Module.h"
297a6dacacSDimitry Andric #include "llvm/IR/PassManager.h"
307a6dacacSDimitry Andric #include "llvm/IR/Verifier.h"
317a6dacacSDimitry Andric #include "llvm/IRReader/IRReader.h"
32*0fca6ea1SDimitry Andric #include "llvm/Passes/CodeGenPassBuilder.h" // TODO: Include pass headers properly.
337a6dacacSDimitry Andric #include "llvm/Passes/PassBuilder.h"
347a6dacacSDimitry Andric #include "llvm/Passes/StandardInstrumentations.h"
357a6dacacSDimitry Andric #include "llvm/Support/CommandLine.h"
367a6dacacSDimitry Andric #include "llvm/Support/Debug.h"
377a6dacacSDimitry Andric #include "llvm/Support/Error.h"
387a6dacacSDimitry Andric #include "llvm/Support/ErrorHandling.h"
397a6dacacSDimitry Andric #include "llvm/Support/FormattedStream.h"
407a6dacacSDimitry Andric #include "llvm/Support/ToolOutputFile.h"
417a6dacacSDimitry Andric #include "llvm/Support/WithColor.h"
427a6dacacSDimitry Andric #include "llvm/Target/CGPassBuilderOption.h"
437a6dacacSDimitry Andric #include "llvm/Target/TargetMachine.h"
447a6dacacSDimitry Andric #include "llvm/Target/TargetOptions.h"
457a6dacacSDimitry Andric #include "llvm/Transforms/Scalar/LoopPassManager.h"
467a6dacacSDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
477a6dacacSDimitry Andric 
487a6dacacSDimitry Andric namespace llvm {
497a6dacacSDimitry Andric extern cl::opt<bool> PrintPipelinePasses;
507a6dacacSDimitry Andric } // namespace llvm
517a6dacacSDimitry Andric 
527a6dacacSDimitry Andric using namespace llvm;
537a6dacacSDimitry Andric 
547a6dacacSDimitry Andric static cl::opt<std::string>
557a6dacacSDimitry Andric     RegAlloc("regalloc-npm",
567a6dacacSDimitry Andric              cl::desc("Register allocator to use for new pass manager"),
577a6dacacSDimitry Andric              cl::Hidden, cl::init("default"));
587a6dacacSDimitry Andric 
597a6dacacSDimitry Andric static cl::opt<bool>
607a6dacacSDimitry Andric     DebugPM("debug-pass-manager", cl::Hidden,
617a6dacacSDimitry Andric             cl::desc("Print pass management debugging information"));
627a6dacacSDimitry Andric 
637a6dacacSDimitry Andric bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
647a6dacacSDimitry Andric   DiagnosticHandler::handleDiagnostics(DI);
657a6dacacSDimitry Andric   if (DI.getKind() == llvm::DK_SrcMgr) {
667a6dacacSDimitry Andric     const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
677a6dacacSDimitry Andric     const SMDiagnostic &SMD = DISM.getSMDiag();
687a6dacacSDimitry Andric 
697a6dacacSDimitry Andric     SMD.print(nullptr, errs());
707a6dacacSDimitry Andric 
717a6dacacSDimitry Andric     // For testing purposes, we print the LocCookie here.
727a6dacacSDimitry Andric     if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
737a6dacacSDimitry Andric       WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
747a6dacacSDimitry Andric 
757a6dacacSDimitry Andric     return true;
767a6dacacSDimitry Andric   }
777a6dacacSDimitry Andric 
787a6dacacSDimitry Andric   if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
797a6dacacSDimitry Andric     if (!Remark->isEnabled())
807a6dacacSDimitry Andric       return true;
817a6dacacSDimitry Andric 
827a6dacacSDimitry Andric   DiagnosticPrinterRawOStream DP(errs());
837a6dacacSDimitry Andric   errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
847a6dacacSDimitry Andric   DI.print(DP);
857a6dacacSDimitry Andric   errs() << "\n";
867a6dacacSDimitry Andric   return true;
877a6dacacSDimitry Andric }
887a6dacacSDimitry Andric 
897a6dacacSDimitry Andric static llvm::ExitOnError ExitOnErr;
907a6dacacSDimitry Andric 
917a6dacacSDimitry Andric int llvm::compileModuleWithNewPM(
927a6dacacSDimitry Andric     StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
937a6dacacSDimitry Andric     std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
947a6dacacSDimitry Andric     std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context,
957a6dacacSDimitry Andric     const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline,
967a6dacacSDimitry Andric     CodeGenFileType FileType) {
977a6dacacSDimitry Andric 
987a6dacacSDimitry Andric   if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) {
997a6dacacSDimitry Andric     WithColor::warning(errs(), Arg0)
1007a6dacacSDimitry Andric         << "--passes cannot be used with "
1017a6dacacSDimitry Andric         << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n";
1027a6dacacSDimitry Andric     return 1;
1037a6dacacSDimitry Andric   }
1047a6dacacSDimitry Andric 
1057a6dacacSDimitry Andric   LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target);
1067a6dacacSDimitry Andric 
1077a6dacacSDimitry Andric   raw_pwrite_stream *OS = &Out->os();
1087a6dacacSDimitry Andric 
1097a6dacacSDimitry Andric   // Fetch options from TargetPassConfig
1107a6dacacSDimitry Andric   CGPassBuilderOption Opt = getCGPassBuilderOption();
1117a6dacacSDimitry Andric   Opt.DisableVerify = NoVerify;
1127a6dacacSDimitry Andric   Opt.DebugPM = DebugPM;
1137a6dacacSDimitry Andric   Opt.RegAlloc = RegAlloc;
1147a6dacacSDimitry Andric 
115*0fca6ea1SDimitry Andric   MachineModuleInfo MMI(&LLVMTM);
116*0fca6ea1SDimitry Andric 
1177a6dacacSDimitry Andric   PassInstrumentationCallbacks PIC;
118*0fca6ea1SDimitry Andric   StandardInstrumentations SI(Context, Opt.DebugPM, !NoVerify);
1197a6dacacSDimitry Andric   registerCodeGenCallback(PIC, LLVMTM);
1207a6dacacSDimitry Andric 
121*0fca6ea1SDimitry Andric   MachineFunctionAnalysisManager MFAM;
1227a6dacacSDimitry Andric   LoopAnalysisManager LAM;
1237a6dacacSDimitry Andric   FunctionAnalysisManager FAM;
1247a6dacacSDimitry Andric   CGSCCAnalysisManager CGAM;
1257a6dacacSDimitry Andric   ModuleAnalysisManager MAM;
1267a6dacacSDimitry Andric   PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
1277a6dacacSDimitry Andric   PB.registerModuleAnalyses(MAM);
1287a6dacacSDimitry Andric   PB.registerCGSCCAnalyses(CGAM);
1297a6dacacSDimitry Andric   PB.registerFunctionAnalyses(FAM);
1307a6dacacSDimitry Andric   PB.registerLoopAnalyses(LAM);
131*0fca6ea1SDimitry Andric   PB.registerMachineFunctionAnalyses(MFAM);
132*0fca6ea1SDimitry Andric   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM);
133*0fca6ea1SDimitry Andric   SI.registerCallbacks(PIC, &MAM);
1347a6dacacSDimitry Andric 
1357a6dacacSDimitry Andric   FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
136*0fca6ea1SDimitry Andric   MAM.registerPass([&] { return MachineModuleAnalysis(MMI); });
1377a6dacacSDimitry Andric 
138*0fca6ea1SDimitry Andric   ModulePassManager MPM;
139*0fca6ea1SDimitry Andric   FunctionPassManager FPM;
1407a6dacacSDimitry Andric 
1417a6dacacSDimitry Andric   if (!PassPipeline.empty()) {
1427a6dacacSDimitry Andric     // Construct a custom pass pipeline that starts after instruction
1437a6dacacSDimitry Andric     // selection.
1447a6dacacSDimitry Andric 
1457a6dacacSDimitry Andric     if (!MIR) {
1467a6dacacSDimitry Andric       WithColor::warning(errs(), Arg0) << "-passes is for .mir file only.\n";
1477a6dacacSDimitry Andric       return 1;
1487a6dacacSDimitry Andric     }
1497a6dacacSDimitry Andric 
150*0fca6ea1SDimitry Andric     // FIXME: verify that there are no IR passes.
151*0fca6ea1SDimitry Andric     ExitOnErr(PB.parsePassPipeline(MPM, PassPipeline));
152*0fca6ea1SDimitry Andric     MPM.addPass(PrintMIRPreparePass(*OS));
1537a6dacacSDimitry Andric     MachineFunctionPassManager MFPM;
1547a6dacacSDimitry Andric     MFPM.addPass(PrintMIRPass(*OS));
155*0fca6ea1SDimitry Andric     FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));
156*0fca6ea1SDimitry Andric     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
1577a6dacacSDimitry Andric 
158*0fca6ea1SDimitry Andric     if (MIR->parseMachineFunctions(*M, MAM))
1597a6dacacSDimitry Andric       return 1;
1607a6dacacSDimitry Andric   } else {
161*0fca6ea1SDimitry Andric     ExitOnErr(LLVMTM.buildCodeGenPipeline(
162*0fca6ea1SDimitry Andric         MPM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt, &PIC));
1637a6dacacSDimitry Andric   }
1647a6dacacSDimitry Andric 
1657a6dacacSDimitry Andric   if (PrintPipelinePasses) {
166*0fca6ea1SDimitry Andric     std::string PipelineStr;
167*0fca6ea1SDimitry Andric     raw_string_ostream OS(PipelineStr);
168*0fca6ea1SDimitry Andric     MPM.printPipeline(OS, [&PIC](StringRef ClassName) {
1697a6dacacSDimitry Andric       auto PassName = PIC.getPassNameForClassName(ClassName);
1707a6dacacSDimitry Andric       return PassName.empty() ? ClassName : PassName;
1717a6dacacSDimitry Andric     });
172*0fca6ea1SDimitry Andric     outs() << PipelineStr << '\n';
1737a6dacacSDimitry Andric     return 0;
1747a6dacacSDimitry Andric   }
1757a6dacacSDimitry Andric 
176*0fca6ea1SDimitry Andric   // Before executing passes, print the final values of the LLVM options.
177*0fca6ea1SDimitry Andric   cl::PrintOptionValues();
178*0fca6ea1SDimitry Andric 
179*0fca6ea1SDimitry Andric   MPM.run(*M, MAM);
180*0fca6ea1SDimitry Andric 
181*0fca6ea1SDimitry Andric   if (Context.getDiagHandlerPtr()->HasErrors)
182*0fca6ea1SDimitry Andric     exit(1);
1837a6dacacSDimitry Andric 
1847a6dacacSDimitry Andric   // Declare success.
1857a6dacacSDimitry Andric   Out->keep();
1867a6dacacSDimitry Andric   if (DwoOut)
1877a6dacacSDimitry Andric     DwoOut->keep();
1887a6dacacSDimitry Andric 
1897a6dacacSDimitry Andric   return 0;
1907a6dacacSDimitry Andric }
191