[PATCH] D15540: [PGO] differentiate FE instrumentation and IR level instrumentation profiles
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 8 11:25:36 PST 2016
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?
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.
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