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/CommandFlags.h" |
19 | #include "llvm/CodeGen/MIRParser/MIRParser.h" |
20 | #include "llvm/CodeGen/MIRPrinter.h" |
21 | #include "llvm/CodeGen/MachineFunctionAnalysis.h" |
22 | #include "llvm/CodeGen/MachineModuleInfo.h" |
23 | #include "llvm/CodeGen/MachinePassManager.h" |
24 | #include "llvm/CodeGen/MachineVerifier.h" |
25 | #include "llvm/CodeGen/TargetPassConfig.h" |
26 | #include "llvm/IR/DiagnosticInfo.h" |
27 | #include "llvm/IR/DiagnosticPrinter.h" |
28 | #include "llvm/IR/IRPrintingPasses.h" |
29 | #include "llvm/IR/LLVMContext.h" |
30 | #include "llvm/IR/Module.h" |
31 | #include "llvm/IR/PassManager.h" |
32 | #include "llvm/IR/Verifier.h" |
33 | #include "llvm/IRReader/IRReader.h" |
34 | #include "llvm/Passes/PassBuilder.h" |
35 | #include "llvm/Passes/StandardInstrumentations.h" |
36 | #include "llvm/Support/CommandLine.h" |
37 | #include "llvm/Support/Debug.h" |
38 | #include "llvm/Support/Error.h" |
39 | #include "llvm/Support/ErrorHandling.h" |
40 | #include "llvm/Support/FormattedStream.h" |
41 | #include "llvm/Support/ToolOutputFile.h" |
42 | #include "llvm/Support/WithColor.h" |
43 | #include "llvm/Target/CGPassBuilderOption.h" |
44 | #include "llvm/Target/TargetMachine.h" |
45 | #include "llvm/Target/TargetOptions.h" |
46 | #include "llvm/Transforms/Scalar/LoopPassManager.h" |
47 | #include "llvm/Transforms/Utils/Cloning.h" |
48 | |
49 | using namespace llvm; |
50 | |
51 | static cl::opt<RegAllocType, false, RegAllocTypeParser> |
52 | RegAlloc("regalloc-npm" , |
53 | cl::desc("Register allocator to use for new pass manager" ), |
54 | cl::Hidden, cl::init(Val: RegAllocType::Unset)); |
55 | |
56 | static cl::opt<bool> |
57 | DebugPM("debug-pass-manager" , cl::Hidden, |
58 | cl::desc("Print pass management debugging information" )); |
59 | |
60 | bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { |
61 | DiagnosticHandler::handleDiagnostics(DI); |
62 | if (DI.getKind() == llvm::DK_SrcMgr) { |
63 | const auto &DISM = cast<DiagnosticInfoSrcMgr>(Val: DI); |
64 | const SMDiagnostic &SMD = DISM.getSMDiag(); |
65 | |
66 | SMD.print(ProgName: nullptr, S&: errs()); |
67 | |
68 | // For testing purposes, we print the LocCookie here. |
69 | if (DISM.isInlineAsmDiag() && DISM.getLocCookie()) |
70 | WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n" ; |
71 | |
72 | return true; |
73 | } |
74 | |
75 | if (auto * = dyn_cast<DiagnosticInfoOptimizationBase>(Val: &DI)) |
76 | if (!Remark->isEnabled()) |
77 | return true; |
78 | |
79 | DiagnosticPrinterRawOStream DP(errs()); |
80 | errs() << LLVMContext::getDiagnosticMessagePrefix(Severity: DI.getSeverity()) << ": " ; |
81 | DI.print(DP); |
82 | errs() << "\n" ; |
83 | return true; |
84 | } |
85 | |
86 | static llvm::ExitOnError ExitOnErr; |
87 | |
88 | int llvm::compileModuleWithNewPM( |
89 | StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR, |
90 | std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out, |
91 | std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context, |
92 | const TargetLibraryInfoImpl &TLII, VerifierKind VK, StringRef PassPipeline, |
93 | CodeGenFileType FileType) { |
94 | |
95 | if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) { |
96 | WithColor::error(OS&: errs(), Prefix: Arg0) |
97 | << "--passes cannot be used with " |
98 | << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n" ; |
99 | return 1; |
100 | } |
101 | |
102 | raw_pwrite_stream *OS = &Out->os(); |
103 | |
104 | // Fetch options from TargetPassConfig |
105 | CGPassBuilderOption Opt = getCGPassBuilderOption(); |
106 | Opt.DisableVerify = VK != VerifierKind::InputOutput; |
107 | Opt.DebugPM = DebugPM; |
108 | Opt.RegAlloc = RegAlloc; |
109 | |
110 | MachineModuleInfo MMI(Target.get()); |
111 | |
112 | PassInstrumentationCallbacks PIC; |
113 | StandardInstrumentations SI(Context, Opt.DebugPM, |
114 | VK == VerifierKind::EachPass); |
115 | registerCodeGenCallback(PIC, *Target); |
116 | |
117 | MachineFunctionAnalysisManager MFAM; |
118 | LoopAnalysisManager LAM; |
119 | FunctionAnalysisManager FAM; |
120 | CGSCCAnalysisManager CGAM; |
121 | ModuleAnalysisManager MAM; |
122 | PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC); |
123 | PB.registerModuleAnalyses(MAM); |
124 | PB.registerCGSCCAnalyses(CGAM); |
125 | PB.registerFunctionAnalyses(FAM); |
126 | PB.registerLoopAnalyses(LAM); |
127 | PB.registerMachineFunctionAnalyses(MFAM); |
128 | PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, MFAM: &MFAM); |
129 | SI.registerCallbacks(PIC, MAM: &MAM); |
130 | |
131 | FAM.registerPass(PassBuilder: [&] { return TargetLibraryAnalysis(TLII); }); |
132 | MAM.registerPass(PassBuilder: [&] { return MachineModuleAnalysis(MMI); }); |
133 | |
134 | ModulePassManager MPM; |
135 | FunctionPassManager FPM; |
136 | |
137 | if (!PassPipeline.empty()) { |
138 | // Construct a custom pass pipeline that starts after instruction |
139 | // selection. |
140 | |
141 | if (!MIR) { |
142 | WithColor::error(OS&: errs(), Prefix: Arg0) << "-passes is for .mir file only.\n" ; |
143 | return 1; |
144 | } |
145 | |
146 | // FIXME: verify that there are no IR passes. |
147 | ExitOnErr(PB.parsePassPipeline(MPM, PipelineText: PassPipeline)); |
148 | MPM.addPass(Pass: PrintMIRPreparePass(*OS)); |
149 | MachineFunctionPassManager MFPM; |
150 | if (VK == VerifierKind::InputOutput) |
151 | MFPM.addPass(Pass: MachineVerifierPass()); |
152 | MFPM.addPass(Pass: PrintMIRPass(*OS)); |
153 | FPM.addPass(Pass: createFunctionToMachineFunctionPassAdaptor(Pass: std::move(MFPM))); |
154 | MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM))); |
155 | |
156 | } else { |
157 | ExitOnErr(Target->buildCodeGenPipeline( |
158 | MPM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt, &PIC)); |
159 | } |
160 | |
161 | // If user only wants to print the pipeline, print it before parsing the MIR. |
162 | if (PrintPipelinePasses) { |
163 | std::string PipelineStr; |
164 | raw_string_ostream OS(PipelineStr); |
165 | MPM.printPipeline(OS, MapClassName2PassName: [&PIC](StringRef ClassName) { |
166 | auto PassName = PIC.getPassNameForClassName(ClassName); |
167 | return PassName.empty() ? ClassName : PassName; |
168 | }); |
169 | outs() << PipelineStr << '\n'; |
170 | return 0; |
171 | } |
172 | |
173 | if (MIR && MIR->parseMachineFunctions(M&: *M, MAM)) |
174 | return 1; |
175 | |
176 | // Before executing passes, print the final values of the LLVM options. |
177 | cl::PrintOptionValues(); |
178 | |
179 | MPM.run(IR&: *M, AM&: MAM); |
180 | |
181 | if (Context.getDiagHandlerPtr()->HasErrors) |
182 | exit(status: 1); |
183 | |
184 | // Declare success. |
185 | Out->keep(); |
186 | if (DwoOut) |
187 | DwoOut->keep(); |
188 | |
189 | return 0; |
190 | } |
191 | |