Line data Source code
1 : //=-- SampleProf.cpp - Sample profiling format support --------------------===//
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 common definitions used in the reading and writing of
11 : // sample profile data.
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "llvm/ProfileData/SampleProf.h"
16 : #include "llvm/Config/llvm-config.h"
17 : #include "llvm/IR/DebugInfoMetadata.h"
18 : #include "llvm/Support/Compiler.h"
19 : #include "llvm/Support/Debug.h"
20 : #include "llvm/Support/ErrorHandling.h"
21 : #include "llvm/Support/ManagedStatic.h"
22 : #include "llvm/Support/raw_ostream.h"
23 : #include <string>
24 : #include <system_error>
25 :
26 : using namespace llvm;
27 : using namespace sampleprof;
28 :
29 : namespace llvm {
30 : namespace sampleprof {
31 : SampleProfileFormat FunctionSamples::Format;
32 : DenseMap<uint64_t, StringRef> FunctionSamples::GUIDToFuncNameMap;
33 : Module *FunctionSamples::CurrentModule;
34 : } // namespace sampleprof
35 : } // namespace llvm
36 :
37 : namespace {
38 :
39 : // FIXME: This class is only here to support the transition to llvm::Error. It
40 : // will be removed once this transition is complete. Clients should prefer to
41 : // deal with the Error value directly, rather than converting to error_code.
42 101 : class SampleProfErrorCategoryType : public std::error_category {
43 0 : const char *name() const noexcept override { return "llvm.sampleprof"; }
44 :
45 6 : std::string message(int IE) const override {
46 : sampleprof_error E = static_cast<sampleprof_error>(IE);
47 6 : switch (E) {
48 : case sampleprof_error::success:
49 0 : return "Success";
50 : case sampleprof_error::bad_magic:
51 0 : return "Invalid sample profile data (bad magic)";
52 : case sampleprof_error::unsupported_version:
53 0 : return "Unsupported sample profile format version";
54 : case sampleprof_error::too_large:
55 0 : return "Too much profile data";
56 : case sampleprof_error::truncated:
57 0 : return "Truncated profile data";
58 : case sampleprof_error::malformed:
59 0 : return "Malformed sample profile data";
60 : case sampleprof_error::unrecognized_format:
61 3 : return "Unrecognized sample profile encoding format";
62 : case sampleprof_error::unsupported_writing_format:
63 0 : return "Profile encoding format unsupported for writing operations";
64 : case sampleprof_error::truncated_name_table:
65 0 : return "Truncated function name table";
66 : case sampleprof_error::not_implemented:
67 0 : return "Unimplemented feature";
68 : case sampleprof_error::counter_overflow:
69 3 : return "Counter overflow";
70 : case sampleprof_error::ostream_seek_unsupported:
71 0 : return "Ostream does not support seek";
72 : }
73 0 : llvm_unreachable("A value of sampleprof_error has no message.");
74 : }
75 : };
76 :
77 : } // end anonymous namespace
78 :
79 : static ManagedStatic<SampleProfErrorCategoryType> ErrorCategory;
80 :
81 3656 : const std::error_category &llvm::sampleprof_category() {
82 3656 : return *ErrorCategory;
83 : }
84 :
85 162 : void LineLocation::print(raw_ostream &OS) const {
86 162 : OS << LineOffset;
87 162 : if (Discriminator > 0)
88 90 : OS << "." << Discriminator;
89 162 : }
90 :
91 162 : raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
92 : const LineLocation &Loc) {
93 162 : Loc.print(OS);
94 162 : return OS;
95 : }
96 :
97 : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
98 : LLVM_DUMP_METHOD void LineLocation::dump() const { print(dbgs()); }
99 : #endif
100 :
101 : /// Print the sample record to the stream \p OS indented by \p Indent.
102 132 : void SampleRecord::print(raw_ostream &OS, unsigned Indent) const {
103 132 : OS << NumSamples;
104 132 : if (hasCalls()) {
105 7 : OS << ", calls:";
106 24 : for (const auto &I : getCallTargets())
107 10 : OS << " " << I.first() << ":" << I.second;
108 : }
109 132 : OS << "\n";
110 132 : }
111 :
112 : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
113 : LLVM_DUMP_METHOD void SampleRecord::dump() const { print(dbgs(), 0); }
114 : #endif
115 :
116 132 : raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
117 : const SampleRecord &Sample) {
118 132 : Sample.print(OS, 0);
119 132 : return OS;
120 : }
121 :
122 : /// Print the samples collected for a function on stream \p OS.
123 52 : void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
124 52 : OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size()
125 52 : << " sampled lines\n";
126 :
127 52 : OS.indent(Indent);
128 52 : if (!BodySamples.empty()) {
129 52 : OS << "Samples collected in the function's body {\n";
130 52 : SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples);
131 184 : for (const auto &SI : SortedBodySamples.get()) {
132 132 : OS.indent(Indent + 2);
133 132 : OS << SI->first << ": " << SI->second;
134 : }
135 52 : OS.indent(Indent);
136 52 : OS << "}\n";
137 : } else {
138 0 : OS << "No samples collected in the function's body\n";
139 : }
140 :
141 52 : OS.indent(Indent);
142 52 : if (!CallsiteSamples.empty()) {
143 15 : OS << "Samples collected in inlined callsites {\n";
144 : SampleSorter<LineLocation, FunctionSamplesMap> SortedCallsiteSamples(
145 15 : CallsiteSamples);
146 42 : for (const auto &CS : SortedCallsiteSamples.get()) {
147 57 : for (const auto &FS : CS->second) {
148 30 : OS.indent(Indent + 2);
149 30 : OS << CS->first << ": inlined callee: " << FS.second.getName() << ": ";
150 30 : FS.second.print(OS, Indent + 4);
151 : }
152 : }
153 15 : OS << "}\n";
154 : } else {
155 37 : OS << "No inlined callsites in this function\n";
156 : }
157 52 : }
158 :
159 22 : raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
160 : const FunctionSamples &FS) {
161 22 : FS.print(OS);
162 22 : return OS;
163 : }
164 :
165 1347 : unsigned FunctionSamples::getOffset(const DILocation *DIL) {
166 2694 : return (DIL->getLine() - DIL->getScope()->getSubprogram()->getLine()) &
167 1347 : 0xffff;
168 : }
169 :
170 : const FunctionSamples *
171 1537 : FunctionSamples::findFunctionSamples(const DILocation *DIL) const {
172 : assert(DIL);
173 : SmallVector<std::pair<LineLocation, StringRef>, 10> S;
174 :
175 : const DILocation *PrevDIL = DIL;
176 1692 : for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
177 155 : S.push_back(std::make_pair(
178 155 : LineLocation(getOffset(DIL), DIL->getBaseDiscriminator()),
179 155 : PrevDIL->getScope()->getSubprogram()->getLinkageName()));
180 : PrevDIL = DIL;
181 : }
182 1537 : if (S.size() == 0)
183 : return this;
184 : const FunctionSamples *FS = this;
185 310 : for (int i = S.size() - 1; i >= 0 && FS != nullptr; i--) {
186 310 : FS = FS->findFunctionSamplesAt(S[i].first, S[i].second);
187 : }
188 : return FS;
189 : }
190 :
191 : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
192 : LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); }
193 : #endif
|