Skip to content

Commit a87204c

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

File tree

8 files changed

+362
-47
lines changed

8 files changed

+362
-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
@@ -516,6 +516,9 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
516516
unsigned StopBeforeInstanceNum = 0;
517517
unsigned StopAfterInstanceNum = 0;
518518

519+
bool IsStopBeforeMachinePass = false;
520+
bool IsStopAfterMachinePass = false;
521+
519522
std::tie(StartBefore, StartBeforeInstanceNum) =
520523
getPassNameAndInstanceNum(StartBeforeOpt);
521524
std::tie(StartAfter, StartAfterInstanceNum) =
@@ -544,7 +547,15 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
544547
report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") +
545548
Twine(StopAfterOptName) + Twine(" specified!"));
546549

547-
PIC.registerShouldRunOptionalPassCallback(
550+
std::vector<StringRef> SpecialPasses = {"PassManager", "PassAdaptor",
551+
"PrintMIRPass", "PrintModulePass"};
552+
553+
PassInstrumentationCallbacks::CodeGenStartStopInfo Info;
554+
Info.Start = StartBefore.empty() ? StartAfter : StartBefore;
555+
Info.Stop = StopBefore.empty() ? StopAfter : StopBefore;
556+
557+
Info.IsStopMachinePass = IsStopBeforeMachinePass || IsStopAfterMachinePass;
558+
Info.StartStopCallback =
548559
[=, EnableCurrent = StartBefore.empty() && StartAfter.empty(),
549560
EnableNext = std::optional<bool>(), StartBeforeCount = 0u,
550561
StartAfterCount = 0u, StopBeforeCount = 0u,
@@ -575,8 +586,10 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
575586
EnableCurrent = true;
576587
if (StopBeforePass && StopBeforeCount++ == StopBeforeInstanceNum)
577588
EnableCurrent = false;
578-
return EnableCurrent;
579-
});
589+
return EnableCurrent || isSpecialPass(P, SpecialPasses);
590+
};
591+
592+
PIC.registerStartStopInfo(std::move(Info));
580593
}
581594

582595
void llvm::registerCodeGenCallback(PassInstrumentationCallbacks &PIC,

llvm/lib/Passes/StandardInstrumentations.cpp

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

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

10471048
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: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
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(MAM && "");
104+
assert(M && "invalid input module!");
105+
106+
// Before executing passes, print the final values of the LLVM options.
107+
cl::PrintOptionValues();
108+
109+
if (MPM) {
110+
assert(MAM);
111+
MPM->run(*M, *MAM);
112+
}
113+
114+
ExitOnErr(MFPM.run(*M, MFAM));
115+
116+
auto HasError =
117+
((const LLCDiagnosticHandler *)(Context.getDiagHandlerPtr()))->HasError;
118+
if (*HasError)
119+
exit(1);
120+
121+
if (BOS)
122+
Out->os() << Buffer;
123+
}
124+
125+
int llvm::compileModuleWithNewPM(
126+
StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
127+
std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
128+
std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context,
129+
const TargetLibraryInfoImpl &TLII, bool NoVerify,
130+
const std::vector<std::string> &RunPassNames, CodeGenFileType FileType) {
131+
132+
if (!RunPassNames.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) {
133+
WithColor::warning(errs(), Arg0)
134+
<< "run-pass cannot be used with "
135+
<< TargetPassConfig::getLimitedCodeGenPipelineReason(" and ") << ".\n";
136+
return 1;
137+
}
138+
139+
LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target);
140+
141+
{
142+
raw_pwrite_stream *OS = &Out->os();
143+
144+
// Manually do the buffering rather than using buffer_ostream,
145+
// so we can memcmp the contents in CompileTwice mode in future.
146+
SmallString<0> Buffer;
147+
std::unique_ptr<raw_svector_ostream> BOS;
148+
if ((codegen::getFileType() != CodeGenFileType::AssemblyFile &&
149+
!Out->os().supportsSeeking())) {
150+
BOS = std::make_unique<raw_svector_ostream>(Buffer);
151+
OS = BOS.get();
152+
}
153+
154+
// Fetch options from TargetPassConfig
155+
CGPassBuilderOption Opt = getCGPassBuilderOption();
156+
Opt.DisableVerify = NoVerify;
157+
Opt.DebugPM = DebugPM;
158+
Opt.RegAlloc = RegAlloc;
159+
160+
PassInstrumentationCallbacks PIC;
161+
StandardInstrumentations SI(Context, Opt.DebugPM);
162+
SI.registerCallbacks(PIC);
163+
registerCodeGenCallback(PIC, LLVMTM);
164+
165+
LoopAnalysisManager LAM;
166+
FunctionAnalysisManager FAM;
167+
CGSCCAnalysisManager CGAM;
168+
ModuleAnalysisManager MAM;
169+
PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
170+
PB.registerModuleAnalyses(MAM);
171+
PB.registerCGSCCAnalyses(CGAM);
172+
PB.registerFunctionAnalyses(FAM);
173+
PB.registerLoopAnalyses(LAM);
174+
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
175+
176+
FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
177+
MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); });
178+
179+
MachineFunctionAnalysisManager MFAM(FAM, MAM);
180+
181+
if (!RunPassNames.empty()) {
182+
// Construct a custom pass pipeline that starts after instruction
183+
// selection.
184+
185+
if (!MIR) {
186+
WithColor::warning(errs(), Arg0) << "run-pass is for .mir file only.\n";
187+
return 1;
188+
}
189+
190+
MachineFunctionPassManager MFPM;
191+
ExitOnErr(LLVMTM.parseMIRPipeline(MFPM, llvm::join(RunPassNames, ","),
192+
Opt, MFAM, &PIC));
193+
MFPM.addPass(PrintMIRPass(*OS));
194+
MFPM.addPass(FreeMachineFunctionPass());
195+
196+
auto &MMI = MFAM.getResult<MachineModuleAnalysis>(*M);
197+
if (MIR->parseMachineFunctions(*M, MMI))
198+
return 1;
199+
200+
RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, nullptr,
201+
nullptr, MFPM, MFAM);
202+
} else {
203+
ModulePassManager MPM;
204+
MachineFunctionPassManager MFPM;
205+
206+
ExitOnErr(LLVMTM.buildCodeGenPipeline(MPM, MFPM, MFAM, *OS,
207+
DwoOut ? &DwoOut->os() : nullptr,
208+
FileType, Opt, &PIC));
209+
210+
// Add IR or MIR printing pass according the pass type.
211+
if (PIC.isStartStopInfoRegistered()) {
212+
auto &Info = PIC.getStartStopInfo();
213+
if (!Info.willCompleteCodeGenPipeline()) {
214+
if (Info.isStopMachineFunctionPass())
215+
MFPM.addPass(PrintMIRPass(*OS));
216+
else
217+
MPM.addPass(PrintModulePass(*OS));
218+
}
219+
}
220+
221+
RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM,
222+
MFPM, MFAM);
223+
}
224+
}
225+
226+
// Declare success.
227+
Out->keep();
228+
if (DwoOut)
229+
DwoOut->keep();
230+
231+
return 0;
232+
}

0 commit comments

Comments
 (0)