<div dir="ltr"><div dir="ltr">Should be fixed in rL342301. </div><div dir="ltr"><br></div><div dir="ltr">Thanks!</div><div dir="ltr">Wei.<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 14, 2018 at 4:35 PM, Wei Mi <span dir="ltr"><<a href="mailto:wmi@google.com" target="_blank">wmi@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">There is file system race indeed. I will fix that. Thanks Reid!<span class="HOEnZb"><font color="#888888"><div><br></div><div>Wei.</div></font></span></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 14, 2018 at 4:09 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div dir="ltr">These tests seem flaky when I run them locally. Are there possible filesystem race issues here?<div><br></div><div><div>FAIL: LLVM-Unit :: ProfileData/./ProfileDataTests<wbr>.exe/SampleProfTest.roundtrip_<wbr>compact_binary_profile (2329 of 27766)</div><div>******************** TEST 'LLVM-Unit :: ProfileData/./ProfileDataTests<wbr>.exe/SampleProfTest.roundtrip_<wbr>compact_binary_profile' FAILED ********************</div><div>Note: Google Test filter = SampleProfTest.roundtrip_compa<wbr>ct_binary_profile</div><div>[==========] Running 1 test from 1 test case.</div><div>[----------] Global test environment set-up.</div><div>[----------] 1 test from SampleProfTest</div><div>[ RUN ] SampleProfTest.roundtrip_compa<wbr>ct_binary_profile</div><div>C:\src\llvm-project\llvm\unitt<wbr>ests\ProfileData\SampleProfTes<wbr>t.cpp(59): error: Value of: NoError(ReaderOrErr.getError()<wbr>)</div><div> Actual: false (error 6: Unrecognized sample profile encoding format)</div><div>Expected: true</div><div>unknown file: error: SEH exception with code 0x3221225477 thrown in the test body.</div><div>unknown file: error: SEH exception with code 0x3221225477 thrown in the test fixture's destructor.</div><div>[ FAILED ] SampleProfTest.roundtrip_compa<wbr>ct_binary_profile (2 ms)</div><div>[----------] 1 test from SampleProfTest (2 ms total)</div><div><br></div><div>[----------] Global test environment tear-down</div><div>[==========] 1 test from 1 test case ran. (2 ms total)</div><div>[ PASSED ] 0 tests.</div><div>[ FAILED ] 1 test, listed below:</div><div>[ FAILED ] SampleProfTest.roundtrip_compa<wbr>ct_binary_profile</div><div><br></div><div> 1 FAILED TEST</div><div><br></div><div>********************</div><div>Testing: 0 ..</div><div>FAIL: LLVM-Unit :: ProfileData/./ProfileDataTests<wbr>.exe/SampleProfTest.roundtrip_<wbr>text_profile (2330 of 27766)</div><div>******************** TEST 'LLVM-Unit :: ProfileData/./ProfileDataTests<wbr>.exe/SampleProfTest.roundtrip_<wbr>text_profile' FAILED ********************</div><div>Note: Google Test filter = SampleProfTest.roundtrip_text_<wbr>profile</div><div>[==========] Running 1 test from 1 test case.</div><div>[----------] Global test environment set-up.</div><div>[----------] 1 test from SampleProfTest</div><div>[ RUN ] SampleProfTest.roundtrip_text_<wbr>profile</div><div>C:\src\llvm-project\llvm\unitt<wbr>ests\ProfileData\SampleProfTes<wbr>t.cpp(59): error: Value of: NoError(ReaderOrErr.getError()<wbr>)</div><div> Actual: false (error 6: Unrecognized sample profile encoding format)</div><div>Expected: true</div><div>unknown file: error: SEH exception with code 0x3221225477 thrown in the test body.</div><div>unknown file: error: SEH exception with code 0x3221225477 thrown in the test fixture's destructor.</div><div>[ FAILED ] SampleProfTest.roundtrip_text_<wbr>profile (2 ms)</div><div>[----------] 1 test from SampleProfTest (2 ms total)</div><div><br></div><div>[----------] Global test environment tear-down</div><div>[==========] 1 test from 1 test case ran. (2 ms total)</div><div>[ PASSED ] 0 tests.</div><div>[ FAILED ] 1 test, listed below:</div><div>[ FAILED ] SampleProfTest.roundtrip_text_<wbr>profile</div><div><br></div><div> 1 FAILED TEST</div><div><br></div><div>********************</div></div></div></div><div><div><br><div class="gmail_quote"><div dir="ltr">On Fri, Sep 14, 2018 at 1:54 PM Wei Mi via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: wmi<br>
Date: Fri Sep 14 13:52:59 2018<br>
New Revision: 342283<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=342283&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=342283&view=rev</a><br>
Log:<br>
[SampleFDO] Add FunctionOffsetTable in compact binary format profile.<br>
<br>
The patch saves a function offset table which maps function name index to the<br>
offset of its function profile to the start of the binary profile. By using<br>
the function offset table, for those function profiles which will not be used<br>
when compiling a module, the profile reader does't have to read them. For<br>
profile size around 10~20M, it saves ~10% compile time.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D51863" rel="noreferrer" target="_blank">https://reviews.llvm.org/D5186<wbr>3</a><br>
<br>
<br>
Modified:<br>
llvm/trunk/include/llvm/Profil<wbr>eData/SampleProf.h<br>
llvm/trunk/include/llvm/Profil<wbr>eData/SampleProfReader.h<br>
llvm/trunk/include/llvm/Profil<wbr>eData/SampleProfWriter.h<br>
llvm/trunk/lib/ProfileData/Sam<wbr>pleProf.cpp<br>
llvm/trunk/lib/ProfileData/Sam<wbr>pleProfReader.cpp<br>
llvm/trunk/lib/ProfileData/Sam<wbr>pleProfWriter.cpp<br>
llvm/trunk/lib/Transforms/IPO/<wbr>SampleProfile.cpp<br>
llvm/trunk/test/Transforms/Sam<wbr>pleProfile/Inputs/function_met<wbr>adata.compact.afdo<br>
llvm/trunk/test/Transforms/Sam<wbr>pleProfile/Inputs/indirect-cal<wbr>l.compact.afdo<br>
llvm/trunk/test/Transforms/Sam<wbr>pleProfile/Inputs/inline.compa<wbr>ctbinary.afdo<br>
llvm/trunk/unittests/ProfileDa<wbr>ta/SampleProfTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/Profil<wbr>eData/SampleProf.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProf.h?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>ProfileData/SampleProf.h?rev=<wbr>342283&r1=342282&r2=342283&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/Profil<wbr>eData/SampleProf.h (original)<br>
+++ llvm/trunk/include/llvm/Profil<wbr>eData/SampleProf.h Fri Sep 14 13:52:59 2018<br>
@@ -49,7 +49,8 @@ enum class sampleprof_error {<br>
unsupported_writing_format,<br>
truncated_name_table,<br>
not_implemented,<br>
- counter_overflow<br>
+ counter_overflow,<br>
+ ostream_seek_unsupported<br>
};<br>
<br>
inline std::error_code make_error_code(sampleprof_err<wbr>or E) {<br>
<br>
Modified: llvm/trunk/include/llvm/Profil<wbr>eData/SampleProfReader.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProfReader.h?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>ProfileData/SampleProfReader.<wbr>h?rev=342283&r1=342282&r2=<wbr>342283&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/Profil<wbr>eData/SampleProfReader.h (original)<br>
+++ llvm/trunk/include/llvm/Profil<wbr>eData/SampleProfReader.h Fri Sep 14 13:52:59 2018<br>
@@ -279,6 +279,8 @@ public:<br>
/// Print the profile for \p FName on stream \p OS.<br>
void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs());<br>
<br>
+ virtual void collectFuncsToUse(const Module &M) {}<br>
+<br>
/// Print all the profiles on stream \p OS.<br>
void dump(raw_ostream &OS = dbgs());<br>
<br>
@@ -364,7 +366,7 @@ public:<br>
: SampleProfileReader(std::move(<wbr>B), C, Format) {}<br>
<br>
/// Read and validate the file header.<br>
- std::error_code readHeader() override;<br>
+ virtual std::error_code readHeader() override;<br>
<br>
/// Read sample profiles from the associated file.<br>
std::error_code read() override;<br>
@@ -378,6 +380,10 @@ protected:<br>
/// \returns the read value.<br>
template <typename T> ErrorOr<T> readNumber();<br>
<br>
+ /// Read a numeric value of type T from the profile. The value is saved<br>
+ /// without encoded.<br>
+ template <typename T> ErrorOr<T> readUnencodedNumber();<br>
+<br>
/// Read a string from the profile.<br>
///<br>
/// If an error occurs during decoding, a diagnostic message is emitted and<br>
@@ -392,6 +398,9 @@ protected:<br>
/// Return true if we've reached the end of file.<br>
bool at_eof() const { return Data >= End; }<br>
<br>
+ /// Read the next function profile instance.<br>
+ std::error_code readFuncProfile();<br>
+<br>
/// Read the contents of the given profile instance.<br>
std::error_code readProfile(FunctionSamples &FProfile);<br>
<br>
@@ -436,10 +445,17 @@ class SampleProfileReaderCompactBina<wbr>ry :<br>
private:<br>
/// Function name table.<br>
std::vector<std::string> NameTable;<br>
+ /// The table mapping from function name to the offset of its FunctionSample<br>
+ /// towards file start.<br>
+ DenseMap<StringRef, uint64_t> FuncOffsetTable;<br>
+ /// The set containing the functions to use when compiling a module.<br>
+ DenseSet<StringRef> FuncsToUse;<br>
virtual std::error_code verifySPMagic(uint64_t Magic) override;<br>
virtual std::error_code readNameTable() override;<br>
/// Read a string indirectly via the name table.<br>
virtual ErrorOr<StringRef> readStringFromTable() override;<br>
+ virtual std::error_code readHeader() override;<br>
+ std::error_code readFuncOffsetTable();<br>
<br>
public:<br>
SampleProfileReaderCompactBin<wbr>ary(std::unique_ptr<MemoryBuff<wbr>er> B,<br>
@@ -448,6 +464,12 @@ public:<br>
<br>
/// \brief Return true if \p Buffer is in the format supported by this class.<br>
static bool hasFormat(const MemoryBuffer &Buffer);<br>
+<br>
+ /// Read samples only for functions to use.<br>
+ std::error_code read() override;<br>
+<br>
+ /// Collect functions to be used when compiling Module \p M.<br>
+ void collectFuncsToUse(const Module &M) override;<br>
};<br>
<br>
using InlineCallStack = SmallVector<FunctionSamples *, 10>;<br>
<br>
Modified: llvm/trunk/include/llvm/Profil<wbr>eData/SampleProfWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>ProfileData/SampleProfWriter.<wbr>h?rev=342283&r1=342282&r2=<wbr>342283&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/Profil<wbr>eData/SampleProfWriter.h (original)<br>
+++ llvm/trunk/include/llvm/Profil<wbr>eData/SampleProfWriter.h Fri Sep 14 13:52:59 2018<br>
@@ -42,7 +42,7 @@ public:<br>
/// Write all the sample profiles in the given map of samples.<br>
///<br>
/// \returns status code of the file update operation.<br>
- std::error_code write(const StringMap<FunctionSamples> &ProfileMap);<br>
+ virtual std::error_code write(const StringMap<FunctionSamples> &ProfileMap);<br>
<br>
raw_ostream &getOutputStream() { return *OutputStream; }<br>
<br>
@@ -103,14 +103,15 @@ private:<br>
/// Sample-based profile writer (binary format).<br>
class SampleProfileWriterBinary : public SampleProfileWriter {<br>
public:<br>
- std::error_code write(const FunctionSamples &S) override;<br>
+ virtual std::error_code write(const FunctionSamples &S) override;<br>
SampleProfileWriterBinary(std<wbr>::unique_ptr<raw_ostream> &OS)<br>
: SampleProfileWriter(OS) {}<br>
<br>
protected:<br>
virtual std::error_code writeNameTable() = 0;<br>
virtual std::error_code writeMagicIdent() = 0;<br>
- std::error_code writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;<br>
+ virtual std::error_code<br>
+ writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;<br>
std::error_code writeSummary();<br>
std::error_code writeNameIdx(StringRef FName);<br>
std::error_code writeBody(const FunctionSamples &S);<br>
@@ -135,12 +136,56 @@ protected:<br>
virtual std::error_code writeMagicIdent() override;<br>
};<br>
<br>
+// CompactBinary is a compact format of binary profile which both reduces<br>
+// the profile size and the load time needed when compiling. It has two<br>
+// major difference with Binary format.<br>
+// 1. It represents all the strings in name table using md5 hash.<br>
+// 2. It saves a function offset table which maps function name index to<br>
+// the offset of its function profile to the start of the binary profile,<br>
+// so by using the function offset table, for those function profiles which<br>
+// will not be needed when compiling a module, the profile reader does't<br>
+// have to read them and it saves compile time if the profile size is huge.<br>
+// The layout of the compact format is shown as follows:<br>
+//<br>
+// Part1: Profile header, the same as binary format, containing magic<br>
+// number, version, summary, name table...<br>
+// Part2: Function Offset Table Offset, which saves the position of<br>
+// Part4.<br>
+// Part3: Function profile collection<br>
+// function1 profile start<br>
+// ....<br>
+// function2 profile start<br>
+// ....<br>
+// function3 profile start<br>
+// ....<br>
+// ......<br>
+// Part4: Function Offset Table<br>
+// function1 name index --> function1 profile start<br>
+// function2 name index --> function2 profile start<br>
+// function3 name index --> function3 profile start<br>
+//<br>
+// We need Part2 because profile reader can use it to find out and read<br>
+// function offset table without reading Part3 first.<br>
class SampleProfileWriterCompactBina<wbr>ry : public SampleProfileWriterBinary {<br>
using SampleProfileWriterBinary::Sam<wbr>pleProfileWriterBinary;<br>
<br>
+public:<br>
+ virtual std::error_code write(const FunctionSamples &S) override;<br>
+ virtual std::error_code<br>
+ write(const StringMap<FunctionSamples> &ProfileMap) override;<br>
+<br>
protected:<br>
+ /// The table mapping from function name to the offset of its FunctionSample<br>
+ /// towards profile start.<br>
+ MapVector<StringRef, uint64_t> FuncOffsetTable;<br>
+ /// The offset of the slot to be filled with the offset of FuncOffsetTable<br>
+ /// towards profile start.<br>
+ uint64_t TableOffset;<br>
virtual std::error_code writeNameTable() override;<br>
virtual std::error_code writeMagicIdent() override;<br>
+ virtual std::error_code<br>
+ writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;<br>
+ std::error_code writeFuncOffsetTable();<br>
};<br>
<br>
} // end namespace sampleprof<br>
<br>
Modified: llvm/trunk/lib/ProfileData/Sam<wbr>pleProf.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProf.cpp?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/ProfileDa<wbr>ta/SampleProf.cpp?rev=342283&<wbr>r1=342282&r2=342283&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/ProfileData/Sam<wbr>pleProf.cpp (original)<br>
+++ llvm/trunk/lib/ProfileData/Sam<wbr>pleProf.cpp Fri Sep 14 13:52:59 2018<br>
@@ -67,6 +67,8 @@ class SampleProfErrorCategoryType : publ<br>
return "Unimplemented feature";<br>
case sampleprof_error::counter_over<wbr>flow:<br>
return "Counter overflow";<br>
+ case sampleprof_error::ostream_seek<wbr>_unsupported:<br>
+ return "Ostream does not support seek";<br>
}<br>
llvm_unreachable("A value of sampleprof_error has no message.");<br>
}<br>
<br>
Modified: llvm/trunk/lib/ProfileData/Sam<wbr>pleProfReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfReader.cpp?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/ProfileDa<wbr>ta/SampleProfReader.cpp?rev=<wbr>342283&r1=342282&r2=342283&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/ProfileData/Sam<wbr>pleProfReader.cpp (original)<br>
+++ llvm/trunk/lib/ProfileData/Sam<wbr>pleProfReader.cpp Fri Sep 14 13:52:59 2018<br>
@@ -30,6 +30,7 @@<br>
#include "llvm/Support/ErrorOr.h"<br>
#include "llvm/Support/LEB128.h"<br>
#include "llvm/Support/LineIterator.h"<br>
+#include "llvm/Support/MD5.h"<br>
#include "llvm/Support/MemoryBuffer.h"<br>
#include "llvm/Support/raw_ostream.h"<br>
#include <algorithm><br>
@@ -320,6 +321,21 @@ ErrorOr<StringRef> SampleProfileReaderBi<br>
}<br>
<br>
template <typename T><br>
+ErrorOr<T> SampleProfileReaderBinary::rea<wbr>dUnencodedNumber() {<br>
+ std::error_code EC;<br>
+<br>
+ if (Data + sizeof(T) > End) {<br>
+ EC = sampleprof_error::truncated;<br>
+ reportError(0, EC.message());<br>
+ return EC;<br>
+ }<br>
+<br>
+ using namespace support;<br>
+ T Val = endian::readNext<T, little, unaligned>(Data);<br>
+ return Val;<br>
+}<br>
+<br>
+template <typename T><br>
inline ErrorOr<uint32_t> SampleProfileReaderBinary::rea<wbr>dStringIndex(T &Table) {<br>
std::error_code EC;<br>
auto Idx = readNumber<uint32_t>();<br>
@@ -423,29 +439,51 @@ SampleProfileReaderBinary::rea<wbr>dProfile(F<br>
return sampleprof_error::success;<br>
}<br>
<br>
-std::error_code SampleProfileReaderBinary::rea<wbr>d() {<br>
- while (!at_eof()) {<br>
- auto NumHeadSamples = readNumber<uint64_t>();<br>
- if (std::error_code EC = NumHeadSamples.getError())<br>
- return EC;<br>
+std::error_code SampleProfileReaderBinary::rea<wbr>dFuncProfile() {<br>
+ auto NumHeadSamples = readNumber<uint64_t>();<br>
+ if (std::error_code EC = NumHeadSamples.getError())<br>
+ return EC;<br>
<br>
- auto FName(readStringFromTable());<br>
- if (std::error_code EC = FName.getError())<br>
- return EC;<br>
+ auto FName(readStringFromTable());<br>
+ if (std::error_code EC = FName.getError())<br>
+ return EC;<br>
<br>
- Profiles[*FName] = FunctionSamples();<br>
- FunctionSamples &FProfile = Profiles[*FName];<br>
- FProfile.setName(*FName);<br>
+ Profiles[*FName] = FunctionSamples();<br>
+ FunctionSamples &FProfile = Profiles[*FName];<br>
+ FProfile.setName(*FName);<br>
<br>
- FProfile.addHeadSamples(*NumHe<wbr>adSamples);<br>
+ FProfile.addHeadSamples(*NumHe<wbr>adSamples);<br>
+<br>
+ if (std::error_code EC = readProfile(FProfile))<br>
+ return EC;<br>
+ return sampleprof_error::success;<br>
+}<br>
<br>
- if (std::error_code EC = readProfile(FProfile))<br>
+std::error_code SampleProfileReaderBinary::rea<wbr>d() {<br>
+ while (!at_eof()) {<br>
+ if (std::error_code EC = readFuncProfile())<br>
return EC;<br>
}<br>
<br>
return sampleprof_error::success;<br>
}<br>
<br>
+std::error_code SampleProfileReaderCompactBina<wbr>ry::read() {<br>
+ for (auto Name : FuncsToUse) {<br>
+ auto GUID = std::to_string(MD5Hash(Name));<br>
+ auto iter = FuncOffsetTable.find(StringRef<wbr>(GUID));<br>
+ if (iter == FuncOffsetTable.end())<br>
+ continue;<br>
+ const uint8_t *SavedData = Data;<br>
+ Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()) +<br>
+ iter->second;<br>
+ if (std::error_code EC = readFuncProfile())<br>
+ return EC;<br>
+ Data = SavedData;<br>
+ }<br>
+ return sampleprof_error::success;<br>
+}<br>
+<br>
std::error_code SampleProfileReaderRawBinary::<wbr>verifySPMagic(uint64_t Magic) {<br>
if (Magic == SPMagic())<br>
return sampleprof_error::success;<br>
@@ -514,6 +552,53 @@ std::error_code SampleProfileReaderBinar<br>
return sampleprof_error::success;<br>
}<br>
<br>
+std::error_code SampleProfileReaderCompactBina<wbr>ry::readHeader() {<br>
+ SampleProfileReaderBinary::rea<wbr>dHeader();<br>
+ if (std::error_code EC = readFuncOffsetTable())<br>
+ return EC;<br>
+ return sampleprof_error::success;<br>
+}<br>
+<br>
+std::error_code SampleProfileReaderCompactBina<wbr>ry::readFuncOffsetTable() {<br>
+ auto TableOffset = readUnencodedNumber<uint64_t>(<wbr>);<br>
+ if (std::error_code EC = TableOffset.getError())<br>
+ return EC;<br>
+<br>
+ const uint8_t *SavedData = Data;<br>
+ const uint8_t *TableStart =<br>
+ reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()) +<br>
+ *TableOffset;<br>
+ Data = TableStart;<br>
+<br>
+ auto Size = readNumber<uint64_t>();<br>
+ if (std::error_code EC = Size.getError())<br>
+ return EC;<br>
+<br>
+ FuncOffsetTable.reserve(*Size)<wbr>;<br>
+ for (uint32_t I = 0; I < *Size; ++I) {<br>
+ auto FName(readStringFromTable());<br>
+ if (std::error_code EC = FName.getError())<br>
+ return EC;<br>
+<br>
+ auto Offset = readNumber<uint64_t>();<br>
+ if (std::error_code EC = Offset.getError())<br>
+ return EC;<br>
+<br>
+ FuncOffsetTable[*FName] = *Offset;<br>
+ }<br>
+ End = TableStart;<br>
+ Data = SavedData;<br>
+ return sampleprof_error::success;<br>
+}<br>
+<br>
+void SampleProfileReaderCompactBina<wbr>ry::collectFuncsToUse(const Module &M) {<br>
+ FuncsToUse.clear();<br>
+ for (auto &F : M) {<br>
+ StringRef Fname = F.getName().split('.').first;<br>
+ FuncsToUse.insert(Fname);<br>
+ }<br>
+}<br>
+<br>
std::error_code SampleProfileReaderBinary::rea<wbr>dSummaryEntry(<br>
std::vector<ProfileSummaryEnt<wbr>ry> &Entries) {<br>
auto Cutoff = readNumber<uint64_t>();<br>
<br>
Modified: llvm/trunk/lib/ProfileData/Sam<wbr>pleProfWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfWriter.cpp?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/ProfileDa<wbr>ta/SampleProfWriter.cpp?rev=<wbr>342283&r1=342282&r2=342283&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/ProfileData/Sam<wbr>pleProfWriter.cpp (original)<br>
+++ llvm/trunk/lib/ProfileData/Sam<wbr>pleProfWriter.cpp Fri Sep 14 13:52:59 2018<br>
@@ -22,6 +22,8 @@<br>
#include "llvm/ADT/StringRef.h"<br>
#include "llvm/ProfileData/ProfileCommo<wbr>n.h"<br>
#include "llvm/ProfileData/SampleProf.h<wbr>"<br>
+#include "llvm/Support/Endian.h"<br>
+#include "llvm/Support/EndianStream.h"<br>
#include "llvm/Support/ErrorOr.h"<br>
#include "llvm/Support/FileSystem.h"<br>
#include "llvm/Support/LEB128.h"<br>
@@ -64,6 +66,15 @@ SampleProfileWriter::write(con<wbr>st StringM<br>
return sampleprof_error::success;<br>
}<br>
<br>
+std::error_code SampleProfileWriterCompactBina<wbr>ry::write(<br>
+ const StringMap<FunctionSamples> &ProfileMap) {<br>
+ if (std::error_code EC = SampleProfileWriter::write(Pro<wbr>fileMap))<br>
+ return EC;<br>
+ if (std::error_code EC = writeFuncOffsetTable())<br>
+ return EC;<br>
+ return sampleprof_error::success;<br>
+}<br>
+<br>
/// Write samples to a text file.<br>
///<br>
/// Note: it may be tempting to implement this in terms of<br>
@@ -168,6 +179,30 @@ std::error_code SampleProfileWriterRawBi<br>
return sampleprof_error::success;<br>
}<br>
<br>
+std::error_code SampleProfileWriterCompactBina<wbr>ry::writeFuncOffsetTable() {<br>
+ auto &OS = *OutputStream;<br>
+<br>
+ // Fill the slot remembered by TableOffset with the offset of FuncOffsetTable.<br>
+ auto &OFS = static_cast<raw_fd_ostream &>(OS);<br>
+ uint64_t FuncOffsetTableStart = OS.tell();<br>
+ if (OFS.seek(TableOffset) == (uint64_t)-1)<br>
+ return sampleprof_error::ostream_seek<wbr>_unsupported;<br>
+ support::endian::Writer Writer(*OutputStream, support::little);<br>
+ Writer.write(FuncOffsetTableSt<wbr>art);<br>
+ if (OFS.seek(FuncOffsetTableStart<wbr>) == (uint64_t)-1)<br>
+ return sampleprof_error::ostream_seek<wbr>_unsupported;<br>
+<br>
+ // Write out the table size.<br>
+ encodeULEB128(FuncOffsetTable.<wbr>size(), OS);<br>
+<br>
+ // Write out FuncOffsetTable.<br>
+ for (auto entry : FuncOffsetTable) {<br>
+ writeNameIdx(entry.first);<br>
+ encodeULEB128(entry.second, OS);<br>
+ }<br>
+ return sampleprof_error::success;<br>
+}<br>
+<br>
std::error_code SampleProfileWriterCompactBina<wbr>ry::writeNameTable() {<br>
auto &OS = *OutputStream;<br>
std::set<StringRef> V;<br>
@@ -215,6 +250,19 @@ std::error_code SampleProfileWriterBinar<br>
return sampleprof_error::success;<br>
}<br>
<br>
+std::error_code SampleProfileWriterCompactBina<wbr>ry::writeHeader(<br>
+ const StringMap<FunctionSamples> &ProfileMap) {<br>
+ support::endian::Writer Writer(*OutputStream, support::little);<br>
+ if (auto EC = SampleProfileWriterBinary::wri<wbr>teHeader(ProfileMap))<br>
+ return EC;<br>
+<br>
+ // Reserve a slot for the offset of function offset table. The slot will<br>
+ // be populated with the offset of FuncOffsetTable later.<br>
+ TableOffset = OutputStream->tell();<br>
+ Writer.write(static_cast<uint6<wbr>4_t>(-2));<br>
+ return sampleprof_error::success;<br>
+}<br>
+<br>
std::error_code SampleProfileWriterBinary::wri<wbr>teSummary() {<br>
auto &OS = *OutputStream;<br>
encodeULEB128(Summary->getTot<wbr>alCount(), OS);<br>
@@ -282,6 +330,15 @@ std::error_code SampleProfileWriterBinar<br>
encodeULEB128(S.getHeadSample<wbr>s(), *OutputStream);<br>
return writeBody(S);<br>
}<br>
+<br>
+std::error_code<br>
+SampleProfileWriterCompactBin<wbr>ary::write(const FunctionSamples &S) {<br>
+ uint64_t Offset = OutputStream->tell();<br>
+ StringRef Name = S.getName();<br>
+ FuncOffsetTable[Name] = Offset;<br>
+ encodeULEB128(S.getHeadSamples<wbr>(), *OutputStream);<br>
+ return writeBody(S);<br>
+}<br>
<br>
/// Create a sample profile file writer based on the specified format.<br>
///<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/<wbr>SampleProfile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/IPO/SampleProfile.cpp?rev=<wbr>342283&r1=342282&r2=342283&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/IPO/<wbr>SampleProfile.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/<wbr>SampleProfile.cpp Fri Sep 14 13:52:59 2018<br>
@@ -1515,6 +1515,7 @@ bool SampleProfileLoader::doInitial<wbr>izati<br>
return false;<br>
}<br>
Reader = std::move(ReaderOrErr.get());<br>
+ Reader->collectFuncsToUse(M);<br>
ProfileIsValid = (Reader->read() == sampleprof_error::success);<br>
return true;<br>
}<br>
<br>
Modified: llvm/trunk/test/Transforms/Sam<wbr>pleProfile/Inputs/function_met<wbr>adata.compact.afdo<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/Inputs/function_metadata.compact.afdo?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Transfor<wbr>ms/SampleProfile/Inputs/<wbr>function_metadata.compact.<wbr>afdo?rev=342283&r1=342282&r2=<wbr>342283&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
Binary files - no diff available.<br>
<br>
Modified: llvm/trunk/test/Transforms/Sam<wbr>pleProfile/Inputs/indirect-cal<wbr>l.compact.afdo<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/Inputs/indirect-call.compact.afdo?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Transfor<wbr>ms/SampleProfile/Inputs/<wbr>indirect-call.compact.afdo?<wbr>rev=342283&r1=342282&r2=342283<wbr>&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
Binary files - no diff available.<br>
<br>
Modified: llvm/trunk/test/Transforms/Sam<wbr>pleProfile/Inputs/inline.compa<wbr>ctbinary.afdo<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/Inputs/inline.compactbinary.afdo?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Transfor<wbr>ms/SampleProfile/Inputs/<wbr>inline.compactbinary.afdo?rev=<wbr>342283&r1=342282&r2=342283&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
Binary files - no diff available.<br>
<br>
Modified: llvm/trunk/unittests/ProfileDa<wbr>ta/SampleProfTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/SampleProfTest.cpp?rev=342283&r1=342282&r2=342283&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/unittests/Pro<wbr>fileData/SampleProfTest.cpp?<wbr>rev=342283&r1=342282&r2=342283<wbr>&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/unittests/ProfileDa<wbr>ta/SampleProfTest.cpp (original)<br>
+++ llvm/trunk/unittests/ProfileDa<wbr>ta/SampleProfTest.cpp Fri Sep 14 13:52:59 2018<br>
@@ -36,14 +36,17 @@ static ::testing::AssertionResult NoErro<br>
namespace {<br>
<br>
struct SampleProfTest : ::testing::Test {<br>
- std::string Data;<br>
LLVMContext Context;<br>
+ std::string Profile;<br>
std::unique_ptr<raw_ostream> OS;<br>
std::unique_ptr<SampleProfile<wbr>Writer> Writer;<br>
std::unique_ptr<SampleProfile<wbr>Reader> Reader;<br>
+ std::error_code EC;<br>
<br>
SampleProfTest()<br>
- : Data(), OS(new raw_string_ostream(Data)), Writer(), Reader() {}<br>
+ : Profile("profile"),<br>
+ OS(new raw_fd_ostream(Profile, EC, sys::fs::F_None)), Writer(),<br>
+ Reader() {}<br>
<br>
void createWriter(SampleProfileForm<wbr>at Format) {<br>
auto WriterOrErr = SampleProfileWriter::create(OS<wbr>, Format);<br>
@@ -51,10 +54,11 @@ struct SampleProfTest : ::testing::Test<br>
Writer = std::move(WriterOrErr.get());<br>
}<br>
<br>
- void readProfile(std::unique_ptr<Me<wbr>moryBuffer> &Profile) {<br>
+ void readProfile(const Module &M) {<br>
auto ReaderOrErr = SampleProfileReader::create(Pr<wbr>ofile, Context);<br>
ASSERT_TRUE(NoError(ReaderOrE<wbr>rr.getError()));<br>
Reader = std::move(ReaderOrErr.get());<br>
+ Reader->collectFuncsToUse(M);<br>
}<br>
<br>
void testRoundTrip(SampleProfileFor<wbr>mat Format) {<br>
@@ -83,6 +87,12 @@ struct SampleProfTest : ::testing::Test<br>
BarSamples.addCalledTargetSam<wbr>ples(1, 0, MconstructName, 1000);<br>
BarSamples.addCalledTargetSam<wbr>ples(1, 0, StringviewName, 437);<br>
<br>
+ Module M("my_module", Context);<br>
+ FunctionType *fn_type =<br>
+ FunctionType::get(Type::getVoi<wbr>dTy(Context), {}, false);<br>
+ M.getOrInsertFunction(FooName, fn_type);<br>
+ M.getOrInsertFunction(BarName, fn_type);<br>
+<br>
StringMap<FunctionSamples> Profiles;<br>
Profiles[FooName] = std::move(FooSamples);<br>
Profiles[BarName] = std::move(BarSamples);<br>
@@ -93,8 +103,7 @@ struct SampleProfTest : ::testing::Test<br>
<br>
Writer->getOutputStream().flu<wbr>sh();<br>
<br>
- auto Profile = MemoryBuffer::getMemBufferCopy<wbr>(Data);<br>
- readProfile(Profile);<br>
+ readProfile(M);<br>
<br>
EC = Reader->read();<br>
ASSERT_TRUE(NoError(EC));<br>
@@ -164,7 +173,6 @@ struct SampleProfTest : ::testing::Test<br>
delete PS;<br>
<br>
// Test that summary can be attached to and read back from module.<br>
- Module M("my_module", Context);<br>
M.setProfileSummary(MD);<br>
MD = M.getProfileSummary();<br>
ASSERT_TRUE(MD);<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>