Re-factor sample profile reader into lib/ProfileData.
[oota-llvm.git] / include / llvm / ProfileData / SampleProfReader.h
1 //===- SampleProfReader.h - Read LLVM sample profile data -----------------===//
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 // This file contains definitions needed for reading sample profiles.
11 //
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H
14 #define LLVM_PROFILEDATA_SAMPLEPROFREADER_H
15
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/IR/DiagnosticInfo.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/LLVMContext.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/Twine.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/raw_ostream.h"
26
27 using namespace llvm;
28
29 namespace sampleprof {
30
31 /// \brief Represents the relative location of an instruction.
32 ///
33 /// Instruction locations are specified by the line offset from the
34 /// beginning of the function (marked by the line where the function
35 /// header is) and the discriminator value within that line.
36 ///
37 /// The discriminator value is useful to distinguish instructions
38 /// that are on the same line but belong to different basic blocks
39 /// (e.g., the two post-increment instructions in "if (p) x++; else y++;").
40 struct LineLocation {
41   LineLocation(int L, unsigned D) : LineOffset(L), Discriminator(D) {}
42   int LineOffset;
43   unsigned Discriminator;
44 };
45 } // End namespace sampleprof
46
47 namespace llvm {
48 template <> struct DenseMapInfo<sampleprof::LineLocation> {
49   typedef DenseMapInfo<int> OffsetInfo;
50   typedef DenseMapInfo<unsigned> DiscriminatorInfo;
51   static inline sampleprof::LineLocation getEmptyKey() {
52     return sampleprof::LineLocation(OffsetInfo::getEmptyKey(),
53                                     DiscriminatorInfo::getEmptyKey());
54   }
55   static inline sampleprof::LineLocation getTombstoneKey() {
56     return sampleprof::LineLocation(OffsetInfo::getTombstoneKey(),
57                                     DiscriminatorInfo::getTombstoneKey());
58   }
59   static inline unsigned getHashValue(sampleprof::LineLocation Val) {
60     return DenseMapInfo<std::pair<int, unsigned>>::getHashValue(
61         std::pair<int, unsigned>(Val.LineOffset, Val.Discriminator));
62   }
63   static inline bool isEqual(sampleprof::LineLocation LHS,
64                              sampleprof::LineLocation RHS) {
65     return LHS.LineOffset == RHS.LineOffset &&
66            LHS.Discriminator == RHS.Discriminator;
67   }
68 };
69 }
70
71 namespace sampleprof {
72
73 typedef DenseMap<LineLocation, unsigned> BodySampleMap;
74
75 /// \brief Representation of the samples collected for a function.
76 ///
77 /// This data structure contains all the collected samples for the body
78 /// of a function. Each sample corresponds to a LineLocation instance
79 /// within the body of the function.
80 class FunctionSamples {
81 public:
82   FunctionSamples()
83       : TotalSamples(0), TotalHeadSamples(0) {}
84   void print(raw_ostream & OS);
85   void addTotalSamples(unsigned Num) { TotalSamples += Num; }
86   void addHeadSamples(unsigned Num) { TotalHeadSamples += Num; }
87   void addBodySamples(int LineOffset, unsigned Discriminator, unsigned Num) {
88     assert(LineOffset >= 0);
89     BodySamples[LineLocation(LineOffset, Discriminator)] += Num;
90   }
91
92   /// \brief Return the number of samples collected at the given location.
93   /// Each location is specified by \p LineOffset and \p Discriminator.
94   unsigned samplesAt(int LineOffset, unsigned Discriminator) {
95     return BodySamples.lookup(LineLocation(LineOffset, Discriminator));
96   }
97
98   bool empty() { return BodySamples.empty(); }
99
100 private:
101   /// \brief Total number of samples collected inside this function.
102   ///
103   /// Samples are cumulative, they include all the samples collected
104   /// inside this function and all its inlined callees.
105   unsigned TotalSamples;
106
107   /// \brief Total number of samples collected at the head of the function.
108   unsigned TotalHeadSamples;
109
110   /// \brief Map instruction locations to collected samples.
111   ///
112   /// Each entry in this map contains the number of samples
113   /// collected at the corresponding line offset. All line locations
114   /// are an offset from the start of the function.
115   BodySampleMap BodySamples;
116 };
117
118 /// \brief Sample-based profile reader.
119 ///
120 /// Each profile contains sample counts for all the functions
121 /// executed. Inside each function, statements are annotated with the
122 /// collected samples on all the instructions associated with that
123 /// statement.
124 ///
125 /// For this to produce meaningful data, the program needs to be
126 /// compiled with some debug information (at minimum, line numbers:
127 /// -gline-tables-only). Otherwise, it will be impossible to match IR
128 /// instructions to the line numbers collected by the profiler.
129 ///
130 /// From the profile file, we are interested in collecting the
131 /// following information:
132 ///
133 /// * A list of functions included in the profile (mangled names).
134 ///
135 /// * For each function F:
136 ///   1. The total number of samples collected in F.
137 ///
138 ///   2. The samples collected at each line in F. To provide some
139 ///      protection against source code shuffling, line numbers should
140 ///      be relative to the start of the function.
141 ///
142 /// The reader supports two file formats: text and bitcode. The text format
143 /// is useful for debugging and testing, while the bitcode format is more
144 /// compact. They can both be used interchangeably.
145 class SampleProfileReader {
146 public:
147   SampleProfileReader(const Module &M, StringRef F)
148       : Profiles(0), Filename(F), M(M) {}
149
150   /// \brief Print all the profiles to dbgs().
151   void dump();
152
153   /// \brief Load sample profiles from the associated file.
154   bool load();
155
156   /// \brief Print the profile for \p FName on stream \p OS.
157   void printFunctionProfile(raw_ostream &OS, StringRef FName);
158
159   /// \brief Print the profile for \p FName on dbgs().
160   void dumpFunctionProfile(StringRef FName);
161
162   /// \brief Return the samples collected for function \p F.
163   FunctionSamples *getSamplesFor(const Function &F) {
164     return &Profiles[F.getName()];
165   }
166
167   /// \brief Report a parse error message.
168   void reportParseError(int64_t LineNumber, Twine Msg) const {
169     DiagnosticInfoSampleProfile Diag(Filename.data(), LineNumber, Msg);
170     M.getContext().diagnose(Diag);
171   }
172
173 protected:
174   bool loadText();
175   bool loadBitcode() { llvm_unreachable("not implemented"); }
176
177   /// \brief Map every function to its associated profile.
178   ///
179   /// The profile of every function executed at runtime is collected
180   /// in the structure FunctionSamples. This maps function objects
181   /// to their corresponding profiles.
182   StringMap<FunctionSamples> Profiles;
183
184   /// \brief Path name to the file holding the profile data.
185   StringRef Filename;
186
187   /// \brief Module being compiled. Used to access the current
188   /// LLVM context for diagnostics.
189   const Module &M;
190 };
191
192 } // End namespace sampleprof
193
194 #endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H