Mercurial > hg > CbC > CbC_llvm
comparison lib/ProfileData/SampleProfWriter.cpp @ 100:7d135dc70f03 LLVM 3.9
LLVM 3.9
author | Miyagi Mitsuki <e135756@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 26 Jan 2016 22:53:40 +0900 |
parents | afa8332a0e37 |
children | 1172e4bd9c6f |
comparison
equal
deleted
inserted
replaced
96:6418606d0ead | 100:7d135dc70f03 |
---|---|
28 | 28 |
29 using namespace llvm::sampleprof; | 29 using namespace llvm::sampleprof; |
30 using namespace llvm; | 30 using namespace llvm; |
31 | 31 |
32 /// \brief Write samples to a text file. | 32 /// \brief Write samples to a text file. |
33 bool SampleProfileWriterText::write(StringRef FName, const FunctionSamples &S) { | 33 /// |
34 /// Note: it may be tempting to implement this in terms of | |
35 /// FunctionSamples::print(). Please don't. The dump functionality is intended | |
36 /// for debugging and has no specified form. | |
37 /// | |
38 /// The format used here is more structured and deliberate because | |
39 /// it needs to be parsed by the SampleProfileReaderText class. | |
40 std::error_code SampleProfileWriterText::write(StringRef FName, | |
41 const FunctionSamples &S) { | |
42 auto &OS = *OutputStream; | |
43 | |
34 OS << FName << ":" << S.getTotalSamples(); | 44 OS << FName << ":" << S.getTotalSamples(); |
35 if (Indent == 0) | 45 if (Indent == 0) |
36 OS << ":" << S.getHeadSamples(); | 46 OS << ":" << S.getHeadSamples(); |
37 OS << "\n"; | 47 OS << "\n"; |
38 | 48 |
39 for (const auto &I : S.getBodySamples()) { | 49 SampleSorter<LineLocation, SampleRecord> SortedSamples(S.getBodySamples()); |
40 LineLocation Loc = I.first; | 50 for (const auto &I : SortedSamples.get()) { |
41 const SampleRecord &Sample = I.second; | 51 LineLocation Loc = I->first; |
52 const SampleRecord &Sample = I->second; | |
42 OS.indent(Indent + 1); | 53 OS.indent(Indent + 1); |
43 if (Loc.Discriminator == 0) | 54 if (Loc.Discriminator == 0) |
44 OS << Loc.LineOffset << ": "; | 55 OS << Loc.LineOffset << ": "; |
45 else | 56 else |
46 OS << Loc.LineOffset << "." << Loc.Discriminator << ": "; | 57 OS << Loc.LineOffset << "." << Loc.Discriminator << ": "; |
50 for (const auto &J : Sample.getCallTargets()) | 61 for (const auto &J : Sample.getCallTargets()) |
51 OS << " " << J.first() << ":" << J.second; | 62 OS << " " << J.first() << ":" << J.second; |
52 OS << "\n"; | 63 OS << "\n"; |
53 } | 64 } |
54 | 65 |
66 SampleSorter<CallsiteLocation, FunctionSamples> SortedCallsiteSamples( | |
67 S.getCallsiteSamples()); | |
55 Indent += 1; | 68 Indent += 1; |
56 for (const auto &I : S.getCallsiteSamples()) { | 69 for (const auto &I : SortedCallsiteSamples.get()) { |
57 CallsiteLocation Loc = I.first; | 70 CallsiteLocation Loc = I->first; |
58 const FunctionSamples &CalleeSamples = I.second; | 71 const FunctionSamples &CalleeSamples = I->second; |
59 OS.indent(Indent); | 72 OS.indent(Indent); |
60 if (Loc.Discriminator == 0) | 73 if (Loc.Discriminator == 0) |
61 OS << Loc.LineOffset << ": "; | 74 OS << Loc.LineOffset << ": "; |
62 else | 75 else |
63 OS << Loc.LineOffset << "." << Loc.Discriminator << ": "; | 76 OS << Loc.LineOffset << "." << Loc.Discriminator << ": "; |
64 write(Loc.CalleeName, CalleeSamples); | 77 if (std::error_code EC = write(Loc.CalleeName, CalleeSamples)) |
78 return EC; | |
65 } | 79 } |
66 Indent -= 1; | 80 Indent -= 1; |
67 | 81 |
68 return true; | 82 return sampleprof_error::success; |
69 } | 83 } |
70 | 84 |
71 SampleProfileWriterBinary::SampleProfileWriterBinary(StringRef F, | 85 std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) { |
72 std::error_code &EC) | 86 const auto &ret = NameTable.find(FName); |
73 : SampleProfileWriter(F, EC, sys::fs::F_None) { | 87 if (ret == NameTable.end()) |
74 if (EC) | 88 return sampleprof_error::truncated_name_table; |
75 return; | 89 encodeULEB128(ret->second, *OutputStream); |
76 | 90 return sampleprof_error::success; |
77 // Write the file header. | 91 } |
92 | |
93 void SampleProfileWriterBinary::addName(StringRef FName) { | |
94 auto NextIdx = NameTable.size(); | |
95 NameTable.insert(std::make_pair(FName, NextIdx)); | |
96 } | |
97 | |
98 void SampleProfileWriterBinary::addNames(const FunctionSamples &S) { | |
99 // Add all the names in indirect call targets. | |
100 for (const auto &I : S.getBodySamples()) { | |
101 const SampleRecord &Sample = I.second; | |
102 for (const auto &J : Sample.getCallTargets()) | |
103 addName(J.first()); | |
104 } | |
105 | |
106 // Recursively add all the names for inlined callsites. | |
107 for (const auto &J : S.getCallsiteSamples()) { | |
108 CallsiteLocation Loc = J.first; | |
109 const FunctionSamples &CalleeSamples = J.second; | |
110 addName(Loc.CalleeName); | |
111 addNames(CalleeSamples); | |
112 } | |
113 } | |
114 | |
115 std::error_code SampleProfileWriterBinary::writeHeader( | |
116 const StringMap<FunctionSamples> &ProfileMap) { | |
117 auto &OS = *OutputStream; | |
118 | |
119 // Write file magic identifier. | |
78 encodeULEB128(SPMagic(), OS); | 120 encodeULEB128(SPMagic(), OS); |
79 encodeULEB128(SPVersion(), OS); | 121 encodeULEB128(SPVersion(), OS); |
80 } | 122 |
81 | 123 // Generate the name table for all the functions referenced in the profile. |
82 /// \brief Write samples to a binary file. | 124 for (const auto &I : ProfileMap) { |
83 /// | 125 addName(I.first()); |
84 /// \returns true if the samples were written successfully, false otherwise. | 126 addNames(I.second); |
85 bool SampleProfileWriterBinary::write(StringRef FName, | 127 } |
86 const FunctionSamples &S) { | 128 |
87 OS << FName; | 129 // Write out the name table. |
88 encodeULEB128(0, OS); | 130 encodeULEB128(NameTable.size(), OS); |
131 for (auto N : NameTable) { | |
132 OS << N.first; | |
133 encodeULEB128(0, OS); | |
134 } | |
135 | |
136 return sampleprof_error::success; | |
137 } | |
138 | |
139 std::error_code SampleProfileWriterBinary::writeBody(StringRef FName, | |
140 const FunctionSamples &S) { | |
141 auto &OS = *OutputStream; | |
142 | |
143 if (std::error_code EC = writeNameIdx(FName)) | |
144 return EC; | |
145 | |
89 encodeULEB128(S.getTotalSamples(), OS); | 146 encodeULEB128(S.getTotalSamples(), OS); |
90 encodeULEB128(S.getHeadSamples(), OS); | 147 |
148 // Emit all the body samples. | |
91 encodeULEB128(S.getBodySamples().size(), OS); | 149 encodeULEB128(S.getBodySamples().size(), OS); |
92 | |
93 // Emit all the body samples. | |
94 for (const auto &I : S.getBodySamples()) { | 150 for (const auto &I : S.getBodySamples()) { |
95 LineLocation Loc = I.first; | 151 LineLocation Loc = I.first; |
96 const SampleRecord &Sample = I.second; | 152 const SampleRecord &Sample = I.second; |
97 encodeULEB128(Loc.LineOffset, OS); | 153 encodeULEB128(Loc.LineOffset, OS); |
98 encodeULEB128(Loc.Discriminator, OS); | 154 encodeULEB128(Loc.Discriminator, OS); |
99 encodeULEB128(Sample.getSamples(), OS); | 155 encodeULEB128(Sample.getSamples(), OS); |
100 encodeULEB128(Sample.getCallTargets().size(), OS); | 156 encodeULEB128(Sample.getCallTargets().size(), OS); |
101 for (const auto &J : Sample.getCallTargets()) { | 157 for (const auto &J : Sample.getCallTargets()) { |
102 std::string Callee = J.first(); | 158 StringRef Callee = J.first(); |
103 unsigned CalleeSamples = J.second; | 159 uint64_t CalleeSamples = J.second; |
104 OS << Callee; | 160 if (std::error_code EC = writeNameIdx(Callee)) |
105 encodeULEB128(0, OS); | 161 return EC; |
106 encodeULEB128(CalleeSamples, OS); | 162 encodeULEB128(CalleeSamples, OS); |
107 } | 163 } |
108 } | 164 } |
109 | 165 |
110 // Recursively emit all the callsite samples. | 166 // Recursively emit all the callsite samples. |
112 for (const auto &J : S.getCallsiteSamples()) { | 168 for (const auto &J : S.getCallsiteSamples()) { |
113 CallsiteLocation Loc = J.first; | 169 CallsiteLocation Loc = J.first; |
114 const FunctionSamples &CalleeSamples = J.second; | 170 const FunctionSamples &CalleeSamples = J.second; |
115 encodeULEB128(Loc.LineOffset, OS); | 171 encodeULEB128(Loc.LineOffset, OS); |
116 encodeULEB128(Loc.Discriminator, OS); | 172 encodeULEB128(Loc.Discriminator, OS); |
117 write(Loc.CalleeName, CalleeSamples); | 173 if (std::error_code EC = writeBody(Loc.CalleeName, CalleeSamples)) |
118 } | 174 return EC; |
119 | 175 } |
120 return true; | 176 |
121 } | 177 return sampleprof_error::success; |
122 | 178 } |
123 /// \brief Create a sample profile writer based on the specified format. | 179 |
180 /// \brief Write samples of a top-level function to a binary file. | |
181 /// | |
182 /// \returns true if the samples were written successfully, false otherwise. | |
183 std::error_code SampleProfileWriterBinary::write(StringRef FName, | |
184 const FunctionSamples &S) { | |
185 encodeULEB128(S.getHeadSamples(), *OutputStream); | |
186 return writeBody(FName, S); | |
187 } | |
188 | |
189 /// \brief Create a sample profile file writer based on the specified format. | |
124 /// | 190 /// |
125 /// \param Filename The file to create. | 191 /// \param Filename The file to create. |
126 /// | 192 /// |
127 /// \param Writer The writer to instantiate according to the specified format. | 193 /// \param Writer The writer to instantiate according to the specified format. |
128 /// | 194 /// |
130 /// | 196 /// |
131 /// \returns an error code indicating the status of the created writer. | 197 /// \returns an error code indicating the status of the created writer. |
132 ErrorOr<std::unique_ptr<SampleProfileWriter>> | 198 ErrorOr<std::unique_ptr<SampleProfileWriter>> |
133 SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) { | 199 SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) { |
134 std::error_code EC; | 200 std::error_code EC; |
201 std::unique_ptr<raw_ostream> OS; | |
202 if (Format == SPF_Binary) | |
203 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::F_None)); | |
204 else | |
205 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::F_Text)); | |
206 if (EC) | |
207 return EC; | |
208 | |
209 return create(OS, Format); | |
210 } | |
211 | |
212 /// \brief Create a sample profile stream writer based on the specified format. | |
213 /// | |
214 /// \param OS The output stream to store the profile data to. | |
215 /// | |
216 /// \param Writer The writer to instantiate according to the specified format. | |
217 /// | |
218 /// \param Format Encoding format for the profile file. | |
219 /// | |
220 /// \returns an error code indicating the status of the created writer. | |
221 ErrorOr<std::unique_ptr<SampleProfileWriter>> | |
222 SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS, | |
223 SampleProfileFormat Format) { | |
224 std::error_code EC; | |
135 std::unique_ptr<SampleProfileWriter> Writer; | 225 std::unique_ptr<SampleProfileWriter> Writer; |
136 | 226 |
137 if (Format == SPF_Binary) | 227 if (Format == SPF_Binary) |
138 Writer.reset(new SampleProfileWriterBinary(Filename, EC)); | 228 Writer.reset(new SampleProfileWriterBinary(OS)); |
139 else if (Format == SPF_Text) | 229 else if (Format == SPF_Text) |
140 Writer.reset(new SampleProfileWriterText(Filename, EC)); | 230 Writer.reset(new SampleProfileWriterText(OS)); |
231 else if (Format == SPF_GCC) | |
232 EC = sampleprof_error::unsupported_writing_format; | |
141 else | 233 else |
142 EC = sampleprof_error::unrecognized_format; | 234 EC = sampleprof_error::unrecognized_format; |
143 | 235 |
144 if (EC) | 236 if (EC) |
145 return EC; | 237 return EC; |