llvm.org GIT mirror llvm / 1904561
[PM] Enable registration of out-of-tree passes with PassBuilder Summary: This patch adds a callback registration API to the PassBuilder, enabling registering out-of-tree passes with it. Through the Callback API, callers may register callbacks with the various stages at which passes are added into pass managers, including parsing of a pass pipeline as well as at extension points within the default -O pipelines. Registering utilities like `require<>` and `invalidate<>` needs to be handled manually by the caller, but a helper is provided. Additionally, adding passes at pipeline extension points is exposed through the opt tool. This patch adds a `-passes-ep-X` commandline option for every extension point X, which opt parses into pipelines inserted into that extension point. Reviewers: chandlerc Reviewed By: chandlerc Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny Differential Revision: https://reviews.llvm.org/D33464 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307532 91177308-0d34-0410-b5e6-96231b3b80d8 Philip Pfaffe 2 years ago
7 changed file(s) with 1114 addition(s) and 58 deletion(s). Raw diff Collapse all Expand all
4545 Optional PGOOpt;
4646
4747 public:
48 /// \brief A struct to capture parsed pass pipeline names.
49 ///
50 /// A pipeline is defined as a series of names, each of which may in itself
51 /// recursively contain a nested pipeline. A name is either the name of a pass
52 /// (e.g. "instcombine") or the name of a pipeline type (e.g. "cgscc"). If the
53 /// name is the name of a pass, the InnerPipeline is empty, since passes
54 /// cannot contain inner pipelines. See parsePassPipeline() for a more
55 /// detailed description of the textual pipeline format.
56 struct PipelineElement {
57 StringRef Name;
58 std::vector InnerPipeline;
59 };
60
4861 /// \brief LLVM-provided high-level optimization levels.
4962 ///
5063 /// This enumerates the LLVM-provided high-level optimization levels. Each
311324 /// registered.
312325 AAManager buildDefaultAAPipeline();
313326
314 /// \brief Parse a textual pass pipeline description into a \c ModulePassManager.
327 /// \brief Parse a textual pass pipeline description into a \c
328 /// ModulePassManager.
315329 ///
316330 /// The format of the textual pass pipeline description looks something like:
317331 ///
321335 /// are comma separated. As a special shortcut, if the very first pass is not
322336 /// a module pass (as a module pass manager is), this will automatically form
323337 /// the shortest stack of pass managers that allow inserting that first pass.
324 /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes
325 /// 'lpassN', all of these are valid:
338 /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop
339 /// passes 'lpassN', all of these are valid:
326340 ///
327341 /// fpass1,fpass2,fpass3
328342 /// cgpass1,cgpass2,cgpass3
335349 /// module(function(loop(lpass1,lpass2,lpass3)))
336350 ///
337351 /// This shortcut is especially useful for debugging and testing small pass
338 /// combinations. Note that these shortcuts don't introduce any other magic. If
339 /// the sequence of passes aren't all the exact same kind of pass, it will be
340 /// an error. You cannot mix different levels implicitly, you must explicitly
341 /// form a pass manager in which to nest passes.
352 /// combinations. Note that these shortcuts don't introduce any other magic.
353 /// If the sequence of passes aren't all the exact same kind of pass, it will
354 /// be an error. You cannot mix different levels implicitly, you must
355 /// explicitly form a pass manager in which to nest passes.
342356 bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
343357 bool VerifyEachPass = true, bool DebugLogging = false);
358
359 /// {{@ Parse a textual pass pipeline description into a specific PassManager
360 ///
361 /// Automatic deduction of an appropriate pass manager stack is not supported.
362 /// For example, to insert a loop pass 'lpass' into a FunctinoPassManager,
363 /// this is the valid pipeline text:
364 ///
365 /// function(lpass)
366 bool parsePassPipeline(CGSCCPassManager &CGPM, StringRef PipelineText,
367 bool VerifyEachPass = true, bool DebugLogging = false);
368 bool parsePassPipeline(FunctionPassManager &FPM, StringRef PipelineText,
369 bool VerifyEachPass = true, bool DebugLogging = false);
370 bool parsePassPipeline(LoopPassManager &LPM, StringRef PipelineText,
371 bool VerifyEachPass = true, bool DebugLogging = false);
372 /// @}}
344373
345374 /// Parse a textual alias analysis pipeline into the provided AA manager.
346375 ///
359388 /// returns false.
360389 bool parseAAPipeline(AAManager &AA, StringRef PipelineText);
361390
391 /// \brief Register a callback for a default optimizer pipeline extension
392 /// point
393 ///
394 /// This extension point allows adding passes that perform peephole
395 /// optimizations similar to the instruction combiner. These passes will be
396 /// inserted after each instance of the instruction combiner pass.
397 void registerPeepholeEPCallback(
398 const std::function &C) {
399 PeepholeEPCallbacks.push_back(C);
400 }
401
402 /// \brief Register a callback for a default optimizer pipeline extension
403 /// point
404 ///
405 /// This extension point allows adding late loop canonicalization and
406 /// simplification passes. This is the last point in the loop optimization
407 /// pipeline before loop deletion. Each pass added
408 /// here must be an instance of LoopPass.
409 /// This is the place to add passes that can remove loops, such as target-
410 /// specific loop idiom recognition.
411 void registerLateLoopOptimizationsEPCallback(
412 const std::function &C) {
413 LateLoopOptimizationsEPCallbacks.push_back(C);
414 }
415
416 /// \brief Register a callback for a default optimizer pipeline extension
417 /// point
418 ///
419 /// This extension point allows adding loop passes to the end of the loop
420 /// optimizer.
421 void registerLoopOptimizerEndEPCallback(
422 const std::function &C) {
423 LoopOptimizerEndEPCallbacks.push_back(C);
424 }
425
426 /// \brief Register a callback for a default optimizer pipeline extension
427 /// point
428 ///
429 /// This extension point allows adding optimization passes after most of the
430 /// main optimizations, but before the last cleanup-ish optimizations.
431 void registerScalarOptimizerLateEPCallback(
432 const std::function &C) {
433 ScalarOptimizerLateEPCallbacks.push_back(C);
434 }
435
436 /// \brief Register a callback for a default optimizer pipeline extension
437 /// point
438 ///
439 /// This extension point allows adding CallGraphSCC passes at the end of the
440 /// main CallGraphSCC passes and before any function simplification passes run
441 /// by CGPassManager.
442 void registerCGSCCOptimizerLateEPCallback(
443 const std::function &C) {
444 CGSCCOptimizerLateEPCallbacks.push_back(C);
445 }
446
447 /// \brief Register a callback for a default optimizer pipeline extension
448 /// point
449 ///
450 /// This extension point allows adding optimization passes before the
451 /// vectorizer and other highly target specific optimization passes are
452 /// executed.
453 void registerVectorizerStartEPCallback(
454 const std::function &C) {
455 VectorizerStartEPCallbacks.push_back(C);
456 }
457
458 /// \brief Register a callback for parsing an AliasAnalysis Name to populate
459 /// the given AAManager \p AA
460 void registerParseAACallback(
461 const std::function &C) {
462 AAParsingCallbacks.push_back(C);
463 }
464
465 /// {{@ Register callbacks for analysis registration with this PassBuilder
466 /// instance.
467 /// Callees register their analyses with the given AnalysisManager objects.
468 void registerAnalysisRegistrationCallback(
469 const std::function &C) {
470 CGSCCAnalysisRegistrationCallbacks.push_back(C);
471 }
472 void registerAnalysisRegistrationCallback(
473 const std::function &C) {
474 FunctionAnalysisRegistrationCallbacks.push_back(C);
475 }
476 void registerAnalysisRegistrationCallback(
477 const std::function &C) {
478 LoopAnalysisRegistrationCallbacks.push_back(C);
479 }
480 void registerAnalysisRegistrationCallback(
481 const std::function &C) {
482 ModuleAnalysisRegistrationCallbacks.push_back(C);
483 }
484 /// @}}
485
486 /// {{@ Register pipeline parsing callbacks with this pass builder instance.
487 /// Using these callbacks, callers can parse both a single pass name, as well
488 /// as entire sub-pipelines, and populate the PassManager instance
489 /// accordingly.
490 void registerPipelineParsingCallback(
491 const std::function
492 ArrayRef)> &C) {
493 CGSCCPipelineParsingCallbacks.push_back(C);
494 }
495 void registerPipelineParsingCallback(
496 const std::function
497 ArrayRef)> &C) {
498 FunctionPipelineParsingCallbacks.push_back(C);
499 }
500 void registerPipelineParsingCallback(
501 const std::function
502 ArrayRef)> &C) {
503 LoopPipelineParsingCallbacks.push_back(C);
504 }
505 void registerPipelineParsingCallback(
506 const std::function
507 ArrayRef)> &C) {
508 ModulePipelineParsingCallbacks.push_back(C);
509 }
510 /// @}}
511
512 /// \brief Register a callback for a top-level pipeline entry.
513 ///
514 /// If the PassManager type is not given at the top level of the pipeline
515 /// text, this Callback should be used to determine the appropriate stack of
516 /// PassManagers and populate the passed ModulePassManager.
517 void registerParseTopLevelPipelineCallback(
518 const std::function,
519 bool VerifyEachPass, bool DebugLogging)> &C) {
520 TopLevelPipelineParsingCallbacks.push_back(C);
521 }
522
362523 private:
363 /// A struct to capture parsed pass pipeline names.
364 struct PipelineElement {
365 StringRef Name;
366 std::vector InnerPipeline;
367 };
368
369524 static Optional>
370525 parsePipelineText(StringRef Text);
371526
391546 bool parseModulePassPipeline(ModulePassManager &MPM,
392547 ArrayRef Pipeline,
393548 bool VerifyEachPass, bool DebugLogging);
549
550 void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
551 OptimizationLevel Level, bool RunProfileGen,
552 std::string ProfileGenFile,
553 std::string ProfileUseFile);
554
555 void invokePeepholeEPCallbacks(FunctionPassManager &, OptimizationLevel);
556
557 // Extension Point callbacks
558 SmallVector, 2>
559 PeepholeEPCallbacks;
560 SmallVector, 2>
561 LateLoopOptimizationsEPCallbacks;
562 SmallVector, 2>
563 LoopOptimizerEndEPCallbacks;
564 SmallVector, 2>
565 ScalarOptimizerLateEPCallbacks;
566 SmallVector, 2>
567 CGSCCOptimizerLateEPCallbacks;
568 SmallVector, 2>
569 VectorizerStartEPCallbacks;
570 // Module callbacks
571 SmallVector, 2>
572 ModuleAnalysisRegistrationCallbacks;
573 SmallVector
574 ArrayRef)>,
575 2>
576 ModulePipelineParsingCallbacks;
577 SmallVector,
578 bool VerifyEachPass, bool DebugLogging)>,
579 2>
580 TopLevelPipelineParsingCallbacks;
581 // CGSCC callbacks
582 SmallVector, 2>
583 CGSCCAnalysisRegistrationCallbacks;
584 SmallVector
585 ArrayRef)>,
586 2>
587 CGSCCPipelineParsingCallbacks;
588 // Function callbacks
589 SmallVector, 2>
590 FunctionAnalysisRegistrationCallbacks;
591 SmallVector
592 ArrayRef)>,
593 2>
594 FunctionPipelineParsingCallbacks;
595 // Loop callbacks
596 SmallVector, 2>
597 LoopAnalysisRegistrationCallbacks;
598 SmallVector
599 ArrayRef)>,
600 2>
601 LoopPipelineParsingCallbacks;
602 // AA callbacks
603 SmallVector, 2>
604 AAParsingCallbacks;
394605 };
606
607 /// This utility template takes care of adding require<> and invalidate<>
608 /// passes for an analysis to a given \c PassManager. It is intended to be used
609 /// during parsing of a pass pipeline when parsing a single PipelineName.
610 /// When registering a new function analysis FancyAnalysis with the pass
611 /// pipeline name "fancy-analysis", a matching ParsePipelineCallback could look
612 /// like this:
613 ///
614 /// static bool parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM,
615 /// ArrayRef P) {
616 /// if (parseAnalysisUtilityPasses("fancy-analysis", Name,
617 /// FPM))
618 /// return true;
619 /// return false;
620 /// }
621 template
622 typename... ExtraArgTs>
623 bool parseAnalysisUtilityPasses(
624 StringRef AnalysisName, StringRef PipelineName,
625 PassManager &PM) {
626 if (!PipelineName.endswith(">"))
627 return false;
628 // See if this is an invalidate<> pass name
629 if (PipelineName.startswith("invalidate<")) {
630 PipelineName = PipelineName.substr(11, PipelineName.size() - 12);
631 if (PipelineName != AnalysisName)
632 return false;
633 PM.addPass(InvalidateAnalysisPass());
634 return true;
635 }
636
637 // See if this is a require<> pass name
638 if (PipelineName.startswith("require<")) {
639 PipelineName = PipelineName.substr(8, PipelineName.size() - 9);
640 if (PipelineName != AnalysisName)
641 return false;
642 PM.addPass(RequireAnalysisPass
643 ExtraArgTs...>());
644 return true;
645 }
646
647 return false;
395648 }
649 }
396650
397651 #endif
280280
281281 } // End anonymous namespace.
282282
283 void PassBuilder::invokePeepholeEPCallbacks(
284 FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
285 for (auto &C : PeepholeEPCallbacks)
286 C(FPM, Level);
287 }
288
283289 void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) {
284290 #define MODULE_ANALYSIS(NAME, CREATE_PASS) \
285291 MAM.registerPass([&] { return CREATE_PASS; });
286292 #include "PassRegistry.def"
293
294 for (auto &C : ModuleAnalysisRegistrationCallbacks)
295 C(MAM);
287296 }
288297
289298 void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {
290299 #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
291300 CGAM.registerPass([&] { return CREATE_PASS; });
292301 #include "PassRegistry.def"
302
303 for (auto &C : CGSCCAnalysisRegistrationCallbacks)
304 C(CGAM);
293305 }
294306
295307 void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
296308 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
297309 FAM.registerPass([&] { return CREATE_PASS; });
298310 #include "PassRegistry.def"
311
312 for (auto &C : FunctionAnalysisRegistrationCallbacks)
313 C(FAM);
299314 }
300315
301316 void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {
302317 #define LOOP_ANALYSIS(NAME, CREATE_PASS) \
303318 LAM.registerPass([&] { return CREATE_PASS; });
304319 #include "PassRegistry.def"
320
321 for (auto &C : LoopAnalysisRegistrationCallbacks)
322 C(LAM);
305323 }
306324
307325 FunctionPassManager
339357
340358 if (!isOptimizingForSize(Level))
341359 FPM.addPass(LibCallsShrinkWrapPass());
360
361 invokePeepholeEPCallbacks(FPM, Level);
342362
343363 FPM.addPass(TailCallElimPass());
344364 FPM.addPass(SimplifyCFGPass());
363383 LPM1.addPass(SimpleLoopUnswitchPass());
364384 LPM2.addPass(IndVarSimplifyPass());
365385 LPM2.addPass(LoopIdiomRecognizePass());
386
387 for (auto &C : LateLoopOptimizationsEPCallbacks)
388 C(LPM2, Level);
389
366390 LPM2.addPass(LoopDeletionPass());
367391 // Do not enable unrolling in PrepareForThinLTO phase during sample PGO
368392 // because it changes IR to makes profile annotation in back compile
369393 // inaccurate.
370394 if (!PrepareForThinLTO || !PGOOpt || PGOOpt->SampleProfileFile.empty())
371395 LPM2.addPass(LoopUnrollPass::createFull(Level));
396
397 for (auto &C : LoopOptimizerEndEPCallbacks)
398 C(LPM2, Level);
372399
373400 // We provide the opt remark emitter pass for LICM to use. We only need to do
374401 // this once as it is immutable.
404431 // Run instcombine after redundancy and dead bit elimination to exploit
405432 // opportunities opened up by them.
406433 FPM.addPass(InstCombinePass());
434 invokePeepholeEPCallbacks(FPM, Level);
407435
408436 // Re-consider control flow based optimizations after redundancy elimination,
409437 // redo DCE, etc.
412440 FPM.addPass(DSEPass());
413441 FPM.addPass(createFunctionToLoopPassAdaptor(LICMPass()));
414442
443 for (auto &C : ScalarOptimizerLateEPCallbacks)
444 C(FPM, Level);
445
415446 // Finally, do an expensive DCE pass to catch all the dead code exposed by
416447 // the simplifications and basic cleanup after all the simplifications.
417448 FPM.addPass(ADCEPass());
418449 FPM.addPass(SimplifyCFGPass());
419450 FPM.addPass(InstCombinePass());
451 invokePeepholeEPCallbacks(FPM, Level);
420452
421453 return FPM;
422454 }
423455
424 static void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
425 PassBuilder::OptimizationLevel Level,
426 bool RunProfileGen, std::string ProfileGenFile,
427 std::string ProfileUseFile) {
456 void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
457 PassBuilder::OptimizationLevel Level,
458 bool RunProfileGen,
459 std::string ProfileGenFile,
460 std::string ProfileUseFile) {
428461 // Generally running simplification passes and the inliner with an high
429462 // threshold results in smaller executables, but there may be cases where
430463 // the size grows, so let's be conservative here and skip this simplification
449482 FPM.addPass(EarlyCSEPass()); // Catch trivial redundancies.
450483 FPM.addPass(SimplifyCFGPass()); // Merge & remove basic blocks.
451484 FPM.addPass(InstCombinePass()); // Combine silly sequences.
452
453 // FIXME: Here the old pass manager inserts peephole extensions.
454 // Add them when they're supported.
485 invokePeepholeEPCallbacks(FPM, Level);
486
455487 CGPipeline.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM)));
456488
457489 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPipeline)));
532564 // optimizations.
533565 FunctionPassManager GlobalCleanupPM(DebugLogging);
534566 GlobalCleanupPM.addPass(InstCombinePass());
567 invokePeepholeEPCallbacks(GlobalCleanupPM, Level);
568
535569 GlobalCleanupPM.addPass(SimplifyCFGPass());
536570 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM)));
537571
596630 buildFunctionSimplificationPipeline(Level, DebugLogging,
597631 PrepareForThinLTO)));
598632
633 for (auto &C : CGSCCOptimizerLateEPCallbacks)
634 C(MainCGPipeline, Level);
635
599636 // We wrap the CGSCC pipeline in a devirtualization repeater. This will try
600637 // to detect when we devirtualize indirect calls and iterate the SCC passes
601638 // in that case to try and catch knock-on inlining or function attrs
653690 // Optimize the loop execution. These passes operate on entire loop nests
654691 // rather than on each loop in an inside-out manner, and so they are actually
655692 // function passes.
693
694 for (auto &C : VectorizerStartEPCallbacks)
695 C(OptimizePM, Level);
656696
657697 // First rotate loops that may have been un-rotated by prior passes.
658698 OptimizePM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass()));
882922 // simplification opportunities, and both can propagate functions through
883923 // function pointers. When this happens, we often have to resolve varargs
884924 // calls, etc, so let instcombine do this.
885 // FIXME: add peephole extensions here as the legacy PM does.
886 MPM.addPass(createModuleToFunctionPassAdaptor(InstCombinePass()));
925 FunctionPassManager PeepholeFPM(DebugLogging);
926 PeepholeFPM.addPass(InstCombinePass());
927 invokePeepholeEPCallbacks(PeepholeFPM, Level);
928
929 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(PeepholeFPM)));
887930
888931 // Note: historically, the PruneEH pass was run first to deduce nounwind and
889932 // generally clean up exception handling overhead. It isn't clear this is
901944 MPM.addPass(GlobalDCEPass());
902945
903946 FunctionPassManager FPM(DebugLogging);
904
905947 // The IPO Passes may leave cruft around. Clean up after them.
906 // FIXME: add peephole extensions here as the legacy PM does.
907948 FPM.addPass(InstCombinePass());
949 invokePeepholeEPCallbacks(FPM, Level);
950
908951 FPM.addPass(JumpThreadingPass());
909952
910953 // Break up allocas
951994 MainFPM.add(AlignmentFromAssumptionsPass());
952995 #endif
953996
954 // FIXME: add peephole extensions to the PM here.
997 // FIXME: Conditionally run LoadCombine here, after it's ported
998 // (in case we still have this pass, given its questionable usefulness).
999
9551000 MainFPM.addPass(InstCombinePass());
1001 invokePeepholeEPCallbacks(MainFPM, Level);
9561002 MainFPM.addPass(JumpThreadingPass());
9571003 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(MainFPM)));
9581004
10351081 Name.startswith("lto");
10361082 }
10371083
1038 static bool isModulePassName(StringRef Name) {
1084 /// Tests whether registered callbacks will accept a given pass name.
1085 ///
1086 /// When parsing a pipeline text, the type of the outermost pipeline may be
1087 /// omitted, in which case the type is automatically determined from the first
1088 /// pass name in the text. This may be a name that is handled through one of the
1089 /// callbacks. We check this through the oridinary parsing callbacks by setting
1090 /// up a dummy PassManager in order to not force the client to also handle this
1091 /// type of query.
1092 template
1093 static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {
1094 if (!Callbacks.empty()) {
1095 PassManagerT DummyPM;
1096 for (auto &CB : Callbacks)
1097 if (CB(Name, DummyPM, {}))
1098 return true;
1099 }
1100 return false;
1101 }
1102
1103 template
1104 static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {
10391105 // Manually handle aliases for pre-configured pipeline fragments.
10401106 if (startsWithDefaultPipelineAliasPrefix(Name))
10411107 return DefaultAliasRegex.match(Name);
10601126 return true;
10611127 #include "PassRegistry.def"
10621128
1063 return false;
1064 }
1065
1066 static bool isCGSCCPassName(StringRef Name) {
1129 return callbacksAcceptPassName(Name, Callbacks);
1130 }
1131
1132 template
1133 static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) {
10671134 // Explicitly handle pass manager names.
10681135 if (Name == "cgscc")
10691136 return true;
10841151 return true;
10851152 #include "PassRegistry.def"
10861153
1087 return false;
1088 }
1089
1090 static bool isFunctionPassName(StringRef Name) {
1154 return callbacksAcceptPassName(Name, Callbacks);
1155 }
1156
1157 template
1158 static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
10911159 // Explicitly handle pass manager names.
10921160 if (Name == "function")
10931161 return true;
11061174 return true;
11071175 #include "PassRegistry.def"
11081176
1109 return false;
1110 }
1111
1112 static bool isLoopPassName(StringRef Name) {
1177 return callbacksAcceptPassName(Name, Callbacks);
1178 }
1179
1180 template
1181 static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks) {
11131182 // Explicitly handle pass manager names.
11141183 if (Name == "loop")
11151184 return true;
11261195 return true;
11271196 #include "PassRegistry.def"
11281197
1129 return false;
1198 return callbacksAcceptPassName(Name, Callbacks);
11301199 }
11311200
11321201 Optional>
12271296 MPM.addPass(createRepeatedPass(*Count, std::move(NestedMPM)));
12281297 return true;
12291298 }
1299
1300 for (auto &C : ModulePipelineParsingCallbacks)
1301 if (C(Name, MPM, InnerPipeline))
1302 return true;
1303
12301304 // Normal passes can't have pipelines.
12311305 return false;
12321306 }
12391313 assert(Matches.size() == 3 && "Must capture two matched strings!");
12401314
12411315 OptimizationLevel L = StringSwitch(Matches[2])
1242 .Case("O0", O0)
1243 .Case("O1", O1)
1244 .Case("O2", O2)
1245 .Case("O3", O3)
1246 .Case("Os", Os)
1247 .Case("Oz", Oz);
1316 .Case("O0", O0)
1317 .Case("O1", O1)
1318 .Case("O2", O2)
1319 .Case("O3", O3)
1320 .Case("Os", Os)
1321 .Case("Oz", Oz);
12481322 if (L == O0)
12491323 // At O0 we do nothing at all!
12501324 return true;
12841358 }
12851359 #include "PassRegistry.def"
12861360
1361 for (auto &C : ModulePipelineParsingCallbacks)
1362 if (C(Name, MPM, InnerPipeline))
1363 return true;
12871364 return false;
12881365 }
12891366
13311408 *MaxRepetitions, DebugLogging));
13321409 return true;
13331410 }
1411
1412 for (auto &C : CGSCCPipelineParsingCallbacks)
1413 if (C(Name, CGPM, InnerPipeline))
1414 return true;
1415
13341416 // Normal passes can't have pipelines.
13351417 return false;
13361418 }
13371419
1338 // Now expand the basic registered passes from the .inc file.
1420 // Now expand the basic registered passes from the .inc file.
13391421 #define CGSCC_PASS(NAME, CREATE_PASS) \
13401422 if (Name == NAME) { \
13411423 CGPM.addPass(CREATE_PASS); \
13561438 }
13571439 #include "PassRegistry.def"
13581440
1441 for (auto &C : CGSCCPipelineParsingCallbacks)
1442 if (C(Name, CGPM, InnerPipeline))
1443 return true;
13591444 return false;
13601445 }
13611446
13931478 FPM.addPass(createRepeatedPass(*Count, std::move(NestedFPM)));
13941479 return true;
13951480 }
1481
1482 for (auto &C : FunctionPipelineParsingCallbacks)
1483 if (C(Name, FPM, InnerPipeline))
1484 return true;
1485
13961486 // Normal passes can't have pipelines.
13971487 return false;
13981488 }
13991489
1400 // Now expand the basic registered passes from the .inc file.
1490 // Now expand the basic registered passes from the .inc file.
14011491 #define FUNCTION_PASS(NAME, CREATE_PASS) \
14021492 if (Name == NAME) { \
14031493 FPM.addPass(CREATE_PASS); \
14171507 }
14181508 #include "PassRegistry.def"
14191509
1510 for (auto &C : FunctionPipelineParsingCallbacks)
1511 if (C(Name, FPM, InnerPipeline))
1512 return true;
14201513 return false;
14211514 }
14221515
14441537 LPM.addPass(createRepeatedPass(*Count, std::move(NestedLPM)));
14451538 return true;
14461539 }
1540
1541 for (auto &C : LoopPipelineParsingCallbacks)
1542 if (C(Name, LPM, InnerPipeline))
1543 return true;
1544
14471545 // Normal passes can't have pipelines.
14481546 return false;
14491547 }
14501548
1451 // Now expand the basic registered passes from the .inc file.
1549 // Now expand the basic registered passes from the .inc file.
14521550 #define LOOP_PASS(NAME, CREATE_PASS) \
14531551 if (Name == NAME) { \
14541552 LPM.addPass(CREATE_PASS); \
14691567 }
14701568 #include "PassRegistry.def"
14711569
1570 for (auto &C : LoopPipelineParsingCallbacks)
1571 if (C(Name, LPM, InnerPipeline))
1572 return true;
14721573 return false;
14731574 }
14741575
14871588 }
14881589 #include "PassRegistry.def"
14891590
1591 for (auto &C : AAParsingCallbacks)
1592 if (C(Name, AA))
1593 return true;
14901594 return false;
14911595 }
14921596
15531657 return true;
15541658 }
15551659
1556 // Primary pass pipeline description parsing routine.
1660 // Primary pass pipeline description parsing routine for a \c ModulePassManager
15571661 // FIXME: Should this routine accept a TargetMachine or require the caller to
15581662 // pre-populate the analysis managers with target-specific stuff?
15591663 bool PassBuilder::parsePassPipeline(ModulePassManager &MPM,
15671671 // automatically.
15681672 StringRef FirstName = Pipeline->front().Name;
15691673
1570 if (!isModulePassName(FirstName)) {
1571 if (isCGSCCPassName(FirstName))
1674 if (!isModulePassName(FirstName, ModulePipelineParsingCallbacks)) {
1675 if (isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) {
15721676 Pipeline = {{"cgscc", std::move(*Pipeline)}};
1573 else if (isFunctionPassName(FirstName))
1677 } else if (isFunctionPassName(FirstName,
1678 FunctionPipelineParsingCallbacks)) {
15741679 Pipeline = {{"function", std::move(*Pipeline)}};
1575 else if (isLoopPassName(FirstName))
1680 } else if (isLoopPassName(FirstName, LoopPipelineParsingCallbacks)) {
15761681 Pipeline = {{"function", {{"loop", std::move(*Pipeline)}}}};
1577 else
1682 } else {
1683 for (auto &C : TopLevelPipelineParsingCallbacks)
1684 if (C(MPM, *Pipeline, VerifyEachPass, DebugLogging))
1685 return true;
1686
15781687 // Unknown pass name!
15791688 return false;
1689 }
15801690 }
15811691
15821692 return parseModulePassPipeline(MPM, *Pipeline, VerifyEachPass, DebugLogging);
1693 }
1694
1695 // Primary pass pipeline description parsing routine for a \c CGSCCPassManager
1696 bool PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM,
1697 StringRef PipelineText, bool VerifyEachPass,
1698 bool DebugLogging) {
1699 auto Pipeline = parsePipelineText(PipelineText);
1700 if (!Pipeline || Pipeline->empty())
1701 return false;
1702
1703 StringRef FirstName = Pipeline->front().Name;
1704 if (!isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks))
1705 return false;
1706
1707 return parseCGSCCPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging);
1708 }
1709
1710 // Primary pass pipeline description parsing routine for a \c
1711 // FunctionPassManager
1712 bool PassBuilder::parsePassPipeline(FunctionPassManager &FPM,
1713 StringRef PipelineText, bool VerifyEachPass,
1714 bool DebugLogging) {
1715 auto Pipeline = parsePipelineText(PipelineText);
1716 if (!Pipeline || Pipeline->empty())
1717 return false;
1718
1719 StringRef FirstName = Pipeline->front().Name;
1720 if (!isFunctionPassName(FirstName, FunctionPipelineParsingCallbacks))
1721 return false;
1722
1723 return parseFunctionPassPipeline(FPM, *Pipeline, VerifyEachPass,
1724 DebugLogging);
1725 }
1726
1727 // Primary pass pipeline description parsing routine for a \c LoopPassManager
1728 bool PassBuilder::parsePassPipeline(LoopPassManager &CGPM,
1729 StringRef PipelineText, bool VerifyEachPass,
1730 bool DebugLogging) {
1731 auto Pipeline = parsePipelineText(PipelineText);
1732 if (!Pipeline || Pipeline->empty())
1733 return false;
1734
1735 return parseLoopPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging);
15831736 }
15841737
15851738 bool PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
2424 ; RUN: opt -disable-verify -debug-pass-manager \
2525 ; RUN: -passes='lto-pre-link' -S %s 2>&1 \
2626 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2
27
28 ; RUN: opt -disable-verify -debug-pass-manager \
29 ; RUN: -passes-ep-peephole='no-op-function' \
30 ; RUN: -passes='default' -S %s 2>&1 \
31 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \
32 ; RUN: --check-prefix=CHECK-EP-PEEPHOLE
33 ; RUN: opt -disable-verify -debug-pass-manager \
34 ; RUN: -passes-ep-late-loop-optimizations='no-op-loop' \
35 ; RUN: -passes='default' -S %s 2>&1 \
36 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \
37 ; RUN: --check-prefix=CHECK-EP-LOOP-LATE
38 ; RUN: opt -disable-verify -debug-pass-manager \
39 ; RUN: -passes-ep-loop-optimizer-end='no-op-loop' \
40 ; RUN: -passes='default' -S %s 2>&1 \
41 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \
42 ; RUN: --check-prefix=CHECK-EP-LOOP-END
43 ; RUN: opt -disable-verify -debug-pass-manager \
44 ; RUN: -passes-ep-scalar-optimizer-late='no-op-function' \
45 ; RUN: -passes='default' -S %s 2>&1 \
46 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \
47 ; RUN: --check-prefix=CHECK-EP-SCALAR-LATE
48 ; RUN: opt -disable-verify -debug-pass-manager \
49 ; RUN: -passes-ep-cgscc-optimizer-late='no-op-cgscc' \
50 ; RUN: -passes='default' -S %s 2>&1 \
51 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \
52 ; RUN: --check-prefix=CHECK-EP-CGSCC-LATE
53 ; RUN: opt -disable-verify -debug-pass-manager \
54 ; RUN: -passes-ep-vectorizer-start='no-op-function' \
55 ; RUN: -passes='default' -S %s 2>&1 \
56 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \
57 ; RUN: --check-prefix=CHECK-EP-VECTORIZER-START
2758
2859 ; CHECK-O: Starting llvm::Module pass manager run.
2960 ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module{{.*}}>
5283 ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
5384 ; CHECK-O-NEXT: Starting llvm::Function pass manager run.
5485 ; CHECK-O-NEXT: Running pass: InstCombinePass
86 ; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass
5587 ; CHECK-O-NEXT: Running pass: SimplifyCFGPass
5688 ; CHECK-O-NEXT: Finished llvm::Function pass manager run.
5789 ; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}GlobalsAA
83115 ; CHECK-O1-NEXT: Running pass: LibCallsShrinkWrapPass
84116 ; CHECK-O2-NEXT: Running pass: LibCallsShrinkWrapPass
85117 ; CHECK-O3-NEXT: Running pass: LibCallsShrinkWrapPass
118 ; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass
86119 ; CHECK-O-NEXT: Running pass: TailCallElimPass
87120 ; CHECK-O-NEXT: Running pass: SimplifyCFGPass
88121 ; CHECK-O-NEXT: Running pass: ReassociatePass
104137 ; CHECK-O-NEXT: Starting Loop pass manager run.
105138 ; CHECK-O-NEXT: Running pass: IndVarSimplifyPass
106139 ; CHECK-O-NEXT: Running pass: LoopIdiomRecognizePass
140 ; CHECK-EP-LOOP-LATE-NEXT: Running pass: NoOpLoopPass
107141 ; CHECK-O-NEXT: Running pass: LoopDeletionPass
108142 ; CHECK-O-NEXT: Running pass: LoopUnrollPass
143 ; CHECK-EP-LOOP-END-NEXT: Running pass: NoOpLoopPass
109144 ; CHECK-O-NEXT: Finished Loop pass manager run.
110145 ; CHECK-Os-NEXT: Running pass: MergedLoadStoreMotionPass
111146 ; CHECK-Os-NEXT: Running pass: GVN
125160 ; CHECK-O-NEXT: Running pass: BDCEPass
126161 ; CHECK-O-NEXT: Running analysis: DemandedBitsAnalysis
127162 ; CHECK-O-NEXT: Running pass: InstCombinePass
163 ; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass
128164 ; CHECK-O-NEXT: Running pass: JumpThreadingPass
129165 ; CHECK-O-NEXT: Running pass: CorrelatedValuePropagationPass
130166 ; CHECK-O-NEXT: Running pass: DSEPass
131167 ; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LICMPass{{.*}}>
168 ; CHECK-EP-SCALAR-LATE-NEXT: Running pass: NoOpFunctionPass
132169 ; CHECK-O-NEXT: Running pass: ADCEPass
133170 ; CHECK-O-NEXT: Running analysis: PostDominatorTreeAnalysis
134171 ; CHECK-O-NEXT: Running pass: SimplifyCFGPass
135172 ; CHECK-O-NEXT: Running pass: InstCombinePass
136 ; CHECK-O-NEXT: Finished llvm::Function pass manager run.
173 ; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass
174 ; CHECK-O-NEXT: Finished llvm::Function pass manager run.
175 ; CHECK-EP-CGSCC-LATE-NEXT: Running pass: NoOpCGSCCPass
137176 ; CHECK-O-NEXT: Finished CGSCC pass manager run.
138177 ; CHECK-O-NEXT: Finished llvm::Module pass manager run.
139178 ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module{{.*}}>
145184 ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
146185 ; CHECK-O-NEXT: Starting llvm::Function pass manager run.
147186 ; CHECK-O-NEXT: Running pass: Float2IntPass
187 ; CHECK-EP-VECTORIZER-START-NEXT: Running pass: NoOpFunctionPass
148188 ; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LoopRotatePass
149189 ; CHECK-O-NEXT: Running pass: LoopDistributePass
150190 ; CHECK-O-NEXT: Running pass: LoopVectorizePass
1616 ; RUN: opt -disable-verify -debug-pass-manager \
1717 ; RUN: -passes='lto' -S %s 2>&1 \
1818 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2
19 ; RUN: opt -disable-verify -debug-pass-manager \
20 ; RUN: -passes='lto' -S %s -passes-ep-peephole='no-op-function' 2>&1 \
21 ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 \
22 ; RUN: --check-prefix=CHECK-EP-Peephole
1923
2024 ; CHECK-O: Starting llvm::Module pass manager run.
2125 ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module
4448 ; CHECK-O2-NEXT: Running analysis: AssumptionAnalysis
4549 ; CHECK-O2-NEXT: Running pass: ConstantMergePass
4650 ; CHECK-O2-NEXT: Running pass: DeadArgumentEliminationPass
47 ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}InstCombinePass>
51 ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
52 ; CHECK-O2-NEXT: Starting llvm::Function pass manager run.
53 ; CHECK-O2-NEXT: Running pass: InstCombinePass
54 ; CHECK-EP-Peephole-NEXT: Running pass: NoOpFunctionPass
55 ; CHECK-O2-NEXT: Finished llvm::Function pass manager run.
4856 ; CHECK-O2-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}InlinerPass>
4957 ; CHECK-O2-NEXT: Running pass: GlobalOptPass
5058 ; CHECK-O2-NEXT: Running pass: GlobalDCEPass
5159 ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
5260 ; CHECK-O2-NEXT: Starting llvm::Function pass manager run.
5361 ; CHECK-O2-NEXT: Running pass: InstCombinePass
62 ; CHECK-EP-Peephole-NEXT: Running pass: NoOpFunctionPass
5463 ; CHECK-O2-NEXT: Running pass: JumpThreadingPass
5564 ; CHECK-O2-NEXT: Running analysis: LazyValueAnalysis
5665 ; CHECK-O2-NEXT: Running pass: SROA on foo
4747 "pipeline for handling managed aliasing queries"),
4848 cl::Hidden);
4949
50 /// {{@ These options accept textual pipeline descriptions which will be
51 /// inserted into default pipelines at the respective extension points
52 static cl::opt PeepholeEPPipeline(
53 "passes-ep-peephole",
54 cl::desc("A textual description of the function pass pipeline inserted at "
55 "the Peephole extension points into default pipelines"),
56 cl::Hidden);
57 static cl::opt LateLoopOptimizationsEPPipeline(
58 "passes-ep-late-loop-optimizations",
59 cl::desc(
60 "A textual description of the loop pass pipeline inserted at "
61 "the LateLoopOptimizations extension point into default pipelines"),
62 cl::Hidden);
63 static cl::opt LoopOptimizerEndEPPipeline(
64 "passes-ep-loop-optimizer-end",
65 cl::desc("A textual description of the loop pass pipeline inserted at "
66 "the LoopOptimizerEnd extension point into default pipelines"),
67 cl::Hidden);
68 static cl::opt ScalarOptimizerLateEPPipeline(
69 "passes-ep-scalar-optimizer-late",
70 cl::desc("A textual description of the function pass pipeline inserted at "
71 "the ScalarOptimizerLate extension point into default pipelines"),
72 cl::Hidden);
73 static cl::opt CGSCCOptimizerLateEPPipeline(
74 "passes-ep-cgscc-optimizer-late",
75 cl::desc("A textual description of the cgscc pass pipeline inserted at "
76 "the CGSCCOptimizerLate extension point into default pipelines"),
77 cl::Hidden);
78 static cl::opt VectorizerStartEPPipeline(
79 "passes-ep-vectorizer-start",
80 cl::desc("A textual description of the function pass pipeline inserted at "
81 "the VectorizerStart extension point into default pipelines"),
82 cl::Hidden);
83 /// @}}
84
85 /// If one of the EPPipeline command line options was given, register callbacks
86 /// for parsing and inserting the given pipeline
87 static void registerEPCallbacks(PassBuilder &PB, bool VerifyEachPass,
88 bool DebugLogging) {
89 if (!PeepholeEPPipeline.empty())
90 PB.registerPeepholeEPCallback(
91 [&](FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
92 return PB.parsePassPipeline(PM, PeepholeEPPipeline, VerifyEachPass,
93 DebugPM);
94 });
95 if (!LateLoopOptimizationsEPPipeline.empty())
96 PB.registerLateLoopOptimizationsEPCallback(
97 [&](LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
98 return PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipeline,
99 VerifyEachPass, DebugPM);
100 });
101 if (!LoopOptimizerEndEPPipeline.empty())
102 PB.registerLoopOptimizerEndEPCallback(
103 [&](LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
104 return PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline,
105 VerifyEachPass, DebugPM);
106 });
107 if (!ScalarOptimizerLateEPPipeline.empty())
108 PB.registerScalarOptimizerLateEPCallback(
109 [&](FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
110 return PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline,
111 VerifyEachPass, DebugPM);
112 });
113 if (!CGSCCOptimizerLateEPPipeline.empty())
114 PB.registerCGSCCOptimizerLateEPCallback(
115 [&](CGSCCPassManager &PM, PassBuilder::OptimizationLevel Level) {
116 return PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline,
117 VerifyEachPass, DebugPM);
118 });
119 if (!VectorizerStartEPPipeline.empty())
120 PB.registerVectorizerStartEPCallback(
121 [&](FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
122 return PB.parsePassPipeline(PM, VectorizerStartEPPipeline,
123 VerifyEachPass, DebugPM);
124 });
125 }
126
50127 bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
51128 tool_output_file *Out,
52129 tool_output_file *ThinLTOLinkOut,
55132 bool ShouldPreserveAssemblyUseListOrder,
56133 bool ShouldPreserveBitcodeUseListOrder,
57134 bool EmitSummaryIndex, bool EmitModuleHash) {
135 bool VerifyEachPass = VK == VK_VerifyEachPass;
58136 PassBuilder PB(TM);
137 registerEPCallbacks(PB, VerifyEachPass, DebugPM);
59138
60139 // Specially handle the alias analysis manager so that we can register
61140 // a custom pipeline of AA passes with it.
84163 if (VK > VK_NoVerifier)
85164 MPM.addPass(VerifierPass());
86165
87 if (!PB.parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass,
88 DebugPM)) {
166 if (!PB.parsePassPipeline(MPM, PassPipeline, VerifyEachPass, DebugPM)) {
89167 errs() << Arg0 << ": unable to parse pass pipeline description.\n";
90168 return false;
91169 }
22 AsmParser
33 Core
44 Support
5 Passes
56 )
67
78 set(IRSources
1415 DebugTypeODRUniquingTest.cpp
1516 DominatorTreeTest.cpp
1617 FunctionTest.cpp
18 PassBuilderCallbacksTest.cpp
1719 IRBuilderTest.cpp
1820 InstructionsTest.cpp
1921 IntrinsicsTest.cpp
0 //===- unittests/IR/PassBuilderCallbacksTest.cpp - PB Callback Tests --===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19
20 using namespace llvm;
21
22 namespace llvm {
23 /// Provide an ostream operator for StringRef.
24 ///
25 /// For convenience we provide a custom matcher below for IRUnit's and analysis
26 /// result's getName functions, which most of the time returns a StringRef. The
27 /// matcher makes use of this operator.
28 static std::ostream &operator<<(std::ostream &O, StringRef S) {
29 return O << S.str();
30 }
31 }
32
33 namespace {
34 using testing::DoDefault;
35 using testing::Return;
36 using testing::Expectation;
37 using testing::Invoke;
38 using testing::WithArgs;
39 using testing::_;
40
41 /// \brief A CRTP base for analysis mock handles
42 ///
43 /// This class reconciles mocking with the value semantics implementation of the
44 /// AnalysisManager. Analysis mock handles should derive from this class and
45 /// call \c setDefault() in their constroctur for wiring up the defaults defined
46 /// by this base with their mock run() and invalidate() implementations.
47 template
48 typename AnalysisManagerT = AnalysisManager,
49 typename... ExtraArgTs>
50 class MockAnalysisHandleBase {
51 public:
52 class Analysis : public AnalysisInfoMixin {
53 friend AnalysisInfoMixin;
54 friend MockAnalysisHandleBase;
55 static AnalysisKey Key;
56
57 DerivedT *Handle;
58
59 Analysis(DerivedT &Handle) : Handle(&Handle) {
60 static_assert(std::is_base_of::value,
61 "Must pass the derived type to this template!");
62 }
63
64 public:
65 class Result {
66 friend MockAnalysisHandleBase;
67
68 DerivedT *Handle;
69
70 Result(DerivedT &Handle) : Handle(&Handle) {}
71
72 public:
73 // Forward invalidation events to the mock handle.
74 bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
75 typename AnalysisManagerT::Invalidator &Inv) {
76 return Handle->invalidate(IR, PA, Inv);
77 }
78 };
79
80 Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
81 return Handle->run(IR, AM, ExtraArgs...);
82 }
83 };
84
85 Analysis getAnalysis() { return Analysis(static_cast(*this)); }
86 typename Analysis::Result getResult() {
87 return typename Analysis::Result(static_cast(*this));
88 }
89
90 protected:
91 // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
92 // the template, so we use a boring static function.
93 static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA,
94 typename AnalysisManagerT::Invalidator &Inv) {
95 auto PAC = PA.template getChecker();
96 return !PAC.preserved() &&
97 !PAC.template preservedSet>();
98 }
99
100 /// Derived classes should call this in their constructor to set up default
101 /// mock actions. (We can't do this in our constructor because this has to
102 /// run after the DerivedT is constructed.)
103 void setDefaults() {
104 ON_CALL(static_cast(*this),
105 run(_, _, testing::Matcher(_)...))
106 .WillByDefault(Return(this->getResult()));
107 ON_CALL(static_cast(*this), invalidate(_, _, _))
108 .WillByDefault(Invoke(&invalidateCallback));
109 }
110 };
111
112 /// \brief A CRTP base for pass mock handles
113 ///
114 /// This class reconciles mocking with the value semantics implementation of the
115 /// PassManager. Pass mock handles should derive from this class and
116 /// call \c setDefault() in their constroctur for wiring up the defaults defined
117 /// by this base with their mock run() and invalidate() implementations.
118 template
119 typename... ExtraArgTs>
120 AnalysisKey MockAnalysisHandleBase
121 ExtraArgTs...>::Analysis::Key;
122
123 template
124 typename AnalysisManagerT = AnalysisManager,
125 typename... ExtraArgTs>
126 class MockPassHandleBase {
127 public:
128 class Pass : public PassInfoMixin {
129 friend MockPassHandleBase;
130
131 DerivedT *Handle;
132
133 Pass(DerivedT &Handle) : Handle(&Handle) {
134 static_assert(std::is_base_of::value,
135 "Must pass the derived type to this template!");
136 }
137
138 public:
139 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
140 ExtraArgTs... ExtraArgs) {
141 return Handle->run(IR, AM, ExtraArgs...);
142 }
143 };
144
145 Pass getPass() { return Pass(static_cast(*this)); }
146
147 protected:
148 /// Derived classes should call this in their constructor to set up default
149 /// mock actions. (We can't do this in our constructor because this has to
150 /// run after the DerivedT is constructed.)
151 void setDefaults() {
152 ON_CALL(static_cast(*this),
153 run(_, _, testing::Matcher(_)...))
154 .WillByDefault(Return(PreservedAnalyses::all()));
155 }
156 };
157
158 /// Mock handles for passes for the IRUnits Module, CGSCC, Function, Loop.
159 /// These handles define the appropriate run() mock interface for the respective
160 /// IRUnit type.
161 template struct MockPassHandle;
162 template <>
163 struct MockPassHandle
164 : MockPassHandleBase, Loop, LoopAnalysisManager,
165 LoopStandardAnalysisResults &, LPMUpdater &> {
166 MOCK_METHOD4(run,
167 PreservedAnalyses(Loop &, LoopAnalysisManager &,
168 LoopStandardAnalysisResults &, LPMUpdater &));
169 MockPassHandle() { setDefaults(); }
170 };
171
172 template <>
173 struct MockPassHandle
174 : MockPassHandleBase, Function> {
175 MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &));
176
177 MockPassHandle() { setDefaults(); }
178 };
179
180 template <>
181 struct MockPassHandle
182 : MockPassHandleBase, LazyCallGraph::SCC,
183 CGSCCAnalysisManager, LazyCallGraph &,
184 CGSCCUpdateResult &> {
185 MOCK_METHOD4(run,
186 PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
187 LazyCallGraph &G, CGSCCUpdateResult &UR));
188
189 MockPassHandle() { setDefaults(); }
190 };
191
192 template <>
193 struct MockPassHandle
194 : MockPassHandleBase, Module> {
195 MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager &));
196
197 MockPassHandle() { setDefaults(); }
198 };
199
200 /// Mock handles for analyses for the IRUnits Module, CGSCC, Function, Loop.
201 /// These handles define the appropriate run() and invalidate() mock interfaces
202 /// for the respective IRUnit type.
203 template struct MockAnalysisHandle;
204 template <>
205 struct MockAnalysisHandle
206 : MockAnalysisHandleBase, Loop,
207 LoopAnalysisManager,
208 LoopStandardAnalysisResults &> {
209
210 MOCK_METHOD3_T(run, typename Analysis::Result(Loop &, LoopAnalysisManager &,
211 LoopStandardAnalysisResults &));
212
213 MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &,
214 LoopAnalysisManager::Invalidator &));
215
216 MockAnalysisHandle() { this->setDefaults(); }
217 };
218
219 template <>
220 struct MockAnalysisHandle
221 : MockAnalysisHandleBase, Function> {
222 MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager &));
223
224 MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &,
225 FunctionAnalysisManager::Invalidator &));
226
227 MockAnalysisHandle() { setDefaults(); }
228 };
229
230 template <>
231 struct MockAnalysisHandle
232 : MockAnalysisHandleBase,
233 LazyCallGraph::SCC, CGSCCAnalysisManager,
234 LazyCallGraph &> {
235 MOCK_METHOD3(run, Analysis::Result(LazyCallGraph::SCC &,
236 CGSCCAnalysisManager &, LazyCallGraph &));
237
238 MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const PreservedAnalyses &,
239 CGSCCAnalysisManager::Invalidator &));
240
241 MockAnalysisHandle() { setDefaults(); }
242 };
243
244 template <>
245 struct MockAnalysisHandle
246 : MockAnalysisHandleBase, Module> {
247 MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &));
248
249 MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &,
250 ModuleAnalysisManager::Invalidator &));
251
252 MockAnalysisHandle() { setDefaults(); }
253 };
254
255 static std::unique_ptr parseIR(LLVMContext &C, const char *IR) {
256 SMDiagnostic Err;
257 return parseAssemblyString(IR, Err, C);
258 }
259
260 template class PassBuilderCallbacksTest;
261
262 /// This test fixture is shared between all the actual tests below and
263 /// takes care of setting up appropriate defaults.
264 ///
265 /// The template specialization serves to extract the IRUnit and AM types from
266 /// the given PassManagerT.
267 template
268 typename... ExtraAnalysisArgTs>
269 class PassBuilderCallbacksTest
270 TestIRUnitT, AnalysisManager,
271 ExtraPassArgTs...>> : public testing::Test {
272 protected:
273 using IRUnitT = TestIRUnitT;
274 using AnalysisManagerT = AnalysisManager;
275 using PassManagerT =
276 PassManager;
277 using AnalysisT = typename MockAnalysisHandle::Analysis;
278
279 LLVMContext Context;
280 std::unique_ptr M;
281
282 PassBuilder PB;
283 ModulePassManager PM;
284 LoopAnalysisManager LAM;
285 FunctionAnalysisManager FAM;
286 CGSCCAnalysisManager CGAM;
287 ModuleAnalysisManager AM;
288
289 MockPassHandle PassHandle;
290 MockAnalysisHandle AnalysisHandle;
291
292 static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
293 ExtraAnalysisArgTs &&... Args) {
294 (void)AM.template getResult(
295 U, std::forward(Args)...);
296 return PreservedAnalyses::all();
297 }
298
299 PassBuilderCallbacksTest()
300 : M(parseIR(Context,
301 "declare void @bar()\n"
302 "define void @foo(i32 %n) {\n"
303 "entry:\n"
304 " br label %loop\n"
305 "loop:\n"
306 " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
307 " %iv.next = add i32 %iv, 1\n"
308 " tail call void @bar()\n"
309 " %cmp = icmp eq i32 %iv, %n\n"
310 " br i1 %cmp, label %exit, label %loop\n"
311 "exit:\n"
312 " ret void\n"
313 "}\n")),
314 PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
315
316 /// Register a callback for analysis registration.
317 ///
318 /// The callback is a function taking a reference to an AnalyisManager
319 /// object. When called, the callee gets to register its own analyses with
320 /// this PassBuilder instance.
321 PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
322 // Register our mock analysis
323 AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
324 });
325
326 /// Register a callback for pipeline parsing.
327 ///
328 /// During parsing of a textual pipeline, the PassBuilder will call these
329 /// callbacks for each encountered pass name that it does not know. This
330 /// includes both simple pass names as well as names of sub-pipelines. In
331 /// the latter case, the InnerPipeline is not empty.
332 PB.registerPipelineParsingCallback(
333 [this](StringRef Name, PassManagerT &PM,
334 ArrayRef InnerPipeline) {
335 /// Handle parsing of the names of analysis utilities such as
336 /// require and invalidate for our
337 /// analysis mock handle
338 if (parseAnalysisUtilityPasses("test-analysis", Name, PM))
339 return true;
340
341 /// Parse the name of our pass mock handle
342 if (Name == "test-transform") {
343 PM.addPass(PassHandle.getPass());
344 return true;
345 }
346 return false;
347 });
348
349 /// Register builtin analyses and cross-register the analysis proxies
350 PB.registerModuleAnalyses(AM);
351 PB.registerCGSCCAnalyses(CGAM);
352 PB.registerFunctionAnalyses(FAM);
353 PB.registerLoopAnalyses(LAM);
354 PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
355 }
356 };
357
358 /// Define a custom matcher for objects which support a 'getName' method.
359 ///
360 /// LLVM often has IR objects or analysis objects which expose a name
361 /// and in tests it is convenient to match these by name for readability.
362 /// Usually, this name is either a StringRef or a plain std::string. This
363 /// matcher supports any type exposing a getName() method of this form whose
364 /// return value is compatible with an std::ostream. For StringRef, this uses
365 /// the shift operator defined above.
366 ///
367 /// It should be used as:
368 ///
369 /// HasName("my_function")
370 ///
371 /// No namespace or other qualification is required.
372 MATCHER_P(HasName, Name, "") {
373 *result_listener << "has name '" << arg.getName() << "'";
374 return Name == arg.getName();
375 }
376
377 using ModuleCallbacksTest = PassBuilderCallbacksTest;
378 using CGSCCCallbacksTest = PassBuilderCallbacksTest;
379 using FunctionCallbacksTest = PassBuilderCallbacksTest;
380 using LoopCallbacksTest = PassBuilderCallbacksTest;
381
382 /// Test parsing of the name of our mock pass for all IRUnits.
383 ///
384 /// The pass should by default run our mock analysis and then preserve it.
385 TEST_F(ModuleCallbacksTest, Passes) {
386 EXPECT_CALL(AnalysisHandle, run(HasName(""), _));
387 EXPECT_CALL(PassHandle, run(HasName(""), _))
388 .WillOnce(Invoke(getAnalysisResult));
389
390 StringRef PipelineText = "test-transform";
391 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
392 << "Pipeline was: " << PipelineText;
393 PM.run(*M, AM);
394 }
395
396 TEST_F(FunctionCallbacksTest, Passes) {
397 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
398 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
399 .WillOnce(Invoke(getAnalysisResult));
400
401 StringRef PipelineText = "test-transform";
402 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
403 << "Pipeline was: " << PipelineText;
404 PM.run(*M, AM);
405 }
406
407 TEST_F(LoopCallbacksTest, Passes) {
408 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
409 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
410 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
411
412 StringRef PipelineText = "test-transform";
413 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
414 << "Pipeline was: " << PipelineText;
415 PM.run(*M, AM);
416 }
417
418 TEST_F(CGSCCCallbacksTest, Passes) {
419 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
420 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
421 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
422
423 StringRef PipelineText = "test-transform";
424 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
425 << "Pipeline was: " << PipelineText;
426 PM.run(*M, AM);
427 }
428
429 /// Test parsing of the names of analysis utilities for our mock analysis
430 /// for all IRUnits.
431 ///
432 /// We first require<>, then invalidate<> it, expecting the analysis to be run
433 /// once and subsequently invalidated.
434 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
435 EXPECT_CALL(AnalysisHandle, run(HasName(""), _));
436 EXPECT_CALL(AnalysisHandle, invalidate(HasName(""), _, _));
437
438 StringRef PipelineText = "require,invalidate";
439 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
440 << "Pipeline was: " << PipelineText;
441 PM.run(*M, AM);
442 }
443
444 TEST_F(CGSCCCallbacksTest, PassUtilities) {
445 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
446 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
447
448 StringRef PipelineText = "require,invalidate";
449 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
450 << "Pipeline was: " << PipelineText;
451 PM.run(*M, AM);
452 }
453
454 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
455 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
456 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
457
458 StringRef PipelineText = "require,invalidate";
459 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
460 << "Pipeline was: " << PipelineText;
461 PM.run(*M, AM);
462 }
463
464 TEST_F(LoopCallbacksTest, PassUtilities) {
465 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
466 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
467
468 StringRef PipelineText = "require,invalidate";
469
470 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
471 << "Pipeline was: " << PipelineText;
472 PM.run(*M, AM);
473 }
474
475 /// Test parsing of the top-level pipeline.
476 ///
477 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
478 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
479 /// (i.e., the first entry on the pipeline).
480 /// This test parses a pipeline named 'another-pipeline', whose only elements
481 /// may be the test-transform pass or the analysis utilities
482 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
483 PB.registerParseTopLevelPipelineCallback([this](
484 ModulePassManager &MPM, ArrayRef Pipeline,
485 bool VerifyEachPass, bool DebugLogging) {
486 auto &FirstName = Pipeline.front().Name;
487 auto &InnerPipeline = Pipeline.front().InnerPipeline;
488 if (FirstName == "another-pipeline") {
489 for (auto &E : InnerPipeline) {
490 if (parseAnalysisUtilityPasses("test-analysis", E.Name, PM))
491 continue;
492
493 if (E.Name == "test-transform") {
494 PM.addPass(PassHandle.getPass());
495 continue;
496 }
497 return false;
498 }
499 }
500 return true;
501 });
502
503 EXPECT_CALL(AnalysisHandle, run(HasName(""), _));
504 EXPECT_CALL(PassHandle, run(HasName(""), _))
505 .WillOnce(Invoke(getAnalysisResult));
506 EXPECT_CALL(AnalysisHandle, invalidate(HasName(""), _, _));
507
508 StringRef PipelineText =
509 "another-pipeline(test-transform,invalidate)";
510 ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
511 << "Pipeline was: " << PipelineText;
512 PM.run(*M, AM);
513
514 /// Test the negative case
515 PipelineText = "another-pipeline(instcombine)";
516 ASSERT_FALSE(PB.parsePassPipeline(PM, PipelineText, true))
517 << "Pipeline was: " << PipelineText;
518 }
519 } // end anonymous namespace