diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h --- a/llvm/tools/llvm-profgen/PerfReader.h +++ b/llvm/tools/llvm-profgen/PerfReader.h @@ -562,6 +562,8 @@ void warnIfMissingMMap(); // Emit accumulate warnings. void warnTruncatedStack(); + // Check if the sample range is larger than the function size. + void warnAndFilterInvalidRange(); // Extract call stack from the perf trace lines bool extractCallstack(TraceStream &TraceIt, SmallVectorImpl &CallStack); diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp --- a/llvm/tools/llvm-profgen/PerfReader.cpp +++ b/llvm/tools/llvm-profgen/PerfReader.cpp @@ -30,6 +30,10 @@ IgnoreStackSamples("ignore-stack-samples", cl::init(false), cl::ZeroOrMore, cl::desc("Ignore call stack samples for hybrid samples " "and produce context-insensitive profile.")); +static cl::opt SkipCheckInvalidRange( + "skip-check-invalid-range", cl::init(false), cl::ZeroOrMore, + cl::desc( + "Skip the check of fitering out invalid range and warning message.")); extern cl::opt PerfTraceFilename; extern cl::opt ShowDisassemblyOnly; @@ -1021,6 +1025,37 @@ } } +void PerfReaderBase::warnAndFilterInvalidRange() { + if (SkipCheckInvalidRange) + return; + + for (auto &CI : SampleCounters) { + SmallVector RangeToBeRemoved; + RangeSample &Ranges = CI.second.RangeCounter; + for (auto I = Ranges.begin(); I != Ranges.end(); I++) { + uint64_t RangeBegin = I->first.first; + uint64_t RangeEnd = I->first.second; + // Find the function offset range the current range begin belongs to. + auto FuncRange = Binary->findFuncOffsetRange(RangeBegin); + if (FuncRange.second == 0) { + WithColor::warning() + << "[" << format("%8" PRIx64, RangeBegin) << "," + << format("%8" PRIx64, RangeEnd) + << "]: Invalid range or disassembling error in profiled binary.\n"; + RangeToBeRemoved.push_back(I); + } else if (RangeEnd > FuncRange.second) { + WithColor::warning() << "[" << format("%8" PRIx64, RangeBegin) << "," + << format("%8" PRIx64, RangeEnd) + << "]: Range is across different functions.\n"; + RangeToBeRemoved.push_back(I); + } + for (auto &I : RangeToBeRemoved) { + Ranges.erase(I); + } + } + } +} + void PerfReaderBase::parsePerfTraces() { // Parse perf traces and do aggregation. parseAndAggregateTrace(); @@ -1028,6 +1063,7 @@ // Generate unsymbolized profile. warnTruncatedStack(); generateRawProfile(); + warnAndFilterInvalidRange(); if (SkipSymbolization) writeRawProfile(OutputFilename); diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp --- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp +++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp @@ -343,17 +343,9 @@ uint64_t RangeEnd = I.first.second; // Find the function offset range the current range begin belongs to. auto FuncRange = Binary->findFuncOffsetRange(RangeBegin); - if (FuncRange.second == 0) - WithColor::warning() - << "[" << format("%8" PRIx64, RangeBegin) << " - " - << format("%8" PRIx64, RangeEnd) - << "]: Invalid range or disassembling error in profiled binary.\n"; - else if (RangeEnd > FuncRange.second) - WithColor::warning() << "[" << format("%8" PRIx64, RangeBegin) << " - " - << format("%8" PRIx64, RangeEnd) - << "]: Range is across different functions.\n"; - else - Ranges[FuncRange] += 0; + assert((FuncRange.second && RangeEnd <= FuncRange.second) && + "Invalid range should be filtered out."); + Ranges[FuncRange] += 0; } RangeSample DisjointRanges; findDisjointRanges(DisjointRanges, Ranges);