[PATCH] D15540: [PGO] differentiate FE instrumentation and IR level instrumentation profiles
Xinliang David Li via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 8 12:59:37 PST 2016
On Fri, Jan 8, 2016 at 11:25 AM, Justin Bogner <mail at justinbogner.com> wrote:
> Rong Xu <xur at google.com> writes:
>> This patch uses one bit in profile version to differentiate FE
>> instrumentation and IR level instrumentation profiles. It is based on
>> the suggestion in RFC: PGO Late instrumentation for LLVM
>> (http://lists.llvm.org/pipermail/llvm-dev/2015-August/089058.html)
>>
>> PGOInstrumenation now checks this bit to make sure it's IR level
>> instrumentation profiles. PGOInstrumenation also creates a new COMDAT
>> variable __llvm_profile_ir_level and sets the value to 1. This
>> variable tells the profile runtime to set the right version in the
>> generated profiles.
>
> So this more or less makes sense as a way to emit better error messages
> when clang is invoked with the wrong kind of profile for the provided
> flags, but...
>
>> llvm-profdata also handles the profiles differently: mainly for the
>> MaxFunctionCount. For FE profile, it only needs to find the max of the
>> entry count (the first count in the function). For IR level profile,
>> the entry count might not be available, we will set it as the maximum
>> block count in the profile.
>
> I'm not sure about this at all. I have a couple of issues here:
>
> - This conflates "isIRLevel" and "firstCountIsFunctionEntry". These seem
> like orthogonal issues to me, and might deserve separate bits.
>
> - Calling the maximum block count "MaxFunctionCount" makes no sense
> whatsoever. The maximum block count is almost certainly in a loop and
> is very unlikely to be any function's count. Is the max block count
> actually useful to the ir-level instrumentation?
I think these issues will become moot once the program profile summary
information is available (see Easwaran's RFC) -- the maxFunctionCount
and maxBBCount will be a subset of the program summary so existing
field will become obsolete.
>
> Also, I'm really not a fan of the ":1" indicators in the textual
> format. Since that's a human readable/writeable format, we should
> probably print flags in a human readable way.
>
Nathan has a similar suggestion.
David
> Rong Xu <xur at google.com> writes:
>> xur updated this revision to Diff 43393.
>> xur marked an inline comment as done.
>> xur added a comment.
>>
>> Integrated the latest review comments from David and Nathan.
>>
>> Thanks!
>>
>> -Rong
>>
>>
>> http://reviews.llvm.org/D15540
>>
>> Files:
>> include/llvm/ProfileData/InstrProfData.inc
>> include/llvm/ProfileData/InstrProfReader.h
>> include/llvm/ProfileData/InstrProfWriter.h
>> lib/ProfileData/InstrProfReader.cpp
>> lib/ProfileData/InstrProfWriter.cpp
>> lib/Transforms/Instrumentation/PGOInstrumentation.cpp
>> test/Transforms/PGOProfile/Inputs/branch1.proftext
>> test/Transforms/PGOProfile/Inputs/branch2.proftext
>> test/Transforms/PGOProfile/Inputs/criticaledge.proftext
>> test/Transforms/PGOProfile/Inputs/diag.proftext
>> test/Transforms/PGOProfile/Inputs/diag_FE.proftext
>> test/Transforms/PGOProfile/Inputs/landingpad.proftext
>> test/Transforms/PGOProfile/Inputs/loop1.proftext
>> test/Transforms/PGOProfile/Inputs/loop2.proftext
>> test/Transforms/PGOProfile/Inputs/switch.proftext
>> test/Transforms/PGOProfile/branch1.ll
>> test/Transforms/PGOProfile/branch2.ll
>> test/Transforms/PGOProfile/criticaledge.ll
>> test/Transforms/PGOProfile/diag_FE_profile.ll
>> test/Transforms/PGOProfile/landingpad.ll
>> test/Transforms/PGOProfile/loop1.ll
>> test/Transforms/PGOProfile/loop2.ll
>> test/Transforms/PGOProfile/single_bb.ll
>> test/Transforms/PGOProfile/switch.ll
>> tools/llvm-profdata/llvm-profdata.cpp
>>
>>
>> Index: tools/llvm-profdata/llvm-profdata.cpp
>> ===================================================================
>> --- tools/llvm-profdata/llvm-profdata.cpp
>> +++ tools/llvm-profdata/llvm-profdata.cpp
>> @@ -127,6 +127,10 @@
>> exitWithErrorCode(ec, Input.Filename);
>>
>> auto Reader = std::move(ReaderOrErr.get());
>> + bool IsIRProfile = Reader->isIRLevelProfile();
>> + if (Writer.setIsIRLevelProfile(IsIRProfile))
>> + exitWithError("Merge IR generated profile with Clang generated profile.");
>> +
>> for (auto &I : *Reader) {
>> if (std::error_code EC = Writer.addRecord(std::move(I), Input.Weight)) {
>> // Only show hint the first time an error occurs.
>> @@ -257,6 +261,7 @@
>> exitWithErrorCode(EC, Filename);
>>
>> auto Reader = std::move(ReaderOrErr.get());
>> + bool IsIRInstr = Reader->isIRLevelProfile();
>> uint64_t MaxFunctionCount = 0, MaxBlockCount = 0;
>> size_t ShownFunctions = 0, TotalFunctions = 0;
>> for (const auto &Func : *Reader) {
>> @@ -273,8 +278,10 @@
>>
>> ++TotalFunctions;
>> assert(Func.Counts.size() > 0 && "function missing entry counter");
>> - if (Func.Counts[0] > MaxFunctionCount)
>> - MaxFunctionCount = Func.Counts[0];
>> + if (!IsIRInstr) {
>> + if (Func.Counts[0] > MaxFunctionCount)
>> + MaxFunctionCount = Func.Counts[0];
>> + }
>>
>> for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
>> if (Func.Counts[I] > MaxBlockCount)
>> @@ -290,17 +297,19 @@
>>
>> OS << " " << Func.Name << ":\n"
>> << " Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
>> - << " Counters: " << Func.Counts.size() << "\n"
>> - << " Function count: " << Func.Counts[0] << "\n";
>> + << " Counters: " << Func.Counts.size() << "\n";
>> + if (!IsIRInstr)
>> + OS << " Function count: " << Func.Counts[0] << "\n";
>>
>> if (ShowIndirectCallTargets)
>> OS << " Indirect Call Site Count: "
>> << Func.getNumValueSites(IPVK_IndirectCallTarget) << "\n";
>>
>> if (ShowCounts) {
>> OS << " Block counts: [";
>> - for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
>> - OS << (I == 1 ? "" : ", ") << Func.Counts[I];
>> + size_t Start = (IsIRInstr ? 0 : 1);
>> + for (size_t I = Start, E = Func.Counts.size(); I < E; ++I) {
>> + OS << (I == Start ? "" : ", ") << Func.Counts[I];
>> }
>> OS << "]\n";
>> }
>> @@ -330,8 +339,12 @@
>> if (ShowAllFunctions || !ShowFunction.empty())
>> OS << "Functions shown: " << ShownFunctions << "\n";
>> OS << "Total functions: " << TotalFunctions << "\n";
>> - OS << "Maximum function count: " << MaxFunctionCount << "\n";
>> - OS << "Maximum internal block count: " << MaxBlockCount << "\n";
>> + if (!IsIRInstr) {
>> + OS << "Maximum function count: " << MaxFunctionCount << "\n";
>> + OS << "Maximum internal block count: " << MaxBlockCount << "\n";
>> + } else {
>> + OS << "Maximum count: " << MaxBlockCount << "\n";
>> + }
>> return 0;
>> }
>>
>> Index: test/Transforms/PGOProfile/switch.ll
>> ===================================================================
>> --- test/Transforms/PGOProfile/switch.ll
>> +++ test/Transforms/PGOProfile/switch.ll
>> @@ -4,6 +4,8 @@
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> +; GEN: $__llvm_profile_ir_level = comdat any
>> +; GEN: @__llvm_profile_ir_level = constant i32 1, comdat
>> ; GEN: @__profn_test_switch = private constant [11 x i8] c"test_switch"
>>
>> define void @test_switch(i32 %i) {
>> Index: test/Transforms/PGOProfile/single_bb.ll
>> ===================================================================
>> --- test/Transforms/PGOProfile/single_bb.ll
>> +++ test/Transforms/PGOProfile/single_bb.ll
>> @@ -2,6 +2,8 @@
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> +; GEN: $__llvm_profile_ir_level = comdat any
>> +; GEN: @__llvm_profile_ir_level = constant i32 1, comdat
>> ; GEN: @__profn_single_bb = private constant [9 x i8] c"single_bb"
>>
>> define i32 @single_bb() {
>> Index: test/Transforms/PGOProfile/loop2.ll
>> ===================================================================
>> --- test/Transforms/PGOProfile/loop2.ll
>> +++ test/Transforms/PGOProfile/loop2.ll
>> @@ -4,6 +4,8 @@
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> +; GEN: $__llvm_profile_ir_level = comdat any
>> +; GEN: @__llvm_profile_ir_level = constant i32 1, comdat
>> ; GEN: @__profn_test_nested_for = private constant [15 x i8] c"test_nested_for"
>>
>> define i32 @test_nested_for(i32 %r, i32 %s) {
>> Index: test/Transforms/PGOProfile/loop1.ll
>> ===================================================================
>> --- test/Transforms/PGOProfile/loop1.ll
>> +++ test/Transforms/PGOProfile/loop1.ll
>> @@ -4,6 +4,8 @@
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> +; GEN: $__llvm_profile_ir_level = comdat any
>> +; GEN: @__llvm_profile_ir_level = constant i32 1, comdat
>> ; GEN: @__profn_test_simple_for = private constant [15 x i8] c"test_simple_for"
>>
>> define i32 @test_simple_for(i32 %n) {
>> Index: test/Transforms/PGOProfile/landingpad.ll
>> ===================================================================
>> --- test/Transforms/PGOProfile/landingpad.ll
>> +++ test/Transforms/PGOProfile/landingpad.ll
>> @@ -6,6 +6,8 @@
>>
>> @val = global i32 0, align 4
>> @_ZTIi = external constant i8*
>> +; GEN: $__llvm_profile_ir_level = comdat any
>> +; GEN: @__llvm_profile_ir_level = constant i32 1, comdat
>> ; GEN: @__profn_bar = private constant [3 x i8] c"bar"
>> ; GEN: @__profn_foo = private constant [3 x i8] c"foo"
>>
>> Index: test/Transforms/PGOProfile/diag_FE_profile.ll
>> ===================================================================
>> --- /dev/null
>> +++ test/Transforms/PGOProfile/diag_FE_profile.ll
>> @@ -0,0 +1,12 @@
>> +; RUN: llvm-profdata merge %S/Inputs/diag_FE.proftext -o %t.profdata
>> +; RUN: not opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s
>> +
>> +; CHECK: Not an IR level instrumentation profile
>> +
>> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> +target triple = "x86_64-unknown-linux-gnu"
>> +
>> +define i32 @foo() {
>> +entry:
>> + ret i32 0
>> +}
>> Index: test/Transforms/PGOProfile/criticaledge.ll
>> ===================================================================
>> --- test/Transforms/PGOProfile/criticaledge.ll
>> +++ test/Transforms/PGOProfile/criticaledge.ll
>> @@ -4,6 +4,8 @@
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> +; GEN: $__llvm_profile_ir_level = comdat any
>> +; GEN: @__llvm_profile_ir_level = constant i32 1, comdat
>> ; GEN: @__profn_test_criticalEdge = private constant [17 x i8] c"test_criticalEdge"
>> ; GEN: @__profn__stdin__bar = private constant [11 x i8] c"<stdin>:bar"
>>
>> Index: test/Transforms/PGOProfile/branch2.ll
>> ===================================================================
>> --- test/Transforms/PGOProfile/branch2.ll
>> +++ test/Transforms/PGOProfile/branch2.ll
>> @@ -4,6 +4,8 @@
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> +; GEN: $__llvm_profile_ir_level = comdat any
>> +; GEN: @__llvm_profile_ir_level = constant i32 1, comdat
>> ; GEN: @__profn_test_br_2 = private constant [9 x i8] c"test_br_2"
>>
>> define i32 @test_br_2(i32 %i) {
>> Index: test/Transforms/PGOProfile/branch1.ll
>> ===================================================================
>> --- test/Transforms/PGOProfile/branch1.ll
>> +++ test/Transforms/PGOProfile/branch1.ll
>> @@ -4,6 +4,8 @@
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> +; GEN: $__llvm_profile_ir_level = comdat any
>> +; GEN: @__llvm_profile_ir_level = constant i32 1, comdat
>> ; GEN: @__profn_test_br_1 = private constant [9 x i8] c"test_br_1"
>>
>> define i32 @test_br_1(i32 %i) {
>> Index: test/Transforms/PGOProfile/Inputs/switch.proftext
>> ===================================================================
>> --- test/Transforms/PGOProfile/Inputs/switch.proftext
>> +++ test/Transforms/PGOProfile/Inputs/switch.proftext
>> @@ -1,3 +1,5 @@
>> +# :1 is the flag to indicate this is IR level profile.
>> +:1
>> test_switch
>> 46200943743
>> 4
>> Index: test/Transforms/PGOProfile/Inputs/loop2.proftext
>> ===================================================================
>> --- test/Transforms/PGOProfile/Inputs/loop2.proftext
>> +++ test/Transforms/PGOProfile/Inputs/loop2.proftext
>> @@ -1,3 +1,5 @@
>> +# :1 is the flag to indicate this is IR level profile.
>> +:1
>> test_nested_for
>> 53929068288
>> 3
>> Index: test/Transforms/PGOProfile/Inputs/loop1.proftext
>> ===================================================================
>> --- test/Transforms/PGOProfile/Inputs/loop1.proftext
>> +++ test/Transforms/PGOProfile/Inputs/loop1.proftext
>> @@ -1,3 +1,5 @@
>> +# :1 is the flag to indicate this is IR level profile.
>> +:1
>> test_simple_for
>> 34137660316
>> 2
>> Index: test/Transforms/PGOProfile/Inputs/landingpad.proftext
>> ===================================================================
>> --- test/Transforms/PGOProfile/Inputs/landingpad.proftext
>> +++ test/Transforms/PGOProfile/Inputs/landingpad.proftext
>> @@ -1,3 +1,5 @@
>> +# :1 is the flag to indicate this is IR level profile.
>> +:1
>> foo
>> 59130013419
>> 4
>> Index: test/Transforms/PGOProfile/Inputs/diag_FE.proftext
>> ===================================================================
>> --- /dev/null
>> +++ test/Transforms/PGOProfile/Inputs/diag_FE.proftext
>> @@ -0,0 +1,5 @@
>> +foo
>> +12884999999
>> +1
>> +1
>> +
>> Index: test/Transforms/PGOProfile/Inputs/diag.proftext
>> ===================================================================
>> --- test/Transforms/PGOProfile/Inputs/diag.proftext
>> +++ test/Transforms/PGOProfile/Inputs/diag.proftext
>> @@ -1,3 +1,5 @@
>> +# :1 is the flag to indicate this is IR level profile.
>> +:1
>> foo
>> 12884999999
>> 1
>> Index: test/Transforms/PGOProfile/Inputs/criticaledge.proftext
>> ===================================================================
>> --- test/Transforms/PGOProfile/Inputs/criticaledge.proftext
>> +++ test/Transforms/PGOProfile/Inputs/criticaledge.proftext
>> @@ -1,3 +1,5 @@
>> +# :1 is the flag to indicate this is IR level profile.
>> +:1
>> test_criticalEdge
>> 82323253069
>> 8
>> Index: test/Transforms/PGOProfile/Inputs/branch2.proftext
>> ===================================================================
>> --- test/Transforms/PGOProfile/Inputs/branch2.proftext
>> +++ test/Transforms/PGOProfile/Inputs/branch2.proftext
>> @@ -1,3 +1,5 @@
>> +# :1 is the flag to indicate this is IR level profile.
>> +:1
>> test_br_2
>> 29667547796
>> 2
>> Index: test/Transforms/PGOProfile/Inputs/branch1.proftext
>> ===================================================================
>> --- test/Transforms/PGOProfile/Inputs/branch1.proftext
>> +++ test/Transforms/PGOProfile/Inputs/branch1.proftext
>> @@ -1,3 +1,5 @@
>> +# :1 is the flag to indicate this is IR level profile.
>> +:1
>> test_br_1
>> 25571299074
>> 2
>> Index: lib/Transforms/Instrumentation/PGOInstrumentation.cpp
>> ===================================================================
>> --- lib/Transforms/Instrumentation/PGOInstrumentation.cpp
>> +++ lib/Transforms/Instrumentation/PGOInstrumentation.cpp
>> @@ -665,7 +665,21 @@
>> }
>> } // end anonymous namespace
>>
>> +// Create a COMDAT variable IR_LEVEL_PROF_VARNAME to make the runtime
>> +// aware this is an ir_level profile so it can set the version flag.
>> +static void createIRLevelProfileFlagVariable(Module &M) {
>> + Type *IntTy32 = Type::getInt32Ty(M.getContext());
>> + auto IRLevelFlagVariable =
>> + new GlobalVariable(M, IntTy32, true, GlobalVariable::ExternalLinkage,
>> + Constant::getIntegerValue(IntTy32, APInt(32, 1)),
>> + INSTR_PROF_QUOTE(IR_LEVEL_PROF_VARNAME));
>> + IRLevelFlagVariable->setVisibility(GlobalValue::DefaultVisibility);
>> + IRLevelFlagVariable->setComdat(
>> + M.getOrInsertComdat(StringRef(INSTR_PROF_QUOTE(IR_LEVEL_PROF_VARNAME))));
>> +}
>> +
>> bool PGOInstrumentationGen::runOnModule(Module &M) {
>> + createIRLevelProfileFlagVariable(M);
>> for (auto &F : M) {
>> if (F.isDeclaration())
>> continue;
>> @@ -703,6 +717,12 @@
>> "Cannot get PGOReader"));
>> return false;
>> }
>> + if (!PGOReader->isIRLevelProfile()) {
>> + Ctx.diagnose(DiagnosticInfoPGOProfile(
>> + ProfileFileName.data(), "Not an IR level instrumentation profile"));
>> + return false;
>> + }
>> +
>>
>> for (auto &F : M) {
>> if (F.isDeclaration())
>> Index: lib/ProfileData/InstrProfWriter.cpp
>> ===================================================================
>> --- lib/ProfileData/InstrProfWriter.cpp
>> +++ lib/ProfileData/InstrProfWriter.cpp
>> @@ -130,8 +130,14 @@
>>
>> // We keep track of the max function count as we go for simplicity.
>> // Update this statistic no matter the result of the merge.
>> - if (Dest.Counts[0] > MaxFunctionCount)
>> - MaxFunctionCount = Dest.Counts[0];
>> + if (ProfileKind != PF_IRLevel) {
>> + if (Dest.Counts[0] > MaxFunctionCount)
>> + MaxFunctionCount = Dest.Counts[0];
>> + } else {
>> + for (auto &IT : Dest.Counts)
>> + if (IT > MaxFunctionCount)
>> + MaxFunctionCount = IT;
>> + }
>>
>> return Result;
>> }
>> @@ -149,7 +155,10 @@
>> // Write the header.
>> IndexedInstrProf::Header Header;
>> Header.Magic = IndexedInstrProf::Magic;
>> - Header.Version = IndexedInstrProf::Version;
>> + if (ProfileKind == PF_IRLevel)
>> + Header.Version = IndexedInstrProf::Version | VARIANT_MASK_IR_PROF;
>> + else
>> + Header.Version = IndexedInstrProf::Version;
>> Header.MaxFunctionCount = MaxFunctionCount;
>> Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
>> Header.HashOffset = 0;
>> @@ -227,6 +236,8 @@
>> }
>>
>> void InstrProfWriter::writeText(raw_fd_ostream &OS) {
>> + if (ProfileKind == PF_IRLevel)
>> + OS << "# IR level Instrumentation Flag:\n:" << 1 << "\n";
>> for (const auto &I : FunctionData)
>> for (const auto &Func : I.getValue())
>> writeRecordInText(Func.second, OS);
>> Index: lib/ProfileData/InstrProfReader.cpp
>> ===================================================================
>> --- lib/ProfileData/InstrProfReader.cpp
>> +++ lib/ProfileData/InstrProfReader.cpp
>> @@ -109,6 +109,32 @@
>> [](char c) { return ::isprint(c) || ::isspace(c); });
>> }
>>
>> +// Read the profile variant flag from the header: ":0" means this is a FE
>> +// generated profile. ":1" means this is an IR level profile. Other strings
>> +// with a leading ':' will be reported an error format.
>> +std::error_code TextInstrProfReader::readHeader() {
>> + bool IsIRInstr = false;
>> + if (!Line->startswith(":")) {
>> + IsIRLevelProfile = false;
>> + return success();
>> + }
>> + StringRef Str = (Line)->substr(1);
>> + int32_t V = 0;
>> + if (Str.getAsInteger(0, V))
>> + return instrprof_error::bad_header;
>> +
>> + if (V == 1)
>> + IsIRInstr = true;
>> + else if (V == 0)
>> + IsIRInstr = false;
>> + else
>> + return instrprof_error::bad_header;
>> +
>> + ++Line;
>> + IsIRLevelProfile = IsIRInstr;
>> + return success();
>> +}
>> +
>> std::error_code
>> TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
>>
>> @@ -268,7 +294,8 @@
>> template <class IntPtrT>
>> std::error_code RawInstrProfReader<IntPtrT>::readHeader(
>> const RawInstrProf::Header &Header) {
>> - if (swap(Header.Version) != RawInstrProf::Version)
>> + Version = swap(Header.Version);
>> + if (GET_VERSION(Version) != RawInstrProf::Version)
>> return error(instrprof_error::unsupported_version);
>>
>> CountersDelta = swap(Header.CountersDelta);
>> @@ -460,10 +487,10 @@
>> return data_type();
>> uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
>>
>> - // Initialize number of counters for FormatVersion == 1.
>> + // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
>> uint64_t CountsSize = N / sizeof(uint64_t) - 1;
>> // If format version is different then read the number of counters.
>> - if (FormatVersion != 1) {
>> + if (GET_VERSION(FormatVersion) != 1) {
>> if (D + sizeof(uint64_t) > End)
>> return data_type();
>> CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
>> @@ -480,7 +507,7 @@
>> DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
>>
>> // Read value profiling data.
>> - if (FormatVersion > 2 && !readValueProfilingData(D, End)) {
>> + if (GET_VERSION(FormatVersion) > 2 && !readValueProfilingData(D, End)) {
>> DataBuffer.clear();
>> return data_type();
>> }
>> @@ -567,7 +594,7 @@
>>
>> // Read the version.
>> uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version);
>> - if (FormatVersion > IndexedInstrProf::Version)
>> + if (GET_VERSION(FormatVersion) > IndexedInstrProf::Version)
>> return error(instrprof_error::unsupported_version);
>>
>> // Read the maximal function count.
>> Index: include/llvm/ProfileData/InstrProfWriter.h
>> ===================================================================
>> --- include/llvm/ProfileData/InstrProfWriter.h
>> +++ include/llvm/ProfileData/InstrProfWriter.h
>> @@ -27,13 +27,15 @@
>> class InstrProfWriter {
>> public:
>> typedef SmallDenseMap<uint64_t, InstrProfRecord, 1> ProfilingData;
>> + enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
>>
>> private:
>> InstrProfStringTable StringTable;
>> StringMap<ProfilingData> FunctionData;
>> uint64_t MaxFunctionCount;
>> + ProfKind ProfileKind;
>> public:
>> - InstrProfWriter() : MaxFunctionCount(0) {}
>> + InstrProfWriter() : MaxFunctionCount(0), ProfileKind(PF_Unknown) {}
>>
>> /// Update string entries in profile data with references to StringTable.
>> void updateStringTableReferences(InstrProfRecord &I);
>> @@ -51,6 +53,16 @@
>> /// Write the profile, returning the raw data. For testing.
>> std::unique_ptr<MemoryBuffer> writeBuffer();
>>
>> + /// Set the ProfileKind. Report error if mixing FE and IR level profiles.
>> + std::error_code setIsIRLevelProfile(bool IsIRLevel) {
>> + if (ProfileKind == PF_Unknown) {
>> + ProfileKind = IsIRLevel ? PF_IRLevel: PF_FE;
>> + return instrprof_error::success;
>> + }
>> + return (IsIRLevel == (ProfileKind == PF_IRLevel)) ?
>> + instrprof_error::success : instrprof_error::unsupported_version;
>> + }
>> +
>> // Internal interface for testing purpose only.
>> void setValueProfDataEndianness(support::endianness Endianness);
>>
>> Index: include/llvm/ProfileData/InstrProfReader.h
>> ===================================================================
>> --- include/llvm/ProfileData/InstrProfReader.h
>> +++ include/llvm/ProfileData/InstrProfReader.h
>> @@ -64,6 +64,7 @@
>> /// Iterator over profile data.
>> InstrProfIterator begin() { return InstrProfIterator(this); }
>> InstrProfIterator end() { return InstrProfIterator(); }
>> + virtual bool isIRLevelProfile() const = 0;
>>
>> protected:
>> /// Set the current std::error_code and return same.
>> @@ -105,6 +106,7 @@
>> std::unique_ptr<MemoryBuffer> DataBuffer;
>> /// Iterator over the profile data.
>> line_iterator Line;
>> + bool IsIRLevelProfile;
>>
>> // String table for holding a unique copy of all the strings in the profile.
>> InstrProfStringTable StringTable;
>> @@ -115,13 +117,16 @@
>>
>> public:
>> TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
>> - : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
>> + : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'),
>> + IsIRLevelProfile(false) {}
>>
>> /// Return true if the given buffer is in text instrprof format.
>> static bool hasFormat(const MemoryBuffer &Buffer);
>>
>> + bool isIRLevelProfile() const override { return IsIRLevelProfile; };
>> +
>> /// Read the header.
>> - std::error_code readHeader() override { return success(); }
>> + std::error_code readHeader() override;
>> /// Read a single record.
>> std::error_code readNextRecord(InstrProfRecord &Record) override;
>> };
>> @@ -139,6 +144,8 @@
>> /// The profile data file contents.
>> std::unique_ptr<MemoryBuffer> DataBuffer;
>> bool ShouldSwapBytes;
>> + // Version of the raw profile. It contains the variant profile information.
>> + uint64_t Version;
>> uint64_t CountersDelta;
>> uint64_t NamesDelta;
>> const RawInstrProf::ProfileData<IntPtrT> *Data;
>> @@ -163,6 +170,9 @@
>> static bool hasFormat(const MemoryBuffer &DataBuffer);
>> std::error_code readHeader() override;
>> std::error_code readNextRecord(InstrProfRecord &Record) override;
>> + bool isIRLevelProfile() const override {
>> + return (Version & VARIANT_MASK_IR_PROF) != 0;
>> + }
>>
>> private:
>> std::error_code readNextHeader(const char *CurrentPos);
>> @@ -277,6 +287,7 @@
>> virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
>> virtual ~InstrProfReaderIndexBase() {}
>> virtual uint64_t getVersion() const = 0;
>> + virtual bool isIRLevelProfile() const = 0;
>> };
>>
>> typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait>
>> @@ -310,7 +321,10 @@
>> HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
>> }
>> ~InstrProfReaderIndex() override {}
>> - uint64_t getVersion() const override { return FormatVersion; }
>> + uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
>> + bool isIRLevelProfile() const override {
>> + return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
>> + }
>> };
>>
>> /// Reader for the indexed binary instrprof format.
>> @@ -327,7 +341,9 @@
>> IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
>>
>> public:
>> + /// Return the profile version.
>> uint64_t getVersion() const { return Index->getVersion(); }
>> + bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
>> IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
>> : DataBuffer(std::move(DataBuffer)), Index(nullptr) {}
>>
>> Index: include/llvm/ProfileData/InstrProfData.inc
>> ===================================================================
>> --- include/llvm/ProfileData/InstrProfData.inc
>> +++ include/llvm/ProfileData/InstrProfData.inc
>> @@ -678,6 +678,16 @@
>> /* Raw profile format version. */
>> #define INSTR_PROF_RAW_VERSION 2
>>
>> +/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
>> + * version for other variants of profile. We set the lowest bit of the upper 8
>> + * bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentaiton
>> + * generated profile, and 0 if this is a Clang FE generated profile.
>> + */
>> +#define VARIANT_MASKS_ALL 0xff00000000000000ULL
>> +#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
>> +#define GET_VERSION(V) ((V)&~VARIANT_MASKS_ALL)
>> +#define IR_LEVEL_PROF_VARNAME __llvm_profile_ir_level
>> +
>> /* Runtime section names and name strings. */
>> #define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data
>> #define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names
More information about the llvm-commits
mailing list