100100#include " llvm/IRPrinter/IRPrintingPasses.h"
101101#include " llvm/MC/MCAsmInfo.h"
102102#include " llvm/MC/MCTargetOptions.h"
103+ #include " llvm/Passes/PassBuilder.h"
103104#include " llvm/Support/CodeGen.h"
104105#include " llvm/Support/Debug.h"
105106#include " llvm/Support/Error.h"
117118#include " llvm/Transforms/Utils/EntryExitInstrumenter.h"
118119#include " llvm/Transforms/Utils/LowerInvoke.h"
119120#include < cassert>
121+ #include < tuple>
120122#include < type_traits>
121123#include < utility>
122124
@@ -158,8 +160,9 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
158160public:
159161 explicit CodeGenPassBuilder (TargetMachineT &TM,
160162 const CGPassBuilderOption &Opts,
161- PassInstrumentationCallbacks *PIC)
162- : TM(TM), Opt(Opts), PIC(PIC) {
163+ PassInstrumentationCallbacks *PIC,
164+ PassBuilder &PB)
165+ : TM(TM), Opt(Opts), PIC(PIC), PB(PB) {
163166 // Target could set CGPassBuilderOption::MISchedPostRA to true to achieve
164167 // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID)
165168
@@ -295,6 +298,7 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
295298 TargetMachineT &TM;
296299 CGPassBuilderOption Opt;
297300 PassInstrumentationCallbacks *PIC;
301+ PassBuilder &PB;
298302
299303 template <typename TMC> TMC &getTM () const { return static_cast <TMC &>(TM); }
300304 CodeGenOptLevel getOptLevel () const { return TM.getOptLevel (); }
@@ -502,6 +506,13 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
502506 // / addMachinePasses helper to create the target-selected or overriden
503507 // / regalloc pass.
504508 void addRegAllocPass (AddMachinePass &, bool Optimized) const ;
509+ // / Read the --regalloc-npm option to add the next pass in line.
510+ bool addRegAllocPassFromOpt (AddMachinePass &,
511+ StringRef MatchPassTo = StringRef{}) const ;
512+ // / Add the next pass in the cli option, or return false if there is no pass
513+ // / left in the option.
514+ template <typename RegAllocPassT>
515+ void addRegAllocPassOrOpt (AddMachinePass &, RegAllocPassT Pass) const ;
505516
506517 // / Add core register alloator passes which do the actual register assignment
507518 // / and rewriting. \returns true if any passes were added.
@@ -598,6 +609,11 @@ Error CodeGenPassBuilder<Derived, TargetMachineT>::buildPipeline(
598609 if (PrintMIR)
599610 addPass (PrintMIRPass (Out), /* Force=*/ true );
600611
612+ if (!Opt.RegAllocPipeline .empty ())
613+ return make_error<StringError>(
614+ " Extra passes in regalloc pipeline: " + Opt.RegAllocPipeline ,
615+ std::make_error_code (std::errc::invalid_argument));
616+
601617 return verifyStartStop (*StartStopInfo);
602618}
603619
@@ -1095,6 +1111,49 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addTargetRegisterAllocator(
10951111 addPass (RegAllocFastPass ());
10961112}
10971113
1114+ template <typename Derived, typename TargetMachineT>
1115+ template <typename RegAllocPassT>
1116+ void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPassOrOpt(
1117+ AddMachinePass &addPass, RegAllocPassT Pass) const {
1118+ if (!addRegAllocPassFromOpt (addPass))
1119+ addPass (std::move (Pass));
1120+ }
1121+
1122+ template <typename Derived, typename TargetMachineT>
1123+ bool CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPassFromOpt(
1124+ AddMachinePass &addPass, StringRef MatchPassTo) const {
1125+ if (!Opt.RegAllocPipeline .empty ()) {
1126+ StringRef PassOpt;
1127+ std::tie (PassOpt, Opt.RegAllocPipeline ) = Opt.RegAllocPipeline .split (' ,' );
1128+ // Reuse the registered parser to parse the pass name.
1129+ #define MACHINE_FUNCTION_PASS_WITH_PARAMS (NAME, CLASS, CREATE_PASS, PARSER, \
1130+ PARAMS) \
1131+ if (PB.checkParametrizedPassName (PassOpt, NAME)) { \
1132+ auto Params = PB.parsePassParameters (PARSER, PassOpt, NAME, \
1133+ const_cast <const PassBuilder &>(PB)); \
1134+ if (!Params) { \
1135+ auto Err = Params.takeError (); \
1136+ ExitOnError ()(std::move (Err)); \
1137+ } \
1138+ if (!MatchPassTo.empty ()) { \
1139+ if (MatchPassTo != CLASS) \
1140+ report_fatal_error (" Expected " + \
1141+ PIC->getPassNameForClassName (MatchPassTo) + \
1142+ " in option -regalloc-npm" , \
1143+ false ); \
1144+ } \
1145+ addPass (CREATE_PASS (Params.get ())); \
1146+ return true ; \
1147+ }
1148+ #include " llvm/Passes/MachinePassRegistry.def"
1149+ if (PassOpt != " default" ) {
1150+ report_fatal_error (" Unknown register allocator pass: " + PassOpt, false );
1151+ }
1152+ }
1153+ // If user did not give a specific pass, use the default provided.
1154+ return false ;
1155+ }
1156+
10981157// / Find and instantiate the register allocation pass requested by this target
10991158// / at the current optimization level. Different register allocators are
11001159// / defined as separate passes because they may require different analysis.
@@ -1105,22 +1164,13 @@ template <typename Derived, typename TargetMachineT>
11051164void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPass(
11061165 AddMachinePass &addPass, bool Optimized) const {
11071166 // Use the specified -regalloc-npm={basic|greedy|fast|pbqp}
1108- if (Opt.RegAlloc > RegAllocType::Default) {
1109- switch (Opt.RegAlloc ) {
1110- case RegAllocType::Fast:
1111- addPass (RegAllocFastPass ());
1112- break ;
1113- case RegAllocType::Greedy:
1114- addPass (RAGreedyPass ());
1115- break ;
1116- default :
1117- report_fatal_error (" register allocator not supported yet" , false );
1118- }
1119- return ;
1167+ StringRef RegAllocPassName;
1168+ if (!Optimized)
1169+ RegAllocPassName = RegAllocFastPass::name ();
1170+
1171+ if (!addRegAllocPassFromOpt (addPass, RegAllocPassName)) {
1172+ derived ().addTargetRegisterAllocator (addPass, Optimized);
11201173 }
1121- // -regalloc=default or unspecified, so pick based on the optimization level
1122- // or ask the target for the regalloc pass.
1123- derived ().addTargetRegisterAllocator (addPass, Optimized);
11241174}
11251175
11261176template <typename Derived, typename TargetMachineT>
0 commit comments