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