blob: 48d36e5a01e58ad9f9335dca6be6fb3bbe5875c8 [file] [log] [blame]
Fedor Sergeev662e5682018-09-24 16:08:15 +00001//===- Standard pass instrumentations handling ----------------*- C++ -*--===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10///
11/// This file defines IR-printing pass instrumentation callbacks as well as
12/// StandardInstrumentations class that manages standard pass instrumentations.
13///
14//===----------------------------------------------------------------------===//
15
16#include "llvm/Passes/StandardInstrumentations.h"
17#include "llvm/Analysis/CallGraphSCCPass.h"
18#include "llvm/Analysis/LazyCallGraph.h"
19#include "llvm/Analysis/LoopInfo.h"
20#include "llvm/IR/Function.h"
21#include "llvm/IR/IRPrintingPasses.h"
22#include "llvm/IR/Module.h"
23#include "llvm/IR/PassInstrumentation.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/FormatVariadic.h"
26#include "llvm/Support/raw_ostream.h"
27
28using namespace llvm;
29
30namespace {
31namespace PrintIR {
32
33//===----------------------------------------------------------------------===//
34// IR-printing instrumentation
35//===----------------------------------------------------------------------===//
36
37/// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
38/// llvm::Any and does actual print job.
39void unwrapAndPrint(StringRef Banner, Any IR) {
Fedor Sergeev662e5682018-09-24 16:08:15 +000040 SmallString<40> Extra{"\n"};
41 const Module *M = nullptr;
42 if (any_isa<const Module *>(IR)) {
43 M = any_cast<const Module *>(IR);
44 } else if (any_isa<const Function *>(IR)) {
45 const Function *F = any_cast<const Function *>(IR);
46 if (!llvm::isFunctionInPrintList(F->getName()))
47 return;
48 if (!llvm::forcePrintModuleIR()) {
49 dbgs() << Banner << Extra << static_cast<const Value &>(*F);
50 return;
51 }
52 M = F->getParent();
53 Extra = formatv(" (function: {0})\n", F->getName());
Fedor Sergeev0dc6ac92018-10-15 10:46:35 +000054 } else if (any_isa<const LazyCallGraph::SCC *>(IR)) {
55 const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
56 assert(C);
57 if (!llvm::forcePrintModuleIR()) {
58 Extra = formatv(" (scc: {0})\n", C->getName());
59 bool BannerPrinted = false;
60 for (const LazyCallGraph::Node &N : *C) {
61 const Function &F = N.getFunction();
62 if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
63 if (!BannerPrinted) {
64 dbgs() << Banner << Extra;
65 BannerPrinted = true;
66 }
67 F.print(dbgs());
68 }
69 }
70 return;
71 }
72 for (const LazyCallGraph::Node &N : *C) {
73 const Function &F = N.getFunction();
74 if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
75 M = F.getParent();
76 break;
77 }
78 }
79 if (!M)
80 return;
81 Extra = formatv(" (for scc: {0})\n", C->getName());
Fedor Sergeev662e5682018-09-24 16:08:15 +000082 } else if (any_isa<const Loop *>(IR)) {
83 const Loop *L = any_cast<const Loop *>(IR);
84 const Function *F = L->getHeader()->getParent();
85 if (!isFunctionInPrintList(F->getName()))
86 return;
87 if (!llvm::forcePrintModuleIR()) {
88 llvm::printLoop(const_cast<Loop &>(*L), dbgs(), Banner);
89 return;
90 }
91 M = F->getParent();
92 {
93 std::string LoopName;
94 raw_string_ostream ss(LoopName);
95 L->getHeader()->printAsOperand(ss, false);
96 Extra = formatv(" (loop: {0})\n", ss.str());
97 }
98 }
99 if (M) {
100 dbgs() << Banner << Extra;
101 M->print(dbgs(), nullptr, false);
102 } else {
103 llvm_unreachable("Unknown wrapped IR type");
104 }
105}
106
107bool printBeforePass(StringRef PassID, Any IR) {
108 if (!llvm::shouldPrintBeforePass(PassID))
109 return true;
110
111 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
112 return true;
113
114 SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
115 unwrapAndPrint(Banner, IR);
116 return true;
117}
118
119void printAfterPass(StringRef PassID, Any IR) {
120 if (!llvm::shouldPrintAfterPass(PassID))
121 return;
122
123 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
124 return;
125
126 SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
127 unwrapAndPrint(Banner, IR);
128 return;
129}
130} // namespace PrintIR
131} // namespace
132
133void StandardInstrumentations::registerCallbacks(
134 PassInstrumentationCallbacks &PIC) {
135 if (llvm::shouldPrintBeforePass())
136 PIC.registerBeforePassCallback(PrintIR::printBeforePass);
137 if (llvm::shouldPrintAfterPass())
138 PIC.registerAfterPassCallback(PrintIR::printAfterPass);
Fedor Sergeev884e52a2018-10-05 22:32:01 +0000139 TimePasses.registerCallbacks(PIC);
Fedor Sergeev662e5682018-09-24 16:08:15 +0000140}