Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h
Line
Count
Source (jump to first uncovered line)
1
//===- OptimizationDiagnosticInfo.h - Optimization Diagnostic ---*- 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
//
10
// Optimization diagnostic interfaces.  It's packaged as an analysis pass so
11
// that by using this service passes become dependent on BFI as well.  BFI is
12
// used to compute the "hotness" of the diagnostic message.
13
//===----------------------------------------------------------------------===//
14
15
#ifndef LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
16
#define LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
17
18
#include "llvm/ADT/Optional.h"
19
#include "llvm/Analysis/BlockFrequencyInfo.h"
20
#include "llvm/IR/DiagnosticInfo.h"
21
#include "llvm/IR/Function.h"
22
#include "llvm/IR/PassManager.h"
23
#include "llvm/Pass.h"
24
25
namespace llvm {
26
class DebugLoc;
27
class Loop;
28
class Pass;
29
class Twine;
30
class Value;
31
32
/// The optimization diagnostic interface.
33
///
34
/// It allows reporting when optimizations are performed and when they are not
35
/// along with the reasons for it.  Hotness information of the corresponding
36
/// code region can be included in the remark if DiagnosticsHotnessRequested is
37
/// enabled in the LLVM context.
38
class OptimizationRemarkEmitter {
39
public:
40
  OptimizationRemarkEmitter(const Function *F, BlockFrequencyInfo *BFI)
41
7.83M
      : F(F), BFI(BFI) {}
42
43
  /// \brief This variant can be used to generate ORE on demand (without the
44
  /// analysis pass).
45
  ///
46
  /// Note that this ctor has a very different cost depending on whether
47
  /// F->getContext().getDiagnosticsHotnessRequested() is on or not.  If it's off
48
  /// the operation is free.
49
  ///
50
  /// Whereas if DiagnosticsHotnessRequested is on, it is fairly expensive
51
  /// operation since BFI and all its required analyses are computed.  This is
52
  /// for example useful for CGSCC passes that can't use function analyses
53
  /// passes in the old PM.
54
  OptimizationRemarkEmitter(const Function *F);
55
56
  OptimizationRemarkEmitter(OptimizationRemarkEmitter &&Arg)
57
1.85k
      : F(Arg.F), BFI(Arg.BFI) {}
58
59
0
  OptimizationRemarkEmitter &operator=(OptimizationRemarkEmitter &&RHS) {
60
0
    F = RHS.F;
61
0
    BFI = RHS.BFI;
62
0
    return *this;
63
0
  }
64
65
  /// Handle invalidation events in the new pass manager.
66
  bool invalidate(Function &F, const PreservedAnalyses &PA,
67
                  FunctionAnalysisManager::Invalidator &Inv);
68
69
  /// \brief Output the remark via the diagnostic handler and to the
70
  /// optimization record file.
71
  void emit(DiagnosticInfoOptimizationBase &OptDiag);
72
73
  /// \brief Take a lambda that returns a remark which will be emitted.  Second
74
  /// argument is only used to restrict this to functions.
75
  template <typename T>
76
1.81M
  void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
77
1.81M
    // Avoid building the remark unless we know there are at least *some*
78
1.81M
    // remarks enabled. We can't currently check whether remarks are requested
79
1.81M
    // for the calling pass since that requires actually building the remark.
80
1.81M
81
1.81M
    if (F->getContext().getDiagnosticsOutputFile() ||
82
1.81M
        
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()1.81M
) {
83
57
      auto R = RemarkBuilder();
84
57
      emit((DiagnosticInfoOptimizationBase &)R);
85
57
    }
86
1.81M
  }
Inliner.cpp:void llvm::OptimizationRemarkEmitter::emit<inlineCallsImpl(llvm::CallGraphSCC&, llvm::CallGraph&, std::__1::function<llvm::AssumptionCache& (llvm::Function&)>, llvm::ProfileSummaryInfo*, llvm::TargetLibraryInfo&, bool, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::function_ref<llvm::AAResults& (llvm::Function&)>, llvm::ImportedFunctionsInliningStatistics&)::$_9>(inlineCallsImpl(llvm::CallGraphSCC&, llvm::CallGraph&, std::__1::function<llvm::AssumptionCache& (llvm::Function&)>, llvm::ProfileSummaryInfo*, llvm::TargetLibraryInfo&, bool, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::function_ref<llvm::AAResults& (llvm::Function&)>, llvm::ImportedFunctionsInliningStatistics&)::$_9, decltype(fp())*)
Line
Count
Source
76
191k
  void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
77
191k
    // Avoid building the remark unless we know there are at least *some*
78
191k
    // remarks enabled. We can't currently check whether remarks are requested
79
191k
    // for the calling pass since that requires actually building the remark.
80
191k
81
191k
    if (F->getContext().getDiagnosticsOutputFile() ||
82
191k
        
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()191k
) {
83
18
      auto R = RemarkBuilder();
84
18
      emit((DiagnosticInfoOptimizationBase &)R);
85
18
    }
86
191k
  }
Inliner.cpp:void llvm::OptimizationRemarkEmitter::emit<shouldInline(llvm::CallSite, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::OptimizationRemarkEmitter&)::$_7>(shouldInline(llvm::CallSite, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::OptimizationRemarkEmitter&)::$_7, decltype(fp())*)
Line
Count
Source
76
1.52M
  void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
77
1.52M
    // Avoid building the remark unless we know there are at least *some*
78
1.52M
    // remarks enabled. We can't currently check whether remarks are requested
79
1.52M
    // for the calling pass since that requires actually building the remark.
80
1.52M
81
1.52M
    if (F->getContext().getDiagnosticsOutputFile() ||
82
1.52M
        
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()1.52M
) {
83
30
      auto R = RemarkBuilder();
84
30
      emit((DiagnosticInfoOptimizationBase &)R);
85
30
    }
86
1.52M
  }
Inliner.cpp:void llvm::OptimizationRemarkEmitter::emit<shouldInline(llvm::CallSite, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::OptimizationRemarkEmitter&)::$_8>(shouldInline(llvm::CallSite, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::OptimizationRemarkEmitter&)::$_8, decltype(fp())*)
Line
Count
Source
76
83.3k
  void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
77
83.3k
    // Avoid building the remark unless we know there are at least *some*
78
83.3k
    // remarks enabled. We can't currently check whether remarks are requested
79
83.3k
    // for the calling pass since that requires actually building the remark.
80
83.3k
81
83.3k
    if (F->getContext().getDiagnosticsOutputFile() ||
82
83.3k
        
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()83.3k
) {
83
0
      auto R = RemarkBuilder();
84
0
      emit((DiagnosticInfoOptimizationBase &)R);
85
0
    }
86
83.3k
  }
LoopUnroll.cpp:void llvm::OptimizationRemarkEmitter::emit<llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_2>(llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_2, decltype(fp())*)
Line
Count
Source
76
95
  void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
77
95
    // Avoid building the remark unless we know there are at least *some*
78
95
    // remarks enabled. We can't currently check whether remarks are requested
79
95
    // for the calling pass since that requires actually building the remark.
80
95
81
95
    if (F->getContext().getDiagnosticsOutputFile() ||
82
95
        
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()95
) {
83
2
      auto R = RemarkBuilder();
84
2
      emit((DiagnosticInfoOptimizationBase &)R);
85
2
    }
86
95
  }
LoopUnroll.cpp:void llvm::OptimizationRemarkEmitter::emit<llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_3>(llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_3, decltype(fp())*)
Line
Count
Source
76
12
  void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
77
12
    // Avoid building the remark unless we know there are at least *some*
78
12
    // remarks enabled. We can't currently check whether remarks are requested
79
12
    // for the calling pass since that requires actually building the remark.
80
12
81
12
    if (F->getContext().getDiagnosticsOutputFile() ||
82
12
        
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()12
) {
83
0
      auto R = RemarkBuilder();
84
0
      emit((DiagnosticInfoOptimizationBase &)R);
85
0
    }
86
12
  }
LoopUnroll.cpp:void llvm::OptimizationRemarkEmitter::emit<llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_4>(llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_4, decltype(fp())*)
Line
Count
Source
76
502
  void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
77
502
    // Avoid building the remark unless we know there are at least *some*
78
502
    // remarks enabled. We can't currently check whether remarks are requested
79
502
    // for the calling pass since that requires actually building the remark.
80
502
81
502
    if (F->getContext().getDiagnosticsOutputFile() ||
82
502
        
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()502
) {
83
1
      auto R = RemarkBuilder();
84
1
      emit((DiagnosticInfoOptimizationBase &)R);
85
1
    }
86
502
  }
LoopVectorize.cpp:void llvm::OptimizationRemarkEmitter::emit<(anonymous namespace)::LoopVectorizeHints::allowVectorization(llvm::Function*, llvm::Loop*, bool) const::'lambda'()>((anonymous namespace)::LoopVectorizeHints::allowVectorization(llvm::Function*, llvm::Loop*, bool) const::'lambda'(), decltype(fp())*)
Line
Count
Source
76
11.1k
  void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
77
11.1k
    // Avoid building the remark unless we know there are at least *some*
78
11.1k
    // remarks enabled. We can't currently check whether remarks are requested
79
11.1k
    // for the calling pass since that requires actually building the remark.
80
11.1k
81
11.1k
    if (F->getContext().getDiagnosticsOutputFile() ||
82
11.1k
        
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()11.1k
) {
83
6
      auto R = RemarkBuilder();
84
6
      emit((DiagnosticInfoOptimizationBase &)R);
85
6
    }
86
11.1k
  }
87
88
  /// \brief Whether we allow for extra compile-time budget to perform more
89
  /// analysis to produce fewer false positives.
90
  ///
91
  /// This is useful when reporting missed optimizations.  In this case we can
92
  /// use the extra analysis (1) to filter trivial false positives or (2) to
93
  /// provide more context so that non-trivial false positives can be quickly
94
  /// detected by the user.
95
5.08M
  bool allowExtraAnalysis(StringRef PassName) const {
96
5.08M
    return (F->getContext().getDiagnosticsOutputFile() ||
97
5.08M
            F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
98
5.08M
  }
99
100
private:
101
  const Function *F;
102
103
  BlockFrequencyInfo *BFI;
104
105
  /// If we generate BFI on demand, we need to free it when ORE is freed.
106
  std::unique_ptr<BlockFrequencyInfo> OwnedBFI;
107
108
  /// Compute hotness from IR value (currently assumed to be a block) if PGO is
109
  /// available.
110
  Optional<uint64_t> computeHotness(const Value *V);
111
112
  /// Similar but use value from \p OptDiag and update hotness there.
113
  void computeHotness(DiagnosticInfoIROptimization &OptDiag);
114
115
  /// \brief Only allow verbose messages if we know we're filtering by hotness
116
  /// (BFI is only set in this case).
117
660k
  bool shouldEmitVerbose() { return BFI != nullptr; }
118
119
  OptimizationRemarkEmitter(const OptimizationRemarkEmitter &) = delete;
120
  void operator=(const OptimizationRemarkEmitter &) = delete;
121
};
122
123
/// \brief Add a small namespace to avoid name clashes with the classes used in
124
/// the streaming interface.  We want these to be short for better
125
/// write/readability.
126
namespace ore {
127
using NV = DiagnosticInfoOptimizationBase::Argument;
128
using setIsVerbose = DiagnosticInfoOptimizationBase::setIsVerbose;
129
using setExtraArgs = DiagnosticInfoOptimizationBase::setExtraArgs;
130
}
131
132
/// OptimizationRemarkEmitter legacy analysis pass
133
///
134
/// Note that this pass shouldn't generally be marked as preserved by other
135
/// passes.  It's holding onto BFI, so if the pass does not preserve BFI, BFI
136
/// could be freed.
137
class OptimizationRemarkEmitterWrapperPass : public FunctionPass {
138
  std::unique_ptr<OptimizationRemarkEmitter> ORE;
139
140
public:
141
  OptimizationRemarkEmitterWrapperPass();
142
143
  bool runOnFunction(Function &F) override;
144
145
  void getAnalysisUsage(AnalysisUsage &AU) const override;
146
147
7.83M
  OptimizationRemarkEmitter &getORE() {
148
7.83M
    assert(ORE && "pass not run yet");
149
7.83M
    return *ORE;
150
7.83M
  }
151
152
  static char ID;
153
};
154
155
class OptimizationRemarkEmitterAnalysis
156
    : public AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis> {
157
  friend AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis>;
158
  static AnalysisKey Key;
159
160
public:
161
  /// \brief Provide the result typedef for this analysis pass.
162
  typedef OptimizationRemarkEmitter Result;
163
164
  /// \brief Run the analysis pass over a function and produce BFI.
165
  Result run(Function &F, FunctionAnalysisManager &AM);
166
};
167
168
namespace yaml {
169
template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
170
  static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
171
};
172
}
173
}
174
#endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H