31 #include <unordered_set> 48 cl::desc(
"Print all pass management debugging information. " 49 "`-debug-pass-manager` must also be specified"));
83 cl::desc(
"Only consider IR changes for passes whose names " 84 "match for the print-changed option"),
91 cl::desc(
"Print before passes that change them"),
99 unwrapModule(
Any IR,
bool Force =
false) {
100 if (any_isa<const Module *>(
IR))
101 return std::make_pair(any_cast<const Module *>(
IR), std::string());
103 if (any_isa<const Function *>(
IR)) {
104 const Function *
F = any_cast<const Function *>(
IR);
109 return std::make_pair(M,
formatv(
" (function: {0})",
F->getName()).str());
112 if (any_isa<const LazyCallGraph::SCC *>(
IR)) {
121 assert(!Force &&
"Expected to have made a pair when forced.");
125 if (any_isa<const Loop *>(
IR)) {
126 const Loop *L = any_cast<const Loop *>(
IR);
131 std::string LoopName;
134 return std::make_pair(M,
formatv(
" (loop: {0})", ss.str()).str());
143 OS <<
F->getName() <<
'\n';
149 OS << Banner << Extra <<
"\n" << static_cast<const Value &>(*
F);
154 bool ShouldPreserveUseListOrder =
false) {
156 OS <<
M->getName() <<
'\n';
161 OS << Banner << Extra <<
"\n";
162 M->print(OS,
nullptr, ShouldPreserveUseListOrder);
164 for (
const auto &
F :
M->functions()) {
165 printIR(OS, &
F, Banner, Extra);
177 bool BannerPrinted =
false;
181 if (!BannerPrinted) {
182 OS << Banner << Extra <<
"\n";
183 BannerPrinted =
true;
191 bool Brief =
false) {
200 printLoop(const_cast<Loop &>(*L), OS, std::string(Banner));
206 bool ForceModule =
false,
bool Brief =
false,
207 bool ShouldPreserveUseListOrder =
false) {
209 if (
auto UnwrappedModule = unwrapModule(
IR))
210 printIR(OS, UnwrappedModule->first, Banner, UnwrappedModule->second,
211 Brief, ShouldPreserveUseListOrder);
215 if (any_isa<const Module *>(
IR)) {
216 const Module *
M = any_cast<const Module *>(
IR);
217 assert(M &&
"module should be valid for printing");
218 printIR(OS, M, Banner,
"", Brief, ShouldPreserveUseListOrder);
222 if (any_isa<const Function *>(
IR)) {
223 const Function *
F = any_cast<const Function *>(
IR);
224 assert(
F &&
"function should be valid for printing");
225 printIR(OS,
F, Banner,
"", Brief);
229 if (any_isa<const LazyCallGraph::SCC *>(
IR)) {
231 assert(
C &&
"scc should be valid for printing");
233 printIR(OS,
C, Banner, Extra, Brief);
237 if (any_isa<const Loop *>(
IR)) {
238 const Loop *L = any_cast<const Loop *>(
IR);
239 assert(L &&
"Loop should be valid for printing");
240 printIR(OS, L, Banner, Brief);
249 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy"});
254 template <
typename IRUnitT>
256 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
259 template <
typename IRUnitT>
264 template <
typename IRUnitT>
266 if (isIgnored(PassID))
269 static std::unordered_set<std::string> PrintPassNames(
PrintPassesList.begin(),
271 return PrintPassNames.empty() || PrintPassNames.count(PassID.
str());
276 template <
typename IRUnitT>
278 if (!isInterestingPass(PassID))
280 if (any_isa<const Function *>(
IR))
281 return isInterestingFunction(*any_cast<const Function *>(
IR));
285 template <
typename IRUnitT>
290 BeforeStack.emplace_back();
302 IRUnitT &
Data = BeforeStack.back();
303 generateIRRepresentation(
IR, PassID,
Data);
306 template <
typename IRUnitT>
308 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
312 if (any_isa<const Function *>(
IR)) {
313 const Function *
F = any_cast<const Function *>(
IR);
316 if (
auto UM = unwrapModule(
IR))
322 if (isIgnored(PassID)) {
324 handleIgnored(PassID,
Name);
327 handleFiltered(PassID,
Name);
330 IRUnitT &Before = BeforeStack.back();
333 generateIRRepresentation(
IR, PassID, After);
336 if (same(Before, After)) {
338 omitAfter(PassID,
Name);
340 handleAfter(PassID,
Name, Before, After,
IR);
342 BeforeStack.pop_back();
345 template <
typename IRUnitT>
347 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
354 handleInvalidated(PassID);
355 BeforeStack.pop_back();
358 template <
typename IRUnitT>
366 handleIRAfterPass(
IR,
P);
370 handleInvalidatedPass(
P);
374 template <
typename IRUnitT>
378 template <
typename IRUnitT>
382 auto UnwrappedModule = unwrapModule(
IR,
true);
383 assert(UnwrappedModule &&
"Expected module to be unwrapped when forced.");
384 Out <<
"*** IR Dump At Start: ***" << UnwrappedModule->second <<
"\n";
385 UnwrappedModule->first->print(Out,
nullptr,
389 template <
typename IRUnitT>
392 Out <<
formatv(
"*** IR Dump After {0}{1} omitted because no change ***\n",
396 template <
typename IRUnitT>
398 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
401 template <
typename IRUnitT>
405 formatv(
"*** IR Dump After {0}{1} filtered out ***\n", PassID,
Name);
409 template <
typename IRUnitT>
412 Out <<
formatv(
"*** IR Pass {0}{1} ignored ***\n", PassID,
Name);
415 IRChangedPrinter::~IRChangedPrinter() {}
423 std::string &Output) {
434 const std::string &Before,
435 const std::string &After,
Any) {
436 assert(After.find(
"*** IR Dump") == 0 &&
"Unexpected banner format.");
439 AfterRef.
take_until([](
char C) ->
bool {
return C ==
'\n'; });
443 Out <<
"*** IR Dump Before" << Banner.
substr(17);
460 Out << After.substr(Banner.size());
468 assert(ModuleDescStack.
empty() &&
"ModuleDescStack is not empty at exit");
471 void PrintIRInstrumentation::pushModuleDesc(
StringRef PassID,
Any IR) {
473 const Module *M =
nullptr;
475 if (
auto UnwrappedModule = unwrapModule(
IR))
476 std::tie(M, Extra) = UnwrappedModule.getValue();
480 PrintIRInstrumentation::PrintModuleDesc
481 PrintIRInstrumentation::popModuleDesc(
StringRef PassID) {
482 assert(!ModuleDescStack.
empty() &&
"empty ModuleDescStack");
483 PrintModuleDesc ModuleDesc = ModuleDescStack.
pop_back_val();
484 assert(std::get<2>(ModuleDesc).equals(PassID) &&
"malformed ModuleDescStack");
488 void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
489 if (isIgnored(PassID))
496 if (StoreModuleDesc && shouldPrintAfterPass(PassID))
497 pushModuleDesc(PassID,
IR);
499 if (!shouldPrintBeforePass(PassID))
506 void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
507 if (isIgnored(PassID))
510 if (!shouldPrintAfterPass(PassID))
514 popModuleDesc(PassID);
520 void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
522 if (!StoreModuleDesc || !shouldPrintAfterPass(
PassName))
525 if (isIgnored(PassID))
531 std::tie(M, Extra, StoredPassID) = popModuleDesc(PassID);
538 formatv(
"*** IR Dump After {0} *** invalidated: ", PassID);
539 printIR(
dbgs(), M, Banner, Extra);
542 bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
554 bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
580 this->printAfterPass(
P,
IR);
584 this->printAfterPassInvalidated(
P);
595 bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
Any IR) {
597 if (any_isa<const Function *>(
IR)) {
598 F = any_cast<const Function *>(
IR);
599 }
else if (any_isa<const Loop *>(
IR)) {
600 F = any_cast<const Loop *>(
IR)->getHeader()->getParent();
602 bool ShouldRun = !(
F &&
F->hasOptNone());
603 if (!ShouldRun && DebugLogging) {
604 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
605 <<
" due to optnone attribute\n";
611 if (any_isa<const Module *>(
IR)) {
612 const Module *M = any_cast<const Module *>(
IR);
613 assert(M &&
"module should be valid for printing");
614 return "module (" + M->getName().str() +
")";
617 if (any_isa<const Function *>(
IR)) {
618 const Function *
F = any_cast<const Function *>(
IR);
619 assert(
F &&
"function should be valid for printing");
620 return "function (" +
F->getName().str() +
")";
623 if (any_isa<const LazyCallGraph::SCC *>(
IR)) {
625 assert(
C &&
"scc should be valid for printing");
629 if (any_isa<const Loop *>(
IR)) {
641 return isIgnored(PassID) ||
651 std::vector<StringRef> SpecialPasses = {
"PassManager"};
653 SpecialPasses.emplace_back(
"PassAdaptor");
658 "Unexpectedly skipping special pass");
660 dbgs() <<
"Skipping pass: " << PassID <<
" on ";
661 unwrapAndPrint(
dbgs(),
IR,
"",
false,
true);
669 dbgs() <<
"Running pass: " << PassID <<
" on ";
670 unwrapAndPrint(
dbgs(),
IR,
"",
false,
true);
674 dbgs() <<
"Running analysis: " << PassID <<
" on ";
675 unwrapAndPrint(
dbgs(),
IR,
"",
false,
true);
680 bool TrackBBLifetime) {
683 for (
const auto &BB : *
F) {
689 BBGuards->try_emplace(
intptr_t(Succ), Succ);
696 out << BB->
getName() <<
"<" << BB <<
">";
701 out <<
"unnamed_removed<" << BB <<
">";
711 unsigned FuncOrderBlockNum = 0;
717 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
720 void PreservedCFGCheckerInstrumentation::CFG::printDiff(
raw_ostream &out,
723 assert(!After.isPoisoned());
726 const CFG *FuncGraph =
nullptr;
727 if (!After.Graph.empty())
729 else if (!Before.isPoisoned() && !Before.Graph.empty())
733 out <<
"In function @" 734 << FuncGraph->Graph.begin()->first->getParent()->getName() <<
"\n";
736 if (Before.isPoisoned()) {
737 out <<
"Some blocks were deleted\n";
742 if (Before.Graph.size() != After.Graph.size())
743 out <<
"Different number of non-leaf basic blocks: before=" 744 << Before.Graph.size() <<
", after=" << After.Graph.size() <<
"\n";
746 for (
auto &BB : Before.Graph) {
747 auto BA = After.Graph.find(BB.first);
748 if (BA == After.Graph.end()) {
749 out <<
"Non-leaf block ";
751 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
755 for (
auto &BA : After.Graph) {
756 auto BB = Before.Graph.find(BA.first);
757 if (BB == Before.Graph.end()) {
758 out <<
"Non-leaf block ";
760 out <<
" is added (" << BA.second.size() <<
" successors)\n";
764 if (BB->second == BA.second)
767 out <<
"Different successors of block ";
769 out <<
" (unordered):\n";
770 out <<
"- before (" << BB->second.size() <<
"): ";
771 for (
auto &SuccB : BB->second) {
773 if (SuccB.second != 1)
774 out <<
"(" << SuccB.second <<
"), ";
779 out <<
"- after (" << BA.second.size() <<
"): ";
780 for (
auto &SuccA : BA.second) {
782 if (SuccA.second != 1)
783 out <<
"(" << SuccA.second <<
"), ";
797 if (any_isa<const Function *>(
IR))
798 GraphStackBefore.emplace_back(
P,
CFG(any_cast<const Function *>(
IR)));
800 GraphStackBefore.emplace_back(
P,
None);
805 auto Before = GraphStackBefore.pop_back_val();
807 "Before and After callbacks must correspond");
813 auto Before = GraphStackBefore.pop_back_val();
814 assert(Before.first ==
P &&
"Before and After callbacks must correspond");
815 auto &GraphBefore = Before.second;
820 if (any_isa<const Function *>(
IR)) {
821 assert(GraphBefore &&
"Must be built in BeforePassCallback");
822 CFG GraphAfter(any_cast<const Function *>(
IR),
false );
823 if (GraphAfter == *GraphBefore)
826 dbgs() <<
"Error: " <<
P 827 <<
" reported it preserved CFG, but changes detected:\n";
828 CFG::printDiff(
dbgs(), *GraphBefore, GraphAfter);
838 if (isIgnored(
P) ||
P ==
"VerifierPass")
840 if (any_isa<const Function *>(
IR) || any_isa<const Loop *>(
IR)) {
842 if (any_isa<const Loop *>(
IR))
843 F = any_cast<const Loop *>(
IR)->getHeader()->
getParent();
845 F = any_cast<const Function *>(
IR);
847 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
851 }
else if (any_isa<const Module *>(
IR) ||
852 any_isa<const LazyCallGraph::SCC *>(
IR)) {
854 if (any_isa<const LazyCallGraph::SCC *>(
IR))
855 M = any_cast<const LazyCallGraph::SCC *>(
IR)
860 M = any_cast<const Module *>(
IR);
862 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
872 : PrintPass(DebugLogging), OptNone(DebugLogging),
874 VerifyEach(VerifyEach) {}
bool shouldPrintBeforeAll()
reference emplace_back(ArgTypes &&... Args)
bool forcePrintModuleIR()
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
static void printBBName(raw_ostream &out, const BasicBlock *BB)
LLVM_NODISCARD StringRef take_until(function_ref< bool(char)> F) const
Return the longest prefix of 'this' such that no character in the prefix satisfies the given predicat...
A Module instance is used to store all the information related to an LLVM module.
LLVM_NODISCARD bool empty() const
static std::string getBisectDescription(Any IR)
Implements a lazy call graph analysis and related passes for the new pass manager.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
bool isInterestingFunction(const Function &F)
void registerBeforeNonSkippedPassCallback(CallableT C)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void handleIRAfterPass(Any IR, StringRef PassID)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void saveIRBeforePass(Any IR, StringRef PassID)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
std::vector< std::string > printBeforePasses()
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
BlockT * getHeader() const
ppc ctr loops PowerPC CTR Loops Verify
LLVM_NODISCARD size_t size() const
size - Get the string size.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
bool isInteresting(Any IR, StringRef PassID)
~PrintIRInstrumentation()
const BasicBlock & getEntryBlock() const
This class implements a mechanism to disable passes and individual optimizations at compile time base...
initializer< Ty > init(const Ty &Val)
A set of analyses that are preserved following a run of a transformation pass.
LLVM Basic Block Representation.
static cl::opt< bool > PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), cl::init(false), cl::Hidden)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
void registerShouldRunOptionalPassCallback(CallableT C)
void registerBeforeAnalysisCallback(CallableT C)
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
StandardInstrumentations(bool DebugLogging, bool VerifyEach=false)
static cl::opt< bool > VerifyPreservedCFG
void handleInvalidatedPass(StringRef PassID)
A node in the call graph.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
TextChangeReporter(bool Verbose)
ManagedStatic< OptBisect > OptBisector
Singleton instance of the OptBisect class, so multiple pass managers don't need to coordinate their u...
void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&... Args)
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, ScalarEvolution *SE, LoopInfo *LI)
isInteresting - Test whether the given expression is "interesting" when used by the given expression,...
bool shouldPrintAfterSomePass()
static const char PassName[]
Module.h This file contains the declarations for the Module class.
LLVM_NODISCARD T pop_back_val()
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
bool isFunctionInPrintList(StringRef FunctionName)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Represents analyses that only rely on functions' control flow.
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
bool same(const std::string &Before, const std::string &After) override
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
bool shouldPrintAfterAll()
std::vector< std::string > printAfterPasses()
This header defines a class that provides bookkeeping for all standard (i.e in-tree) pass instrumenta...
void registerAfterPassInvalidatedCallback(CallableT C)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Represents a single loop in the control flow graph.
StringRef getName() const
Return a constant reference to the value's name.
const Function * getParent() const
Return the enclosing method, or null if none.
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override
static cl::opt< bool > DebugPMVerbose("debug-pass-manager-verbose", cl::Hidden, cl::init(false), cl::desc("Print all pass management debugging information. " "`-debug-pass-manager` must also be specified"))
bool isInterestingPass(StringRef PassID)
static cl::list< std::string > PrintPassesList("filter-passes", cl::value_desc("pass names"), cl::desc("Only consider IR changes for passes whose names " "match for the print-changed option"), cl::CommaSeparated, cl::Hidden)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
An SCC of the call graph.
succ_range successors(Instruction *I)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
static const Function * getParent(const Value *V)
void registerAfterPassCallback(CallableT C)
This class implements an extremely fast bulk output stream that can only output to a stream.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name.
StringRef - Represent a constant reference to a string, i.e.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
Statically lint checks LLVM IR
void registerBeforeSkippedPassCallback(CallableT C)
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
static cl::opt< ChangePrinter > PrintChanged("print-changed", cl::desc("Print changed IRs"), cl::Hidden, cl::ValueOptional, cl::init(NoChangePrinter), cl::values(clEnumValN(PrintChangedQuiet, "quiet", "Run in quiet mode"), clEnumValN(PrintChangedVerbose, "", "")))