From 428c605dff38347495060e5df983bbc7df3c67df Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Wed, 18 Feb 2015 18:40:46 +0000 Subject: [PATCH] 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 --- .../llvm/ProfileData/CoverageMapping.h | 14 +++++++++---- llvm/lib/ProfileData/CoverageMapping.cpp | 21 ++++++++++--------- .../ProfileData/CoverageMappingTest.cpp | 13 ++++++++++++ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/ProfileData/CoverageMapping.h b/llvm/include/llvm/ProfileData/CoverageMapping.h index 147d17c3bd88..4d393b3e948c 100644 --- a/llvm/include/llvm/ProfileData/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/CoverageMapping.h @@ -237,6 +237,8 @@ public: ArrayRef CounterValues = ArrayRef()) : Expressions(Expressions), CounterValues(CounterValues) {} + void setCounts(ArrayRef 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 Filenames, - uint64_t ExecutionCount) - : Name(Name), Filenames(Filenames.begin(), Filenames.end()), - ExecutionCount(ExecutionCount) {} + FunctionRecord(StringRef Name, ArrayRef 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. diff --git a/llvm/lib/ProfileData/CoverageMapping.cpp b/llvm/lib/ProfileData/CoverageMapping.cpp index 3c615d5b784b..bef8605df48f 100644 --- a/llvm/lib/ProfileData/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/CoverageMapping.cpp @@ -184,25 +184,26 @@ CoverageMapping::load(CoverageMappingReader &CoverageReader, std::vector 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) + if (EC == instrprof_error::hash_mismatch) { + Coverage->MismatchedFunctionCount++; + continue; + } else if (EC != instrprof_error::unknown_function) return EC; - Coverage->MismatchedFunctionCount++; - continue; - } + } 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 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++; diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp index d079b4792168..5e64843b6d6a 100644 --- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp +++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp @@ -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 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