103103#include " llvm/IRPrinter/IRPrintingPasses.h"
104104#include " llvm/MC/MCAsmInfo.h"
105105#include " llvm/MC/MCTargetOptions.h"
106+ #include " llvm/Passes/PassBuilder.h"
106107#include " llvm/Support/CodeGen.h"
107108#include " llvm/Support/Debug.h"
108109#include " llvm/Support/Error.h"
120121#include " llvm/Transforms/Utils/EntryExitInstrumenter.h"
121122#include " llvm/Transforms/Utils/LowerInvoke.h"
122123#include < cassert>
124+ #include < tuple>
123125#include < type_traits>
124126#include < utility>
125127
@@ -161,8 +163,9 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
161163public:
162164 explicit CodeGenPassBuilder (TargetMachineT &TM,
163165 const CGPassBuilderOption &Opts,
164- PassInstrumentationCallbacks *PIC)
165- : TM(TM), Opt(Opts), PIC(PIC) {
166+ PassInstrumentationCallbacks *PIC,
167+ PassBuilder &PB)
168+ : TM(TM), Opt(Opts), PIC(PIC), PB(PB) {
166169 // Target could set CGPassBuilderOption::MISchedPostRA to true to achieve
167170 // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID)
168171
@@ -298,6 +301,7 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
298301 TargetMachineT &TM;
299302 CGPassBuilderOption Opt;
300303 PassInstrumentationCallbacks *PIC;
304+ PassBuilder &PB;
301305
302306 template <typename TMC> TMC &getTM () const { return static_cast <TMC &>(TM); }
303307 CodeGenOptLevel getOptLevel () const { return TM.getOptLevel (); }
@@ -505,6 +509,13 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
505509 // / addMachinePasses helper to create the target-selected or overriden
506510 // / regalloc pass.
507511 void addRegAllocPass (AddMachinePass &, bool Optimized) const ;
512+ // / Read the --regalloc-npm option to add the next pass in line.
513+ bool addRegAllocPassFromOpt (AddMachinePass &,
514+ StringRef MatchPassTo = StringRef{}) const ;
515+ // / Add the next pass in the cli option, or return false if there is no pass
516+ // / left in the option.
517+ template <typename RegAllocPassT>
518+ void addRegAllocPassOrOpt (AddMachinePass &, RegAllocPassT Pass) const ;
508519
509520 // / Add core register alloator passes which do the actual register assignment
510521 // / and rewriting. \returns true if any passes were added.
@@ -601,6 +612,11 @@ Error CodeGenPassBuilder<Derived, TargetMachineT>::buildPipeline(
601612 if (PrintMIR)
602613 addPass (PrintMIRPass (Out), /* Force=*/ true );
603614
615+ if (!Opt.RegAllocPipeline .empty ())
616+ return make_error<StringError>(
617+ " Extra passes in regalloc pipeline: " + Opt.RegAllocPipeline ,
618+ std::make_error_code (std::errc::invalid_argument));
619+
604620 return verifyStartStop (*StartStopInfo);
605621}
606622
@@ -1098,6 +1114,49 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addTargetRegisterAllocator(
10981114 addPass (RegAllocFastPass ());
10991115}
11001116
1117+ template <typename Derived, typename TargetMachineT>
1118+ template <typename RegAllocPassT>
1119+ void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPassOrOpt(
1120+ AddMachinePass &addPass, RegAllocPassT Pass) const {
1121+ if (!addRegAllocPassFromOpt (addPass))
1122+ addPass (std::move (Pass));
1123+ }
1124+
1125+ template <typename Derived, typename TargetMachineT>
1126+ bool CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPassFromOpt(
1127+ AddMachinePass &addPass, StringRef MatchPassTo) const {
1128+ if (!Opt.RegAllocPipeline .empty ()) {
1129+ StringRef PassOpt;
1130+ std::tie (PassOpt, Opt.RegAllocPipeline ) = Opt.RegAllocPipeline .split (' ,' );
1131+ // Reuse the registered parser to parse the pass name.
1132+ #define MACHINE_FUNCTION_PASS_WITH_PARAMS (NAME, CLASS, CREATE_PASS, PARSER, \
1133+ PARAMS) \
1134+ if (PB.checkParametrizedPassName (PassOpt, NAME)) { \
1135+ auto Params = PB.parsePassParameters (PARSER, PassOpt, NAME, \
1136+ const_cast <const PassBuilder &>(PB)); \
1137+ if (!Params) { \
1138+ auto Err = Params.takeError (); \
1139+ ExitOnError ()(std::move (Err)); \
1140+ } \
1141+ if (!MatchPassTo.empty ()) { \
1142+ if (MatchPassTo != CLASS) \
1143+ report_fatal_error (" Expected " + \
1144+ PIC->getPassNameForClassName (MatchPassTo) + \
1145+ " in option -regalloc-npm" , \
1146+ false ); \
1147+ } \
1148+ addPass (CREATE_PASS (Params.get ())); \
1149+ return true ; \
1150+ }
1151+ #include " llvm/Passes/MachinePassRegistry.def"
1152+ if (PassOpt != " default" ) {
1153+ report_fatal_error (" Unknown register allocator pass: " + PassOpt, false );
1154+ }
1155+ }
1156+ // If user did not give a specific pass, use the default provided.
1157+ return false ;
1158+ }
1159+
11011160// / Find and instantiate the register allocation pass requested by this target
11021161// / at the current optimization level. Different register allocators are
11031162// / defined as separate passes because they may require different analysis.
@@ -1108,22 +1167,13 @@ template <typename Derived, typename TargetMachineT>
11081167void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPass(
11091168 AddMachinePass &addPass, bool Optimized) const {
11101169 // Use the specified -regalloc-npm={basic|greedy|fast|pbqp}
1111- if (Opt.RegAlloc > RegAllocType::Default) {
1112- switch (Opt.RegAlloc ) {
1113- case RegAllocType::Fast:
1114- addPass (RegAllocFastPass ());
1115- break ;
1116- case RegAllocType::Greedy:
1117- addPass (RAGreedyPass ());
1118- break ;
1119- default :
1120- report_fatal_error (" register allocator not supported yet" , false );
1121- }
1122- return ;
1170+ StringRef RegAllocPassName;
1171+ if (!Optimized)
1172+ RegAllocPassName = RegAllocFastPass::name ();
1173+
1174+ if (!addRegAllocPassFromOpt (addPass, RegAllocPassName)) {
1175+ derived ().addTargetRegisterAllocator (addPass, Optimized);
11231176 }
1124- // -regalloc=default or unspecified, so pick based on the optimization level
1125- // or ask the target for the regalloc pass.
1126- derived ().addTargetRegisterAllocator (addPass, Optimized);
11271177}
11281178
11291179template <typename Derived, typename TargetMachineT>
0 commit comments