summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/OptBisect.cpp
blob: d06f40fce350c5c40e397de308bb92c58902b4ee (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//===------- llvm/IR/OptBisect/Bisect.cpp - LLVM Bisect support --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements support for a bisecting optimizations based on a
/// command line option.
///
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
                                   cl::init(INT_MAX), cl::Optional,
                                   cl::desc("Maximum optimization to perform"));

OptBisect::OptBisect() {
  BisectEnabled = OptBisectLimit != INT_MAX;
}

static void printPassMessage(const StringRef &Name, int PassNum,
                             StringRef TargetDesc, bool Running) {
  StringRef Status = Running ? "" : "NOT ";
  errs() << "BISECT: " << Status << "running pass "
         << "(" << PassNum << ") " << Name << " on " << TargetDesc << "\n";
}

static void printCaseMessage(int CaseNum, StringRef Msg, bool Running) {
  if (Running)
    errs() << "BISECT: running case (";
  else
    errs() << "BISECT: NOT running case (";
  errs() << CaseNum << "): " << Msg << "\n";
}

static std::string getDescription(const Module &M) {
  return "module (" + M.getName().str() + ")";
}

static std::string getDescription(const Function &F) {
  return "function (" + F.getName().str() + ")";
}

static std::string getDescription(const BasicBlock &BB) {
  return "basic block (" + BB.getName().str() + ") in function (" +
         BB.getParent()->getName().str() + ")";
}

static std::string getDescription(const Loop &L) {
  // FIXME: I'd like to be able to provide a better description here, but
  //        calling L->getHeader() would introduce a new dependency on the
  //        LLVMCore library.
  return "loop";
}

static std::string getDescription(const CallGraphSCC &SCC) {
  std::string Desc = "SCC (";
  bool First = true;
  for (CallGraphNode *CGN : SCC) {
    if (First)
      First = false;
    else
      Desc += ", ";
    Function *F = CGN->getFunction();
    if (F)
      Desc += F->getName();
    else
      Desc += "<<null function>>";
  }
  Desc += ")";
  return Desc;
}

static std::string getDescription(const LazyCallGraph::SCC &SCC) {
  std::string Desc = "SCC (";
  bool First = true;
  for (LazyCallGraph::Node &CGN : SCC) {
    if (First)
      First = false;
    else
      Desc += ", ";
    Function &F = CGN.getFunction();
    Desc += F.getName();
  }
  Desc += ")";
  return Desc;
}

// Force instantiations.
template bool OptBisect::shouldRunPass(const Pass *, const Module &);
template bool OptBisect::shouldRunPass(const Pass *, const Function &);
template bool OptBisect::shouldRunPass(const Pass *, const BasicBlock &);
template bool OptBisect::shouldRunPass(const Pass *, const Loop &);
template bool OptBisect::shouldRunPass(const Pass *, const CallGraphSCC &);
template bool OptBisect::shouldRunPass(const StringRef PassName,
                                       const Module &);
template bool OptBisect::shouldRunPass(const StringRef PassName,
                                       const Function &);
template bool OptBisect::shouldRunPass(const StringRef PassName,
                                       const BasicBlock &);
template bool OptBisect::shouldRunPass(const StringRef PassName, const Loop &);
template bool OptBisect::shouldRunPass(const StringRef PassName,
                                       const LazyCallGraph::SCC &);

template <class UnitT>
bool OptBisect::shouldRunPass(const Pass *P, const UnitT &U) {
  if (!BisectEnabled)
    return true;
  return checkPass(P->getPassName(), getDescription(U));
}

// Interface function for the new pass manager.
template <class UnitT>
bool OptBisect::shouldRunPass(const StringRef PassName, const UnitT &U) {
  if (!BisectEnabled)
    return true;
  return checkPass(PassName, getDescription(U));
}

bool OptBisect::checkPass(const StringRef PassName,
                          const StringRef TargetDesc) {
  assert(BisectEnabled);

  int CurBisectNum = ++LastBisectNum;
  bool ShouldRun = (OptBisectLimit == -1 || CurBisectNum <= OptBisectLimit);
  printPassMessage(PassName, CurBisectNum, TargetDesc, ShouldRun);
  return ShouldRun;
}

bool OptBisect::shouldRunCase(const Twine &Msg) {
  if (!BisectEnabled)
    return true;
  int CurFuelNum = ++LastBisectNum;
  bool ShouldRun = (OptBisectLimit == -1 || CurFuelNum <= OptBisectLimit);
  printCaseMessage(CurFuelNum, Msg.str(), ShouldRun);
  return ShouldRun;
}

bool llvm::skipPassForModule(const StringRef PassName, const Module &M) {
  return !M.getContext().getOptBisect().shouldRunPass(PassName, M);
}

bool llvm::skipPassForFunction(const StringRef PassName, const Function &F) {
  return !F.getContext().getOptBisect().shouldRunPass(PassName, F);
}
#if 0
bool llvm::skipPassForBasicBlock(const StringRef PassName, const BasicBlock &BB) {
  return !BB.getContext().getOptBisect().shouldRunPass(PassName, BB);
}

bool llvm::skipPassForLoop(const StringRef PassName, const Loop &L) {
  const Function *F = L.getHeader()->getParent();
  if (!F)
    return false;
  return !F->getContext().getOptBisect().shouldRunPass(PassName, L);
}
#endif
bool llvm::skipPassForSCC(const StringRef PassName, const LazyCallGraph::SCC &SCC) {
  LLVMContext &Context = SCC.begin()->getFunction().getContext();
  return !Context.getOptBisect().shouldRunPass(PassName, SCC);
}

OpenPOWER on IntegriCloud