summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/OptBisect.cpp
blob: 74eb9e19e9dd6d36433fab2e45da8618d39ec7a8 (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
//===------- 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 <class UnitT>
bool OptBisect::shouldRunPass(const Pass *P, const UnitT &U) {
  if (!BisectEnabled)
    return true;
  return checkPass(P->getPassName(), 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;
}

OpenPOWER on IntegriCloud