130130#include " llvm/Transforms/Utils/EntryExitInstrumenter.h"
131131#include " llvm/Transforms/Utils/LowerInvoke.h"
132132#include < cassert>
133+ #include < tuple>
133134#include < type_traits>
134135#include < utility>
135136
@@ -171,8 +172,9 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
171172public:
172173 explicit CodeGenPassBuilder (TargetMachineT &TM,
173174 const CGPassBuilderOption &Opts,
174- PassInstrumentationCallbacks *PIC)
175- : TM(TM), Opt(Opts), PIC(PIC) {
175+ PassInstrumentationCallbacks *PIC,
176+ PassBuilder &PB)
177+ : TM(TM), Opt(Opts), PIC(PIC), PB(PB) {
176178 // Target could set CGPassBuilderOption::MISchedPostRA to true to achieve
177179 // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID)
178180
@@ -359,6 +361,7 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
359361 TargetMachineT &TM;
360362 CGPassBuilderOption Opt;
361363 PassInstrumentationCallbacks *PIC;
364+ PassBuilder &PB;
362365 mutable IntrusiveRefCntPtr<AsmPrinter> PrinterImpl;
363366
364367 template <typename TMC> TMC &getTM () const { return static_cast <TMC &>(TM); }
@@ -569,6 +572,15 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
569572 // / addMachinePasses helper to create the target-selected or overriden
570573 // / regalloc pass.
571574 void addRegAllocPass (AddMachinePass &, bool Optimized) const ;
575+ // / Read the --regalloc-npm option to add the next pass in line.
576+ // / Returns false if no pass is left in the option.
577+ bool addRegAllocPassFromOpt (AddMachinePass &,
578+ StringRef MatchPassTo = StringRef{}) const ;
579+ // / Add the next pass in the cli option or the pass specified if no pass is
580+ // / left in the option.
581+ template <typename RegAllocPassBuilderT>
582+ void addRegAllocPassOrOpt (AddMachinePass &,
583+ RegAllocPassBuilderT PassBuilder) const ;
572584
573585 // / Add core register alloator passes which do the actual register assignment
574586 // / and rewriting. \returns true if any passes were added.
@@ -688,6 +700,11 @@ Error CodeGenPassBuilder<Derived, TargetMachineT>::buildPipeline(
688700
689701 PrinterImpl.reset ();
690702
703+ if (!Opt.RegAllocPipeline .empty ())
704+ return make_error<StringError>(
705+ " extra passes in regalloc pipeline: " + Opt.RegAllocPipeline ,
706+ std::make_error_code (std::errc::invalid_argument));
707+
691708 return verifyStartStop (*StartStopInfo);
692709}
693710
@@ -1187,6 +1204,48 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addTargetRegisterAllocator(
11871204 addPass (RegAllocFastPass ());
11881205}
11891206
1207+ template <typename Derived, typename TargetMachineT>
1208+ template <typename RegAllocPassBuilderT>
1209+ void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPassOrOpt(
1210+ AddMachinePass &addPass, RegAllocPassBuilderT PassBuilder) const {
1211+ if (!addRegAllocPassFromOpt (addPass))
1212+ addPass (std::move (PassBuilder ()));
1213+ }
1214+
1215+ template <typename Derived, typename TargetMachineT>
1216+ bool CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPassFromOpt(
1217+ AddMachinePass &addPass, StringRef MatchPassTo) const {
1218+ if (!Opt.RegAllocPipeline .empty ()) {
1219+ StringRef PassOpt;
1220+ std::tie (PassOpt, Opt.RegAllocPipeline ) = Opt.RegAllocPipeline .split (' ,' );
1221+ // Reuse the registered parser to parse the pass name.
1222+ #define RA_PASS_WITH_PARAMS (NAME, CLASS, CREATE_PASS, PARSER, PARAMS ) \
1223+ if (PB.checkParametrizedPassName (PassOpt, NAME)) { \
1224+ auto Params = PB.parsePassParameters (PARSER, PassOpt, NAME, \
1225+ const_cast <const PassBuilder &>(PB)); \
1226+ if (!Params) { \
1227+ auto Err = Params.takeError (); \
1228+ ExitOnError ()(std::move (Err)); \
1229+ } \
1230+ if (!MatchPassTo.empty ()) { \
1231+ if (MatchPassTo != CLASS) \
1232+ report_fatal_error (" expected " + \
1233+ PIC->getPassNameForClassName (MatchPassTo) + \
1234+ " in option --regalloc-npm" , \
1235+ false ); \
1236+ } \
1237+ addPass (CREATE_PASS (Params.get ())); \
1238+ return true ; \
1239+ }
1240+ #include " llvm/Passes/MachinePassRegistry.def"
1241+ if (PassOpt != " default" ) {
1242+ report_fatal_error (" unknown register allocator pass: " + PassOpt, false );
1243+ }
1244+ }
1245+ // If user did not give a specific pass, use the default provided.
1246+ return false ;
1247+ }
1248+
11901249// / Find and instantiate the register allocation pass requested by this target
11911250// / at the current optimization level. Different register allocators are
11921251// / defined as separate passes because they may require different analysis.
@@ -1197,22 +1256,13 @@ template <typename Derived, typename TargetMachineT>
11971256void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPass(
11981257 AddMachinePass &addPass, bool Optimized) const {
11991258 // Use the specified -regalloc-npm={basic|greedy|fast|pbqp}
1200- if (Opt.RegAlloc > RegAllocType::Default) {
1201- switch (Opt.RegAlloc ) {
1202- case RegAllocType::Fast:
1203- addPass (RegAllocFastPass ());
1204- break ;
1205- case RegAllocType::Greedy:
1206- addPass (RAGreedyPass ());
1207- break ;
1208- default :
1209- reportFatalUsageError (" register allocator not supported yet" );
1210- }
1211- return ;
1259+ StringRef RegAllocPassName;
1260+ if (!Optimized)
1261+ RegAllocPassName = RegAllocFastPass::name ();
1262+
1263+ if (!addRegAllocPassFromOpt (addPass, RegAllocPassName)) {
1264+ derived ().addTargetRegisterAllocator (addPass, Optimized);
12121265 }
1213- // -regalloc=default or unspecified, so pick based on the optimization level
1214- // or ask the target for the regalloc pass.
1215- derived ().addTargetRegisterAllocator (addPass, Optimized);
12161266}
12171267
12181268template <typename Derived, typename TargetMachineT>
0 commit comments