Skip to content

Commit 976c581

Browse files
committed
[CodeGen][NewPM] Handle --regalloc-npm option
The final register allocation pass is now determined by `PassBuilder`. However, register allocation passes are now wrapped by pass manager, start/stop options will no longer works for these passes, becuase I'm not sure will LLVM allow plugins to replace register allocator.
1 parent c5ff983 commit 976c581

17 files changed

+196
-64
lines changed

llvm/include/llvm/Passes/CodeGenPassBuilder.h

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,12 @@
5959
#include "llvm/IRPrinter/IRPrintingPasses.h"
6060
#include "llvm/MC/MCAsmInfo.h"
6161
#include "llvm/MC/MCTargetOptions.h"
62+
#include "llvm/Passes/PassBuilder.h"
6263
#include "llvm/Support/CodeGen.h"
6364
#include "llvm/Support/Debug.h"
6465
#include "llvm/Support/Error.h"
6566
#include "llvm/Support/ErrorHandling.h"
67+
#include "llvm/Support/FormatVariadic.h"
6668
#include "llvm/Target/CGPassBuilderOption.h"
6769
#include "llvm/Target/TargetMachine.h"
6870
#include "llvm/Transforms/CFGuard.h"
@@ -116,9 +118,8 @@ namespace llvm {
116118
template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
117119
public:
118120
explicit CodeGenPassBuilder(TargetMachineT &TM,
119-
const CGPassBuilderOption &Opts,
120-
PassInstrumentationCallbacks *PIC)
121-
: TM(TM), Opt(Opts), PIC(PIC) {
121+
const CGPassBuilderOption &Opts, PassBuilder &PB)
122+
: TM(TM), Opt(Opts), PB(PB), PIC(PB.getPassInstrumentationCallbacks()) {
122123
// Target could set CGPassBuilderOption::MISchedPostRA to true to achieve
123124
// substitutePass(&PostRASchedulerID, &PostMachineSchedulerID)
124125

@@ -253,6 +254,7 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
253254

254255
TargetMachineT &TM;
255256
CGPassBuilderOption Opt;
257+
PassBuilder &PB;
256258
PassInstrumentationCallbacks *PIC;
257259

258260
template <typename TMC> TMC &getTM() const { return static_cast<TMC &>(TM); }
@@ -453,13 +455,9 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
453455
/// Utilities for targets to add passes to the pass manager.
454456
///
455457

456-
/// createTargetRegisterAllocator - Create the register allocator pass for
457-
/// this target at the current optimization level.
458-
void addTargetRegisterAllocator(AddMachinePass &, bool Optimized) const;
459-
460458
/// addMachinePasses helper to create the target-selected or overriden
461459
/// regalloc pass.
462-
void addRegAllocPass(AddMachinePass &, bool Optimized) const;
460+
Error addRegAllocPass(AddMachinePass &, StringRef FilterName = "all") const;
463461

464462
/// Add core register alloator passes which do the actual register assignment
465463
/// and rewriting. \returns true if any passes were added.
@@ -521,6 +519,9 @@ Error CodeGenPassBuilder<Derived, TargetMachineT>::buildPipeline(
521519
return StartStopInfo.takeError();
522520
setStartStopPasses(*StartStopInfo);
523521

522+
if (auto Err = PB.parseRegAllocOpt(Opt.RegAlloc))
523+
return Err;
524+
524525
bool PrintAsm = TargetPassConfig::willCompleteCodeGenPipeline();
525526
bool PrintMIR = !PrintAsm && FileType != CodeGenFileType::Null;
526527

@@ -1025,45 +1026,40 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addMachineSSAOptimization(
10251026
/// Register Allocation Pass Configuration
10261027
//===---------------------------------------------------------------------===//
10271028

1028-
/// Instantiate the default register allocator pass for this target for either
1029-
/// the optimized or unoptimized allocation path. This will be added to the pass
1030-
/// manager by addFastRegAlloc in the unoptimized case or addOptimizedRegAlloc
1031-
/// in the optimized case.
1032-
///
1033-
/// A target that uses the standard regalloc pass order for fast or optimized
1034-
/// allocation may still override this for per-target regalloc
1035-
/// selection. But -regalloc=... always takes precedence.
1036-
template <typename Derived, typename TargetMachineT>
1037-
void CodeGenPassBuilder<Derived, TargetMachineT>::addTargetRegisterAllocator(
1038-
AddMachinePass &addPass, bool Optimized) const {
1039-
if (Optimized)
1040-
addPass(RAGreedyPass());
1041-
else
1042-
addPass(RegAllocFastPass());
1043-
}
1044-
10451029
/// Find and instantiate the register allocation pass requested by this target
10461030
/// at the current optimization level. Different register allocators are
10471031
/// defined as separate passes because they may require different analysis.
10481032
template <typename Derived, typename TargetMachineT>
1049-
void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPass(
1050-
AddMachinePass &addPass, bool Optimized) const {
1051-
// TODO: Parse Opt.RegAlloc to add register allocator.
1033+
Error CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPass(
1034+
AddMachinePass &addPass, StringRef FilterName) const {
1035+
auto &RegAllocMap = PB.getRegAllocMap();
1036+
if (RegAllocMap.contains("none"))
1037+
return Error::success();
1038+
1039+
if (!RegAllocMap.contains(FilterName)) {
1040+
return make_error<StringError>(
1041+
formatv("No register allocator for register class filter '{0}'",
1042+
FilterName)
1043+
.str(),
1044+
inconvertibleErrorCode());
1045+
}
1046+
1047+
addPass(std::move(RegAllocMap[FilterName]));
1048+
return Error::success();
10521049
}
10531050

10541051
template <typename Derived, typename TargetMachineT>
10551052
Error CodeGenPassBuilder<Derived, TargetMachineT>::addRegAssignmentFast(
10561053
AddMachinePass &addPass) const {
1057-
// TODO: Ensure allocator is default or fast.
1058-
addRegAllocPass(addPass, false);
1059-
return Error::success();
1054+
return addRegAllocPass(addPass);
10601055
}
10611056

10621057
template <typename Derived, typename TargetMachineT>
10631058
Error CodeGenPassBuilder<Derived, TargetMachineT>::addRegAssignmentOptimized(
10641059
AddMachinePass &addPass) const {
10651060
// Add the selected register allocation pass.
1066-
addRegAllocPass(addPass, true);
1061+
if (auto Err = addRegAllocPass(addPass))
1062+
return Err;
10671063

10681064
// Allow targets to change the register assignments before rewriting.
10691065
derived().addPreRewrite(addPass);

llvm/include/llvm/Passes/PassBuilder.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class PassBuilder {
107107
PipelineTuningOptions PTO;
108108
std::optional<PGOOptions> PGOOpt;
109109
PassInstrumentationCallbacks *PIC;
110+
StringMap<MachineFunctionPassManager> RegAllocMap;
110111

111112
public:
112113
/// A struct to capture parsed pass pipeline names.
@@ -582,12 +583,28 @@ class PassBuilder {
582583

583584
/// Register callbacks to parse target specific filter field if regalloc pass
584585
/// needs it. E.g. AMDGPU requires regalloc passes can handle sgpr and vgpr
585-
/// separately.
586+
/// separately. Currently "all" and "none" are preserved filter name.
586587
void registerRegClassFilterParsingCallback(
587588
const std::function<RegClassFilterFunc(StringRef)> &C) {
588589
RegClassFilterParsingCallbacks.push_back(C);
589590
}
590591

592+
/// Parse command line option `--regalloc-npm`
593+
/// Should only be called by CodeGenPassBuilder.
594+
Error parseRegAllocOpt(StringRef Text);
595+
596+
/// Target hook to set default regalloc.
597+
void setDefaultRegAllocBuilder(
598+
const std::function<void(StringMap<MachineFunctionPassManager> &)> &C) {
599+
DefaultRegAllocBuilder = C;
600+
}
601+
602+
/// Used by CodeGenPassBuilder to add correct regalloc pass.
603+
/// Should only be called by CodeGenPassBuilder.
604+
StringMap<MachineFunctionPassManager> &getRegAllocMap() {
605+
return RegAllocMap;
606+
}
607+
591608
/// Register a callback for a top-level pipeline entry.
592609
///
593610
/// If the PassManager type is not given at the top level of the pipeline
@@ -807,6 +824,8 @@ class PassBuilder {
807824
// Callbacks to parse `filter` parameter in register allocation passes
808825
SmallVector<std::function<RegClassFilterFunc(StringRef)>, 2>
809826
RegClassFilterParsingCallbacks;
827+
std::function<void(StringMap<MachineFunctionPassManager> &)>
828+
DefaultRegAllocBuilder;
810829
};
811830

812831
/// This utility template takes care of adding require<> and invalidate<>

llvm/include/llvm/Target/TargetMachine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ class LLVMTargetMachine : public TargetMachine {
472472
virtual Error buildCodeGenPipeline(ModulePassManager &, raw_pwrite_stream &,
473473
raw_pwrite_stream *, CodeGenFileType,
474474
const CGPassBuilderOption &,
475-
PassInstrumentationCallbacks *) {
475+
PassBuilder &) {
476476
return make_error<StringError>("buildCodeGenPipeline is not overridden",
477477
inconvertibleErrorCode());
478478
}

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,13 +409,33 @@ class RequireAllMachineFunctionPropertiesPass
409409

410410
} // namespace
411411

412+
static void defaultRegAllocBuilder(TargetMachine *TM,
413+
StringMap<MachineFunctionPassManager> &M) {
414+
if (!TM)
415+
return;
416+
417+
MachineFunctionPassManager MFPM;
418+
auto Opts = getCGPassBuilderOption();
419+
if (Opts.OptimizeRegAlloc.value_or(TM->getOptLevel() !=
420+
CodeGenOptLevel::None)) {
421+
// TODO: Add greedy register allocator.
422+
} else {
423+
MFPM.addPass(RegAllocFastPass());
424+
}
425+
M["all"] = std::move(MFPM);
426+
}
427+
412428
PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
413429
std::optional<PGOOptions> PGOOpt,
414430
PassInstrumentationCallbacks *PIC)
415431
: TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) {
416432
bool ShouldPopulateClassToPassNames = PIC && shouldPopulateClassToPassNames();
417-
if (TM)
433+
if (TM) {
434+
DefaultRegAllocBuilder = [TM](StringMap<MachineFunctionPassManager> &M) {
435+
defaultRegAllocBuilder(TM, M);
436+
};
418437
TM->registerPassBuilderCallbacks(*this, ShouldPopulateClassToPassNames);
438+
}
419439
if (ShouldPopulateClassToPassNames) {
420440
#define MODULE_PASS(NAME, CREATE_PASS) \
421441
PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
@@ -2219,6 +2239,18 @@ Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
22192239
return Error::success();
22202240
}
22212241

2242+
static StringRef getFilterName(StringRef PassName) {
2243+
PassName = PassName.drop_until([](char C) { return C == '<'; });
2244+
StringRef Params = PassName.drop_front().drop_back();
2245+
while (!Params.empty()) {
2246+
StringRef ParamName;
2247+
std::tie(ParamName, Params) = Params.split(';');
2248+
if (ParamName.consume_front("filter="))
2249+
return ParamName;
2250+
}
2251+
return "all";
2252+
}
2253+
22222254
RegClassFilterFunc PassBuilder::parseRegAllocFilter(StringRef FilterName) {
22232255
if (FilterName == "all")
22242256
return allocateAllRegClasses;
@@ -2228,6 +2260,45 @@ RegClassFilterFunc PassBuilder::parseRegAllocFilter(StringRef FilterName) {
22282260
return nullptr;
22292261
}
22302262

2263+
Error PassBuilder::parseRegAllocOpt(StringRef Text) {
2264+
assert(TM && "Need target machine to parse this option!");
2265+
if (RegAllocMap.empty())
2266+
DefaultRegAllocBuilder(RegAllocMap);
2267+
2268+
MachineFunctionPassManager MFPM;
2269+
if (Text == "default") {
2270+
// Add nothing when target inserts "none" into the map.
2271+
if (RegAllocMap.contains("none"))
2272+
RegAllocMap["all"] = MachineFunctionPassManager();
2273+
return Error::success();
2274+
}
2275+
2276+
if (RegAllocMap.contains("none")) {
2277+
return make_error<StringError>(
2278+
"Target doesn't support register allocation!",
2279+
inconvertibleErrorCode());
2280+
}
2281+
2282+
bool IsOptimized = TM->getOptLevel() != CodeGenOptLevel::None;
2283+
while (!Text.empty()) {
2284+
StringRef PassName;
2285+
std::tie(PassName, Text) = Text.split(',');
2286+
if (!IsOptimized &&
2287+
!PassBuilder::checkParametrizedPassName(PassName, "regallocfast")) {
2288+
return make_error<StringError>(
2289+
"Must use fast (default) register allocator for "
2290+
"unoptimized regalloc.",
2291+
inconvertibleErrorCode());
2292+
}
2293+
// FIXME: Should only accept reg-alloc passes.
2294+
if (auto Err = parsePassPipeline(MFPM, PassName))
2295+
return Err;
2296+
RegAllocMap[getFilterName(PassName)] = std::move(MFPM);
2297+
MFPM = MachineFunctionPassManager();
2298+
}
2299+
return Error::success();
2300+
}
2301+
22312302
static void printPassName(StringRef PassName, raw_ostream &OS) {
22322303
OS << " " << PassName << "\n";
22332304
}

llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@
1414
using namespace llvm;
1515

1616
AMDGPUCodeGenPassBuilder::AMDGPUCodeGenPassBuilder(
17-
AMDGPUTargetMachine &TM, const CGPassBuilderOption &Opts,
18-
PassInstrumentationCallbacks *PIC)
19-
: CodeGenPassBuilder(TM, Opts, PIC) {
17+
AMDGPUTargetMachine &TM, const CGPassBuilderOption &Opts, PassBuilder &PB)
18+
: CodeGenPassBuilder(TM, Opts, PB) {
2019
Opt.RequiresCodeGenSCCOrder = true;
2120
// Exceptions and StackMaps are not supported, so these passes will never do
2221
// anything.
@@ -40,3 +39,13 @@ Error AMDGPUCodeGenPassBuilder::addInstSelector(AddMachinePass &addPass) const {
4039
addPass(AMDGPUISelDAGToDAGPass(TM));
4140
return Error::success();
4241
}
42+
43+
Error AMDGPUCodeGenPassBuilder::addRegAssignmentFast(
44+
AddMachinePass &addPass) const {
45+
if (auto Err = addRegAllocPass(addPass, "sgpr"))
46+
return Err;
47+
// TODO: Add other passes.
48+
if (auto Err = addRegAllocPass(addPass, "vgpr"))
49+
return Err;
50+
return Error::success();
51+
}

llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ class AMDGPUCodeGenPassBuilder
2020
: public CodeGenPassBuilder<AMDGPUCodeGenPassBuilder, AMDGPUTargetMachine> {
2121
public:
2222
AMDGPUCodeGenPassBuilder(AMDGPUTargetMachine &TM,
23-
const CGPassBuilderOption &Opts,
24-
PassInstrumentationCallbacks *PIC);
23+
const CGPassBuilderOption &Opts, PassBuilder &PB);
2524

2625
void addPreISel(AddIRPass &addPass) const;
2726
void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const;
2827
Error addInstSelector(AddMachinePass &) const;
28+
Error addRegAssignmentFast(AddMachinePass &addPass) const;
2929
};
3030

3131
} // namespace llvm

llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
4747
#include "llvm/CodeGen/MIRParser/MIParser.h"
4848
#include "llvm/CodeGen/Passes.h"
49+
#include "llvm/CodeGen/RegAllocFast.h"
4950
#include "llvm/CodeGen/RegAllocRegistry.h"
5051
#include "llvm/CodeGen/TargetPassConfig.h"
5152
#include "llvm/IR/IntrinsicsAMDGPU.h"
@@ -650,11 +651,13 @@ parseAMDGPUAtomicOptimizerStrategy(StringRef Params) {
650651
return make_error<StringError>("invalid parameter", inconvertibleErrorCode());
651652
}
652653

653-
Error AMDGPUTargetMachine::buildCodeGenPipeline(
654-
ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
655-
CodeGenFileType FileType, const CGPassBuilderOption &Opts,
656-
PassInstrumentationCallbacks *PIC) {
657-
AMDGPUCodeGenPassBuilder CGPB(*this, Opts, PIC);
654+
Error AMDGPUTargetMachine::buildCodeGenPipeline(ModulePassManager &MPM,
655+
raw_pwrite_stream &Out,
656+
raw_pwrite_stream *DwoOut,
657+
CodeGenFileType FileType,
658+
const CGPassBuilderOption &Opts,
659+
PassBuilder &PB) {
660+
AMDGPUCodeGenPassBuilder CGPB(*this, Opts, PB);
658661
return CGPB.buildPipeline(MPM, Out, DwoOut, FileType);
659662
}
660663

@@ -749,6 +752,30 @@ void AMDGPUTargetMachine::registerPassBuilderCallbacks(
749752
return onlyAllocateVGPRs;
750753
return nullptr;
751754
});
755+
756+
PB.setDefaultRegAllocBuilder(
757+
[TM = this](StringMap<MachineFunctionPassManager> &RegAllocMap) {
758+
auto Opts = getCGPassBuilderOption();
759+
if (Opts.OptimizeRegAlloc.value_or(TM->getOptLevel() !=
760+
CodeGenOptLevel::None)) {
761+
// TODO: Add greedy register allocator.
762+
} else {
763+
RegAllocFastPassOptions Opts;
764+
Opts.Filter = onlyAllocateSGPRs;
765+
Opts.FilterName = "sgpr";
766+
Opts.ClearVRegs = false;
767+
MachineFunctionPassManager MFPM;
768+
MFPM.addPass(RegAllocFastPass(Opts));
769+
RegAllocMap["sgpr"] = std::move(MFPM);
770+
771+
Opts.Filter = onlyAllocateVGPRs;
772+
Opts.FilterName = "vgpr";
773+
Opts.ClearVRegs = true;
774+
MFPM = MachineFunctionPassManager();
775+
MFPM.addPass(RegAllocFastPass(Opts));
776+
RegAllocMap["vgpr"] = std::move(MFPM);
777+
}
778+
});
752779
}
753780

754781
int64_t AMDGPUTargetMachine::getNullPointerValue(unsigned AddrSpace) {

llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class AMDGPUTargetMachine : public LLVMTargetMachine {
5656
raw_pwrite_stream *DwoOut,
5757
CodeGenFileType FileType,
5858
const CGPassBuilderOption &Opts,
59-
PassInstrumentationCallbacks *PIC) override;
59+
PassBuilder &PB) override;
6060

6161
void registerPassBuilderCallbacks(PassBuilder &PB,
6262
bool PopulateClassToPassNames) override;

0 commit comments

Comments
 (0)