Skip to content

Commit 8c8ec1f

Browse files
committedOct 18, 2019
[SampleFDO] Add profile remapping support for profile on-demand loading used
by ExtBinary format profile Profile on-demand loading was added for ExtBinary format profile in rL374233, but currently profile on-demand loading doesn't work well with profile remapping. The patch adds the support. Suppose a function in the current module has outline instance in the profile. The function name in the module is different from the name of the outline instance, but remapper knows the two names are equal. When loading profile on-demand, the outline instance has to be loaded with remapper's help. At the same time SampleProfileReaderItaniumRemapper is changed from a proxy of SampleProfileReader to a helper member in SampleProfileReader. Differential Revision: https://reviews.llvm.org/D68901 llvm-svn: 375295
1 parent 06a2bea commit 8c8ec1f

File tree

5 files changed

+233
-132
lines changed

5 files changed

+233
-132
lines changed
 

‎llvm/include/llvm/ProfileData/SampleProfReader.h

+88-49
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,62 @@ class raw_ostream;
235235

236236
namespace sampleprof {
237237

238+
class SampleProfileReader;
239+
240+
/// SampleProfileReaderItaniumRemapper remaps the profile data from a
241+
/// sample profile data reader, by applying a provided set of equivalences
242+
/// between components of the symbol names in the profile.
243+
class SampleProfileReaderItaniumRemapper {
244+
public:
245+
SampleProfileReaderItaniumRemapper(std::unique_ptr<MemoryBuffer> B,
246+
std::unique_ptr<SymbolRemappingReader> SRR,
247+
SampleProfileReader &R)
248+
: Buffer(std::move(B)), Remappings(std::move(SRR)), Reader(R) {
249+
assert(Remappings && "Remappings cannot be nullptr");
250+
}
251+
252+
/// Create a remapper from the given remapping file. The remapper will
253+
/// be used for profile read in by Reader.
254+
static ErrorOr<std::unique_ptr<SampleProfileReaderItaniumRemapper>>
255+
create(const std::string Filename, SampleProfileReader &Reader,
256+
LLVMContext &C);
257+
258+
/// Create a remapper from the given Buffer. The remapper will
259+
/// be used for profile read in by Reader.
260+
static ErrorOr<std::unique_ptr<SampleProfileReaderItaniumRemapper>>
261+
create(std::unique_ptr<MemoryBuffer> &B, SampleProfileReader &Reader,
262+
LLVMContext &C);
263+
264+
/// Apply remappings to the profile read by Reader.
265+
void applyRemapping(LLVMContext &Ctx);
266+
267+
bool hasApplied() { return RemappingApplied; }
268+
269+
/// Insert function name into remapper.
270+
void insert(StringRef FunctionName) { Remappings->insert(FunctionName); }
271+
272+
/// Query whether there is equivalent in the remapper which has been
273+
/// inserted.
274+
bool exist(StringRef FunctionName) {
275+
return Remappings->lookup(FunctionName);
276+
}
277+
278+
/// Return the samples collected for function \p F if remapper knows
279+
/// it is present in SampleMap.
280+
FunctionSamples *getSamplesFor(StringRef FunctionName);
281+
282+
private:
283+
// The buffer holding the content read from remapping file.
284+
std::unique_ptr<MemoryBuffer> Buffer;
285+
std::unique_ptr<SymbolRemappingReader> Remappings;
286+
DenseMap<SymbolRemappingReader::Key, FunctionSamples *> SampleMap;
287+
// The Reader the remapper is servicing.
288+
SampleProfileReader &Reader;
289+
// Indicate whether remapping has been applied to the profile read
290+
// by Reader -- by calling applyRemapping.
291+
bool RemappingApplied = false;
292+
};
293+
238294
/// Sample-based profile reader.
239295
///
240296
/// Each profile contains sample counts for all the functions
@@ -273,8 +329,17 @@ class SampleProfileReader {
273329
/// Read and validate the file header.
274330
virtual std::error_code readHeader() = 0;
275331

276-
/// Read sample profiles from the associated file.
277-
virtual std::error_code read() = 0;
332+
/// The interface to read sample profiles from the associated file.
333+
std::error_code read() {
334+
if (std::error_code EC = readImpl())
335+
return EC;
336+
if (Remapper)
337+
Remapper->applyRemapping(Ctx);
338+
return sampleprof_error::success;
339+
}
340+
341+
/// The implementaion to read sample profiles from the associated file.
342+
virtual std::error_code readImpl() = 0;
278343

279344
/// Print the profile for \p FName on stream \p OS.
280345
void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs());
@@ -295,6 +360,10 @@ class SampleProfileReader {
295360

296361
/// Return the samples collected for function \p F.
297362
virtual FunctionSamples *getSamplesFor(StringRef Fname) {
363+
if (Remapper) {
364+
if (auto FS = Remapper->getSamplesFor(Fname))
365+
return FS;
366+
}
298367
std::string FGUID;
299368
Fname = getRepInFormat(Fname, getFormat(), FGUID);
300369
auto It = Profiles.find(Fname);
@@ -313,18 +382,24 @@ class SampleProfileReader {
313382
}
314383

315384
/// Create a sample profile reader appropriate to the file format.
385+
/// Create a remapper underlying if RemapFilename is not empty.
316386
static ErrorOr<std::unique_ptr<SampleProfileReader>>
317-
create(const Twine &Filename, LLVMContext &C);
387+
create(const std::string Filename, LLVMContext &C,
388+
const std::string RemapFilename = "");
318389

319390
/// Create a sample profile reader from the supplied memory buffer.
391+
/// Create a remapper underlying if RemapFilename is not empty.
320392
static ErrorOr<std::unique_ptr<SampleProfileReader>>
321-
create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C);
393+
create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C,
394+
const std::string RemapFilename = "");
322395

323396
/// Return the profile summary.
324-
ProfileSummary &getSummary() { return *(Summary.get()); }
397+
ProfileSummary &getSummary() const { return *(Summary.get()); }
398+
399+
MemoryBuffer *getBuffer() const { return Buffer.get(); }
325400

326401
/// \brief Return the profile format.
327-
SampleProfileFormat getFormat() { return Format; }
402+
SampleProfileFormat getFormat() const { return Format; }
328403

329404
virtual std::unique_ptr<ProfileSymbolList> getProfileSymbolList() {
330405
return nullptr;
@@ -361,6 +436,8 @@ class SampleProfileReader {
361436
/// Compute summary for this profile.
362437
void computeSummary();
363438

439+
std::unique_ptr<SampleProfileReaderItaniumRemapper> Remapper;
440+
364441
/// \brief The format of sample.
365442
SampleProfileFormat Format = SPF_None;
366443
};
@@ -374,7 +451,7 @@ class SampleProfileReaderText : public SampleProfileReader {
374451
std::error_code readHeader() override { return sampleprof_error::success; }
375452

376453
/// Read sample profiles from the associated file.
377-
std::error_code read() override;
454+
std::error_code readImpl() override;
378455

379456
/// Return true if \p Buffer is in the format supported by this class.
380457
static bool hasFormat(const MemoryBuffer &Buffer);
@@ -390,7 +467,7 @@ class SampleProfileReaderBinary : public SampleProfileReader {
390467
virtual std::error_code readHeader() override;
391468

392469
/// Read sample profiles from the associated file.
393-
std::error_code read() override;
470+
std::error_code readImpl() override;
394471

395472
/// It includes all the names that have samples either in outline instance
396473
/// or inline instance.
@@ -512,7 +589,7 @@ class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary {
512589
: SampleProfileReaderBinary(std::move(B), C, Format) {}
513590

514591
/// Read sample profiles in extensible format from the associated file.
515-
std::error_code read() override;
592+
std::error_code readImpl() override;
516593

517594
/// Get the total size of all \p Type sections.
518595
uint64_t getSectionSize(SecType Type);
@@ -581,7 +658,7 @@ class SampleProfileReaderCompactBinary : public SampleProfileReaderBinary {
581658
static bool hasFormat(const MemoryBuffer &Buffer);
582659

583660
/// Read samples only for functions to use.
584-
std::error_code read() override;
661+
std::error_code readImpl() override;
585662

586663
/// Collect functions to be used when compiling Module \p M.
587664
void collectFuncsFrom(const Module &M) override;
@@ -612,7 +689,7 @@ class SampleProfileReaderGCC : public SampleProfileReader {
612689
std::error_code readHeader() override;
613690

614691
/// Read sample profiles from the associated file.
615-
std::error_code read() override;
692+
std::error_code readImpl() override;
616693

617694
/// Return true if \p Buffer is in the format supported by this class.
618695
static bool hasFormat(const MemoryBuffer &Buffer);
@@ -640,44 +717,6 @@ class SampleProfileReaderGCC : public SampleProfileReader {
640717
static const uint32_t GCOVTagAFDOFunction = 0xac000000;
641718
};
642719

643-
/// A profile data reader proxy that remaps the profile data from another
644-
/// sample profile data reader, by applying a provided set of equivalences
645-
/// between components of the symbol names in the profile.
646-
class SampleProfileReaderItaniumRemapper : public SampleProfileReader {
647-
public:
648-
SampleProfileReaderItaniumRemapper(
649-
std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
650-
std::unique_ptr<SampleProfileReader> Underlying)
651-
: SampleProfileReader(std::move(B), C, Underlying->getFormat()) {
652-
Profiles = std::move(Underlying->getProfiles());
653-
Summary = takeSummary(*Underlying);
654-
// Keep the underlying reader alive; the profile data may contain
655-
// StringRefs referencing names in its name table.
656-
UnderlyingReader = std::move(Underlying);
657-
}
658-
659-
/// Create a remapped sample profile from the given remapping file and
660-
/// underlying samples.
661-
static ErrorOr<std::unique_ptr<SampleProfileReader>>
662-
create(const Twine &Filename, LLVMContext &C,
663-
std::unique_ptr<SampleProfileReader> Underlying);
664-
665-
/// Read and validate the file header.
666-
std::error_code readHeader() override { return sampleprof_error::success; }
667-
668-
/// Read remapping file and apply it to the sample profile.
669-
std::error_code read() override;
670-
671-
/// Return the samples collected for function \p F.
672-
FunctionSamples *getSamplesFor(StringRef FunctionName) override;
673-
using SampleProfileReader::getSamplesFor;
674-
675-
private:
676-
SymbolRemappingReader Remappings;
677-
DenseMap<SymbolRemappingReader::Key, FunctionSamples*> SampleMap;
678-
std::unique_ptr<SampleProfileReader> UnderlyingReader;
679-
};
680-
681720
} // end namespace sampleprof
682721

683722
} // end namespace llvm

‎llvm/lib/ProfileData/SampleProfReader.cpp

+83-37
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ static bool ParseLine(const StringRef &Input, bool &IsCallsite, uint32_t &Depth,
191191
/// the expected format.
192192
///
193193
/// \returns true if the file was loaded successfully, false otherwise.
194-
std::error_code SampleProfileReaderText::read() {
194+
std::error_code SampleProfileReaderText::readImpl() {
195195
line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#');
196196
sampleprof_error Result = sampleprof_error::success;
197197

@@ -461,7 +461,7 @@ SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) {
461461
return sampleprof_error::success;
462462
}
463463

464-
std::error_code SampleProfileReaderBinary::read() {
464+
std::error_code SampleProfileReaderBinary::readImpl() {
465465
while (!at_eof()) {
466466
if (std::error_code EC = readFuncProfile(Data))
467467
return EC;
@@ -540,15 +540,23 @@ std::error_code SampleProfileReaderExtBinary::readFuncProfiles() {
540540
return sampleprof_error::success;
541541
}
542542

543-
for (auto Name : FuncsToUse) {
544-
auto iter = FuncOffsetTable.find(Name);
545-
if (iter == FuncOffsetTable.end())
543+
if (Remapper) {
544+
for (auto Name : FuncsToUse) {
545+
Remapper->insert(Name);
546+
}
547+
}
548+
549+
for (auto NameOffset : FuncOffsetTable) {
550+
auto FuncName = NameOffset.first;
551+
if (!FuncsToUse.count(FuncName) &&
552+
(!Remapper || !Remapper->exist(FuncName)))
546553
continue;
547-
const uint8_t *FuncProfileAddr = Start + iter->second;
554+
const uint8_t *FuncProfileAddr = Start + NameOffset.second;
548555
assert(FuncProfileAddr < End && "out of LBRProfile section");
549556
if (std::error_code EC = readFuncProfile(FuncProfileAddr))
550557
return EC;
551558
}
559+
552560
Data = End;
553561
return sampleprof_error::success;
554562
}
@@ -593,7 +601,7 @@ std::error_code SampleProfileReaderExtBinaryBase::decompressSection(
593601
return sampleprof_error::success;
594602
}
595603

596-
std::error_code SampleProfileReaderExtBinaryBase::read() {
604+
std::error_code SampleProfileReaderExtBinaryBase::readImpl() {
597605
const uint8_t *BufStart =
598606
reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
599607

@@ -635,7 +643,7 @@ std::error_code SampleProfileReaderExtBinaryBase::read() {
635643
return sampleprof_error::success;
636644
}
637645

638-
std::error_code SampleProfileReaderCompactBinary::read() {
646+
std::error_code SampleProfileReaderCompactBinary::readImpl() {
639647
std::vector<uint64_t> OffsetsToUse;
640648
if (UseAllFuncs) {
641649
for (auto FuncEntry : FuncOffsetTable) {
@@ -1184,7 +1192,7 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
11841192
///
11851193
/// This format is generated by the Linux Perf conversion tool at
11861194
/// https://github.com/google/autofdo.
1187-
std::error_code SampleProfileReaderGCC::read() {
1195+
std::error_code SampleProfileReaderGCC::readImpl() {
11881196
// Read the string table.
11891197
if (std::error_code EC = readNameTable())
11901198
return EC;
@@ -1201,38 +1209,31 @@ bool SampleProfileReaderGCC::hasFormat(const MemoryBuffer &Buffer) {
12011209
return Magic == "adcg*704";
12021210
}
12031211

1204-
std::error_code SampleProfileReaderItaniumRemapper::read() {
1205-
// If the underlying data is in compact format, we can't remap it because
1212+
void SampleProfileReaderItaniumRemapper::applyRemapping(LLVMContext &Ctx) {
1213+
// If the reader is in compact format, we can't remap it because
12061214
// we don't know what the original function names were.
1207-
if (getFormat() == SPF_Compact_Binary) {
1215+
if (Reader.getFormat() == SPF_Compact_Binary) {
12081216
Ctx.diagnose(DiagnosticInfoSampleProfile(
1209-
Buffer->getBufferIdentifier(),
1217+
Reader.getBuffer()->getBufferIdentifier(),
12101218
"Profile data remapping cannot be applied to profile data "
12111219
"in compact format (original mangled names are not available).",
12121220
DS_Warning));
1213-
return sampleprof_error::success;
1214-
}
1215-
1216-
if (Error E = Remappings.read(*Buffer)) {
1217-
handleAllErrors(
1218-
std::move(E), [&](const SymbolRemappingParseError &ParseError) {
1219-
reportError(ParseError.getLineNum(), ParseError.getMessage());
1220-
});
1221-
return sampleprof_error::malformed;
1221+
return;
12221222
}
12231223

1224-
for (auto &Sample : getProfiles())
1225-
if (auto Key = Remappings.insert(Sample.first()))
1224+
assert(Remappings && "should be initialized while creating remapper");
1225+
for (auto &Sample : Reader.getProfiles())
1226+
if (auto Key = Remappings->insert(Sample.first()))
12261227
SampleMap.insert({Key, &Sample.second});
12271228

1228-
return sampleprof_error::success;
1229+
RemappingApplied = true;
12291230
}
12301231

12311232
FunctionSamples *
12321233
SampleProfileReaderItaniumRemapper::getSamplesFor(StringRef Fname) {
1233-
if (auto Key = Remappings.lookup(Fname))
1234+
if (auto Key = Remappings->lookup(Fname))
12341235
return SampleMap.lookup(Key);
1235-
return SampleProfileReader::getSamplesFor(Fname);
1236+
return nullptr;
12361237
}
12371238

12381239
/// Prepare a memory buffer for the contents of \p Filename.
@@ -1258,34 +1259,65 @@ setupMemoryBuffer(const Twine &Filename) {
12581259
///
12591260
/// \param C The LLVM context to use to emit diagnostics.
12601261
///
1262+
/// \param RemapFilename The file used for profile remapping.
1263+
///
12611264
/// \returns an error code indicating the status of the created reader.
12621265
ErrorOr<std::unique_ptr<SampleProfileReader>>
1263-
SampleProfileReader::create(const Twine &Filename, LLVMContext &C) {
1266+
SampleProfileReader::create(const std::string Filename, LLVMContext &C,
1267+
const std::string RemapFilename) {
12641268
auto BufferOrError = setupMemoryBuffer(Filename);
12651269
if (std::error_code EC = BufferOrError.getError())
12661270
return EC;
1267-
return create(BufferOrError.get(), C);
1271+
return create(BufferOrError.get(), C, RemapFilename);
12681272
}
12691273

12701274
/// Create a sample profile remapper from the given input, to remap the
12711275
/// function names in the given profile data.
12721276
///
12731277
/// \param Filename The file to open.
12741278
///
1275-
/// \param C The LLVM context to use to emit diagnostics.
1279+
/// \param Reader The profile reader the remapper is going to be applied to.
12761280
///
1277-
/// \param Underlying The underlying profile data reader to remap.
1281+
/// \param C The LLVM context to use to emit diagnostics.
12781282
///
12791283
/// \returns an error code indicating the status of the created reader.
1280-
ErrorOr<std::unique_ptr<SampleProfileReader>>
1281-
SampleProfileReaderItaniumRemapper::create(
1282-
const Twine &Filename, LLVMContext &C,
1283-
std::unique_ptr<SampleProfileReader> Underlying) {
1284+
ErrorOr<std::unique_ptr<SampleProfileReaderItaniumRemapper>>
1285+
SampleProfileReaderItaniumRemapper::create(const std::string Filename,
1286+
SampleProfileReader &Reader,
1287+
LLVMContext &C) {
12841288
auto BufferOrError = setupMemoryBuffer(Filename);
12851289
if (std::error_code EC = BufferOrError.getError())
12861290
return EC;
1291+
return create(BufferOrError.get(), Reader, C);
1292+
}
1293+
1294+
/// Create a sample profile remapper from the given input, to remap the
1295+
/// function names in the given profile data.
1296+
///
1297+
/// \param B The memory buffer to create the reader from (assumes ownership).
1298+
///
1299+
/// \param C The LLVM context to use to emit diagnostics.
1300+
///
1301+
/// \param Reader The profile reader the remapper is going to be applied to.
1302+
///
1303+
/// \returns an error code indicating the status of the created reader.
1304+
ErrorOr<std::unique_ptr<SampleProfileReaderItaniumRemapper>>
1305+
SampleProfileReaderItaniumRemapper::create(std::unique_ptr<MemoryBuffer> &B,
1306+
SampleProfileReader &Reader,
1307+
LLVMContext &C) {
1308+
auto Remappings = std::make_unique<SymbolRemappingReader>();
1309+
if (Error E = Remappings->read(*B.get())) {
1310+
handleAllErrors(
1311+
std::move(E), [&](const SymbolRemappingParseError &ParseError) {
1312+
C.diagnose(DiagnosticInfoSampleProfile(B->getBufferIdentifier(),
1313+
ParseError.getLineNum(),
1314+
ParseError.getMessage()));
1315+
});
1316+
return sampleprof_error::malformed;
1317+
}
1318+
12871319
return std::make_unique<SampleProfileReaderItaniumRemapper>(
1288-
std::move(BufferOrError.get()), C, std::move(Underlying));
1320+
std::move(B), std::move(Remappings), Reader);
12891321
}
12901322

12911323
/// Create a sample profile reader based on the format of the input data.
@@ -1294,9 +1326,12 @@ SampleProfileReaderItaniumRemapper::create(
12941326
///
12951327
/// \param C The LLVM context to use to emit diagnostics.
12961328
///
1329+
/// \param RemapFilename The file used for profile remapping.
1330+
///
12971331
/// \returns an error code indicating the status of the created reader.
12981332
ErrorOr<std::unique_ptr<SampleProfileReader>>
1299-
SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C) {
1333+
SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C,
1334+
const std::string RemapFilename) {
13001335
std::unique_ptr<SampleProfileReader> Reader;
13011336
if (SampleProfileReaderRawBinary::hasFormat(*B))
13021337
Reader.reset(new SampleProfileReaderRawBinary(std::move(B), C));
@@ -1311,6 +1346,17 @@ SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C) {
13111346
else
13121347
return sampleprof_error::unrecognized_format;
13131348

1349+
if (!RemapFilename.empty()) {
1350+
auto ReaderOrErr =
1351+
SampleProfileReaderItaniumRemapper::create(RemapFilename, *Reader, C);
1352+
if (std::error_code EC = ReaderOrErr.getError()) {
1353+
std::string Msg = "Could not create remapper: " + EC.message();
1354+
C.diagnose(DiagnosticInfoSampleProfile(RemapFilename, Msg));
1355+
return EC;
1356+
}
1357+
Reader->Remapper = std::move(ReaderOrErr.get());
1358+
}
1359+
13141360
FunctionSamples::Format = Reader->getFormat();
13151361
if (std::error_code EC = Reader->readHeader()) {
13161362
return EC;

‎llvm/lib/Transforms/IPO/SampleProfile.cpp

+4-15
Original file line numberDiff line numberDiff line change
@@ -1675,7 +1675,10 @@ INITIALIZE_PASS_END(SampleProfileLoaderLegacyPass, "sample-profile",
16751675

16761676
bool SampleProfileLoader::doInitialization(Module &M) {
16771677
auto &Ctx = M.getContext();
1678-
auto ReaderOrErr = SampleProfileReader::create(Filename, Ctx);
1678+
1679+
std::unique_ptr<SampleProfileReaderItaniumRemapper> RemapReader;
1680+
auto ReaderOrErr =
1681+
SampleProfileReader::create(Filename, Ctx, RemappingFilename);
16791682
if (std::error_code EC = ReaderOrErr.getError()) {
16801683
std::string Msg = "Could not open profile: " + EC.message();
16811684
Ctx.diagnose(DiagnosticInfoSampleProfile(Filename, Msg));
@@ -1695,20 +1698,6 @@ bool SampleProfileLoader::doInitialization(Module &M) {
16951698
NamesInProfile.insert(NameTable->begin(), NameTable->end());
16961699
}
16971700

1698-
if (!RemappingFilename.empty()) {
1699-
// Apply profile remappings to the loaded profile data if requested.
1700-
// For now, we only support remapping symbols encoded using the Itanium
1701-
// C++ ABI's name mangling scheme.
1702-
ReaderOrErr = SampleProfileReaderItaniumRemapper::create(
1703-
RemappingFilename, Ctx, std::move(Reader));
1704-
if (std::error_code EC = ReaderOrErr.getError()) {
1705-
std::string Msg = "Could not open profile remapping file: " + EC.message();
1706-
Ctx.diagnose(DiagnosticInfoSampleProfile(Filename, Msg));
1707-
return false;
1708-
}
1709-
Reader = std::move(ReaderOrErr.get());
1710-
ProfileIsValid = (Reader->read() == sampleprof_error::success);
1711-
}
17121701
return true;
17131702
}
17141703

‎llvm/test/Transforms/SampleProfile/remap.ll

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
; RUN: opt %s -passes=sample-profile -sample-profile-file=%S/Inputs/remap.prof -sample-profile-remapping-file=%S/Inputs/remap.map | opt -analyze -branch-prob | FileCheck %s
2-
2+
;
3+
; Check whether profile remapping work with loading profile on demand used by extbinary format profile.
4+
; RUN: llvm-profdata merge -sample -extbinary %S/Inputs/remap.prof -o %t.extbinary.afdo
5+
; RUN: opt %s -passes=sample-profile -sample-profile-file=%S/Inputs/remap.prof -sample-profile-remapping-file=%S/Inputs/remap.map | opt -analyze -branch-prob | FileCheck %s
6+
;
37
; Reduced from branch.ll
48

59
declare i1 @foo()

‎llvm/unittests/ProfileData/SampleProfTest.cpp

+53-30
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,31 @@ struct SampleProfTest : ::testing::Test {
5050
Writer = std::move(WriterOrErr.get());
5151
}
5252

53-
void readProfile(const Module &M, StringRef Profile) {
54-
auto ReaderOrErr = SampleProfileReader::create(Profile, Context);
53+
void readProfile(const Module &M, StringRef Profile,
54+
StringRef RemapFile = "") {
55+
auto ReaderOrErr = SampleProfileReader::create(Profile, Context, RemapFile);
5556
ASSERT_TRUE(NoError(ReaderOrErr.getError()));
5657
Reader = std::move(ReaderOrErr.get());
5758
Reader->collectFuncsFrom(M);
5859
}
5960

61+
void createRemapFile(SmallVectorImpl<char> &RemapPath, StringRef &RemapFile) {
62+
std::error_code EC =
63+
llvm::sys::fs::createTemporaryFile("remapfile", "", RemapPath);
64+
ASSERT_TRUE(NoError(EC));
65+
RemapFile = StringRef(RemapPath.data(), RemapPath.size());
66+
67+
std::unique_ptr<raw_fd_ostream> OS(
68+
new raw_fd_ostream(RemapFile, EC, sys::fs::OF_None));
69+
*OS << R"(
70+
# Types 'int' and 'long' are equivalent
71+
type i l
72+
# Function names 'foo' and 'faux' are equivalent
73+
name 3foo 4faux
74+
)";
75+
OS->close();
76+
}
77+
6078
void testRoundTrip(SampleProfileFormat Format, bool Remap) {
6179
SmallVector<char, 128> ProfilePath;
6280
ASSERT_TRUE(NoError(llvm::sys::fs::createTemporaryFile("profile", "", ProfilePath)));
@@ -93,16 +111,34 @@ struct SampleProfTest : ::testing::Test {
93111
BazSamples.addHeadSamples(1257);
94112
BazSamples.addBodySamples(1, 0, 12557);
95113

96-
Module M("my_module", Context);
97-
FunctionType *fn_type =
98-
FunctionType::get(Type::getVoidTy(Context), {}, false);
99-
M.getOrInsertFunction(FooName, fn_type);
100-
M.getOrInsertFunction(BarName, fn_type);
114+
StringRef BooName("_Z3booi");
115+
FunctionSamples BooSamples;
116+
BooSamples.setName(BooName);
117+
BooSamples.addTotalSamples(1232);
118+
BooSamples.addHeadSamples(1);
119+
BooSamples.addBodySamples(1, 0, 1232);
101120

102121
StringMap<FunctionSamples> Profiles;
103122
Profiles[FooName] = std::move(FooSamples);
104123
Profiles[BarName] = std::move(BarSamples);
105124
Profiles[BazName] = std::move(BazSamples);
125+
Profiles[BooName] = std::move(BooSamples);
126+
127+
Module M("my_module", Context);
128+
FunctionType *fn_type =
129+
FunctionType::get(Type::getVoidTy(Context), {}, false);
130+
131+
SmallVector<char, 128> RemapPath;
132+
StringRef RemapFile;
133+
if (Remap) {
134+
createRemapFile(RemapPath, RemapFile);
135+
FooName = "_Z4fauxi";
136+
BarName = "_Z3barl";
137+
}
138+
139+
M.getOrInsertFunction(FooName, fn_type);
140+
M.getOrInsertFunction(BarName, fn_type);
141+
M.getOrInsertFunction(BooName, fn_type);
106142

107143
ProfileSymbolList List;
108144
if (Format == SampleProfileFormat::SPF_Ext_Binary) {
@@ -117,8 +153,7 @@ struct SampleProfTest : ::testing::Test {
117153

118154
Writer->getOutputStream().flush();
119155

120-
readProfile(M, Profile);
121-
156+
readProfile(M, Profile, RemapFile);
122157
EC = Reader->read();
123158
ASSERT_TRUE(NoError(EC));
124159

@@ -129,22 +164,6 @@ struct SampleProfTest : ::testing::Test {
129164
ReaderList->contains("moo");
130165
}
131166

132-
if (Remap) {
133-
auto MemBuffer = llvm::MemoryBuffer::getMemBuffer(R"(
134-
# Types 'int' and 'long' are equivalent
135-
type i l
136-
# Function names 'foo' and 'faux' are equivalent
137-
name 3foo 4faux
138-
)");
139-
Reader.reset(new SampleProfileReaderItaniumRemapper(
140-
std::move(MemBuffer), Context, std::move(Reader)));
141-
FooName = "_Z4fauxi";
142-
BarName = "_Z3barl";
143-
144-
EC = Reader->read();
145-
ASSERT_TRUE(NoError(EC));
146-
}
147-
148167
FunctionSamples *ReadFooSamples = Reader->getSamplesFor(FooName);
149168
ASSERT_TRUE(ReadFooSamples != nullptr);
150169
if (Format != SampleProfileFormat::SPF_Compact_Binary) {
@@ -171,13 +190,17 @@ struct SampleProfTest : ::testing::Test {
171190
if (Format == SampleProfileFormat::SPF_Ext_Binary ||
172191
Format == SampleProfileFormat::SPF_Compact_Binary) {
173192
ASSERT_TRUE(ReadBazSamples == nullptr);
174-
ASSERT_EQ(2u, Reader->getProfiles().size());
193+
ASSERT_EQ(3u, Reader->getProfiles().size());
175194
} else {
176195
ASSERT_TRUE(ReadBazSamples != nullptr);
177196
ASSERT_EQ(12557u, ReadBazSamples->getTotalSamples());
178-
ASSERT_EQ(3u, Reader->getProfiles().size());
197+
ASSERT_EQ(4u, Reader->getProfiles().size());
179198
}
180199

200+
FunctionSamples *ReadBooSamples = Reader->getSamplesFor(BooName);
201+
ASSERT_TRUE(ReadBooSamples != nullptr);
202+
ASSERT_EQ(1232u, ReadBooSamples->getTotalSamples());
203+
181204
std::string MconstructGUID;
182205
StringRef MconstructRep =
183206
getRepInFormat(MconstructName, Format, MconstructGUID);
@@ -189,9 +212,9 @@ struct SampleProfTest : ::testing::Test {
189212

190213
auto VerifySummary = [](ProfileSummary &Summary) mutable {
191214
ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind());
192-
ASSERT_EQ(136160u, Summary.getTotalCount());
193-
ASSERT_EQ(7u, Summary.getNumCounts());
194-
ASSERT_EQ(3u, Summary.getNumFunctions());
215+
ASSERT_EQ(137392u, Summary.getTotalCount());
216+
ASSERT_EQ(8u, Summary.getNumCounts());
217+
ASSERT_EQ(4u, Summary.getNumFunctions());
195218
ASSERT_EQ(1437u, Summary.getMaxFunctionCount());
196219
ASSERT_EQ(60351u, Summary.getMaxCount());
197220

0 commit comments

Comments
 (0)
Please sign in to comment.