Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Passes/StandardInstrumentations.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- Standard pass instrumentations handling ----------------*- C++ -*--===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// \file
9
///
10
/// This file defines IR-printing pass instrumentation callbacks as well as
11
/// StandardInstrumentations class that manages standard pass instrumentations.
12
///
13
//===----------------------------------------------------------------------===//
14
15
#include "llvm/Passes/StandardInstrumentations.h"
16
#include "llvm/ADT/Optional.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
28
using namespace llvm;
29
30
namespace {
31
32
/// Extracting Module out of \p IR unit. Also fills a textual description
33
/// of \p IR for use in header when printing.
34
64
Optional<std::pair<const Module *, std::string>> unwrapModule(Any IR) {
35
64
  if (any_isa<const Module *>(IR))
36
26
    return std::make_pair(any_cast<const Module *>(IR), std::string());
37
38
38
38
  if (any_isa<const Function *>(IR)) {
39
24
    const Function *F = any_cast<const Function *>(IR);
40
24
    if (!llvm::isFunctionInPrintList(F->getName()))
41
8
      return None;
42
16
    const Module *M = F->getParent();
43
16
    return std::make_pair(M, formatv(" (function: {0})", F->getName()).str());
44
16
  }
45
14
46
14
  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
47
9
    const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
48
9
    for (const LazyCallGraph::Node &N : *C) {
49
9
      const Function &F = N.getFunction();
50
9
      if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
51
9
        const Module *M = F.getParent();
52
9
        return std::make_pair(M, formatv(" (scc: {0})", C->getName()).str());
53
9
      }
54
9
    }
55
9
    
return None0
;
56
5
  }
57
5
58
5
  if (any_isa<const Loop *>(IR)) {
59
5
    const Loop *L = any_cast<const Loop *>(IR);
60
5
    const Function *F = L->getHeader()->getParent();
61
5
    if (!isFunctionInPrintList(F->getName()))
62
2
      return None;
63
3
    const Module *M = F->getParent();
64
3
    std::string LoopName;
65
3
    raw_string_ostream ss(LoopName);
66
3
    L->getHeader()->printAsOperand(ss, false);
67
3
    return std::make_pair(M, formatv(" (loop: {0})", ss.str()).str());
68
3
  }
69
0
70
0
  llvm_unreachable("Unknown IR unit");
71
0
}
72
73
46
void printIR(const Module *M, StringRef Banner, StringRef Extra = StringRef()) {
74
46
  dbgs() << Banner << Extra << "\n";
75
46
  M->print(dbgs(), nullptr, false);
76
46
}
77
void printIR(const Function *F, StringRef Banner,
78
18
             StringRef Extra = StringRef()) {
79
18
  if (!llvm::isFunctionInPrintList(F->getName()))
80
3
    return;
81
15
  dbgs() << Banner << Extra << "\n" << static_cast<const Value &>(*F);
82
15
}
83
void printIR(const LazyCallGraph::SCC *C, StringRef Banner,
84
5
             StringRef Extra = StringRef()) {
85
5
  bool BannerPrinted = false;
86
7
  for (const LazyCallGraph::Node &N : *C) {
87
7
    const Function &F = N.getFunction();
88
7
    if (!F.isDeclaration() && llvm::isFunctionInPrintList(F.getName())) {
89
7
      if (!BannerPrinted) {
90
5
        dbgs() << Banner << Extra << "\n";
91
5
        BannerPrinted = true;
92
5
      }
93
7
      F.print(dbgs());
94
7
    }
95
7
  }
96
5
}
97
5
void printIR(const Loop *L, StringRef Banner) {
98
5
  const Function *F = L->getHeader()->getParent();
99
5
  if (!llvm::isFunctionInPrintList(F->getName()))
100
1
    return;
101
4
  llvm::printLoop(const_cast<Loop &>(*L), dbgs(), Banner);
102
4
}
103
104
/// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
105
/// llvm::Any and does actual print job.
106
77
void unwrapAndPrint(Any IR, StringRef Banner, bool ForceModule = false) {
107
77
  if (ForceModule) {
108
33
    if (auto UnwrappedModule = unwrapModule(IR))
109
28
      printIR(UnwrappedModule->first, Banner, UnwrappedModule->second);
110
33
    return;
111
33
  }
112
44
113
44
  if (any_isa<const Module *>(IR)) {
114
16
    const Module *M = any_cast<const Module *>(IR);
115
16
    assert(M && "module should be valid for printing");
116
16
    printIR(M, Banner);
117
16
    return;
118
16
  }
119
28
120
28
  if (any_isa<const Function *>(IR)) {
121
18
    const Function *F = any_cast<const Function *>(IR);
122
18
    assert(F && "function should be valid for printing");
123
18
    printIR(F, Banner);
124
18
    return;
125
18
  }
126
10
127
10
  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
128
5
    const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
129
5
    assert(C && "scc should be valid for printing");
130
5
    std::string Extra = formatv(" (scc: {0})", C->getName());
131
5
    printIR(C, Banner, Extra);
132
5
    return;
133
5
  }
134
5
135
5
  if (any_isa<const Loop *>(IR)) {
136
5
    const Loop *L = any_cast<const Loop *>(IR);
137
5
    assert(L && "Loop should be valid for printing");
138
5
    printIR(L, Banner);
139
5
    return;
140
5
  }
141
0
  llvm_unreachable("Unknown wrapped IR type");
142
0
}
143
144
} // namespace
145
146
1.24k
PrintIRInstrumentation::~PrintIRInstrumentation() {
147
1.24k
  assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
148
1.24k
}
149
150
31
void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
151
31
  assert(StoreModuleDesc);
152
31
  const Module *M = nullptr;
153
31
  std::string Extra;
154
31
  if (auto UnwrappedModule = unwrapModule(IR))
155
26
    std::tie(M, Extra) = UnwrappedModule.getValue();
156
31
  ModuleDescStack.emplace_back(M, Extra, PassID);
157
31
}
158
159
PrintIRInstrumentation::PrintModuleDesc
160
31
PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
161
31
  assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
162
31
  PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
163
31
  assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
164
31
  return ModuleDesc;
165
31
}
166
167
81
bool PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
168
81
  if (PassID.startswith("PassManager<") || 
PassID.contains("PassAdaptor<")56
)
169
38
    return true;
170
43
171
43
  // Saving Module for AfterPassInvalidated operations.
172
43
  // Note: here we rely on a fact that we do not change modules while
173
43
  // traversing the pipeline, so the latest captured module is good
174
43
  // for all print operations that has not happen yet.
175
43
  if (StoreModuleDesc && 
llvm::shouldPrintAfterPass(PassID)31
)
176
31
    pushModuleDesc(PassID, IR);
177
43
178
43
  if (!llvm::shouldPrintBeforePass(PassID))
179
27
    return true;
180
16
181
16
  SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
182
16
  unwrapAndPrint(IR, Banner, llvm::forcePrintModuleIR());
183
16
  return true;
184
16
}
185
186
111
void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
187
111
  if (PassID.startswith("PassManager<") || 
PassID.contains("PassAdaptor<")80
)
188
50
    return;
189
61
190
61
  if (!llvm::shouldPrintAfterPass(PassID))
191
0
    return;
192
61
193
61
  if (StoreModuleDesc)
194
29
    popModuleDesc(PassID);
195
61
196
61
  SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
197
61
  unwrapAndPrint(IR, Banner, llvm::forcePrintModuleIR());
198
61
}
199
200
8
void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
201
8
  if (!StoreModuleDesc || 
!llvm::shouldPrintAfterPass(PassID)4
)
202
4
    return;
203
4
204
4
  if (PassID.startswith("PassManager<") || 
PassID.contains("PassAdaptor<")2
)
205
2
    return;
206
2
207
2
  const Module *M;
208
2
  std::string Extra;
209
2
  StringRef StoredPassID;
210
2
  std::tie(M, Extra, StoredPassID) = popModuleDesc(PassID);
211
2
  // Additional filtering (e.g. -filter-print-func) can lead to module
212
2
  // printing being skipped.
213
2
  if (!M)
214
0
    return;
215
2
216
2
  SmallString<20> Banner =
217
2
      formatv("*** IR Dump After {0} *** invalidated: ", PassID);
218
2
  printIR(M, Banner, Extra);
219
2
}
220
221
void PrintIRInstrumentation::registerCallbacks(
222
1.25k
    PassInstrumentationCallbacks &PIC) {
223
1.25k
  // BeforePass callback is not just for printing, it also saves a Module
224
1.25k
  // for later use in AfterPassInvalidated.
225
1.25k
  StoreModuleDesc = llvm::forcePrintModuleIR() && 
llvm::shouldPrintAfterPass()6
;
226
1.25k
  if (llvm::shouldPrintBeforePass() || 
StoreModuleDesc1.24k
)
227
8
    PIC.registerBeforePassCallback(
228
81
        [this](StringRef P, Any IR) { return this->printBeforePass(P, IR); });
229
1.25k
230
1.25k
  if (llvm::shouldPrintAfterPass()) {
231
12
    PIC.registerAfterPassCallback(
232
111
        [this](StringRef P, Any IR) { this->printAfterPass(P, IR); });
233
12
    PIC.registerAfterPassInvalidatedCallback(
234
12
        [this](StringRef P) 
{ this->printAfterPassInvalidated(P); }8
);
235
12
  }
236
1.25k
}
237
238
void StandardInstrumentations::registerCallbacks(
239
1.25k
    PassInstrumentationCallbacks &PIC) {
240
1.25k
  PrintIR.registerCallbacks(PIC);
241
1.25k
  TimePasses.registerCallbacks(PIC);
242
1.25k
}