InstrProf: Handle unknown functions if they consist only of zero-regions

This comes up when we generate coverage for a function but don't end
up emitting the function at all - dead static functions or inline
functions that aren't referenced in a particular TU, for example. In
these cases we'd like to show that the function was never called,
which is trivially true.

llvm-svn: 229717
This commit is contained in:
Justin Bogner 2015-02-18 18:40:46 +00:00
parent 34e79ed319
commit 428c605dff
3 changed files with 34 additions and 14 deletions

View File

@ -237,6 +237,8 @@ public:
ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>())
: Expressions(Expressions), CounterValues(CounterValues) {}
void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
void dump(const Counter &C, llvm::raw_ostream &OS) const;
void dump(const Counter &C) const { dump(C, dbgs()); }
@ -256,10 +258,14 @@ struct FunctionRecord {
/// \brief The number of times this function was executed.
uint64_t ExecutionCount;
FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames,
uint64_t ExecutionCount)
: Name(Name), Filenames(Filenames.begin(), Filenames.end()),
ExecutionCount(ExecutionCount) {}
FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
: Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
void pushRegion(CounterMappingRegion Region, uint64_t Count) {
if (CountedRegions.empty())
ExecutionCount = Count;
CountedRegions.emplace_back(Region, Count);
}
};
/// \brief Iterator over Functions, optionally filtered to a single file.

View File

@ -184,25 +184,26 @@ CoverageMapping::load(CoverageMappingReader &CoverageReader,
std::vector<uint64_t> Counts;
for (const auto &Record : CoverageReader) {
CounterMappingContext Ctx(Record.Expressions);
Counts.clear();
if (std::error_code EC = ProfileReader.getFunctionCounts(
Record.FunctionName, Record.FunctionHash, Counts)) {
if (EC != instrprof_error::hash_mismatch &&
EC != instrprof_error::unknown_function)
return EC;
if (EC == instrprof_error::hash_mismatch) {
Coverage->MismatchedFunctionCount++;
continue;
}
} else if (EC != instrprof_error::unknown_function)
return EC;
} else
Ctx.setCounts(Counts);
assert(Counts.size() != 0 && "Function's counts are empty");
FunctionRecord Function(Record.FunctionName, Record.Filenames,
Counts.front());
CounterMappingContext Ctx(Record.Expressions, Counts);
assert(!Record.MappingRegions.empty() && "Function has no regions");
FunctionRecord Function(Record.FunctionName, Record.Filenames);
for (const auto &Region : Record.MappingRegions) {
ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
if (!ExecutionCount)
break;
Function.CountedRegions.push_back(CountedRegion(Region, *ExecutionCount));
Function.pushRegion(Region, *ExecutionCount);
}
if (Function.CountedRegions.size() != Record.MappingRegions.size()) {
Coverage->MismatchedFunctionCount++;

View File

@ -209,4 +209,17 @@ TEST_F(CoverageMappingTest, basic_coverage_iteration) {
ASSERT_EQ(CoverageSegment(11, 11, false), Segments[6]);
}
TEST_F(CoverageMappingTest, uncovered_function) {
readProfCounts();
addCMR(Counter::getZero(), "file1", 1, 2, 3, 4);
loadCoverageMapping("func", 0x1234);
CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
ASSERT_EQ(2U, Segments.size());
ASSERT_EQ(CoverageSegment(1, 2, 0, true), Segments[0]);
ASSERT_EQ(CoverageSegment(3, 4, false), Segments[1]);
}
} // end anonymous namespace