Skip to content

Commit 2b50263

Browse files
yuanfang-chenpaperchalice
authored andcommitted
[NewPM][CodeGen] Add NPM support to llc
1 parent 7f96af2 commit 2b50263

File tree

4 files changed

+329
-32
lines changed

4 files changed

+329
-32
lines changed

llvm/tools/llc/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ set(LLVM_LINK_COMPONENTS
88
CodeGen
99
CodeGenTypes
1010
Core
11+
IRPrinter
1112
IRReader
1213
MC
1314
MIRParser
15+
Passes
1416
Remarks
1517
ScalarOpts
1618
SelectionDAG
@@ -23,6 +25,7 @@ set(LLVM_LINK_COMPONENTS
2325

2426
add_llvm_tool(llc
2527
llc.cpp
28+
NewPMDriver.cpp
2629

2730
DEPENDS
2831
intrinsics_gen

llvm/tools/llc/NewPMDriver.cpp

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
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<RegAllocType> RegAlloc(
55+
"regalloc-npm", cl::desc("Register allocator to use for new pass manager"),
56+
cl::Hidden, cl::ValueOptional, cl::init(RegAllocType::Default),
57+
cl::values(
58+
clEnumValN(RegAllocType::Default, "default",
59+
"pick register allocator based on -O option"),
60+
clEnumValN(RegAllocType::Basic, "basic", "basic register allocator"),
61+
clEnumValN(RegAllocType::Fast, "fast", "fast register allocator"),
62+
clEnumValN(RegAllocType::Greedy, "greedy", "greedy register allocator"),
63+
clEnumValN(RegAllocType::PBQP, "pbqp", "PBQP register allocator")));
64+
65+
static cl::opt<bool>
66+
DebugPM("debug-pass-manager", cl::Hidden,
67+
cl::desc("Print pass management debugging information"));
68+
69+
bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
70+
DiagnosticHandler::handleDiagnostics(DI);
71+
if (DI.getKind() == llvm::DK_SrcMgr) {
72+
const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
73+
const SMDiagnostic &SMD = DISM.getSMDiag();
74+
75+
SMD.print(nullptr, errs());
76+
77+
// For testing purposes, we print the LocCookie here.
78+
if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
79+
WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
80+
81+
return true;
82+
}
83+
84+
if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
85+
if (!Remark->isEnabled())
86+
return true;
87+
88+
DiagnosticPrinterRawOStream DP(errs());
89+
errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
90+
DI.print(DP);
91+
errs() << "\n";
92+
return true;
93+
}
94+
95+
static llvm::ExitOnError ExitOnErr;
96+
97+
static void RunPasses(bool BOS, ToolOutputFile *Out, Module *M,
98+
LLVMContext &Context, SmallString<0> &Buffer,
99+
ModulePassManager *MPM, ModuleAnalysisManager *MAM,
100+
MachineFunctionPassManager &MFPM,
101+
MachineFunctionAnalysisManager &MFAM) {
102+
assert(M && "invalid input module!");
103+
104+
// Before executing passes, print the final values of the LLVM options.
105+
cl::PrintOptionValues();
106+
107+
if (MPM) {
108+
assert(MAM && "expect a ModuleAnalysisManager!");
109+
MPM->run(*M, *MAM);
110+
}
111+
112+
ExitOnErr(MFPM.run(*M, MFAM));
113+
114+
if (Context.getDiagHandlerPtr()->HasErrors)
115+
exit(1);
116+
117+
if (BOS)
118+
Out->os() << Buffer;
119+
}
120+
121+
int llvm::compileModuleWithNewPM(
122+
StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
123+
std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
124+
std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context,
125+
const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline,
126+
CodeGenFileType FileType) {
127+
128+
if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) {
129+
WithColor::warning(errs(), Arg0)
130+
<< "run-pass cannot be used with "
131+
<< TargetPassConfig::getLimitedCodeGenPipelineReason(" and ") << ".\n";
132+
return 1;
133+
}
134+
135+
LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target);
136+
137+
{
138+
raw_pwrite_stream *OS = &Out->os();
139+
140+
// Manually do the buffering rather than using buffer_ostream,
141+
// so we can memcmp the contents in CompileTwice mode in future.
142+
SmallString<0> Buffer;
143+
std::unique_ptr<raw_svector_ostream> BOS;
144+
if ((codegen::getFileType() != CodeGenFileType::AssemblyFile &&
145+
!Out->os().supportsSeeking())) {
146+
BOS = std::make_unique<raw_svector_ostream>(Buffer);
147+
OS = BOS.get();
148+
}
149+
150+
// Fetch options from TargetPassConfig
151+
CGPassBuilderOption Opt = getCGPassBuilderOption();
152+
Opt.DisableVerify = NoVerify;
153+
Opt.DebugPM = DebugPM;
154+
Opt.RegAlloc = RegAlloc;
155+
156+
PassInstrumentationCallbacks PIC;
157+
StandardInstrumentations SI(Context, Opt.DebugPM);
158+
SI.registerCallbacks(PIC);
159+
registerCodeGenCallback(PIC, LLVMTM);
160+
161+
LoopAnalysisManager LAM;
162+
FunctionAnalysisManager FAM;
163+
CGSCCAnalysisManager CGAM;
164+
ModuleAnalysisManager MAM;
165+
PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
166+
PB.registerModuleAnalyses(MAM);
167+
PB.registerCGSCCAnalyses(CGAM);
168+
PB.registerFunctionAnalyses(FAM);
169+
PB.registerLoopAnalyses(LAM);
170+
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
171+
172+
FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
173+
MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); });
174+
175+
MachineFunctionAnalysisManager MFAM(FAM, MAM);
176+
177+
if (!PassPipeline.empty()) {
178+
// Construct a custom pass pipeline that starts after instruction
179+
// selection.
180+
181+
if (!MIR) {
182+
WithColor::warning(errs(), Arg0) << "-passes is for .mir file only.\n";
183+
return 1;
184+
}
185+
186+
MachineFunctionPassManager MFPM;
187+
ExitOnErr(PB.parsePassPipeline(MFPM, PassPipeline));
188+
MFPM.addPass(PrintMIRPass(*OS));
189+
MFPM.addPass(FreeMachineFunctionPass());
190+
191+
auto &MMI = MFAM.getResult<MachineModuleAnalysis>(*M);
192+
if (MIR->parseMachineFunctions(*M, MMI))
193+
return 1;
194+
195+
RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, nullptr,
196+
nullptr, MFPM, MFAM);
197+
} else {
198+
ModulePassManager MPM;
199+
MachineFunctionPassManager MFPM;
200+
201+
ExitOnErr(LLVMTM.buildCodeGenPipeline(MPM, MFPM, MFAM, *OS,
202+
DwoOut ? &DwoOut->os() : nullptr,
203+
FileType, Opt, &PIC));
204+
205+
auto StartStopInfo = TargetPassConfig::getStartStopInfo(PIC);
206+
assert(StartStopInfo && "Expect StartStopInfo!");
207+
// Add IR or MIR printing pass according the pass type.
208+
209+
if (auto StopPassName = StartStopInfo->StopPass; !StopPassName.empty()) {
210+
MFPM.addPass(PrintMIRPass(*OS));
211+
MFPM.addPass(FreeMachineFunctionPass());
212+
}
213+
214+
if (PrintPipelinePasses) {
215+
std::string IRPipeline;
216+
raw_string_ostream IRSOS(IRPipeline);
217+
MPM.printPipeline(IRSOS, [&PIC](StringRef ClassName) {
218+
auto PassName = PIC.getPassNameForClassName(ClassName);
219+
return PassName.empty() ? ClassName : PassName;
220+
});
221+
outs() << "IR pipeline: " << IRPipeline << '\n';
222+
223+
std::string MIRPipeline;
224+
raw_string_ostream MIRSOS(MIRPipeline);
225+
MFPM.printPipeline(MIRSOS, [&PIC](StringRef ClassName) {
226+
auto PassName = PIC.getPassNameForClassName(ClassName);
227+
return PassName.empty() ? ClassName : PassName;
228+
});
229+
outs() << "MIR pipeline: " << MIRPipeline << '\n';
230+
}
231+
232+
RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM,
233+
MFPM, MFAM);
234+
}
235+
}
236+
237+
// Declare success.
238+
Out->keep();
239+
if (DwoOut)
240+
DwoOut->keep();
241+
242+
return 0;
243+
}

llvm/tools/llc/NewPMDriver.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===- NewPMDriver.h - Function to drive llc with the new PM ----*- C++ -*-===//
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+
/// A single function which is called to drive the llc behavior for the new
11+
/// PassManager.
12+
///
13+
/// This is only in a separate TU with a header to avoid including all of the
14+
/// old pass manager headers and the new pass manager headers into the same
15+
/// file. Eventually all of the routines here will get folded back into
16+
/// llc.cpp.
17+
///
18+
//===----------------------------------------------------------------------===//
19+
#ifndef LLVM_TOOLS_LLC_NEWPMDRIVER_H
20+
#define LLVM_TOOLS_LLC_NEWPMDRIVER_H
21+
22+
#include "llvm/IR/DiagnosticHandler.h"
23+
#include "llvm/Support/CodeGen.h"
24+
#include <memory>
25+
#include <vector>
26+
27+
namespace llvm {
28+
class Module;
29+
class TargetLibraryInfoImpl;
30+
class TargetMachine;
31+
class ToolOutputFile;
32+
class LLVMContext;
33+
class MIRParser;
34+
35+
struct LLCDiagnosticHandler : public DiagnosticHandler {
36+
bool handleDiagnostics(const DiagnosticInfo &DI) override;
37+
};
38+
39+
int compileModuleWithNewPM(StringRef Arg0, std::unique_ptr<Module> M,
40+
std::unique_ptr<MIRParser> MIR,
41+
std::unique_ptr<TargetMachine> Target,
42+
std::unique_ptr<ToolOutputFile> Out,
43+
std::unique_ptr<ToolOutputFile> DwoOut,
44+
LLVMContext &Context,
45+
const TargetLibraryInfoImpl &TLII, bool NoVerify,
46+
StringRef PassPipeline, CodeGenFileType FileType);
47+
} // namespace llvm
48+
49+
#endif

0 commit comments

Comments
 (0)