diff options
Diffstat (limited to 'llvm/lib/ProfileData')
-rw-r--r-- | llvm/lib/ProfileData/InstrProfIndexed.h | 2 | ||||
-rw-r--r-- | llvm/lib/ProfileData/InstrProfReader.cpp | 63 | ||||
-rw-r--r-- | llvm/lib/ProfileData/InstrProfWriter.cpp | 57 |
3 files changed, 82 insertions, 40 deletions
diff --git a/llvm/lib/ProfileData/InstrProfIndexed.h b/llvm/lib/ProfileData/InstrProfIndexed.h index 776170407bc..792863d0707 100644 --- a/llvm/lib/ProfileData/InstrProfIndexed.h +++ b/llvm/lib/ProfileData/InstrProfIndexed.h @@ -46,7 +46,7 @@ static inline uint64_t ComputeHash(HashT Type, StringRef K) { } const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81" -const uint64_t Version = 1; +const uint64_t Version = 2; const HashT HashType = HashT::MD5; } diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp index e8f64614df5..5c1993766aa 100644 --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -307,8 +307,8 @@ std::error_code IndexedInstrProfReader::readHeader() { return error(instrprof_error::bad_magic); // Read the version. - uint64_t Version = endian::readNext<uint64_t, little, unaligned>(Cur); - if (Version != IndexedInstrProf::Version) + FormatVersion = endian::readNext<uint64_t, little, unaligned>(Cur); + if (FormatVersion > IndexedInstrProf::Version) return error(instrprof_error::unsupported_version); // Read the maximal function count. @@ -331,18 +331,31 @@ std::error_code IndexedInstrProfReader::readHeader() { } std::error_code IndexedInstrProfReader::getFunctionCounts( - StringRef FuncName, uint64_t &FuncHash, std::vector<uint64_t> &Counts) { - const auto &Iter = Index->find(FuncName); + StringRef FuncName, uint64_t FuncHash, std::vector<uint64_t> &Counts) { + auto Iter = Index->find(FuncName); if (Iter == Index->end()) return error(instrprof_error::unknown_function); - // Found it. Make sure it's valid before giving back a result. - const InstrProfRecord &Record = *Iter; - if (Record.Name.empty()) - return error(instrprof_error::malformed); - FuncHash = Record.Hash; - Counts = Record.Counts; - return success(); + // Found it. Look for counters with the right hash. + ArrayRef<uint64_t> Data = (*Iter).Data; + uint64_t NumCounts; + for (uint64_t I = 0, E = Data.size(); I != E; I += NumCounts) { + // The function hash comes first. + uint64_t FoundHash = Data[I++]; + // In v1, we have at least one count. Later, we have the number of counts. + if (I == E) + return error(instrprof_error::malformed); + NumCounts = FormatVersion == 1 ? E - I : Data[I++]; + // If we have more counts than data, this is bogus. + if (I + NumCounts > E) + return error(instrprof_error::malformed); + // Check for a match and fill the vector if there is one. + if (FoundHash == FuncHash) { + Counts = Data.slice(I, NumCounts); + return success(); + } + } + return error(instrprof_error::hash_mismatch); } std::error_code @@ -351,10 +364,30 @@ IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) { if (RecordIterator == Index->data_end()) return error(instrprof_error::eof); - // Read the next one. - Record = *RecordIterator; - ++RecordIterator; - if (Record.Name.empty()) + // Record the current function name. + Record.Name = (*RecordIterator).Name; + + ArrayRef<uint64_t> Data = (*RecordIterator).Data; + // Valid data starts with a hash and either a count or the number of counts. + if (CurrentOffset + 1 > Data.size()) + return error(instrprof_error::malformed); + // First we have a function hash. + Record.Hash = Data[CurrentOffset++]; + // In version 1 we knew the number of counters implicitly, but in newer + // versions we store the number of counters next. + uint64_t NumCounts = + FormatVersion == 1 ? Data.size() - CurrentOffset : Data[CurrentOffset++]; + if (CurrentOffset + NumCounts > Data.size()) return error(instrprof_error::malformed); + // And finally the counts themselves. + Record.Counts = Data.slice(CurrentOffset, NumCounts); + + // If we've exhausted this function's data, increment the record. + CurrentOffset += NumCounts; + if (CurrentOffset == Data.size()) { + ++RecordIterator; + CurrentOffset = 0; + } + return success(); } diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index e55c2991813..1c4a4fede28 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -45,7 +45,9 @@ public: offset_type N = K.size(); LE.write<offset_type>(N); - offset_type M = (1 + V->Counts.size()) * sizeof(uint64_t); + offset_type M = 0; + for (const auto &Counts : *V) + M += (2 + Counts.second.size()) * sizeof(uint64_t); LE.write<offset_type>(M); return std::make_pair(N, M); @@ -59,9 +61,13 @@ public: offset_type) { using namespace llvm::support; endian::Writer<little> LE(Out); - LE.write<uint64_t>(V->Hash); - for (uint64_t I : V->Counts) - LE.write<uint64_t>(I); + + for (const auto &Counts : *V) { + LE.write<uint64_t>(Counts.first); + LE.write<uint64_t>(Counts.second.size()); + for (uint64_t I : Counts.second) + LE.write<uint64_t>(I); + } } }; } @@ -70,41 +76,44 @@ std::error_code InstrProfWriter::addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, ArrayRef<uint64_t> Counters) { - auto Where = FunctionData.find(FunctionName); - if (Where == FunctionData.end()) { - // If this is the first time we've seen this function, just add it. - auto &Data = FunctionData[FunctionName]; - Data.Hash = FunctionHash; - Data.Counts = Counters; + auto &CounterData = FunctionData[FunctionName]; + + auto Where = CounterData.find(FunctionHash); + if (Where == CounterData.end()) { + // We've never seen a function with this name and hash, add it. + CounterData[FunctionHash] = Counters; + // We keep track of the max function count as we go for simplicity. + if (Counters[0] > MaxFunctionCount) + MaxFunctionCount = Counters[0]; return instrprof_error::success; } - auto &Data = Where->getValue(); - // We can only add to existing functions if they match, so we check the hash - // and number of counters. - if (Data.Hash != FunctionHash) - return instrprof_error::hash_mismatch; - if (Data.Counts.size() != Counters.size()) + // We're updating a function we've seen before. + auto &FoundCounters = Where->second; + // If the number of counters doesn't match we either have bad data or a hash + // collision. + if (FoundCounters.size() != Counters.size()) return instrprof_error::count_mismatch; - // These match, add up the counters. + for (size_t I = 0, E = Counters.size(); I < E; ++I) { - if (Data.Counts[I] + Counters[I] < Data.Counts[I]) + if (FoundCounters[I] + Counters[I] < FoundCounters[I]) return instrprof_error::counter_overflow; - Data.Counts[I] += Counters[I]; + FoundCounters[I] += Counters[I]; } + // We keep track of the max function count as we go for simplicity. + if (FoundCounters[0] > MaxFunctionCount) + MaxFunctionCount = FoundCounters[0]; + return instrprof_error::success; } void InstrProfWriter::write(raw_fd_ostream &OS) { OnDiskChainedHashTableGenerator<InstrProfRecordTrait> Generator; - uint64_t MaxFunctionCount = 0; // Populate the hash table generator. - for (const auto &I : FunctionData) { + std::vector<uint64_t> CounterBuffer; + for (const auto &I : FunctionData) Generator.insert(I.getKey(), &I.getValue()); - if (I.getValue().Counts[0] > MaxFunctionCount) - MaxFunctionCount = I.getValue().Counts[0]; - } using namespace llvm::support; endian::Writer<little> LE(OS); |