Skip to content

Commit b5f4127

Browse files
yuanfang-chenpaperchalice
authored andcommitted
[NewPM][CodeGen] Add NPM support to llc
1 parent f64a057 commit b5f4127

File tree

8 files changed

+361
-47
lines changed

8 files changed

+361
-47
lines changed

llvm/include/llvm/IR/PassInstrumentation.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,23 @@ class PassInstrumentationCallbacks {
8484
using AfterAnalysisFunc = void(StringRef, Any);
8585
using AnalysisInvalidatedFunc = void(StringRef, Any);
8686
using AnalysesClearedFunc = void(StringRef);
87+
using StartStopFunc = bool(StringRef, Any);
88+
89+
struct CodeGenStartStopInfo {
90+
StringRef Start;
91+
StringRef Stop;
92+
93+
bool IsStopMachinePass = false;
94+
95+
llvm::unique_function<StartStopFunc> StartStopCallback;
96+
97+
bool operator()(StringRef PassID, Any IR) {
98+
return StartStopCallback(PassID, IR);
99+
}
100+
bool isStopMachineFunctionPass() const { return IsStopMachinePass; }
101+
bool willCompleteCodeGenPipeline() const { return Stop.empty(); }
102+
StringRef getStop() const { return Stop; }
103+
};
87104

88105
public:
89106
PassInstrumentationCallbacks() = default;
@@ -148,6 +165,17 @@ class PassInstrumentationCallbacks {
148165
AnalysesClearedCallbacks.emplace_back(std::move(C));
149166
}
150167

168+
void registerStartStopInfo(CodeGenStartStopInfo &&C) {
169+
StartStopInfo = std::move(C);
170+
}
171+
172+
bool isStartStopInfoRegistered() const { return StartStopInfo.has_value(); }
173+
174+
CodeGenStartStopInfo &getStartStopInfo() {
175+
assert(StartStopInfo.has_value() && "StartStopInfo is unregistered!");
176+
return *StartStopInfo;
177+
}
178+
151179
/// Add a class name to pass name mapping for use by pass instrumentation.
152180
void addClassToPassName(StringRef ClassName, StringRef PassName);
153181
/// Get the pass name for a given pass class name.
@@ -183,6 +211,8 @@ class PassInstrumentationCallbacks {
183211
/// These are run on analyses that have been cleared.
184212
SmallVector<llvm::unique_function<AnalysesClearedFunc>, 4>
185213
AnalysesClearedCallbacks;
214+
/// For `llc` -start-* -stop-* options.
215+
std::optional<CodeGenStartStopInfo> StartStopInfo;
186216

187217
StringMap<std::string> ClassToPassName;
188218
};
@@ -236,6 +266,9 @@ class PassInstrumentation {
236266
ShouldRun &= C(Pass.name(), llvm::Any(&IR));
237267
}
238268

269+
if (Callbacks->StartStopInfo)
270+
ShouldRun &= (*Callbacks->StartStopInfo)(Pass.name(), llvm::Any(&IR));
271+
239272
if (ShouldRun) {
240273
for (auto &C : Callbacks->BeforeNonSkippedPassCallbacks)
241274
C(Pass.name(), llvm::Any(&IR));

llvm/include/llvm/Target/TargetMachine.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,15 @@ class LLVMTargetMachine : public TargetMachine {
461461
}
462462

463463
virtual std::pair<StringRef, bool> getPassNameFromLegacyName(StringRef) {
464-
llvm_unreachable(
465-
"getPassNameFromLegacyName parseMIRPipeline is not overridden");
464+
llvm_unreachable("getPassNameFromLegacyName is not overridden");
465+
}
466+
467+
virtual Error parseMIRPipeline(MachineFunctionPassManager &MFPM,
468+
StringRef PipelineText,
469+
CGPassBuilderOption Opts,
470+
MachineFunctionAnalysisManager &MFAM,
471+
PassInstrumentationCallbacks *PIC) {
472+
llvm_unreachable("parseMIRPipeline is not overridden");
466473
}
467474

468475
/// Add passes to the specified pass manager to get machine code emitted with

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,9 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
506506
unsigned StopBeforeInstanceNum = 0;
507507
unsigned StopAfterInstanceNum = 0;
508508

509+
bool IsStopBeforeMachinePass = false;
510+
bool IsStopAfterMachinePass = false;
511+
509512
std::tie(StartBefore, StartBeforeInstanceNum) =
510513
getPassNameAndInstanceNum(StartBeforeOpt);
511514
std::tie(StartAfter, StartAfterInstanceNum) =
@@ -534,7 +537,15 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
534537
report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") +
535538
Twine(StopAfterOptName) + Twine(" specified!"));
536539

537-
PIC.registerShouldRunOptionalPassCallback(
540+
std::vector<StringRef> SpecialPasses = {"PassManager", "PassAdaptor",
541+
"PrintMIRPass", "PrintModulePass"};
542+
543+
PassInstrumentationCallbacks::CodeGenStartStopInfo Info;
544+
Info.Start = StartBefore.empty() ? StartAfter : StartBefore;
545+
Info.Stop = StopBefore.empty() ? StopAfter : StopBefore;
546+
547+
Info.IsStopMachinePass = IsStopBeforeMachinePass || IsStopAfterMachinePass;
548+
Info.StartStopCallback =
538549
[=, EnableCurrent = StartBefore.empty() && StartAfter.empty(),
539550
EnableNext = std::optional<bool>(), StartBeforeCount = 0u,
540551
StartAfterCount = 0u, StopBeforeCount = 0u,
@@ -565,8 +576,10 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
565576
EnableCurrent = true;
566577
if (StopBeforePass && StopBeforeCount++ == StopBeforeInstanceNum)
567578
EnableCurrent = false;
568-
return EnableCurrent;
569-
});
579+
return EnableCurrent || isSpecialPass(P, SpecialPasses);
580+
};
581+
582+
PIC.registerStartStopInfo(std::move(Info));
570583
}
571584

572585
void llvm::registerCodeGenCallback(PassInstrumentationCallbacks &PIC,

llvm/lib/Passes/StandardInstrumentations.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,9 +1040,10 @@ void PrintPassInstrumentation::registerCallbacks(
10401040
SpecialPasses.emplace_back("PassAdaptor");
10411041
}
10421042

1043-
PIC.registerBeforeSkippedPassCallback([this, SpecialPasses](StringRef PassID,
1044-
Any IR) {
1045-
assert(!isSpecialPass(PassID, SpecialPasses) &&
1043+
PIC.registerBeforeSkippedPassCallback([this, SpecialPasses,
1044+
&PIC](StringRef PassID, Any IR) {
1045+
assert((!isSpecialPass(PassID, SpecialPasses) ||
1046+
PIC.isStartStopInfoRegistered()) &&
10461047
"Unexpectedly skipping special pass");
10471048

10481049
print() << "Skipping pass: " << PassID << " on " << getIRName(IR) << "\n";

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

0 commit comments

Comments
 (0)