/// Same as the above interface but using an ArrayRef, as well as \p Sum.
void annotateValueSite(Module &M, Instruction &Inst,
- ArrayRef<InstrProfValueData> VDs,
- uint64_t Sum, InstrProfValueKind ValueKind,
- uint32_t MaxMDCount);
+ ArrayRef<InstrProfValueData> VDs, uint64_t Sum,
+ InstrProfValueKind ValueKind, uint32_t MaxMDCount);
/// Extract the value profile data from \p Inst which is annotated with
/// value profile meta data. Return false if there is no value data annotated,
/// Profiling information for a single function.
struct InstrProfRecord {
- StringRef Name;
- uint64_t Hash;
std::vector<uint64_t> Counts;
SoftInstrProfErrors SIPE;
InstrProfRecord() = default;
- InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)
- : Name(Name), Hash(Hash), Counts(std::move(Counts)) {}
+ InstrProfRecord(std::vector<uint64_t> Counts) : Counts(std::move(Counts)) {}
InstrProfRecord(InstrProfRecord &&) = default;
InstrProfRecord(const InstrProfRecord &RHS)
- : Name(RHS.Name), Hash(RHS.Hash), Counts(RHS.Counts), SIPE(RHS.SIPE),
+ : Counts(RHS.Counts),
ValueData(RHS.ValueData
? llvm::make_unique<ValueProfData>(*RHS.ValueData)
: nullptr) {}
InstrProfRecord &operator=(InstrProfRecord &&) = default;
InstrProfRecord &operator=(const InstrProfRecord &RHS) {
- Name = RHS.Name;
- Hash = RHS.Hash;
Counts = RHS.Counts;
- SIPE = RHS.SIPE;
if (!RHS.ValueData) {
ValueData = nullptr;
return *this;
/// Return the number of value profile kinds with non-zero number
/// of profile sites.
inline uint32_t getNumValueKinds() const;
-
/// Return the number of instrumented sites for ValueKind.
inline uint32_t getNumValueSites(uint32_t ValueKind) const;
void scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
};
+struct NamedInstrProfRecord : InstrProfRecord {
+ StringRef Name;
+ uint64_t Hash;
+
+ NamedInstrProfRecord() = default;
+ NamedInstrProfRecord(StringRef Name, uint64_t Hash,
+ std::vector<uint64_t> Counts)
+ : InstrProfRecord(std::move(Counts)), Name(Name), Hash(Hash) {}
+};
+
uint32_t InstrProfRecord::getNumValueKinds() const {
uint32_t NumValueKinds = 0;
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
/// A file format agnostic iterator over profiling data.
class InstrProfIterator : public std::iterator<std::input_iterator_tag,
- InstrProfRecord> {
+ NamedInstrProfRecord> {
InstrProfReader *Reader = nullptr;
- InstrProfRecord Record;
+ value_type Record;
void Increment();
InstrProfIterator &operator++() { Increment(); return *this; }
bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
- InstrProfRecord &operator*() { return Record; }
- InstrProfRecord *operator->() { return &Record; }
+ value_type &operator*() { return Record; }
+ value_type *operator->() { return &Record; }
};
/// Base class and interface for reading profiling data of any known instrprof
-/// format. Provides an iterator over InstrProfRecords.
+/// format. Provides an iterator over NamedInstrProfRecords.
class InstrProfReader {
instrprof_error LastError = instrprof_error::success;
virtual Error readHeader() = 0;
/// Read a single record.
- virtual Error readNextRecord(InstrProfRecord &Record) = 0;
+ virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0;
/// Iterator over profile data.
InstrProfIterator begin() { return InstrProfIterator(this); }
Error readHeader() override;
/// Read a single record.
- Error readNextRecord(InstrProfRecord &Record) override;
+ Error readNextRecord(NamedInstrProfRecord &Record) override;
InstrProfSymtab &getSymtab() override {
assert(Symtab.get());
static bool hasFormat(const MemoryBuffer &DataBuffer);
Error readHeader() override;
- Error readNextRecord(InstrProfRecord &Record) override;
+ Error readNextRecord(NamedInstrProfRecord &Record) override;
bool isIRLevelProfile() const override {
return (Version & VARIANT_MASK_IR_PROF) != 0;
return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
}
- Error readName(InstrProfRecord &Record);
- Error readFuncHash(InstrProfRecord &Record);
+ Error readName(NamedInstrProfRecord &Record);
+ Error readFuncHash(NamedInstrProfRecord &Record);
Error readRawCounts(InstrProfRecord &Record);
Error readValueProfilingData(InstrProfRecord &Record);
bool atEnd() const { return Data == DataEnd; }
/// Trait for lookups into the on-disk hash table for the binary instrprof
/// format.
class InstrProfLookupTrait {
- std::vector<InstrProfRecord> DataBuffer;
+ std::vector<NamedInstrProfRecord> DataBuffer;
IndexedInstrProf::HashT HashType;
unsigned FormatVersion;
// Endianness of the input value profile data.
InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
: HashType(HashType), FormatVersion(FormatVersion) {}
- using data_type = ArrayRef<InstrProfRecord>;
+ using data_type = ArrayRef<NamedInstrProfRecord>;
using internal_key_type = StringRef;
using external_key_type = StringRef;
// Read all the profile records with the same key pointed to the current
// iterator.
- virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
+ virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0;
// Read all the profile records with the key equal to FuncName
virtual Error getRecords(StringRef FuncName,
- ArrayRef<InstrProfRecord> &Data) = 0;
+ ArrayRef<NamedInstrProfRecord> &Data) = 0;
virtual void advanceToNextKey() = 0;
virtual bool atEnd() const = 0;
virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
IndexedInstrProf::HashT HashType, uint64_t Version);
~InstrProfReaderIndex() override = default;
- Error getRecords(ArrayRef<InstrProfRecord> &Data) override;
+ Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
Error getRecords(StringRef FuncName,
- ArrayRef<InstrProfRecord> &Data) override;
+ ArrayRef<NamedInstrProfRecord> &Data) override;
void advanceToNextKey() override { RecordIterator++; }
bool atEnd() const override {
/// Read the file header.
Error readHeader() override;
/// Read a single record.
- Error readNextRecord(InstrProfRecord &Record) override;
+ Error readNextRecord(NamedInstrProfRecord &Record) override;
- /// Return the pointer to InstrProfRecord associated with FuncName
- /// and FuncHash
+ /// Return the NamedInstrProfRecord associated with FuncName and FuncHash
Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
uint64_t FuncHash);
class InstrProfWriter {
public:
- using ProfilingData = SmallDenseMap<uint64_t, InstrProfRecord, 1>;
+ using ProfilingData =
+ SmallDenseMap<uint64_t, InstrProfRecord, 1>;
enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
private:
/// Add function counts for the given function. If there are already counts
/// for this function and the hash and number of counts match, each counter is
/// summed. Optionally scale counts by \p Weight.
- Error addRecord(InstrProfRecord &&I, uint64_t Weight = 1);
+ Error addRecord(NamedInstrProfRecord &&I, uint64_t Weight = 1);
/// Merge existing function counts from the given writer.
Error mergeRecordsFromWriter(InstrProfWriter &&IPW);
Error writeText(raw_fd_ostream &OS);
/// Write \c Record in text format to \c OS
- static void writeRecordInText(const InstrProfRecord &Record,
+ static void writeRecordInText(StringRef Name, uint64_t Hash,
+ const InstrProfRecord &Counters,
InstrProfSymtab &Symtab, raw_fd_ostream &OS);
/// Write the profile, returning the raw data. For testing.
void setOutputSparse(bool Sparse);
private:
+ Error addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
+ uint64_t Weight = 1);
bool shouldEncodeData(const ProfilingData &PD);
void writeImpl(ProfOStream &OS);
};
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/ProfileSummary.h"
+#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <cstdint>
namespace llvm {
-struct InstrProfRecord;
-
namespace sampleprof {
class FunctionSamples;
#undef VP_READ_ADVANCE
}
-Error TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
+Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
// Skip empty lines and comments.
while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
++Line;
}
template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readName(InstrProfRecord &Record) {
+Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
Record.Name = getName(Data->NameRef);
return success();
}
template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readFuncHash(InstrProfRecord &Record) {
+Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
Record.Hash = swap(Data->FuncHash);
return success();
}
}
template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
+Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
if (atEnd())
// At this point, ValueDataStart field points to the next header.
if (Error E = readNextHeader(getNextHeaderPos()))
template <typename HashTableImpl>
Error InstrProfReaderIndex<HashTableImpl>::getRecords(
- StringRef FuncName, ArrayRef<InstrProfRecord> &Data) {
+ StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
auto Iter = HashTable->find(FuncName);
if (Iter == HashTable->end())
return make_error<InstrProfError>(instrprof_error::unknown_function);
template <typename HashTableImpl>
Error InstrProfReaderIndex<HashTableImpl>::getRecords(
- ArrayRef<InstrProfRecord> &Data) {
+ ArrayRef<NamedInstrProfRecord> &Data) {
if (atEnd())
return make_error<InstrProfError>(instrprof_error::eof);
InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
// FIXME: This only computes an empty summary. Need to call addRecord for
- // all InstrProfRecords to get the correct summary.
+ // all NamedInstrProfRecords to get the correct summary.
this->Summary = Builder.getSummary();
return Cur;
}
Expected<InstrProfRecord>
IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
uint64_t FuncHash) {
- ArrayRef<InstrProfRecord> Data;
+ ArrayRef<NamedInstrProfRecord> Data;
Error Err = Index->getRecords(FuncName, Data);
if (Err)
return std::move(Err);
return success();
}
-Error IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) {
+Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
static unsigned RecordIndex = 0;
- ArrayRef<InstrProfRecord> Data;
+ ArrayRef<NamedInstrProfRecord> Data;
Error E = Index->getRecords(Data);
if (E)
this->Sparse = Sparse;
}
-Error InstrProfWriter::addRecord(InstrProfRecord &&I, uint64_t Weight) {
- auto &ProfileDataMap = FunctionData[I.Name];
+Error InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight) {
+ auto Name = I.Name;
+ auto Hash = I.Hash;
+ return addRecord(Name, Hash, std::move(I), Weight);
+}
+
+Error InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
+ InstrProfRecord &&I, uint64_t Weight) {
+ auto &ProfileDataMap = FunctionData[Name];
bool NewFunc;
ProfilingData::iterator Where;
std::tie(Where, NewFunc) =
- ProfileDataMap.insert(std::make_pair(I.Hash, InstrProfRecord()));
+ ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
InstrProfRecord &Dest = Where->second;
if (NewFunc) {
// We've never seen a function with this name and hash, add it.
Dest = std::move(I);
- // Fix up the name to avoid dangling reference.
- Dest.Name = FunctionData.find(Dest.Name)->getKey();
if (Weight > 1)
Dest.scale(Weight);
} else {
Error InstrProfWriter::mergeRecordsFromWriter(InstrProfWriter &&IPW) {
for (auto &I : IPW.FunctionData)
for (auto &Func : I.getValue())
- if (Error E = addRecord(std::move(Func.second), 1))
+ if (Error E = addRecord(I.getKey(), Func.first, std::move(Func.second)))
return E;
return Error::success();
}
#include "llvm/ProfileData/InstrProfData.inc"
};
-void InstrProfWriter::writeRecordInText(const InstrProfRecord &Func,
+void InstrProfWriter::writeRecordInText(StringRef Name, uint64_t Hash,
+ const InstrProfRecord &Func,
InstrProfSymtab &Symtab,
raw_fd_ostream &OS) {
- OS << Func.Name << "\n";
- OS << "# Func Hash:\n" << Func.Hash << "\n";
+ 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)
for (const auto &I : FunctionData)
if (shouldEncodeData(I.getValue()))
for (const auto &Func : I.getValue())
- writeRecordInText(Func.second, Symtab, OS);
+ writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
return Error::success();
}
if (doTextFormatDump) {
InstrProfSymtab &Symtab = Reader->getSymtab();
- InstrProfWriter::writeRecordInText(Func, Symtab, OS);
+ InstrProfWriter::writeRecordInText(Func.Name, Func.Hash, Func, Symtab,
+ OS);
continue;
}
static const char callee6[] = "callee6";
TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) {
- InstrProfRecord Record1("caller", 0x1234, {1, 2});
+ NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
// 4 value sites.
Record1.reserveSites(IPVK_IndirectCallTarget, 4);
}
TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
- InstrProfRecord Record("caller", 0x1234, {1, 2});
+ NamedInstrProfRecord Record("caller", 0x1234, {1, 2});
Record.reserveSites(IPVK_IndirectCallTarget, 1);
InstrProfValueData VD0[] = {{1000, 1}, {2000, 2}, {3000, 3}, {5000, 5},
{4000, 4}, {6000, 6}};
}
TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) {
- InstrProfRecord Record1("caller", 0x1234, {1, 2});
+ NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
// 4 value sites.
Record1.reserveSites(IPVK_IndirectCallTarget, 4);
}
TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) {
- InstrProfRecord Record1("caller", 0x1234, {1, 2});
+ NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
// 4 value sites.
Record1.reserveSites(IPVK_IndirectCallTarget, 4);
TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) {
static const char caller[] = "caller";
- InstrProfRecord Record11(caller, 0x1234, {1, 2});
- InstrProfRecord Record12(caller, 0x1234, {1, 2});
+ NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
+ NamedInstrProfRecord Record12(caller, 0x1234, {1, 2});
// 5 value sites.
Record11.reserveSites(IPVK_IndirectCallTarget, 5);
ASSERT_EQ(InstrProfError::take(std::move(Result3)),
instrprof_error::success);
- InstrProfRecord Record4("baz", 0x5678, {3, 4});
+ NamedInstrProfRecord Record4("baz", 0x5678, {3, 4});
Record4.reserveSites(IPVK_IndirectCallTarget, 1);
InstrProfValueData VD4[] = {{uint64_t(bar), 1}};
Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
instrprof_error::success);
// Verify value data counter overflow.
- InstrProfRecord Record5("baz", 0x5678, {5, 6});
+ NamedInstrProfRecord Record5("baz", 0x5678, {5, 6});
Record5.reserveSites(IPVK_IndirectCallTarget, 1);
InstrProfValueData VD5[] = {{uint64_t(bar), Max}};
Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge_site_trunc) {
static const char caller[] = "caller";
- InstrProfRecord Record11(caller, 0x1234, {1, 2});
- InstrProfRecord Record12(caller, 0x1234, {1, 2});
+ NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
+ NamedInstrProfRecord Record12(caller, 0x1234, {1, 2});
// 2 value sites.
Record11.reserveSites(IPVK_IndirectCallTarget, 2);
}
TEST_P(MaybeSparseInstrProfTest, value_prof_data_read_write) {
- InstrProfRecord SrcRecord("caller", 0x1234, {1ULL << 31, 2});
+ InstrProfRecord SrcRecord({1ULL << 31, 2});
addValueProfData(SrcRecord);
std::unique_ptr<ValueProfData> VPData =
ValueProfData::serializeFrom(SrcRecord);
- InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
+ InstrProfRecord Record({1ULL << 31, 2});
VPData->deserializeTo(Record, nullptr);
// Now read data from Record and sanity check the data
TEST_P(MaybeSparseInstrProfTest, value_prof_data_read_write_mapping) {
- InstrProfRecord SrcRecord("caller", 0x1234, {1ULL << 31, 2});
+ NamedInstrProfRecord SrcRecord("caller", 0x1234, {1ULL << 31, 2});
addValueProfData(SrcRecord);
std::unique_ptr<ValueProfData> VPData =
ValueProfData::serializeFrom(SrcRecord);
- InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
+ NamedInstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
InstrProfSymtab Symtab;
Symtab.mapAddress(uint64_t(callee1), 0x1000ULL);
Symtab.mapAddress(uint64_t(callee2), 0x2000ULL);