Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
2
aabb1122:4005dc
aabb1122:400634
aabb1122:400684
7f68c5788793
aabb1122:0x4005c8/aabb1122:0x4005dc aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005d7/aabb1122:0x4005e5 aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005d7/aabb1122:0x4005e5 aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005c8/aabb1122:0x4005dc
2
aabb1122:4005b0
aabb1122:400684
7f68c5788793
aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005c8/aabb1122:0x4005dc aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005d7/aabb1122:0x4005e5 aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005d7/aabb1122:0x4005e5 aabb1122:0x40062f/aabb1122:0x4005b0
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
aabb1122:4005dc
aabb1122:400634
aabb1122:400684
7f68c5788793
aabb1122:0x4005c8/aabb1122:0x4005dc aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005d7/aabb1122:0x4005e5 aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005d7/aabb1122:0x4005e5 aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005c8/aabb1122:0x4005dc
aabb1122:4005b0
aabb1122:400684
7f68c5788793
aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005c8/aabb1122:0x4005dc aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005d7/aabb1122:0x4005e5 aabb1122:0x40062f/aabb1122:0x4005b0 aabb1122:0x400645/aabb1122:0x4005ff aabb1122:0x400637/aabb1122:0x400645 aabb1122:0x4005e9/aabb1122:0x400634 aabb1122:0x4005d7/aabb1122:0x4005e5 aabb1122:0x40062f/aabb1122:0x4005b0
57 changes: 57 additions & 0 deletions llvm/test/tools/llvm-profgen/filter-build-id.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
; REQUIRES: x86_64-linux
; Test that [buildid:]0xaddr format is correctly parsed in hybrid perfscript
; input. Both callstack frames and LBR entries may carry buildid prefixes.

;; Test 1: Hybrid perfscript with buildid prefix on callstack frames and
;; LBR entries, using --filter-build-id to match "aabb1122".
; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/buildid-cs-noprobe.aggperfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0 --filter-build-id=aabb1122
; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-HYBRID

; CHECK-HYBRID: [foo]
; CHECK-HYBRID-NEXT: 3
; CHECK-HYBRID-NEXT: 5ff-62f:6
; CHECK-HYBRID-NEXT: 634-637:6
; CHECK-HYBRID-NEXT: 645-645:6
; CHECK-HYBRID-NEXT: 3
; CHECK-HYBRID-NEXT: 62f->5b0:6
; CHECK-HYBRID-NEXT: 637->645:6
; CHECK-HYBRID-NEXT: 645->5ff:6
; CHECK-HYBRID-NEXT: [foo:3 @ bar]
; CHECK-HYBRID-NEXT: 4
; CHECK-HYBRID-NEXT: 5b0-5c8:2
; CHECK-HYBRID-NEXT: 5b0-5d7:4
; CHECK-HYBRID-NEXT: 5dc-5e9:2
; CHECK-HYBRID-NEXT: 5e5-5e9:4
; CHECK-HYBRID-NEXT: 3
; CHECK-HYBRID-NEXT: 5c8->5dc:4
; CHECK-HYBRID-NEXT: 5d7->5e5:4
; CHECK-HYBRID-NEXT: 5e9->634:6

;; Test 2: Non-pre-aggregated perfscript with buildid prefix (no leading count).
; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/buildid-cs-noprobe.perfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t2 --skip-symbolization --profile-summary-cold-count=0 --filter-build-id=aabb1122
; RUN: FileCheck %s --input-file %t2 --check-prefix=CHECK-NOAGG

; CHECK-NOAGG: [foo]
; CHECK-NOAGG-NEXT: 3
; CHECK-NOAGG-NEXT: 5ff-62f:3
; CHECK-NOAGG-NEXT: 634-637:3
; CHECK-NOAGG-NEXT: 645-645:3
; CHECK-NOAGG-NEXT: 3
; CHECK-NOAGG-NEXT: 62f->5b0:3
; CHECK-NOAGG-NEXT: 637->645:3
; CHECK-NOAGG-NEXT: 645->5ff:3
; CHECK-NOAGG-NEXT: [foo:3 @ bar]
; CHECK-NOAGG-NEXT: 4
; CHECK-NOAGG-NEXT: 5b0-5c8:1
; CHECK-NOAGG-NEXT: 5b0-5d7:2
; CHECK-NOAGG-NEXT: 5dc-5e9:1
; CHECK-NOAGG-NEXT: 5e5-5e9:2
; CHECK-NOAGG-NEXT: 3
; CHECK-NOAGG-NEXT: 5c8->5dc:2
; CHECK-NOAGG-NEXT: 5d7->5e5:2
; CHECK-NOAGG-NEXT: 5e9->634:3

;; Test 3: With non-matching filter, callstack frames are filtered out,
;; resulting in no samples.
; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/buildid-cs-noprobe.aggperfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t3 --skip-symbolization --filter-build-id=ccdd3344 2>&1 | FileCheck %s --check-prefix=CHECK-NOMATCH
; CHECK-NOMATCH: warning: No samples in perf script!
71 changes: 58 additions & 13 deletions llvm/tools/llvm-profgen/PerfReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ cl::opt<bool> TimeProfGen("time-profgen", cl::desc("Time llvm-profgen phases"),
static const char *TimerGroupName = "profgen";
static const char *TimerGroupDesc = "llvm-profgen";

static cl::opt<std::string> FilterBuildID(
"filter-build-id",
cl::desc("Override auto-detected build ID for filtering perfscript "
"addresses in [buildid:]addr format. When set, only addresses "
"with a matching build ID prefix are kept."),
cl::cat(ProfGenCategory));

namespace sampleprof {

void VirtualUnwinder::unwindCall(UnwindState &State) {
Expand Down Expand Up @@ -665,12 +672,37 @@ void HybridPerfReader::unwindSamples() {
}

/// Parse a hex address from \p Str.
static bool parseAddress(StringRef Str, uint64_t &Addr, bool HasPrefix) {
/// Parse an optional [buildid:] prefix into \p BuildID.
static bool parseAddress(StringRef Str, uint64_t &Addr, bool HasPrefix,
StringRef &BuildID) {
size_t ColonPos = Str.find(':');
if (ColonPos != StringRef::npos) {
BuildID = Str.substr(0, ColonPos);
Str = Str.substr(ColonPos + 1);
}
if (Str.consume_front("0x") != HasPrefix)
return true;
return Str.getAsInteger(16, Addr);
}

/// Return the build ID to use for filtering perfscript addresses.
/// If --filter-build-id is specified, use it as an override (with a warning
/// if it doesn't match the binary's auto-detected build ID).
/// Otherwise, use the auto-detected value from the binary.
static StringRef getFilterBuildID(const ProfiledBinary *Binary) {
Comment thread
aaupov marked this conversation as resolved.
StringRef BinaryBuildID = Binary->getFilterBuildID();
if (FilterBuildID.getNumOccurrences() == 0)
return BinaryBuildID;
static bool Warned = false;
if (!Warned && !BinaryBuildID.empty() && FilterBuildID != BinaryBuildID) {
WithColor::warning() << "--filter-build-id=" << FilterBuildID
<< " does not match binary build ID " << BinaryBuildID
<< "\n";
Warned = true;
}
return FilterBuildID;
}

bool PerfScriptReader::extractLBRStack(TraceStream &TraceIt,
SmallVectorImpl<LBREntry> &LBRStack) {
// The raw format of LBR stack is like:
Expand All @@ -688,8 +720,9 @@ bool PerfScriptReader::extractLBRStack(TraceStream &TraceIt,
// Skip the leading instruction pointer.
size_t Index = 0;
uint64_t LeadingAddr;
StringRef LeadingBuildID;
if (!Records.empty() && !Records[0].contains('/')) {
if (parseAddress(Records[0], LeadingAddr, false)) {
if (parseAddress(Records[0], LeadingAddr, false, LeadingBuildID)) {
WarnInvalidLBR(TraceIt);
TraceIt.advance();
return false;
Expand All @@ -709,19 +742,25 @@ bool PerfScriptReader::extractLBRStack(TraceStream &TraceIt,
Token.split(Addresses, "/");
uint64_t Src;
uint64_t Dst;
StringRef SrcBuildID, DstBuildID;

// Stop at broken LBR records.
if (Addresses.size() < 2 || parseAddress(Addresses[0], Src, true) ||
parseAddress(Addresses[1], Dst, true)) {
if (Addresses.size() < 2 ||
parseAddress(Addresses[0], Src, true, SrcBuildID) ||
parseAddress(Addresses[1], Dst, true, DstBuildID)) {
WarnInvalidLBR(TraceIt);
break;
}

// Canonicalize to use preferred load address as base address.
Src = Binary->canonicalizeVirtualAddress(Src);
Dst = Binary->canonicalizeVirtualAddress(Dst);
bool SrcIsInternal = Binary->addressIsCode(Src);
bool DstIsInternal = Binary->addressIsCode(Dst);
// Filter by build ID.
StringRef BinaryBuildID = getFilterBuildID(Binary);
bool SrcIsInternal =
SrcBuildID == BinaryBuildID && Binary->addressIsCode(Src);
bool DstIsInternal =
DstBuildID == BinaryBuildID && Binary->addressIsCode(Dst);
if (!SrcIsInternal)
Src = ExternalAddr;
if (!DstIsInternal)
Expand All @@ -739,16 +778,17 @@ bool PerfScriptReader::extractLBRStack(TraceStream &TraceIt,
bool PerfScriptReader::extractCallstack(TraceStream &TraceIt,
SmallVectorImpl<uint64_t> &CallStack) {
// The raw format of call stack is like:
// 4005dc # leaf frame
// 4005dc # leaf frame (no buildid)
// 400634
// 400684 # root frame
// deadbeef:400684 # root frame (with buildid prefix)
// It's in bottom-up order with each frame in one line.

// Extract stack frames from sample
while (!TraceIt.isAtEoF() && !isLBRSample(TraceIt.getCurrentLine(), true)) {
StringRef FrameStr = TraceIt.getCurrentLine().ltrim();
uint64_t FrameAddr = 0;
if (parseAddress(FrameStr, FrameAddr, false)) {
StringRef FrameBuildID;
if (parseAddress(FrameStr, FrameAddr, false, FrameBuildID)) {
// We might parse a non-perf sample line like empty line and comments,
// skip it
TraceIt.advance();
Expand All @@ -758,7 +798,9 @@ bool PerfScriptReader::extractCallstack(TraceStream &TraceIt,

FrameAddr = Binary->canonicalizeVirtualAddress(FrameAddr);
// Currently intermixed frame from different binaries is not supported.
if (!Binary->addressIsCode(FrameAddr)) {
bool IsExternal = FrameBuildID != getFilterBuildID(Binary) ||
!Binary->addressIsCode(FrameAddr);
if (IsExternal) {
if (CallStack.empty())
NumLeafExternalFrame++;
// Push a special value(ExternalAddr) for the external frames so that
Expand Down Expand Up @@ -1171,7 +1213,7 @@ void PerfScriptReader::parseAndAggregateTrace() {
// A LBR sample is like:
// 40062f 0x5c6313f/0x5c63170/P/-/-/0 0x5c630e7/0x5c63130/P/-/-/0 ...
// A heuristic for fast detection by checking whether a
// leading " 0x" and the '/' exist.
// leading " 0x" or " buildid:0x" and the '/' exist.
bool PerfScriptReader::isLBRSample(StringRef Line, bool CheckLineStart) {
// Skip the leading instruction pointer
SmallVector<StringRef, 32> Records;
Expand All @@ -1180,7 +1222,8 @@ bool PerfScriptReader::isLBRSample(StringRef Line, bool CheckLineStart) {
Line.split(Records, " ", 2, CheckLineStart);
if (Records.size() < 2)
return false;
if (Records[1].starts_with("0x") && Records[1].contains('/'))
if ((Records[1].starts_with("0x") || Records[1].contains(":0x")) &&
Records[1].contains('/'))
return true;
return false;
}
Expand Down Expand Up @@ -1218,8 +1261,10 @@ PerfContent PerfScriptReader::checkPerfScriptType(StringRef FileName) {

// Detect sample with call stack
int32_t Count = 0;
StringRef FrameBuildId;
while (!TraceIt.isAtEoF() &&
!parseAddress(TraceIt.getCurrentLine().ltrim(), FrameAddr, false)) {
!parseAddress(TraceIt.getCurrentLine().ltrim(), FrameAddr, false,
FrameBuildId)) {
Count++;
TraceIt.advance();
}
Expand Down
Loading