X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FProfileData%2FInstrProfWriter.cpp;h=1c4a4fede2868f1fc655b6cf57528bb81e590bfa;hb=12af22e8cc217827cf4f118b0f5e4ebbda9925ae;hp=3024f9676e329883c8c5f841ef98caadd1079a71;hpb=c61e1f53d97e35b9f75dabb7099f35eabffcce5b;p=oota-llvm.git diff --git a/lib/ProfileData/InstrProfWriter.cpp b/lib/ProfileData/InstrProfWriter.cpp index 3024f9676e3..1c4a4fede28 100644 --- a/lib/ProfileData/InstrProfWriter.cpp +++ b/lib/ProfileData/InstrProfWriter.cpp @@ -13,48 +13,124 @@ //===----------------------------------------------------------------------===// #include "llvm/ProfileData/InstrProfWriter.h" -#include "llvm/Support/Endian.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/OnDiskHashTable.h" + +#include "InstrProfIndexed.h" using namespace llvm; -error_code InstrProfWriter::addFunctionCounts(StringRef FunctionName, - uint64_t FunctionHash, - ArrayRef 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; - return instrprof_error::success;; +namespace { +class InstrProfRecordTrait { +public: + typedef StringRef key_type; + typedef StringRef key_type_ref; + + typedef const InstrProfWriter::CounterData *const data_type; + typedef const InstrProfWriter::CounterData *const data_type_ref; + + typedef uint64_t hash_value_type; + typedef uint64_t offset_type; + + static hash_value_type ComputeHash(key_type_ref K) { + return IndexedInstrProf::ComputeHash(IndexedInstrProf::HashType, K); + } + + static std::pair + EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V) { + using namespace llvm::support; + endian::Writer LE(Out); + + offset_type N = K.size(); + LE.write(N); + + offset_type M = 0; + for (const auto &Counts : *V) + M += (2 + Counts.second.size()) * sizeof(uint64_t); + LE.write(M); + + return std::make_pair(N, M); + } + + static void EmitKey(raw_ostream &Out, key_type_ref K, offset_type N){ + Out.write(K.data(), N); + } + + static void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, + offset_type) { + using namespace llvm::support; + endian::Writer LE(Out); + + for (const auto &Counts : *V) { + LE.write(Counts.first); + LE.write(Counts.second.size()); + for (uint64_t I : Counts.second) + LE.write(I); + } } +}; +} - 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()) +std::error_code +InstrProfWriter::addFunctionCounts(StringRef FunctionName, + uint64_t FunctionHash, + ArrayRef 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; + } + + // 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_ostream &OS) { - // Write out the counts for each function. - for (const auto &I : FunctionData) { - StringRef Name = I.getKey(); - uint64_t Hash = I.getValue().Hash; - const std::vector &Counts = I.getValue().Counts; - - OS << Name << "\n" << Hash << "\n" << Counts.size() << "\n"; - for (uint64_t Count : Counts) - OS << Count << "\n"; - OS << "\n"; - } +void InstrProfWriter::write(raw_fd_ostream &OS) { + OnDiskChainedHashTableGenerator Generator; + + // Populate the hash table generator. + std::vector CounterBuffer; + for (const auto &I : FunctionData) + Generator.insert(I.getKey(), &I.getValue()); + + using namespace llvm::support; + endian::Writer LE(OS); + + // Write the header. + LE.write(IndexedInstrProf::Magic); + LE.write(IndexedInstrProf::Version); + LE.write(MaxFunctionCount); + LE.write(static_cast(IndexedInstrProf::HashType)); + + // Save a space to write the hash table start location. + uint64_t HashTableStartLoc = OS.tell(); + LE.write(0); + // Write the hash table. + uint64_t HashTableStart = Generator.Emit(OS); + + // Go back and fill in the hash table start. + OS.seek(HashTableStartLoc); + LE.write(HashTableStart); }