| //===- Standard pass instrumentations handling ----------------*- C++ -*--===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// |
| /// This file defines IR-printing pass instrumentation callbacks as well as |
| /// StandardInstrumentations class that manages standard pass instrumentations. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Passes/StandardInstrumentations.h" |
| #include "llvm/Analysis/CallGraphSCCPass.h" |
| #include "llvm/Analysis/LazyCallGraph.h" |
| #include "llvm/Analysis/LoopInfo.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/IRPrintingPasses.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/IR/PassInstrumentation.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/FormatVariadic.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| using namespace llvm; |
| |
| namespace { |
| namespace PrintIR { |
| |
| //===----------------------------------------------------------------------===// |
| // IR-printing instrumentation |
| //===----------------------------------------------------------------------===// |
| |
| /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into |
| /// llvm::Any and does actual print job. |
| void unwrapAndPrint(StringRef Banner, Any IR) { |
| SmallString<40> Extra{"\n"}; |
| const Module *M = nullptr; |
| if (any_isa<const Module *>(IR)) { |
| M = any_cast<const Module *>(IR); |
| } else if (any_isa<const Function *>(IR)) { |
| const Function *F = any_cast<const Function *>(IR); |
| if (!llvm::isFunctionInPrintList(F->getName())) |
| return; |
| if (!llvm::forcePrintModuleIR()) { |
| dbgs() << Banner << Extra << static_cast<const Value &>(*F); |
| return; |
| } |
| M = F->getParent(); |
| Extra = formatv(" (function: {0})\n", F->getName()); |
| } else if (any_isa<const LazyCallGraph::SCC *>(IR)) { |
| const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR); |
| assert(C); |
| if (!llvm::forcePrintModuleIR()) { |
| Extra = formatv(" (scc: {0})\n", C->getName()); |
| bool BannerPrinted = false; |
| for (const LazyCallGraph::Node &N : *C) { |
| const Function &F = N.getFunction(); |
| if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) { |
| if (!BannerPrinted) { |
| dbgs() << Banner << Extra; |
| BannerPrinted = true; |
| } |
| F.print(dbgs()); |
| } |
| } |
| return; |
| } |
| for (const LazyCallGraph::Node &N : *C) { |
| const Function &F = N.getFunction(); |
| if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) { |
| M = F.getParent(); |
| break; |
| } |
| } |
| if (!M) |
| return; |
| Extra = formatv(" (for scc: {0})\n", C->getName()); |
| } else if (any_isa<const Loop *>(IR)) { |
| const Loop *L = any_cast<const Loop *>(IR); |
| const Function *F = L->getHeader()->getParent(); |
| if (!isFunctionInPrintList(F->getName())) |
| return; |
| if (!llvm::forcePrintModuleIR()) { |
| llvm::printLoop(const_cast<Loop &>(*L), dbgs(), Banner); |
| return; |
| } |
| M = F->getParent(); |
| { |
| std::string LoopName; |
| raw_string_ostream ss(LoopName); |
| L->getHeader()->printAsOperand(ss, false); |
| Extra = formatv(" (loop: {0})\n", ss.str()); |
| } |
| } |
| if (M) { |
| dbgs() << Banner << Extra; |
| M->print(dbgs(), nullptr, false); |
| } else { |
| llvm_unreachable("Unknown wrapped IR type"); |
| } |
| } |
| |
| bool printBeforePass(StringRef PassID, Any IR) { |
| if (!llvm::shouldPrintBeforePass(PassID)) |
| return true; |
| |
| if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) |
| return true; |
| |
| SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID); |
| unwrapAndPrint(Banner, IR); |
| return true; |
| } |
| |
| void printAfterPass(StringRef PassID, Any IR) { |
| if (!llvm::shouldPrintAfterPass(PassID)) |
| return; |
| |
| if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) |
| return; |
| |
| SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); |
| unwrapAndPrint(Banner, IR); |
| return; |
| } |
| } // namespace PrintIR |
| } // namespace |
| |
| void StandardInstrumentations::registerCallbacks( |
| PassInstrumentationCallbacks &PIC) { |
| if (llvm::shouldPrintBeforePass()) |
| PIC.registerBeforePassCallback(PrintIR::printBeforePass); |
| if (llvm::shouldPrintAfterPass()) |
| PIC.registerAfterPassCallback(PrintIR::printAfterPass); |
| TimePasses.registerCallbacks(PIC); |
| } |