1 //===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file is just a split of the code that logically belongs in llc.cpp but 11 /// that includes the new pass manager headers. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "NewPMDriver.h" 16 #include "llvm/Analysis/CGSCCPassManager.h" 17 #include "llvm/Analysis/TargetLibraryInfo.h" 18 #include "llvm/CodeGen/CodeGenPassBuilder.h" 19 #include "llvm/CodeGen/CommandFlags.h" 20 #include "llvm/CodeGen/MIRParser/MIRParser.h" 21 #include "llvm/CodeGen/MIRPrinter.h" 22 #include "llvm/CodeGen/MachineModuleInfo.h" 23 #include "llvm/CodeGen/MachinePassManager.h" 24 #include "llvm/CodeGen/TargetPassConfig.h" 25 #include "llvm/IR/DiagnosticInfo.h" 26 #include "llvm/IR/DiagnosticPrinter.h" 27 #include "llvm/IR/IRPrintingPasses.h" 28 #include "llvm/IR/LLVMContext.h" 29 #include "llvm/IR/Module.h" 30 #include "llvm/IR/PassManager.h" 31 #include "llvm/IR/Verifier.h" 32 #include "llvm/IRReader/IRReader.h" 33 #include "llvm/Passes/PassBuilder.h" 34 #include "llvm/Passes/StandardInstrumentations.h" 35 #include "llvm/Support/CommandLine.h" 36 #include "llvm/Support/Debug.h" 37 #include "llvm/Support/Error.h" 38 #include "llvm/Support/ErrorHandling.h" 39 #include "llvm/Support/FormattedStream.h" 40 #include "llvm/Support/ToolOutputFile.h" 41 #include "llvm/Support/WithColor.h" 42 #include "llvm/Target/CGPassBuilderOption.h" 43 #include "llvm/Target/TargetMachine.h" 44 #include "llvm/Target/TargetOptions.h" 45 #include "llvm/Transforms/Scalar/LoopPassManager.h" 46 #include "llvm/Transforms/Utils/Cloning.h" 47 48 namespace llvm { 49 extern cl::opt<bool> PrintPipelinePasses; 50 } // namespace llvm 51 52 using namespace llvm; 53 54 static cl::opt<std::string> 55 RegAlloc("regalloc-npm", 56 cl::desc("Register allocator to use for new pass manager"), 57 cl::Hidden, cl::init("default")); 58 59 static cl::opt<bool> 60 DebugPM("debug-pass-manager", cl::Hidden, 61 cl::desc("Print pass management debugging information")); 62 63 bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { 64 DiagnosticHandler::handleDiagnostics(DI); 65 if (DI.getKind() == llvm::DK_SrcMgr) { 66 const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI); 67 const SMDiagnostic &SMD = DISM.getSMDiag(); 68 69 SMD.print(nullptr, errs()); 70 71 // For testing purposes, we print the LocCookie here. 72 if (DISM.isInlineAsmDiag() && DISM.getLocCookie()) 73 WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n"; 74 75 return true; 76 } 77 78 if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) 79 if (!Remark->isEnabled()) 80 return true; 81 82 DiagnosticPrinterRawOStream DP(errs()); 83 errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; 84 DI.print(DP); 85 errs() << "\n"; 86 return true; 87 } 88 89 static llvm::ExitOnError ExitOnErr; 90 91 static void RunPasses(bool BOS, ToolOutputFile *Out, Module *M, 92 LLVMContext &Context, SmallString<0> &Buffer, 93 ModulePassManager *MPM, ModuleAnalysisManager *MAM, 94 MachineFunctionPassManager &MFPM, 95 MachineFunctionAnalysisManager &MFAM) { 96 assert(M && "invalid input module!"); 97 98 // Before executing passes, print the final values of the LLVM options. 99 cl::PrintOptionValues(); 100 101 if (MPM) { 102 assert(MAM && "expect a ModuleAnalysisManager!"); 103 MPM->run(*M, *MAM); 104 } 105 106 ExitOnErr(MFPM.run(*M, MFAM)); 107 108 if (Context.getDiagHandlerPtr()->HasErrors) 109 exit(1); 110 111 if (BOS) 112 Out->os() << Buffer; 113 } 114 115 int llvm::compileModuleWithNewPM( 116 StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR, 117 std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out, 118 std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context, 119 const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline, 120 CodeGenFileType FileType) { 121 122 if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) { 123 WithColor::warning(errs(), Arg0) 124 << "--passes cannot be used with " 125 << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n"; 126 return 1; 127 } 128 129 LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target); 130 131 raw_pwrite_stream *OS = &Out->os(); 132 133 // Manually do the buffering rather than using buffer_ostream, 134 // so we can memcmp the contents in CompileTwice mode in future. 135 SmallString<0> Buffer; 136 std::unique_ptr<raw_svector_ostream> BOS; 137 if ((codegen::getFileType() != CodeGenFileType::AssemblyFile && 138 !Out->os().supportsSeeking())) { 139 BOS = std::make_unique<raw_svector_ostream>(Buffer); 140 OS = BOS.get(); 141 } 142 143 // Fetch options from TargetPassConfig 144 CGPassBuilderOption Opt = getCGPassBuilderOption(); 145 Opt.DisableVerify = NoVerify; 146 Opt.DebugPM = DebugPM; 147 Opt.RegAlloc = RegAlloc; 148 149 PassInstrumentationCallbacks PIC; 150 StandardInstrumentations SI(Context, Opt.DebugPM); 151 SI.registerCallbacks(PIC); 152 registerCodeGenCallback(PIC, LLVMTM); 153 154 LoopAnalysisManager LAM; 155 FunctionAnalysisManager FAM; 156 CGSCCAnalysisManager CGAM; 157 ModuleAnalysisManager MAM; 158 PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC); 159 PB.registerModuleAnalyses(MAM); 160 PB.registerCGSCCAnalyses(CGAM); 161 PB.registerFunctionAnalyses(FAM); 162 PB.registerLoopAnalyses(LAM); 163 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); 164 165 FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); 166 MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); }); 167 168 MachineFunctionAnalysisManager MFAM(FAM, MAM); 169 170 if (!PassPipeline.empty()) { 171 // Construct a custom pass pipeline that starts after instruction 172 // selection. 173 174 if (!MIR) { 175 WithColor::warning(errs(), Arg0) << "-passes is for .mir file only.\n"; 176 return 1; 177 } 178 179 MachineFunctionPassManager MFPM; 180 ExitOnErr(PB.parsePassPipeline(MFPM, PassPipeline)); 181 MFPM.addPass(PrintMIRPass(*OS)); 182 MFPM.addPass(FreeMachineFunctionPass()); 183 184 auto &MMI = MFAM.getResult<MachineModuleAnalysis>(*M); 185 if (MIR->parseMachineFunctions(*M, MMI)) 186 return 1; 187 188 RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, nullptr, nullptr, 189 MFPM, MFAM); 190 } else { 191 ModulePassManager MPM; 192 MachineFunctionPassManager MFPM; 193 194 ExitOnErr(LLVMTM.buildCodeGenPipeline(MPM, MFPM, MFAM, *OS, 195 DwoOut ? &DwoOut->os() : nullptr, 196 FileType, Opt, &PIC)); 197 198 auto StartStopInfo = TargetPassConfig::getStartStopInfo(PIC); 199 assert(StartStopInfo && "Expect StartStopInfo!"); 200 // Add IR or MIR printing pass according the pass type. 201 202 if (auto StopPassName = StartStopInfo->StopPass; !StopPassName.empty()) { 203 MFPM.addPass(PrintMIRPass(*OS)); 204 MFPM.addPass(FreeMachineFunctionPass()); 205 } 206 207 if (PrintPipelinePasses) { 208 std::string IRPipeline; 209 raw_string_ostream IRSOS(IRPipeline); 210 MPM.printPipeline(IRSOS, [&PIC](StringRef ClassName) { 211 auto PassName = PIC.getPassNameForClassName(ClassName); 212 return PassName.empty() ? ClassName : PassName; 213 }); 214 outs() << "IR pipeline: " << IRPipeline << '\n'; 215 216 std::string MIRPipeline; 217 raw_string_ostream MIRSOS(MIRPipeline); 218 MFPM.printPipeline(MIRSOS, [&PIC](StringRef ClassName) { 219 auto PassName = PIC.getPassNameForClassName(ClassName); 220 return PassName.empty() ? ClassName : PassName; 221 }); 222 outs() << "MIR pipeline: " << MIRPipeline << '\n'; 223 return 0; 224 } 225 226 RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM, MFPM, 227 MFAM); 228 } 229 230 // Declare success. 231 Out->keep(); 232 if (DwoOut) 233 DwoOut->keep(); 234 235 return 0; 236 } 237