From: Justin Bogner Date: Wed, 18 Feb 2015 18:40:46 +0000 (+0000) Subject: InstrProf: Handle unknown functions if they consist only of zero-regions X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=e0eae15f6c8684d8c5bd8e7ba00e41d013f41c2e 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229717 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index 147d17c3bd8..4d393b3e948 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/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/lib/ProfileData/CoverageMapping.cpp b/lib/ProfileData/CoverageMapping.cpp index 3c615d5b784..bef8605df48 100644 --- a/lib/ProfileData/CoverageMapping.cpp +++ b/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/unittests/ProfileData/CoverageMappingTest.cpp b/unittests/ProfileData/CoverageMappingTest.cpp index d079b479216..5e64843b6d6 100644 --- a/unittests/ProfileData/CoverageMappingTest.cpp +++ b/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