static void traverseAllValueSites(const InstrProfRecord &Func, uint32_t VK, ValueSitesStats &Stats, raw_fd_ostream &OS, InstrProfSymtab *Symtab) { uint32_t NS = Func.getNumValueSites(VK); Stats.TotalNumValueSites += NS; for (size_t I = 0; I < NS; ++I) { uint32_t NV = Func.getNumValueDataForSite(VK, I); std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, I); Stats.TotalNumValues += NV; if (NV) { Stats.TotalNumValueSitesWithValueProfile++; if (NV > Stats.ValueSitesHistogram.size()) Stats.ValueSitesHistogram.resize(NV, 0); Stats.ValueSitesHistogram[NV - 1]++; } for (uint32_t V = 0; V < NV; V++) { OS << "\t[ " << I << ", "; if (Symtab == nullptr) OS << VD[V].Value; else OS << Symtab->getFuncName(VD[V].Value); OS << ", " << VD[V].Count << " ]\n"; } } }
static std::error_code combineInstrProfRecords(InstrProfRecord &Dest, InstrProfRecord &Source, uint64_t &MaxFunctionCount) { // If the number of counters doesn't match we either have bad data // or a hash collision. if (Dest.Counts.size() != Source.Counts.size()) return instrprof_error::count_mismatch; for (size_t I = 0, E = Source.Counts.size(); I < E; ++I) { if (Dest.Counts[I] + Source.Counts[I] < Dest.Counts[I]) return instrprof_error::counter_overflow; Dest.Counts[I] += Source.Counts[I]; } for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) { if (std::error_code EC = Dest.mergeValueProfData(Kind, Source)) return EC; } // We keep track of the max function count as we go for simplicity. if (Dest.Counts[0] > MaxFunctionCount) MaxFunctionCount = Dest.Counts[0]; return instrprof_error::success; }
std::error_code RawInstrProfReader<IntPtrT>::readValueProfilingData(InstrProfRecord &Record) { Record.clearValueData(); CurValueDataSize = 0; // Need to match the logic in value profile dumper code in compiler-rt: uint32_t NumValueKinds = 0; for (uint32_t I = 0; I < IPVK_Last + 1; I++) NumValueKinds += (Data->NumValueSites[I] != 0); if (!NumValueKinds) return success(); ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr = ValueProfData::getValueProfData(ValueDataStart, (const unsigned char *)ProfileEnd, getDataEndianness()); if (VDataPtrOrErr.getError()) return VDataPtrOrErr.getError(); // Note that besides deserialization, this also performs the conversion for // indirect call targets. The function pointers from the raw profile are // remapped into function name hashes. VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); CurValueDataSize = VDataPtrOrErr.get()->getSize(); return success(); }
std::error_code RawInstrProfReader<IntPtrT>::readValueProfilingData(InstrProfRecord &Record) { Record.clearValueData(); CurValueDataSize = 0; // Need to match the logic in value profile dumper code in compiler-rt: uint32_t NumValueKinds = 0; for (uint32_t I = 0; I < IPVK_Last + 1; I++) NumValueKinds += (Data->NumValueSites[I] != 0); if (!NumValueKinds) return success(); ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr = ValueProfData::getValueProfData(ValueDataStart, (const unsigned char *)ProfileEnd, getDataEndianness()); if (VDataPtrOrErr.getError()) return VDataPtrOrErr.getError(); VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); CurValueDataSize = VDataPtrOrErr.get()->getSize(); return success(); }
std::error_code RawInstrProfReader<IntPtrT>::readValueProfilingData( InstrProfRecord &Record) { Record.clearValueData(); if (!Data->Values || (ValueDataDelta == 0)) return success(); // Read value data. uint64_t NumVSites = 0; for (uint32_t Kind = IPVK_First; Kind <= ValueKindLast; ++Kind) NumVSites += swap(Data->NumValueSites[Kind]); NumVSites += getNumPaddingBytes(NumVSites); auto VDataCounts = makeArrayRef(getValueDataCounts(Data->Values), NumVSites); // Check bounds. if (VDataCounts.data() < ValueDataStart || VDataCounts.data() + VDataCounts.size() > reinterpret_cast<const uint8_t *>(ProfileEnd)) return error(instrprof_error::malformed); const InstrProfValueData *VDataPtr = getValueData(swap(Data->Values) + NumVSites); for (uint32_t Kind = IPVK_First; Kind <= ValueKindLast; ++Kind) { NumVSites = swap(Data->NumValueSites[Kind]); Record.reserveSites(Kind, NumVSites); for (uint32_t VSite = 0; VSite < NumVSites; ++VSite) { uint32_t VDataCount = VDataCounts[VSite]; if ((const char *)(VDataPtr + VDataCount) > ProfileEnd) return error(instrprof_error::malformed); std::vector<InstrProfValueData> CurrentValues; CurrentValues.reserve(VDataCount); for (uint32_t VIndex = 0; VIndex < VDataCount; ++VIndex) { uint64_t TargetValue = swap(VDataPtr->Value); uint64_t Count = swap(VDataPtr->Count); CurrentValues.push_back({TargetValue, Count}); ++VDataPtr; } Record.addValueData(Kind, VSite, CurrentValues.data(), VDataCount, &FunctionPtrToNameMap); } } return success(); }
void InstrProfWriter::writeRecordInText(StringRef Name, uint64_t Hash, const InstrProfRecord &Func, InstrProfSymtab &Symtab, raw_fd_ostream &OS) { OS << Name << "\n"; OS << "# Func Hash:\n" << Hash << "\n"; OS << "# Num Counters:\n" << Func.Counts.size() << "\n"; OS << "# Counter Values:\n"; for (uint64_t Count : Func.Counts) OS << Count << "\n"; uint32_t NumValueKinds = Func.getNumValueKinds(); if (!NumValueKinds) { OS << "\n"; return; } OS << "# Num Value Kinds:\n" << Func.getNumValueKinds() << "\n"; for (uint32_t VK = 0; VK < IPVK_Last + 1; VK++) { uint32_t NS = Func.getNumValueSites(VK); if (!NS) continue; OS << "# ValueKind = " << ValueProfKindStr[VK] << ":\n" << VK << "\n"; OS << "# NumValueSites:\n" << NS << "\n"; for (uint32_t S = 0; S < NS; S++) { uint32_t ND = Func.getNumValueDataForSite(VK, S); OS << ND << "\n"; std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, S); for (uint32_t I = 0; I < ND; I++) { if (VK == IPVK_IndirectCallTarget) OS << Symtab.getFuncNameOrExternalSymbol(VD[I].Value) << ":" << VD[I].Count << "\n"; else OS << VD[I].Value << ":" << VD[I].Count << "\n"; } } } OS << "\n"; }
void InstrProfWriter::updateStringTableReferences(InstrProfRecord &I) { I.updateStrings(&StringTable); }
std::error_code TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { #define CHECK_LINE_END(Line) \ if (Line.is_at_end()) \ return error(instrprof_error::truncated); #define READ_NUM(Str, Dst) \ if ((Str).getAsInteger(10, (Dst))) \ return error(instrprof_error::malformed); #define VP_READ_ADVANCE(Val) \ CHECK_LINE_END(Line); \ uint32_t Val; \ READ_NUM((*Line), (Val)); \ Line++; if (Line.is_at_end()) return success(); uint32_t NumValueKinds; if (Line->getAsInteger(10, NumValueKinds)) { // No value profile data return success(); } if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1) return error(instrprof_error::malformed); Line++; for (uint32_t VK = 0; VK < NumValueKinds; VK++) { VP_READ_ADVANCE(ValueKind); if (ValueKind > IPVK_Last) return error(instrprof_error::malformed); VP_READ_ADVANCE(NumValueSites); if (!NumValueSites) continue; Record.reserveSites(VK, NumValueSites); for (uint32_t S = 0; S < NumValueSites; S++) { VP_READ_ADVANCE(NumValueData); std::vector<InstrProfValueData> CurrentValues; for (uint32_t V = 0; V < NumValueData; V++) { CHECK_LINE_END(Line); std::pair<StringRef, StringRef> VD = Line->split(':'); uint64_t TakenCount, Value; if (VK == IPVK_IndirectCallTarget) { Symtab->addFuncName(VD.first); Value = IndexedInstrProf::ComputeHash(VD.first); } else { READ_NUM(VD.first, Value); } READ_NUM(VD.second, TakenCount); CurrentValues.push_back({Value, TakenCount}); Line++; } Record.addValueData(VK, S, CurrentValues.data(), NumValueData, nullptr); } } return success(); #undef CHECK_LINE_END #undef READ_NUM #undef VP_READ_ADVANCE }