diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/ProfileData/InstrProfReader.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/ProfileData/InstrProfWriter.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp | 27 |
3 files changed, 57 insertions, 6 deletions
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp index f189713c77a..7968cf1f60d 100644 --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -109,8 +109,26 @@ bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) { [](char c) { return ::isprint(c) || ::isspace(c); }); } +// Read the profile variant flag from the header: ":FE" means this is a FE +// generated profile. ":IR" means this is an IR level profile. Other strings +// with a leading ':' will be reported an error format. std::error_code TextInstrProfReader::readHeader() { Symtab.reset(new InstrProfSymtab()); + bool IsIRInstr = false; + if (!Line->startswith(":")) { + IsIRLevelProfile = false; + return success(); + } + StringRef Str = (Line)->substr(1); + if (Str.equals_lower("ir")) + IsIRInstr = true; + else if (Str.equals_lower("fe")) + IsIRInstr = false; + else + return instrprof_error::bad_header; + + ++Line; + IsIRLevelProfile = IsIRInstr; return success(); } @@ -293,7 +311,8 @@ void RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { 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); @@ -470,10 +489,10 @@ data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, 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 != IndexedInstrProf::ProfVersion::Version1) { + if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) { if (D + sizeof(uint64_t) > End) return data_type(); CountsSize = endian::readNext<uint64_t, little, unaligned>(D); @@ -490,7 +509,7 @@ data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer)); // Read value profiling data. - if (FormatVersion > IndexedInstrProf::ProfVersion::Version2 && + if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 && !readValueProfilingData(D, End)) { DataBuffer.clear(); return data_type(); @@ -603,7 +622,8 @@ std::error_code IndexedInstrProfReader::readHeader() { // Read the version. uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version); - if (FormatVersion > IndexedInstrProf::ProfVersion::CurrentVersion) + if (GET_VERSION(FormatVersion) > + IndexedInstrProf::ProfVersion::CurrentVersion) return error(instrprof_error::unsupported_version); Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur); diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index a486d4eecb7..3e325718769 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -142,7 +142,7 @@ public: } InstrProfWriter::InstrProfWriter(bool Sparse) - : Sparse(Sparse), FunctionData(), + : Sparse(Sparse), FunctionData(), ProfileKind(PF_Unknown), InfoObj(new InstrProfRecordWriterTrait()) {} InstrProfWriter::~InstrProfWriter() { delete InfoObj; } @@ -230,6 +230,8 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) { IndexedInstrProf::Header Header; Header.Magic = IndexedInstrProf::Magic; Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion; + if (ProfileKind == PF_IRLevel) + Header.Version |= VARIANT_MASK_IR_PROF; Header.Unused = 0; Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType); Header.HashOffset = 0; @@ -336,6 +338,8 @@ void InstrProfWriter::writeRecordInText(const InstrProfRecord &Func, } void InstrProfWriter::writeText(raw_fd_ostream &OS) { + if (ProfileKind == PF_IRLevel) + OS << "# IR level Instrumentation Flag\n:ir\n"; InstrProfSymtab Symtab; for (const auto &I : FunctionData) if (shouldEncodeData(I.getValue())) diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp index f9e421df354..89e47774fdf 100644 --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -49,6 +49,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/Triple.h" #include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/CFG.h" @@ -713,7 +714,26 @@ void PGOUseFunc::setBranchWeights() { } } // 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 *IntTy64 = Type::getInt64Ty(M.getContext()); + uint64_t ProfileVersion = (INSTR_PROF_RAW_VERSION | VARIANT_MASK_IR_PROF); + auto IRLevelVersionVariable = + new GlobalVariable(M, IntTy64, true, GlobalVariable::ExternalLinkage, + Constant::getIntegerValue(IntTy64, APInt(64, ProfileVersion)), + INSTR_PROF_QUOTE(IR_LEVEL_PROF_VERSION_VAR)); + IRLevelVersionVariable->setVisibility(GlobalValue::DefaultVisibility); + Triple TT(M.getTargetTriple()); + if (TT.isOSBinFormatMachO()) + IRLevelVersionVariable->setLinkage(GlobalValue::LinkOnceODRLinkage); + else + IRLevelVersionVariable->setComdat( + M.getOrInsertComdat(StringRef(INSTR_PROF_QUOTE(IR_LEVEL_PROF_VERSION_VAR)))); +} + bool PGOInstrumentationGen::runOnModule(Module &M) { + createIRLevelProfileFlagVariable(M); for (auto &F : M) { if (F.isDeclaration()) continue; @@ -751,6 +771,13 @@ bool PGOInstrumentationUse::runOnModule(Module &M) { "Cannot get PGOReader")); return false; } + // TODO: might need to change the warning once the clang option is finalized. + if (!PGOReader->isIRLevelProfile()) { + Ctx.diagnose(DiagnosticInfoPGOProfile( + ProfileFileName.data(), "Not an IR level instrumentation profile")); + return false; + } + for (auto &F : M) { if (F.isDeclaration()) |