llvm.org GIT mirror llvm / 6131fb5
[TargetPassConfig] Feature generic options to setup start/stop-after/before This patch refactors the code used in llc such that all the users of the addPassesToEmitFile API have access to a homogeneous way of handling start/stop-after/before options right out of the box. In particular, just invoking addPassesToEmitFile will set the proper pipeline without additional effort (modulo parsing a .mir file if the start-before/after options are used. NFC. Differential Revision: https://reviews.llvm.org/D30913 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309599 91177308-0d34-0410-b5e6-96231b3b80d8 Quentin Colombet 3 years ago
6 changed file(s) with 190 addition(s) and 143 deletion(s). Raw diff Collapse all Expand all
107107 bool Stopped = false;
108108 bool AddingMachinePasses = false;
109109
110 /// Set the StartAfter, StartBefore and StopAfter passes to allow running only
111 /// a portion of the normal code-gen pass sequence.
112 ///
113 /// If the StartAfter and StartBefore pass ID is zero, then compilation will
114 /// begin at the normal point; otherwise, clear the Started flag to indicate
115 /// that passes should not be added until the starting pass is seen. If the
116 /// Stop pass ID is zero, then compilation will continue to the end.
117 ///
118 /// This function expects that at least one of the StartAfter or the
119 /// StartBefore pass IDs is null.
120 void setStartStopPasses();
121
110122 protected:
111123 LLVMTargetMachine *TM;
112124 PassConfigImpl *Impl = nullptr; // Internal data structures
146158
147159 CodeGenOpt::Level getOptLevel() const;
148160
149 /// Set the StartAfter, StartBefore and StopAfter passes to allow running only
150 /// a portion of the normal code-gen pass sequence.
151 ///
152 /// If the StartAfter and StartBefore pass ID is zero, then compilation will
153 /// begin at the normal point; otherwise, clear the Started flag to indicate
154 /// that passes should not be added until the starting pass is seen. If the
155 /// Stop pass ID is zero, then compilation will continue to the end.
156 ///
157 /// This function expects that at least one of the StartAfter or the
158 /// StartBefore pass IDs is null.
159 void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter,
160 AnalysisID StopBefore, AnalysisID StopAfter) {
161 assert(!(StartBefore && StartAfter) &&
162 "Start after and start before passes are given");
163 assert(!(StopBefore && StopAfter) &&
164 "Stop after and stop before passed are given");
165 this->StartBefore = StartBefore;
166 this->StartAfter = StartAfter;
167 this->StopBefore = StopBefore;
168 this->StopAfter = StopAfter;
169 Started = (StartAfter == nullptr) && (StartBefore == nullptr);
161 /// Describe the status of the codegen
162 /// pipeline set by this target pass config.
163 /// Having a limited codegen pipeline means that options
164 /// have been used to restrict what codegen is doing.
165 /// In particular, that means that codegen won't emit
166 /// assembly code.
167 bool hasLimitedCodeGenPipeline() const;
168
169 /// If hasLimitedCodeGenPipeline is true, this method
170 /// returns a string with the name of the options, separated
171 /// by \p Separator that caused this pipeline to be limited.
172 std::string
173 getLimitedCodeGenPipelineReason(const char *Separator = "/") const;
174
175 /// Check if the codegen pipeline is limited in such a way that it
176 /// won't be complete. When the codegen pipeline is not complete,
177 /// this means it may not be possible to generate assembly from it.
178 bool willCompleteCodeGenPipeline() const {
179 return !hasLimitedCodeGenPipeline() || (!StopAfter && !StopBefore);
170180 }
171181
172182 void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); }
2424 namespace llvm {
2525
2626 class GlobalValue;
27 class MachineModuleInfo;
2728 class Mangler;
2829 class MCAsmInfo;
2930 class MCContext;
221222 /// emitted. Typically this will involve several steps of code generation.
222223 /// This method should return true if emission of this file type is not
223224 /// supported, or false on success.
224 virtual bool addPassesToEmitFile(
225 PassManagerBase &, raw_pwrite_stream &, CodeGenFileType,
226 bool /*DisableVerify*/ = true, AnalysisID /*StartBefore*/ = nullptr,
227 AnalysisID /*StartAfter*/ = nullptr, AnalysisID /*StopBefore*/ = nullptr,
228 AnalysisID /*StopAfter*/ = nullptr) {
225 /// \p MMI is an optional parameter that, if set to non-nullptr,
226 /// will be used to set the MachineModuloInfo for this PM.
227 virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &,
228 CodeGenFileType,
229 bool /*DisableVerify*/ = true,
230 MachineModuleInfo *MMI = nullptr) {
229231 return true;
230232 }
231233
269271 CodeModel::Model CM, CodeGenOpt::Level OL);
270272
271273 void initAsmInfo();
274
272275 public:
273276 /// \brief Get a TargetIRAnalysis implementation for the target.
274277 ///
282285
283286 /// Add passes to the specified pass manager to get the specified file
284287 /// emitted. Typically this will involve several steps of code generation.
285 bool addPassesToEmitFile(
286 PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType,
287 bool DisableVerify = true, AnalysisID StartBefore = nullptr,
288 AnalysisID StartAfter = nullptr, AnalysisID StopBefore = nullptr,
289 AnalysisID StopAfter = nullptr) override;
288 /// \p MMI is an optional parameter that, if set to non-nullptr,
289 /// will be used to set the MachineModuloInfofor this PM.
290 bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
291 CodeGenFileType FileType, bool DisableVerify = true,
292 MachineModuleInfo *MMI = nullptr) override;
290293
291294 /// Add passes to the specified pass manager to get machine code emitted with
292295 /// the MCJIT. This method returns true if machine code is not supported. It
9191 /// addPassesToX helper drives creation and initialization of TargetPassConfig.
9292 static MCContext *
9393 addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM,
94 bool DisableVerify, AnalysisID StartBefore,
95 AnalysisID StartAfter, AnalysisID StopBefore,
96 AnalysisID StopAfter) {
94 bool DisableVerify, bool &WillCompleteCodeGenPipeline,
95 raw_pwrite_stream &Out, MachineModuleInfo *MMI) {
9796 // Targets may override createPassConfig to provide a target-specific
9897 // subclass.
9998 TargetPassConfig *PassConfig = TM->createPassConfig(PM);
100 PassConfig->setStartStopPasses(StartBefore, StartAfter, StopBefore,
101 StopAfter);
10299 // Set PassConfig options provided by TargetMachine.
103100 PassConfig->setDisableVerify(DisableVerify);
101 WillCompleteCodeGenPipeline = PassConfig->willCompleteCodeGenPipeline();
104102 PM.add(PassConfig);
105 MachineModuleInfo *MMI = new MachineModuleInfo(TM);
103 if (!MMI)
104 MMI = new MachineModuleInfo(TM);
106105 PM.add(MMI);
107106
108107 if (PassConfig->addISelPasses())
109108 return nullptr;
110109 PassConfig->addMachinePasses();
111110 PassConfig->setInitialized();
111 if (!WillCompleteCodeGenPipeline)
112 PM.add(createPrintMIRPass(Out));
112113
113114 return &MMI->getContext();
114115 }
184185 return false;
185186 }
186187
187 bool LLVMTargetMachine::addPassesToEmitFile(
188 PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType,
189 bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter,
190 AnalysisID StopBefore, AnalysisID StopAfter) {
188 bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
189 raw_pwrite_stream &Out,
190 CodeGenFileType FileType,
191 bool DisableVerify,
192 MachineModuleInfo *MMI) {
191193 // Add common CodeGen passes.
192 MCContext *Context =
193 addPassesToGenerateCode(this, PM, DisableVerify, StartBefore, StartAfter,
194 StopBefore, StopAfter);
194 bool WillCompleteCodeGenPipeline = true;
195 MCContext *Context = addPassesToGenerateCode(
196 this, PM, DisableVerify, WillCompleteCodeGenPipeline, Out, MMI);
195197 if (!Context)
196198 return true;
197199
198 if (StopBefore || StopAfter) {
199 PM.add(createPrintMIRPass(Out));
200 } else {
201 if (addAsmPrinter(PM, Out, FileType, *Context))
202 return true;
203 }
200 if (WillCompleteCodeGenPipeline && addAsmPrinter(PM, Out, FileType, *Context))
201 return true;
204202
205203 PM.add(createFreeMachineFunctionPass());
206204 return false;
215213 raw_pwrite_stream &Out,
216214 bool DisableVerify) {
217215 // Add common CodeGen passes.
218 Ctx = addPassesToGenerateCode(this, PM, DisableVerify, nullptr, nullptr,
219 nullptr, nullptr);
216 bool WillCompleteCodeGenPipeline = true;
217 Ctx = addPassesToGenerateCode(this, PM, DisableVerify,
218 WillCompleteCodeGenPipeline, Out,
219 /*MachineModuleInfo*/ nullptr);
220220 if (!Ctx)
221221 return true;
222 assert(WillCompleteCodeGenPipeline && "CodeGen pipeline has been altered");
222223
223224 if (Options.MCOptions.MCSaveTempLabels)
224225 Ctx->setAllowTemporaryLabels(false);
152152 clEnumValN(CFLAAType::Both, "both",
153153 "Enable both variants of CFL-AA")));
154154
155 /// Option names for limiting the codegen pipeline.
156 /// Those are used in error reporting and we didn't want
157 /// to duplicate their names all over the place.
158 const char *StartAfterOptName = "start-after";
159 const char *StartBeforeOptName = "start-before";
160 const char *StopAfterOptName = "stop-after";
161 const char *StopBeforeOptName = "stop-before";
162
163 static cl::opt
164 StartAfterOpt(StringRef(StartAfterOptName),
165 cl::desc("Resume compilation after a specific pass"),
166 cl::value_desc("pass-name"), cl::init(""));
167
168 static cl::opt
169 StartBeforeOpt(StringRef(StartBeforeOptName),
170 cl::desc("Resume compilation before a specific pass"),
171 cl::value_desc("pass-name"), cl::init(""));
172
173 static cl::opt
174 StopAfterOpt(StringRef(StopAfterOptName),
175 cl::desc("Stop compilation after a specific pass"),
176 cl::value_desc("pass-name"), cl::init(""));
177
178 static cl::opt
179 StopBeforeOpt(StringRef(StopBeforeOptName),
180 cl::desc("Stop compilation before a specific pass"),
181 cl::value_desc("pass-name"), cl::init(""));
182
155183 /// Allow standard passes to be disabled by command line options. This supports
156184 /// simple binary flags that either suppress the pass or do nothing.
157185 /// i.e. -disable-mypass=false has no effect.
281309 delete Impl;
282310 }
283311
312 static const PassInfo *getPassInfo(StringRef PassName) {
313 if (PassName.empty())
314 return nullptr;
315
316 const PassRegistry &PR = *PassRegistry::getPassRegistry();
317 const PassInfo *PI = PR.getPassInfo(PassName);
318 if (!PI)
319 report_fatal_error(Twine('\"') + Twine(PassName) +
320 Twine("\" pass is not registered."));
321 return PI;
322 }
323
324 static AnalysisID getPassIDFromName(StringRef PassName) {
325 const PassInfo *PI = getPassInfo(PassName);
326 return PI ? PI->getTypeInfo() : nullptr;
327 }
328
329 void TargetPassConfig::setStartStopPasses() {
330 StartBefore = getPassIDFromName(StartBeforeOpt);
331 StartAfter = getPassIDFromName(StartAfterOpt);
332 StopBefore = getPassIDFromName(StopBeforeOpt);
333 StopAfter = getPassIDFromName(StopAfterOpt);
334 if (StartBefore && StartAfter)
335 report_fatal_error(Twine(StartBeforeOptName) + Twine(" and ") +
336 Twine(StartAfterOptName) + Twine(" specified!"));
337 if (StopBefore && StopAfter)
338 report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") +
339 Twine(StopAfterOptName) + Twine(" specified!"));
340 Started = (StartAfter == nullptr) && (StartBefore == nullptr);
341 }
342
284343 // Out of line constructor provides default values for pass options and
285344 // registers all common codegen passes.
286345 TargetPassConfig::TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm)
304363
305364 if (TM.Options.EnableIPRA)
306365 setRequiresCodeGenSCCOrder();
366
367 setStartStopPasses();
307368 }
308369
309370 CodeGenOpt::Level TargetPassConfig::getOptLevel() const {
336397 report_fatal_error("Trying to construct TargetPassConfig without a target "
337398 "machine. Scheduling a CodeGen pass without a target "
338399 "triple set?");
400 }
401
402 bool TargetPassConfig::hasLimitedCodeGenPipeline() const {
403 return StartBefore || StartAfter || StopBefore || StopAfter;
404 }
405
406 std::string
407 TargetPassConfig::getLimitedCodeGenPipelineReason(const char *Separator) const {
408 if (!hasLimitedCodeGenPipeline())
409 return std::string();
410 std::string Res;
411 static cl::opt *PassNames[] = {&StartAfterOpt, &StartBeforeOpt,
412 &StopAfterOpt, &StopBeforeOpt};
413 static const char *OptNames[] = {StartAfterOptName, StartBeforeOptName,
414 StopAfterOptName, StopBeforeOptName};
415 bool IsFirst = true;
416 for (int Idx = 0; Idx < 4; ++Idx)
417 if (!PassNames[Idx]->empty()) {
418 if (!IsFirst)
419 Res += Separator;
420 IsFirst = false;
421 Res += OptNames[Idx];
422 }
423 return Res;
339424 }
340425
341426 // Helper to verify the analysis is really immutable.
2626 ; RUN: not llc < %s -stop-before=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-STOP-BEFORE
2727 ; RUN: not llc < %s -start-after=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-START-AFTER
2828 ; RUN: not llc < %s -stop-after=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-STOP-AFTER
29 ; NONEXISTENT-START-BEFORE: start-before pass is not registered.
30 ; NONEXISTENT-STOP-BEFORE: stop-before pass is not registered.
31 ; NONEXISTENT-START-AFTER: start-after pass is not registered.
32 ; NONEXISTENT-STOP-AFTER: stop-after pass is not registered.
29 ; NONEXISTENT-START-BEFORE: "nonexistent" pass is not registered.
30 ; NONEXISTENT-STOP-BEFORE: "nonexistent" pass is not registered.
31 ; NONEXISTENT-START-AFTER: "nonexistent" pass is not registered.
32 ; NONEXISTENT-STOP-AFTER: "nonexistent" pass is not registered.
3333
3434 ; RUN: not llc < %s -start-before=loop-reduce -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=DOUBLE-START
3535 ; RUN: not llc < %s -stop-before=loop-reduce -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=DOUBLE-STOP
36 ; DOUBLE-START: -start-before and -start-after specified!
37 ; DOUBLE-STOP: -stop-before and -stop-after specified!
36 ; DOUBLE-START: start-before and start-after specified!
37 ; DOUBLE-STOP: stop-before and stop-after specified!
125125 cl::desc("Discard names from Value (other than GlobalValue)."),
126126 cl::init(false), cl::Hidden);
127127
128 static cl::opt StopBefore("stop-before",
129 cl::desc("Stop compilation before a specific pass"),
130 cl::value_desc("pass-name"), cl::init(""));
131
132 static cl::opt StopAfter("stop-after",
133 cl::desc("Stop compilation after a specific pass"),
134 cl::value_desc("pass-name"), cl::init(""));
135
136 static cl::opt StartBefore("start-before",
137 cl::desc("Resume compilation before a specific pass"),
138 cl::value_desc("pass-name"), cl::init(""));
139
140 static cl::opt StartAfter("start-after",
141 cl::desc("Resume compilation after a specific pass"),
142 cl::value_desc("pass-name"), cl::init(""));
143
144128 static cl::list IncludeDirs("I", cl::desc("include search path"));
145129
146130 static cl::opt PassRemarksWithHotness(
388372 return false;
389373 }
390374
391 static AnalysisID getPassID(const char *argv0, const char *OptionName,
392 StringRef PassName) {
393 if (PassName.empty())
394 return nullptr;
395
396 const PassRegistry &PR = *PassRegistry::getPassRegistry();
397 const PassInfo *PI = PR.getPassInfo(PassName);
398 if (!PI) {
399 errs() << argv0 << ": " << OptionName << " pass is not registered.\n";
400 exit(1);
401 }
402 return PI->getTypeInfo();
403 }
404
405375 static int compileModule(char **argv, LLVMContext &Context) {
406376 // Load the module to be compiled...
407377 SMDiagnostic Err;
536506 }
537507
538508 const char *argv0 = argv[0];
539 AnalysisID StartBeforeID = getPassID(argv0, "start-before", StartBefore);
540 AnalysisID StartAfterID = getPassID(argv0, "start-after", StartAfter);
541 AnalysisID StopAfterID = getPassID(argv0, "stop-after", StopAfter);
542 AnalysisID StopBeforeID = getPassID(argv0, "stop-before", StopBefore);
543 if (StartBeforeID && StartAfterID) {
544 errs() << argv0 << ": -start-before and -start-after specified!\n";
545 return 1;
546 }
547 if (StopBeforeID && StopAfterID) {
548 errs() << argv0 << ": -stop-before and -stop-after specified!\n";
549 return 1;
550 }
551
552 if (MIR) {
553 // Construct a custom pass pipeline that starts after instruction
554 // selection.
555 LLVMTargetMachine &LLVMTM = static_cast(*Target);
509 LLVMTargetMachine &LLVMTM = static_cast(*Target);
510 MachineModuleInfo *MMI = new MachineModuleInfo(&LLVMTM);
511
512 // Construct a custom pass pipeline that starts after instruction
513 // selection.
514 if (!RunPassNames->empty()) {
515 if (!MIR) {
516 errs() << argv0 << ": run-pass is for .mir file only.\n";
517 return 1;
518 }
556519 TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM);
520 if (TPC.hasLimitedCodeGenPipeline()) {
521 errs() << argv0 << ": run-pass cannot be used with "
522 << TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n";
523 return 1;
524 }
525
557526 TPC.setDisableVerify(NoVerify);
558527 PM.add(&TPC);
559 MachineModuleInfo *MMI = new MachineModuleInfo(&LLVMTM);
528 PM.add(MMI);
529 TPC.printAndVerify("");
530 for (const std::string &RunPassName : *RunPassNames) {
531 if (addPass(PM, argv0, RunPassName, TPC))
532 return 1;
533 }
534 TPC.setInitialized();
535 PM.add(createPrintMIRPass(*OS));
536 PM.add(createFreeMachineFunctionPass());
537 } else if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, MMI)) {
538 errs() << argv0 << ": target does not support generation of this"
539 << " file type!\n";
540 return 1;
541 }
542
543 if (MIR) {
544 assert(MMI && "addPassesToEmitFile didn't set MMI");
560545 if (MIR->parseMachineFunctions(*M, *MMI))
561546 return 1;
562 PM.add(MMI);
563 TPC.printAndVerify("");
564
565 if (!RunPassNames->empty()) {
566 if (!StartAfter.empty() || !StopAfter.empty() || !StartBefore.empty() ||
567 !StopBefore.empty()) {
568 errs() << argv0 << ": start-after and/or stop-after passes are "
569 "redundant when run-pass is specified.\n";
570 return 1;
571 }
572
573 for (const std::string &RunPassName : *RunPassNames) {
574 if (addPass(PM, argv0, RunPassName, TPC))
575 return 1;
576 }
577 } else {
578 TPC.setStartStopPasses(StartBeforeID, StartAfterID, StopBeforeID,
579 StopAfterID);
580 TPC.addISelPasses();
581 TPC.addMachinePasses();
582 }
583 TPC.setInitialized();
584
585 if (!StopBefore.empty() || !StopAfter.empty() || !RunPassNames->empty()) {
586 PM.add(createPrintMIRPass(*OS));
587 } else if (LLVMTM.addAsmPrinter(PM, *OS, FileType, MMI->getContext())) {
588 errs() << argv0 << ": target does not support generation of this"
589 << " file type!\n";
590 return 1;
591 }
592 PM.add(createFreeMachineFunctionPass());
593 } else if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify,
594 StartBeforeID, StartAfterID,
595 StopBeforeID, StopAfterID)) {
596 errs() << argv0 << ": target does not support generation of this"
597 << " file type!\n";
598 return 1;
599547 }
600548
601549 // Before executing passes, print the final values of the LLVM options.