Skip to content

Commit 2664d70

Browse files
profile format change
1 parent ebba554 commit 2664d70

File tree

5 files changed

+230
-10
lines changed

5 files changed

+230
-10
lines changed

llvm/include/llvm/ProfileData/SampleProf.h

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ enum class SecProfSummaryFlags : uint32_t {
201201
/// SecFlagIsPreInlined means this profile contains ShouldBeInlined
202202
/// contexts thus this is CS preinliner computed.
203203
SecFlagIsPreInlined = (1 << 4),
204+
205+
/// SecFlagHasVTableTypeProf means this profile contains vtable type profiles.
206+
SecFlagHasVTableTypeProf = (1 << 5),
204207
};
205208

206209
enum class SecFuncMetadataFlags : uint32_t {
@@ -312,16 +315,19 @@ struct LineLocationHash {
312315

313316
raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc);
314317

318+
using TypeMap = std::map<FunctionId, uint64_t>;
319+
315320
/// Representation of a single sample record.
316321
///
317322
/// A sample record is represented by a positive integer value, which
318323
/// indicates how frequently was the associated line location executed.
319324
///
320325
/// Additionally, if the associated location contains a function call,
321-
/// the record will hold a list of all the possible called targets. For
322-
/// direct calls, this will be the exact function being invoked. For
323-
/// indirect calls (function pointers, virtual table dispatch), this
324-
/// will be a list of one or more functions.
326+
/// the record will hold a list of all the possible called targets and the types
327+
/// for virtual table dispatches. For direct calls, this will be the exact
328+
/// function being invoked. For indirect calls (function pointers, virtual table
329+
/// dispatch), this will be a list of one or more functions. For virtual table
330+
/// dispatches, this record will also hold the type of the object.
325331
class SampleRecord {
326332
public:
327333
using CallTarget = std::pair<FunctionId, uint64_t>;
@@ -336,6 +342,7 @@ class SampleRecord {
336342

337343
using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>;
338344
using CallTargetMap = std::unordered_map<FunctionId, uint64_t>;
345+
339346
SampleRecord() = default;
340347

341348
/// Increment the number of samples for this record by \p S.
@@ -374,6 +381,14 @@ class SampleRecord {
374381
: sampleprof_error::success;
375382
}
376383

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+
}
391+
377392
/// Remove called function from the call target map. Return the target sample
378393
/// count of the called function.
379394
uint64_t removeCalledTarget(FunctionId F) {
@@ -391,6 +406,7 @@ class SampleRecord {
391406

392407
uint64_t getSamples() const { return NumSamples; }
393408
const CallTargetMap &getCallTargets() const { return CallTargets; }
409+
const TypeMap &getTypes() const { return TypeCounts; }
394410
const SortedCallTargetSet getSortedCallTargets() const {
395411
return sortCallTargets(CallTargets);
396412
}
@@ -439,6 +455,7 @@ class SampleRecord {
439455
private:
440456
uint64_t NumSamples = 0;
441457
CallTargetMap CallTargets;
458+
TypeMap TypeCounts;
442459
};
443460

444461
raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample);
@@ -734,6 +751,7 @@ using BodySampleMap = std::map<LineLocation, SampleRecord>;
734751
// memory, which is *very* significant for large profiles.
735752
using FunctionSamplesMap = std::map<FunctionId, FunctionSamples>;
736753
using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;
754+
using CallsiteTypeMap = std::map<LineLocation, TypeMap>;
737755
using LocToLocMap =
738756
std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
739757

@@ -791,6 +809,11 @@ class FunctionSamples {
791809
Func, Num, Weight);
792810
}
793811

812+
sampleprof_error addTypeSamples(const LineLocation &Loc, FunctionId Func,
813+
uint64_t Num, uint64_t Weight = 1) {
814+
return BodySamples[Loc].addTypeCount(Func, Num, Weight);
815+
}
816+
794817
sampleprof_error addSampleRecord(LineLocation Location,
795818
const SampleRecord &SampleRecord,
796819
uint64_t Weight = 1) {
@@ -916,6 +939,13 @@ class FunctionSamples {
916939
return &Iter->second;
917940
}
918941

942+
const TypeMap *findTypeSamplesAt(const LineLocation &Loc) const {
943+
auto Iter = VirtualCallsiteTypes.find(mapIRLocToProfileLoc(Loc));
944+
if (Iter == VirtualCallsiteTypes.end())
945+
return nullptr;
946+
return &Iter->second;
947+
}
948+
919949
/// Returns a pointer to FunctionSamples at the given callsite location
920950
/// \p Loc with callee \p CalleeName. If no callsite can be found, relax
921951
/// the restriction to return the FunctionSamples at callsite location
@@ -977,6 +1007,14 @@ class FunctionSamples {
9771007
return CallsiteSamples;
9781008
}
9791009

1010+
const CallsiteTypeMap &getCallsiteTypes() const {
1011+
return VirtualCallsiteTypes;
1012+
}
1013+
1014+
TypeMap& getTypeSamplesAt(const LineLocation &Loc) {
1015+
return VirtualCallsiteTypes[mapIRLocToProfileLoc(Loc)];
1016+
}
1017+
9801018
/// Return the maximum of sample counts in a function body. When SkipCallSite
9811019
/// is false, which is the default, the return count includes samples in the
9821020
/// inlined functions. When SkipCallSite is true, the return count only
@@ -1274,6 +1312,8 @@ class FunctionSamples {
12741312
/// collected in the call to baz() at line offset 8.
12751313
CallsiteSampleMap CallsiteSamples;
12761314

1315+
CallsiteTypeMap VirtualCallsiteTypes;
1316+
12771317
/// IR to profile location map generated by stale profile matching.
12781318
///
12791319
/// Each entry is a mapping from the location on current build to the matched

llvm/include/llvm/ProfileData/SampleProfReader.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,17 @@ 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+
714+
704715
/// Points to the current location in the buffer.
705716
const uint8_t *Data = nullptr;
706717

@@ -814,6 +825,8 @@ class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary {
814825
/// The set containing the functions to use when compiling a module.
815826
DenseSet<StringRef> FuncsToUse;
816827

828+
bool ReadVTableProf = false;
829+
817830
public:
818831
SampleProfileReaderExtBinaryBase(std::unique_ptr<MemoryBuffer> B,
819832
LLVMContext &C, SampleProfileFormat Format)
@@ -854,6 +867,12 @@ class SampleProfileReaderExtBinary : public SampleProfileReaderExtBinaryBase {
854867
return sampleprof_error::success;
855868
};
856869

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);
857876
public:
858877
SampleProfileReaderExtBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
859878
SampleProfileFormat Format = SPF_Ext_Binary)

llvm/include/llvm/ProfileData/SampleProfWriter.h

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@ 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) {}
212223
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
213224
std::error_code writeSummary();
214225
virtual std::error_code writeContextIdx(const SampleContext &Context);
@@ -218,8 +229,9 @@ class SampleProfileWriterBinary : public SampleProfileWriter {
218229
std::set<FunctionId> &V);
219230

220231
MapVector<FunctionId, uint32_t> NameTable;
221-
232+
222233
void addName(FunctionId FName);
234+
void addTypeName(FunctionId TypeName);
223235
virtual void addContext(const SampleContext &Context);
224236
void addNames(const FunctionSamples &S);
225237

@@ -409,8 +421,23 @@ class SampleProfileWriterExtBinaryBase : public SampleProfileWriterBinary {
409421

410422
class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase {
411423
public:
412-
SampleProfileWriterExtBinary(std::unique_ptr<raw_ostream> &OS)
413-
: SampleProfileWriterExtBinaryBase(OS) {}
424+
SampleProfileWriterExtBinary(std::unique_ptr<raw_ostream> &OS);
425+
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+
}
414441

415442
private:
416443
std::error_code writeDefaultLayout(const SampleProfileMap &ProfileMap);
@@ -426,6 +453,11 @@ class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase {
426453
assert((SL == DefaultLayout || SL == CtxSplitLayout) &&
427454
"Unsupported layout");
428455
}
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;
429461
};
430462

431463
} // end namespace sampleprof

llvm/lib/ProfileData/SampleProfReader.cpp

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,67 @@ SampleProfileReaderBinary::readSampleContextFromTable() {
594594
return std::make_pair(Context, Hash);
595595
}
596596

597+
std::error_code SampleProfileReaderExtBinary::readTypeMap(TypeMap &M) {
598+
auto NumVTableTypes = readNumber<uint32_t>();
599+
if (std::error_code EC = NumVTableTypes.getError())
600+
return EC;
601+
602+
for (uint32_t I = 0; I < *NumVTableTypes; ++I) {
603+
auto VTableType(readStringFromTable());
604+
if (std::error_code EC = VTableType.getError())
605+
return EC;
606+
607+
auto VTableSamples = readNumber<uint64_t>();
608+
if (std::error_code EC = VTableSamples.getError())
609+
return EC;
610+
611+
M.insert(std::make_pair(*VTableType, *VTableSamples));
612+
}
613+
return sampleprof_error::success;
614+
}
615+
616+
std::error_code
617+
SampleProfileReaderExtBinary::readVTableProf(const LineLocation &Loc,
618+
FunctionSamples &FProfile) {
619+
if (!ReadVTableProf)
620+
return sampleprof_error::success;
621+
622+
return readTypeMap(FProfile.getTypeSamplesAt(Loc));
623+
}
624+
625+
std::error_code SampleProfileReaderExtBinary::readCallsiteVTableProf(
626+
FunctionSamples &FProfile) {
627+
if (!ReadVTableProf)
628+
return sampleprof_error::success;
629+
630+
// Read the vtable type profile for the callsite.
631+
auto NumCallsites = readNumber<uint32_t>();
632+
if (std::error_code EC = NumCallsites.getError())
633+
return EC;
634+
635+
for (uint32_t I = 0; I < *NumCallsites; ++I) {
636+
auto LineOffset = readNumber<uint64_t>();
637+
if (std::error_code EC = LineOffset.getError())
638+
return EC;
639+
640+
auto Discriminator = readNumber<uint64_t>();
641+
if (std::error_code EC = Discriminator.getError())
642+
return EC;
643+
644+
// Here we handle FS discriminators:
645+
uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
646+
647+
if (!isOffsetLegal(*LineOffset)) {
648+
return std::error_code();
649+
}
650+
651+
if (std::error_code EC = readVTableProf(
652+
LineLocation(*LineOffset, DiscriminatorVal), FProfile))
653+
return EC;
654+
}
655+
return sampleprof_error::success;
656+
}
657+
597658
std::error_code
598659
SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
599660
auto NumSamples = readNumber<uint64_t>();
@@ -643,6 +704,11 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
643704
*CalledFunction, *CalledFunctionSamples);
644705
}
645706

707+
// read vtable type profiles.
708+
if (std::error_code EC = readVTableProf(
709+
LineLocation(*LineOffset, DiscriminatorVal), FProfile))
710+
return EC;
711+
646712
FProfile.addBodySamples(*LineOffset, DiscriminatorVal, *NumSamples);
647713
}
648714

@@ -674,7 +740,7 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
674740
return EC;
675741
}
676742

677-
return sampleprof_error::success;
743+
return readCallsiteVTableProf(FProfile);
678744
}
679745

680746
std::error_code
@@ -736,6 +802,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
736802
FunctionSamples::ProfileIsPreInlined = ProfileIsPreInlined = true;
737803
if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFSDiscriminator))
738804
FunctionSamples::ProfileIsFS = ProfileIsFS = true;
805+
if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagHasVTableTypeProf))
806+
ReadVTableProf = true;
739807
break;
740808
case SecNameTable: {
741809
bool FixedLengthMD5 =

0 commit comments

Comments
 (0)