9696#include " llvm/IRPrinter/IRPrintingPasses.h"
9797#include " llvm/MC/MCAsmInfo.h"
9898#include " llvm/MC/MCTargetOptions.h"
99+ #include " llvm/Passes/PassBuilder.h"
99100#include " llvm/Support/CodeGen.h"
100101#include " llvm/Support/Debug.h"
101102#include " llvm/Support/Error.h"
113114#include " llvm/Transforms/Utils/EntryExitInstrumenter.h"
114115#include " llvm/Transforms/Utils/LowerInvoke.h"
115116#include < cassert>
117+ #include < tuple>
116118#include < type_traits>
117119#include < utility>
118120
@@ -154,8 +156,9 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
154156public:
155157 explicit CodeGenPassBuilder (TargetMachineT &TM,
156158 const CGPassBuilderOption &Opts,
157- PassInstrumentationCallbacks *PIC)
158- : TM(TM), Opt(Opts), PIC(PIC) {
159+ PassInstrumentationCallbacks *PIC,
160+ PassBuilder &PB)
161+ : TM(TM), Opt(Opts), PIC(PIC), PB(PB) {
159162 // Target could set CGPassBuilderOption::MISchedPostRA to true to achieve
160163 // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID)
161164
@@ -291,6 +294,7 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
291294 TargetMachineT &TM;
292295 CGPassBuilderOption Opt;
293296 PassInstrumentationCallbacks *PIC;
297+ PassBuilder &PB;
294298
295299 template <typename TMC> TMC &getTM () const { return static_cast <TMC &>(TM); }
296300 CodeGenOptLevel getOptLevel () const { return TM.getOptLevel (); }
@@ -498,6 +502,13 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
498502 // / addMachinePasses helper to create the target-selected or overriden
499503 // / regalloc pass.
500504 void addRegAllocPass (AddMachinePass &, bool Optimized) const ;
505+ // / Read the --regalloc-npm option to add the next pass in line.
506+ bool addRegAllocPassFromOpt (AddMachinePass &,
507+ StringRef MatchPassTo = StringRef{}) const ;
508+ // / Add the next pass in the cli option, or return false if there is no pass
509+ // / left in the option.
510+ template <typename RegAllocPassT>
511+ void addRegAllocPassOrOpt (AddMachinePass &, RegAllocPassT Pass) const ;
501512
502513 // / Add core register alloator passes which do the actual register assignment
503514 // / and rewriting. \returns true if any passes were added.
@@ -594,6 +605,11 @@ Error CodeGenPassBuilder<Derived, TargetMachineT>::buildPipeline(
594605 if (PrintMIR)
595606 addPass (PrintMIRPass (Out), /* Force=*/ true );
596607
608+ if (!Opt.RegAllocPipeline .empty ())
609+ return make_error<StringError>(
610+ " Extra passes in regalloc pipeline: " + Opt.RegAllocPipeline ,
611+ std::make_error_code (std::errc::invalid_argument));
612+
597613 return verifyStartStop (*StartStopInfo);
598614}
599615
@@ -1088,6 +1104,49 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addTargetRegisterAllocator(
10881104 addPass (RegAllocFastPass ());
10891105}
10901106
1107+ template <typename Derived, typename TargetMachineT>
1108+ template <typename RegAllocPassT>
1109+ void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPassOrOpt(
1110+ AddMachinePass &addPass, RegAllocPassT Pass) const {
1111+ if (!addRegAllocPassFromOpt (addPass))
1112+ addPass (std::move (Pass));
1113+ }
1114+
1115+ template <typename Derived, typename TargetMachineT>
1116+ bool CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPassFromOpt(
1117+ AddMachinePass &addPass, StringRef MatchPassTo) const {
1118+ if (!Opt.RegAllocPipeline .empty ()) {
1119+ StringRef PassOpt;
1120+ std::tie (PassOpt, Opt.RegAllocPipeline ) = Opt.RegAllocPipeline .split (' ,' );
1121+ // Reuse the registered parser to parse the pass name.
1122+ #define MACHINE_FUNCTION_PASS_WITH_PARAMS (NAME, CLASS, CREATE_PASS, PARSER, \
1123+ PARAMS) \
1124+ if (PB.checkParametrizedPassName (PassOpt, NAME)) { \
1125+ auto Params = PB.parsePassParameters (PARSER, PassOpt, NAME, \
1126+ const_cast <const PassBuilder &>(PB)); \
1127+ if (!Params) { \
1128+ auto Err = Params.takeError (); \
1129+ ExitOnError ()(std::move (Err)); \
1130+ } \
1131+ if (!MatchPassTo.empty ()) { \
1132+ if (MatchPassTo != CLASS) \
1133+ report_fatal_error (" Expected " + \
1134+ PIC->getPassNameForClassName (MatchPassTo) + \
1135+ " in option -regalloc-npm" , \
1136+ false ); \
1137+ } \
1138+ addPass (CREATE_PASS (Params.get ())); \
1139+ return true ; \
1140+ }
1141+ #include " llvm/Passes/MachinePassRegistry.def"
1142+ if (PassOpt != " default" ) {
1143+ report_fatal_error (" Unknown register allocator pass: " + PassOpt, false );
1144+ }
1145+ }
1146+ // If user did not give a specific pass, use the default provided.
1147+ return false ;
1148+ }
1149+
10911150// / Find and instantiate the register allocation pass requested by this target
10921151// / at the current optimization level. Different register allocators are
10931152// / defined as separate passes because they may require different analysis.
@@ -1098,22 +1157,13 @@ template <typename Derived, typename TargetMachineT>
10981157void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPass(
10991158 AddMachinePass &addPass, bool Optimized) const {
11001159 // Use the specified -regalloc-npm={basic|greedy|fast|pbqp}
1101- if (Opt.RegAlloc > RegAllocType::Default) {
1102- switch (Opt.RegAlloc ) {
1103- case RegAllocType::Fast:
1104- addPass (RegAllocFastPass ());
1105- break ;
1106- case RegAllocType::Greedy:
1107- addPass (RAGreedyPass ());
1108- break ;
1109- default :
1110- report_fatal_error (" register allocator not supported yet" , false );
1111- }
1112- return ;
1160+ StringRef RegAllocPassName;
1161+ if (!Optimized)
1162+ RegAllocPassName = RegAllocFastPass::name ();
1163+
1164+ if (!addRegAllocPassFromOpt (addPass, RegAllocPassName)) {
1165+ derived ().addTargetRegisterAllocator (addPass, Optimized);
11131166 }
1114- // -regalloc=default or unspecified, so pick based on the optimization level
1115- // or ask the target for the regalloc pass.
1116- derived ().addTargetRegisterAllocator (addPass, Optimized);
11171167}
11181168
11191169template <typename Derived, typename TargetMachineT>
0 commit comments