Skip to content

Commit f4b332d

Browse files
Update test; non-ext binary format not supported
1 parent ee2e45b commit f4b332d

14 files changed

+295
-214
lines changed

llvm/include/llvm/ProfileData/SampleProf.h

Lines changed: 82 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
#include "llvm/IR/Function.h"
2222
#include "llvm/IR/GlobalValue.h"
2323
#include "llvm/ProfileData/FunctionId.h"
24+
#include "llvm/ProfileData/HashKeyMap.h"
2425
#include "llvm/Support/Allocator.h"
2526
#include "llvm/Support/Debug.h"
2627
#include "llvm/Support/ErrorOr.h"
2728
#include "llvm/Support/MathExtras.h"
28-
#include "llvm/ProfileData/HashKeyMap.h"
2929
#include <algorithm>
3030
#include <cstdint>
3131
#include <list>
@@ -59,7 +59,9 @@ enum class sampleprof_error {
5959
ostream_seek_unsupported,
6060
uncompress_failed,
6161
zlib_unavailable,
62-
hash_mismatch
62+
hash_mismatch,
63+
illegal_line_offset,
64+
duplicate_vtable_type,
6365
};
6466

6567
inline std::error_code make_error_code(sampleprof_error E) {
@@ -88,6 +90,9 @@ struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {};
8890
namespace llvm {
8991
namespace sampleprof {
9092

93+
constexpr char kBodySampleVTableProfPrefix[] = "<vt-call> ";
94+
constexpr char kInlinedCallsiteVTablerofPrefix[] = "<vt-inline> ";
95+
9196
enum SampleProfileFormat {
9297
SPF_None = 0,
9398
SPF_Text = 0x1,
@@ -286,6 +291,9 @@ struct LineLocation {
286291
void print(raw_ostream &OS) const;
287292
void dump() const;
288293

294+
/// Serialize the line location to \p OS using ULEB128 encoding.
295+
void serialize(raw_ostream &OS) const;
296+
289297
bool operator<(const LineLocation &O) const {
290298
return LineOffset < O.LineOffset ||
291299
(LineOffset == O.LineOffset && Discriminator < O.Discriminator);
@@ -315,7 +323,9 @@ struct LineLocationHash {
315323

316324
raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc);
317325

318-
using TypeMap = std::map<FunctionId, uint64_t>;
326+
/// Key represents the id of a vtable and value represents its count.
327+
/// TODO: Rename class FunctionId to SymbolId in a separate PR.
328+
using TypeCountMap = std::map<FunctionId, uint64_t>;
319329

320330
/// Representation of a single sample record.
321331
///
@@ -342,7 +352,6 @@ class SampleRecord {
342352

343353
using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>;
344354
using CallTargetMap = std::unordered_map<FunctionId, uint64_t>;
345-
346355
SampleRecord() = default;
347356

348357
/// Increment the number of samples for this record by \p S.
@@ -372,22 +381,12 @@ class SampleRecord {
372381
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
373382
/// around unsigned integers.
374383
sampleprof_error addCalledTarget(FunctionId F, uint64_t S,
375-
uint64_t Weight = 1) {
376-
uint64_t &TargetSamples = CallTargets[F];
377-
bool Overflowed;
378-
TargetSamples =
379-
SaturatingMultiplyAdd(S, Weight, TargetSamples, &Overflowed);
380-
return Overflowed ? sampleprof_error::counter_overflow
381-
: sampleprof_error::success;
382-
}
384+
uint64_t Weight = 1);
383385

384-
sampleprof_error addTypeCount(FunctionId F, uint64_t S, uint64_t Weight = 1) {
385-
uint64_t &Samples = TypeCounts[F];
386-
bool Overflowed;
387-
Samples = SaturatingMultiplyAdd(S, Weight, Samples, &Overflowed);
388-
return Overflowed ? sampleprof_error::counter_overflow
389-
: sampleprof_error::success;
390-
}
386+
/// Add vtable type \p F with samples \p S.
387+
/// Optionally scale sample count \p S by \p Weight.
388+
sampleprof_error addVTableAccessCount(FunctionId F, uint64_t S,
389+
uint64_t Weight = 1);
391390

392391
/// Remove called function from the call target map. Return the target sample
393392
/// count of the called function.
@@ -406,8 +405,10 @@ class SampleRecord {
406405

407406
uint64_t getSamples() const { return NumSamples; }
408407
const CallTargetMap &getCallTargets() const { return CallTargets; }
409-
const TypeMap &getTypes() const { return TypeCounts; }
410-
TypeMap &getTypes() { return TypeCounts; }
408+
const TypeCountMap &getVTableAccessCounts() const {
409+
return VTableAccessCounts;
410+
}
411+
TypeCountMap &getVTableAccessCounts() { return VTableAccessCounts; }
411412
const SortedCallTargetSet getSortedCallTargets() const {
412413
return sortCallTargets(CallTargets);
413414
}
@@ -456,7 +457,8 @@ class SampleRecord {
456457
private:
457458
uint64_t NumSamples = 0;
458459
CallTargetMap CallTargets;
459-
TypeMap TypeCounts;
460+
// The vtable types and their counts in this sample record.
461+
TypeCountMap VTableAccessCounts;
460462
};
461463

462464
raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample);
@@ -752,7 +754,7 @@ using BodySampleMap = std::map<LineLocation, SampleRecord>;
752754
// memory, which is *very* significant for large profiles.
753755
using FunctionSamplesMap = std::map<FunctionId, FunctionSamples>;
754756
using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;
755-
using CallsiteTypeMap = std::map<LineLocation, TypeMap>;
757+
using CallsiteTypeMap = std::map<LineLocation, TypeCountMap>;
756758
using LocToLocMap =
757759
std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
758760

@@ -810,20 +812,14 @@ class FunctionSamples {
810812
Func, Num, Weight);
811813
}
812814

813-
sampleprof_error addTypeSamples(uint32_t LineOffset, uint32_t Discriminator,
814-
FunctionId Func, uint64_t Num,
815-
uint64_t Weight = 1) {
816-
return BodySamples[LineLocation(LineOffset, Discriminator)].addTypeCount(
817-
Func, Num, Weight);
815+
sampleprof_error addFunctionBodyTypeSamples(const LineLocation &Loc,
816+
FunctionId Func, uint64_t Num,
817+
uint64_t Weight = 1) {
818+
return BodySamples[Loc].addVTableAccessCount(Func, Num, Weight);
818819
}
819820

820-
sampleprof_error addTypeSamples(const LineLocation &Loc, FunctionId Func,
821-
uint64_t Num, uint64_t Weight = 1) {
822-
return BodySamples[Loc].addTypeCount(Func, Num, Weight);
823-
}
824-
825-
TypeMap &getTypeSamples(const LineLocation &Loc) {
826-
return BodySamples[Loc].getTypes();
821+
TypeCountMap &getFunctionBodyTypeSamples(const LineLocation &Loc) {
822+
return BodySamples[Loc].getVTableAccessCounts();
827823
}
828824

829825
sampleprof_error addSampleRecord(LineLocation Location,
@@ -951,7 +947,8 @@ class FunctionSamples {
951947
return &Iter->second;
952948
}
953949

954-
const TypeMap *findTypeSamplesAt(const LineLocation &Loc) const {
950+
/// Returns the TypeCountMap for inlined callsites at the given \p Loc.
951+
const TypeCountMap *findCallsiteTypeSamplesAt(const LineLocation &Loc) const {
955952
auto Iter = VirtualCallsiteTypes.find(mapIRLocToProfileLoc(Loc));
956953
if (Iter == VirtualCallsiteTypes.end())
957954
return nullptr;
@@ -1019,14 +1016,42 @@ class FunctionSamples {
10191016
return CallsiteSamples;
10201017
}
10211018

1022-
const CallsiteTypeMap &getCallsiteTypes() const {
1019+
/// Return all the callsite type samples collected in the body of the
1020+
/// function.
1021+
const CallsiteTypeMap &getCallsiteTypeCounts() const {
10231022
return VirtualCallsiteTypes;
10241023
}
10251024

1026-
TypeMap& getTypeSamplesAt(const LineLocation &Loc) {
1025+
/// Returns the type samples for the un-drifted location of \p Loc.
1026+
TypeCountMap &getTypeSamplesAt(const LineLocation &Loc) {
10271027
return VirtualCallsiteTypes[mapIRLocToProfileLoc(Loc)];
10281028
}
10291029

1030+
/// Scale \p Other sample counts by \p Weight and add the scaled result to the
1031+
/// type samples for the undrifted location of \p Loc.
1032+
template <typename T>
1033+
sampleprof_error addCallsiteVTableTypeProfAt(const LineLocation &Loc,
1034+
const T &Other,
1035+
uint64_t Weight = 1) {
1036+
static_assert((std::is_same_v<typename T::key_type, StringRef> ||
1037+
std::is_same_v<typename T::key_type, FunctionId>) &&
1038+
std::is_same_v<typename T::mapped_type, uint64_t>,
1039+
"T must be a map with StringRef or FunctionId as key and "
1040+
"uint64_t as value");
1041+
TypeCountMap &TypeCounts = getTypeSamplesAt(Loc);
1042+
bool Overflowed = false;
1043+
1044+
for (const auto [Type, Count] : Other) {
1045+
FunctionId TypeId(Type);
1046+
bool RowOverflow = false;
1047+
TypeCounts[TypeId] = SaturatingMultiplyAdd(
1048+
Count, Weight, TypeCounts[TypeId], &RowOverflow);
1049+
Overflowed |= RowOverflow;
1050+
}
1051+
return Overflowed ? sampleprof_error::counter_overflow
1052+
: sampleprof_error::success;
1053+
}
1054+
10301055
/// Return the maximum of sample counts in a function body. When SkipCallSite
10311056
/// is false, which is the default, the return count includes samples in the
10321057
/// inlined functions. When SkipCallSite is true, the return count only
@@ -1073,27 +1098,18 @@ class FunctionSamples {
10731098
const LineLocation &Loc = I.first;
10741099
const SampleRecord &Rec = I.second;
10751100
mergeSampleProfErrors(Result, BodySamples[Loc].merge(Rec, Weight));
1076-
// const auto &OtherTypeCountMap = Rec.getTypes();
1077-
// for (const auto &[Type, Count] : OtherTypeCountMap) {
1078-
// mergeSampleProfErrors(Result, addTypeSamples(Loc, Type, Count,
1079-
// Weight));
1080-
// }
10811101
}
1082-
10831102
for (const auto &I : Other.getCallsiteSamples()) {
10841103
const LineLocation &Loc = I.first;
10851104
FunctionSamplesMap &FSMap = functionSamplesAt(Loc);
10861105
for (const auto &Rec : I.second)
10871106
mergeSampleProfErrors(Result,
10881107
FSMap[Rec.first].merge(Rec.second, Weight));
10891108
}
1090-
for (const auto &[Loc, TypeCountMap] : Other.getCallsiteTypes()) {
1091-
TypeMap &TypeCounts = getTypeSamplesAt(Loc);
1092-
for (const auto &[Type, Count] : TypeCountMap) {
1093-
TypeCounts[Type] =
1094-
SaturatingMultiplyAdd(Count, Weight, TypeCounts[Type]);
1095-
}
1096-
}
1109+
for (const auto &[Loc, OtherTypeMap] : Other.getCallsiteTypeCounts())
1110+
mergeSampleProfErrors(
1111+
Result, addCallsiteVTableTypeProfAt(Loc, OtherTypeMap, Weight));
1112+
10971113
return Result;
10981114
}
10991115

@@ -1337,6 +1353,21 @@ class FunctionSamples {
13371353
/// collected in the call to baz() at line offset 8.
13381354
CallsiteSampleMap CallsiteSamples;
13391355

1356+
/// Map inlined virtual callsites to the vtable from which they are loaded.
1357+
///
1358+
/// Each entry is a mapping from the location to the list of vtables and their
1359+
/// sampled counts. For example, given:
1360+
///
1361+
/// void foo() {
1362+
/// ...
1363+
/// 5 inlined_vcall_bar();
1364+
/// ...
1365+
/// 5 inlined_vcall_baz();
1366+
/// ...
1367+
/// 200 inlined_vcall_qux();
1368+
/// }
1369+
/// This map will contain two entries. One with two types for line offset 5
1370+
/// and one with one type for line offset 200.
13401371
CallsiteTypeMap VirtualCallsiteTypes;
13411372

13421373
/// IR to profile location map generated by stale profile matching.

llvm/include/llvm/ProfileData/SampleProfReader.h

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -701,16 +701,10 @@ class SampleProfileReaderBinary : public SampleProfileReader {
701701
/// otherwise same as readStringFromTable, also return its hash value.
702702
ErrorOr<std::pair<SampleContext, uint64_t>> readSampleContextFromTable();
703703

704-
/// Overridden by SampleProfileReaderExtBinary to read the vtable profile.
705-
virtual std::error_code readVTableProf(const LineLocation &Loc,
706-
FunctionSamples &FProfile) {
707-
return sampleprof_error::success;
708-
}
709-
710-
virtual std::error_code readCallsiteVTableProf(FunctionSamples &FProfile) {
711-
return sampleprof_error::success;
712-
}
713-
704+
std::error_code readBodySampleVTableProf(const LineLocation &Loc,
705+
FunctionSamples &FProfile);
706+
/// Read all callsites' vtable access counts for \p FProfile.
707+
std::error_code readCallsiteVTableProf(FunctionSamples &FProfile);
714708

715709
/// Points to the current location in the buffer.
716710
const uint8_t *Data = nullptr;
@@ -736,6 +730,12 @@ class SampleProfileReaderBinary : public SampleProfileReader {
736730
/// to the start of MD5SampleContextTable.
737731
const uint64_t *MD5SampleContextStart = nullptr;
738732

733+
/// Read bytes from the input buffer pointed by `Data` and decode them into
734+
/// \p M. `Data` will be advanced to the end of the read bytes when this
735+
/// function returns. Returns error if any.
736+
std::error_code readVTableTypeCountMap(TypeCountMap &M);
737+
bool ReadVTableProf = false;
738+
739739
private:
740740
std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
741741
virtual std::error_code verifySPMagic(uint64_t Magic) = 0;
@@ -825,8 +825,6 @@ class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary {
825825
/// The set containing the functions to use when compiling a module.
826826
DenseSet<StringRef> FuncsToUse;
827827

828-
bool ReadVTableProf = false;
829-
830828
public:
831829
SampleProfileReaderExtBinaryBase(std::unique_ptr<MemoryBuffer> B,
832830
LLVMContext &C, SampleProfileFormat Format)
@@ -867,12 +865,6 @@ class SampleProfileReaderExtBinary : public SampleProfileReaderExtBinaryBase {
867865
return sampleprof_error::success;
868866
};
869867

870-
std::error_code readVTableProf(const LineLocation &Loc,
871-
FunctionSamples &FProfile) override;
872-
873-
std::error_code readCallsiteVTableProf(FunctionSamples &FProfile) override;
874-
875-
std::error_code readTypeMap(TypeMap& M);
876868
public:
877869
SampleProfileReaderExtBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
878870
SampleProfileFormat Format = SPF_Ext_Binary)

llvm/include/llvm/ProfileData/SampleProfWriter.h

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -209,17 +209,7 @@ class SampleProfileWriterBinary : public SampleProfileWriter {
209209
virtual MapVector<FunctionId, uint32_t> &getNameTable() { return NameTable; }
210210
virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
211211
virtual std::error_code writeNameTable();
212-
virtual std::error_code
213-
writeSampleRecordVTableProf(const SampleRecord &Record, raw_ostream &OS) {
214-
// TODO: This is not virtual because SampleProfWriter may create objects of
215-
// type SampleProfileWriterRawBinary.
216-
return sampleprof_error::success;
217-
}
218-
virtual std::error_code
219-
writeCallsiteType(const FunctionSamples &FunctionSample, raw_ostream &OS) {
220-
return sampleprof_error::success;
221-
}
222-
virtual void addTypeNames(const TypeMap &M) {}
212+
223213
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
224214
std::error_code writeSummary();
225215
virtual std::error_code writeContextIdx(const SampleContext &Context);
@@ -231,10 +221,23 @@ class SampleProfileWriterBinary : public SampleProfileWriter {
231221
MapVector<FunctionId, uint32_t> NameTable;
232222

233223
void addName(FunctionId FName);
234-
void addTypeName(FunctionId TypeName);
224+
/// void addTypeName(FunctionId TypeName);
235225
virtual void addContext(const SampleContext &Context);
236226
void addNames(const FunctionSamples &S);
237227

228+
/// Add the type names to NameTable.
229+
void addTypeNames(const TypeCountMap &M);
230+
231+
/// Write \p CallsiteTypeMap to the output stream \p OS.
232+
std::error_code
233+
writeCallsiteVTableProf(const CallsiteTypeMap &CallsiteTypeMap,
234+
raw_ostream &OS);
235+
/// Write \p Map to the output stream \p OS.
236+
std::error_code writeTypeMap(const TypeCountMap &Map, raw_ostream &OS);
237+
238+
// TODO:This should be configurable by flag.
239+
bool WriteVTableProf = false;
240+
238241
private:
239242
friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
240243
SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
@@ -423,22 +426,6 @@ class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase {
423426
public:
424427
SampleProfileWriterExtBinary(std::unique_ptr<raw_ostream> &OS);
425428

426-
protected:
427-
std::error_code writeSampleRecordVTableProf(const SampleRecord &Record,
428-
raw_ostream &OS) override;
429-
430-
std::error_code writeCallsiteType(const FunctionSamples &FunctionSample,
431-
raw_ostream &OS) override;
432-
433-
void addTypeNames(const TypeMap &M) override {
434-
if (!WriteVTableProf)
435-
return;
436-
// Add type name to TypeNameTable.
437-
for (const auto &[Type, Cnt] : M) {
438-
addName(Type);
439-
}
440-
}
441-
442429
private:
443430
std::error_code writeDefaultLayout(const SampleProfileMap &ProfileMap);
444431
std::error_code writeCtxSplitLayout(const SampleProfileMap &ProfileMap);
@@ -453,11 +440,6 @@ class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase {
453440
assert((SL == DefaultLayout || SL == CtxSplitLayout) &&
454441
"Unsupported layout");
455442
}
456-
457-
std::error_code writeTypeMap(const TypeMap &Map, raw_ostream& OS);
458-
459-
// TODO:This should be configurable by flag.
460-
bool WriteVTableProf = false;
461443
};
462444

463445
} // end namespace sampleprof

0 commit comments

Comments
 (0)