summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Passes/StandardInstrumentations.cpp
blob: 6abd39c61acbe6bc7391c9515ec46f6ad74983bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//===- 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) {
  if (any_isa<const CallGraphSCC *>(IR) ||
      any_isa<const LazyCallGraph::SCC *>(IR))
    return;

  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 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);
}
OpenPOWER on IntegriCloud