[llvm] r284251 - [Coverage] Support loading multiple binaries into a CoverageMapping
Vedant Kumar via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 14 10:16:53 PDT 2016
Author: vedantk
Date: Fri Oct 14 12:16:53 2016
New Revision: 284251
URL: http://llvm.org/viewvc/llvm-project?rev=284251&view=rev
Log:
[Coverage] Support loading multiple binaries into a CoverageMapping
Add support for loading multiple coverage readers into a single
CoverageMapping instance. This should make it easier to prepare a
unified coverage report for multiple binaries.
Differential Revision: https://reviews.llvm.org/D25535
Modified:
llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMapping.h
llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp
llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp
Modified: llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMapping.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMapping.h?rev=284251&r1=284250&r2=284251&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMapping.h (original)
+++ llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMapping.h Fri Oct 14 12:16:53 2016
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ProfileData/InstrProf.h"
@@ -428,6 +429,7 @@ public:
/// This is the main interface to get coverage information, using a profile to
/// fill out execution counts.
class CoverageMapping {
+ StringSet<> FunctionNames;
std::vector<FunctionRecord> Functions;
unsigned MismatchedFunctionCount;
@@ -446,9 +448,19 @@ public:
load(CoverageMappingReader &CoverageReader,
IndexedInstrProfReader &ProfileReader);
+ static Expected<std::unique_ptr<CoverageMapping>>
+ load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
+ IndexedInstrProfReader &ProfileReader);
+
/// \brief Load the coverage mapping from the given files.
static Expected<std::unique_ptr<CoverageMapping>>
load(StringRef ObjectFilename, StringRef ProfileFilename,
+ StringRef Arch = StringRef()) {
+ return load(ArrayRef<StringRef>(ObjectFilename), ProfileFilename, Arch);
+ }
+
+ static Expected<std::unique_ptr<CoverageMapping>>
+ load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
StringRef Arch = StringRef());
/// \brief The number of functions that couldn't have their profiles mapped.
Modified: llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp?rev=284251&r1=284250&r2=284251&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp (original)
+++ llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp Fri Oct 14 12:16:53 2016
@@ -186,6 +186,16 @@ void FunctionRecordIterator::skipOtherFi
Error CoverageMapping::loadFunctionRecord(
const CoverageMappingRecord &Record,
IndexedInstrProfReader &ProfileReader) {
+ StringRef OrigFuncName = Record.FunctionName;
+ if (Record.Filenames.empty())
+ OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
+ else
+ OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
+
+ // Don't load records for functions we've already seen.
+ if (!FunctionNames.insert(OrigFuncName).second)
+ return Error::success();
+
CounterMappingContext Ctx(Record.Expressions);
std::vector<uint64_t> Counts;
@@ -203,11 +213,6 @@ Error CoverageMapping::loadFunctionRecor
assert(!Record.MappingRegions.empty() && "Function has no regions");
- StringRef OrigFuncName = Record.FunctionName;
- if (Record.Filenames.empty())
- OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
- else
- OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
FunctionRecord Function(OrigFuncName, Record.Filenames);
for (const auto &Region : Record.MappingRegions) {
Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
@@ -238,22 +243,41 @@ CoverageMapping::load(CoverageMappingRea
return std::move(Coverage);
}
+Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
+ ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
+ IndexedInstrProfReader &ProfileReader) {
+ auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
+
+ for (const auto &CoverageReader : CoverageReaders)
+ for (const auto &Record : *CoverageReader)
+ if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
+ return std::move(E);
+
+ return std::move(Coverage);
+}
+
Expected<std::unique_ptr<CoverageMapping>>
-CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename,
- StringRef Arch) {
- auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
- if (std::error_code EC = CounterMappingBuff.getError())
- return errorCodeToError(EC);
- auto CoverageReaderOrErr =
- BinaryCoverageReader::create(CounterMappingBuff.get(), Arch);
- if (Error E = CoverageReaderOrErr.takeError())
- return std::move(E);
- auto CoverageReader = std::move(CoverageReaderOrErr.get());
+CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
+ StringRef ProfileFilename, StringRef Arch) {
auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
if (Error E = ProfileReaderOrErr.takeError())
return std::move(E);
auto ProfileReader = std::move(ProfileReaderOrErr.get());
- return load(*CoverageReader, *ProfileReader);
+
+ SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers;
+ SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
+ for (StringRef ObjectFilename : ObjectFilenames) {
+ auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
+ if (std::error_code EC = CovMappingBufOrErr.getError())
+ return errorCodeToError(EC);
+ auto CoverageReaderOrErr =
+ BinaryCoverageReader::create(CovMappingBufOrErr.get(), Arch);
+ if (Error E = CoverageReaderOrErr.takeError())
+ return std::move(E);
+ Readers.push_back(std::move(CoverageReaderOrErr.get()));
+ Buffers.push_back(std::move(CovMappingBufOrErr.get()));
+ }
+ return load(Readers, *ProfileReader);
}
namespace {
Modified: llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp?rev=284251&r1=284250&r2=284251&view=diff
==============================================================================
--- llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp (original)
+++ llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp Fri Oct 14 12:16:53 2016
@@ -16,6 +16,7 @@
#include "gtest/gtest.h"
#include <ostream>
+#include <utility>
using namespace llvm;
using namespace coverage;
@@ -118,7 +119,8 @@ struct InputFunctionCoverageData {
InputFunctionCoverageData &operator=(InputFunctionCoverageData &&) = delete;
};
-struct CoverageMappingTest : ::testing::TestWithParam<bool> {
+struct CoverageMappingTest : ::testing::TestWithParam<std::pair<bool, bool>> {
+ bool UseMultipleReaders;
StringMap<unsigned> Files;
std::vector<InputFunctionCoverageData> InputFunctions;
std::vector<OutputFunctionCoverageData> OutputFunctions;
@@ -129,7 +131,8 @@ struct CoverageMappingTest : ::testing::
std::unique_ptr<CoverageMapping> LoadedCoverage;
void SetUp() override {
- ProfileWriter.setOutputSparse(GetParam());
+ ProfileWriter.setOutputSparse(GetParam().first);
+ UseMultipleReaders = GetParam().second;
}
unsigned getGlobalFileIndex(StringRef Name) {
@@ -215,12 +218,24 @@ struct CoverageMappingTest : ::testing::
ProfileReader = std::move(ReaderOrErr.get());
}
+ Expected<std::unique_ptr<CoverageMapping>> readOutputFunctions() {
+ if (!UseMultipleReaders) {
+ CoverageMappingReaderMock CovReader(OutputFunctions);
+ return CoverageMapping::load(CovReader, *ProfileReader);
+ }
+
+ std::vector<std::unique_ptr<CoverageMappingReader>> CoverageReaders;
+ for (const auto &OF : OutputFunctions) {
+ ArrayRef<OutputFunctionCoverageData> Funcs(OF);
+ CoverageReaders.push_back(make_unique<CoverageMappingReaderMock>(Funcs));
+ }
+ return CoverageMapping::load(CoverageReaders, *ProfileReader);
+ }
+
void loadCoverageMapping(bool EmitFilenames = true) {
readProfCounts();
writeAndReadCoverageRegions(EmitFilenames);
-
- CoverageMappingReaderMock CovReader(OutputFunctions);
- auto CoverageOrErr = CoverageMapping::load(CovReader, *ProfileReader);
+ auto CoverageOrErr = readOutputFunctions();
ASSERT_TRUE(NoError(CoverageOrErr.takeError()));
LoadedCoverage = std::move(CoverageOrErr.get());
}
@@ -547,7 +562,28 @@ TEST_P(CoverageMappingTest, load_coverag
EXPECT_EQ(CoverageSegment(1, 10, false), Segments[1]);
}
+TEST_P(CoverageMappingTest, skip_duplicate_function_record) {
+ InstrProfRecord Record("func", 0x1234, {1});
+ NoError(ProfileWriter.addRecord(std::move(Record)));
+
+ startFunction("func", 0x1234);
+ addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
+
+ startFunction("func", 0x1234);
+ addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
+
+ loadCoverageMapping();
+
+ auto Funcs = LoadedCoverage->getCoveredFunctions();
+ unsigned NumFuncs = std::distance(Funcs.begin(), Funcs.end());
+ ASSERT_EQ(1U, NumFuncs);
+}
+
+// FIXME: Use ::testing::Combine() when llvm updates its copy of googletest.
INSTANTIATE_TEST_CASE_P(ParameterizedCovMapTest, CoverageMappingTest,
- ::testing::Bool());
+ ::testing::Values(std::pair<bool, bool>({false, false}),
+ std::pair<bool, bool>({false, true}),
+ std::pair<bool, bool>({true, false}),
+ std::pair<bool, bool>({true, true})));
} // end anonymous namespace
More information about the llvm-commits
mailing list