Line data Source code
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 LLVMContext;
28 : class Loop;
29 : class Pass;
30 : class Twine;
31 : class Value;
32 :
33 : /// The optimization diagnostic interface.
34 : ///
35 : /// It allows reporting when optimizations are performed and when they are not
36 : /// along with the reasons for it. Hotness information of the corresponding
37 : /// code region can be included in the remark if DiagnosticsHotnessRequested is
38 : /// enabled in the LLVM context.
39 1461862 : class OptimizationRemarkEmitter {
40 : public:
41 : OptimizationRemarkEmitter(const Function *F, BlockFrequencyInfo *BFI)
42 751476 : : F(F), BFI(BFI) {}
43 :
44 : /// \brief This variant can be used to generate ORE on demand (without the
45 : /// analysis pass).
46 : ///
47 : /// Note that this ctor has a very different cost depending on whether
48 : /// F->getContext().getDiagnosticsHotnessRequested() is on or not. If it's off
49 : /// the operation is free.
50 : ///
51 : /// Whereas if DiagnosticsHotnessRequested is on, it is fairly expensive
52 : /// operation since BFI and all its required analyses are computed. This is
53 : /// for example useful for CGSCC passes that can't use function analyses
54 : /// passes in the old PM.
55 : OptimizationRemarkEmitter(const Function *F);
56 :
57 : OptimizationRemarkEmitter(OptimizationRemarkEmitter &&Arg)
58 3712 : : F(Arg.F), BFI(Arg.BFI) {}
59 :
60 : OptimizationRemarkEmitter &operator=(OptimizationRemarkEmitter &&RHS) {
61 : F = RHS.F;
62 : BFI = RHS.BFI;
63 : return *this;
64 : }
65 :
66 : /// Handle invalidation events in the new pass manager.
67 : bool invalidate(Function &F, const PreservedAnalyses &PA,
68 : FunctionAnalysisManager::Invalidator &Inv);
69 :
70 : /// \brief Output the remark via the diagnostic handler and to the
71 : /// optimization record file.
72 : void emit(DiagnosticInfoOptimizationBase &OptDiag);
73 :
74 : /// \brief Whether we allow for extra compile-time budget to perform more
75 : /// analysis to produce fewer false positives.
76 : ///
77 : /// This is useful when reporting missed optimizations. In this case we can
78 : /// use the extra analysis (1) to filter trivial false positives or (2) to
79 : /// provide more context so that non-trivial false positives can be quickly
80 : /// detected by the user.
81 : bool allowExtraAnalysis() const {
82 : // For now, only allow this with -fsave-optimization-record since the -Rpass
83 : // options are handled in the front-end.
84 691319 : return F->getContext().getDiagnosticsOutputFile();
85 : }
86 :
87 : private:
88 : const Function *F;
89 :
90 : BlockFrequencyInfo *BFI;
91 :
92 : /// If we generate BFI on demand, we need to free it when ORE is freed.
93 : std::unique_ptr<BlockFrequencyInfo> OwnedBFI;
94 :
95 : /// Compute hotness from IR value (currently assumed to be a block) if PGO is
96 : /// available.
97 : Optional<uint64_t> computeHotness(const Value *V);
98 :
99 : /// Similar but use value from \p OptDiag and update hotness there.
100 : void computeHotness(DiagnosticInfoIROptimization &OptDiag);
101 :
102 : /// \brief Only allow verbose messages if we know we're filtering by hotness
103 : /// (BFI is only set in this case).
104 : bool shouldEmitVerbose() { return BFI != nullptr; }
105 :
106 : OptimizationRemarkEmitter(const OptimizationRemarkEmitter &) = delete;
107 : void operator=(const OptimizationRemarkEmitter &) = delete;
108 : };
109 :
110 : /// \brief Add a small namespace to avoid name clashes with the classes used in
111 : /// the streaming interface. We want these to be short for better
112 : /// write/readability.
113 : namespace ore {
114 : using NV = DiagnosticInfoOptimizationBase::Argument;
115 : using setIsVerbose = DiagnosticInfoOptimizationBase::setIsVerbose;
116 : using setExtraArgs = DiagnosticInfoOptimizationBase::setExtraArgs;
117 : }
118 :
119 : /// OptimizationRemarkEmitter legacy analysis pass
120 : ///
121 : /// Note that this pass shouldn't generally be marked as preserved by other
122 : /// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI
123 : /// could be freed.
124 40372 : class OptimizationRemarkEmitterWrapperPass : public FunctionPass {
125 : std::unique_ptr<OptimizationRemarkEmitter> ORE;
126 :
127 : public:
128 : OptimizationRemarkEmitterWrapperPass();
129 :
130 : bool runOnFunction(Function &F) override;
131 :
132 : void getAnalysisUsage(AnalysisUsage &AU) const override;
133 :
134 : OptimizationRemarkEmitter &getORE() {
135 : assert(ORE && "pass not run yet");
136 752462 : return *ORE;
137 : }
138 :
139 : static char ID;
140 : };
141 :
142 : class OptimizationRemarkEmitterAnalysis
143 : : public AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis> {
144 : friend AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis>;
145 : static AnalysisKey Key;
146 :
147 : public:
148 : /// \brief Provide the result typedef for this analysis pass.
149 : typedef OptimizationRemarkEmitter Result;
150 :
151 : /// \brief Run the analysis pass over a function and produce BFI.
152 : Result run(Function &F, FunctionAnalysisManager &AM);
153 : };
154 :
155 : namespace yaml {
156 : template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
157 : static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
158 : };
159 : }
160 : }
161 : #endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
|