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