Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Code coverage and UBSan bug fixes for 4.1 #72

Merged
merged 13 commits into from
Dec 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/CommandGuide/llvm-cov.rst
Original file line number Diff line number Diff line change
Expand Up @@ -382,3 +382,10 @@ OPTIONS
It is an error to specify an architecture that is not included in the
universal binary or to use an architecture that does not match a
non-universal binary.

.. option:: -summary-only

Export only summary information for each file in the coverage data. This mode
will not export coverage information for smaller units such as individual
functions or regions. The result will be the same as produced by :program:
`llvm-cov report` command, but presented in JSON format rather than text.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_GCOV_H
#define LLVM_SUPPORT_GCOV_H
#ifndef LLVM_PROFILEDATA_GCOV_H
#define LLVM_PROFILEDATA_GCOV_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
Expand Down
4 changes: 3 additions & 1 deletion include/llvm/ProfileData/InstrProf.h
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,9 @@ enum ProfVersion {
// In this version, profile summary data \c IndexedInstrProf::Summary is
// stored after the profile header.
Version4 = 4,
// The current version is 4.
// In this version, the frontend PGO stable hash algorithm defaults to V2.
Version5 = 5,
// The current version is 5.
CurrentVersion = INSTR_PROF_INDEX_VERSION
};
const uint64_t Version = ProfVersion::CurrentVersion;
Expand Down
2 changes: 1 addition & 1 deletion include/llvm/ProfileData/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
/* Raw profile format version (start from 1). */
#define INSTR_PROF_RAW_VERSION 4
/* Indexed profile format version (start from 1). */
#define INSTR_PROF_INDEX_VERSION 4
#define INSTR_PROF_INDEX_VERSION 5
/* Coverage mapping format vresion (start from 0). */
#define INSTR_PROF_COVMAP_VERSION 2

Expand Down
8 changes: 5 additions & 3 deletions include/llvm/ProfileData/SampleProf.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample);
class FunctionSamples;

using BodySampleMap = std::map<LineLocation, SampleRecord>;
using FunctionSamplesMap = StringMap<FunctionSamples>;
// NOTE: Using a StringMap here makes parsed profiles consume around 17% more
// memory, which is *very* significant for large profiles.
using FunctionSamplesMap = std::map<std::string, FunctionSamples>;
using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;

/// Representation of the samples collected for a function.
Expand Down Expand Up @@ -278,7 +280,7 @@ class FunctionSamples {
return nullptr;
auto FS = iter->second.find(CalleeName);
if (FS != iter->second.end())
return &FS->getValue();
return &FS->second;
// If we cannot find exact match of the callee name, return the FS with
// the max total count.
uint64_t MaxTotalSamples = 0;
Expand Down Expand Up @@ -324,7 +326,7 @@ class FunctionSamples {
const LineLocation &Loc = I.first;
FunctionSamplesMap &FSMap = functionSamplesAt(Loc);
for (const auto &Rec : I.second)
MergeResult(Result, FSMap[Rec.first()].merge(Rec.second, Weight));
MergeResult(Result, FSMap[Rec.first].merge(Rec.second, Weight));
}
return Result;
}
Expand Down
2 changes: 1 addition & 1 deletion include/llvm/ProfileData/SampleProfReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,10 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/GCOV.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/GCOV.h"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>
#include <cstdint>
Expand Down
1 change: 0 additions & 1 deletion lib/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ add_llvm_library(LLVMCore
DiagnosticPrinter.cpp
Dominators.cpp
Function.cpp
GCOV.cpp
GVMaterializer.cpp
Globals.cpp
IRBuilder.cpp
Expand Down
1 change: 1 addition & 0 deletions lib/ProfileData/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_llvm_library(LLVMProfileData
GCOV.cpp
InstrProf.cpp
InstrProfReader.cpp
InstrProfWriter.cpp
Expand Down
8 changes: 7 additions & 1 deletion lib/ProfileData/Coverage/CoverageMapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <cassert>
#include <cstdint>
#include <iterator>
#include <map>
#include <memory>
#include <string>
#include <system_error>
Expand Down Expand Up @@ -296,7 +297,7 @@ namespace {
/// An instantiation set is a collection of functions that have the same source
/// code, ie, template functions specializations.
class FunctionInstantiationSetCollector {
using MapT = DenseMap<LineColPair, std::vector<const FunctionRecord *>>;
using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
MapT InstantiatedFunctions;

public:
Expand Down Expand Up @@ -387,6 +388,11 @@ class SegmentBuilder {
if (CompletedSegmentLoc == CompletedRegion->endLoc())
continue;

// Use the count from the last completed region which ends at this loc.
for (unsigned J = I + 1; J < E; ++J)
if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
CompletedRegion = ActiveRegions[J];

startSegment(*CompletedRegion, CompletedSegmentLoc, false);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/IR/GCOV.cpp → lib/ProfileData/GCOV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/GCOV.h"
#include "llvm/ProfileData/GCOV.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
Expand Down
4 changes: 3 additions & 1 deletion test/tools/llvm-cov/deferred-region.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void while_loop() {
break; // CHECK: [[@LINE]]|{{ +}}1|
// CHECK: [[@LINE]]|{{ +}}0|
while (++x < 5) {} // CHECK: [[@LINE]]|{{ +}}0|
} // CHECK: [[@LINE]]|{{ +}}1|
} // CHECK: [[@LINE]]|{{ +}}0|

if (x == 0) // CHECK: [[@LINE]]|{{ +}}1|
throw Error(); // CHECK: [[@LINE]]|{{ +}}0|
Expand Down Expand Up @@ -97,6 +97,8 @@ int main() {
// MARKER-NEXT: Highlighted line 47, 14 -> 21
// MARKER-NEXT: Highlighted line 47, 21 -> 23
// MARKER-NEXT: Highlighted line 47, 23 -> 25
// MARKER-NEXT: Highlighted line 47, 25 -> ?
// MARKER-NEXT: Highlighted line 48, 1 -> 6
// MARKER-NEXT: Highlighted line 51, 7 -> 20
// MARKER-NEXT: Marker at 53:5 = 1
// MARKER-NEXT: Highlighted line 55, 9 -> 14
Expand Down
32 changes: 8 additions & 24 deletions test/tools/llvm-cov/showLineExecutionCounts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,36 +39,20 @@ int main() { // TEXT: [[@LINE]]| 161|int main(
// RUN: FileCheck -input-file %t.export.json %S/Inputs/lineExecutionCounts.json
// RUN: cat %t.export.json | %python -c "import json, sys; json.loads(sys.stdin.read())"
//
// RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata 2>/dev/null -summary-only > %t.export-summary.json
// RUN: not grep '"name":"main"' %t.export-summary.json
//
// Test html output.
// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s
// RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.html.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
// RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.html.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
//
// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// before
// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-45]]' href='#L[[@LINE-45]]'><pre>[[@LINE-45]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// before
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> int x = 0
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> if (x)
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre><span class='red'> }</span>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = 1;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> }
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>16.2k</pre></td><td class='code'><pre> for (int i = 0; i &lt; 100; ++i)
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>16.1k</pre></td><td class='code'><pre> x = 1;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>16.1k</pre></td><td class='code'><pre> }
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = x &lt; 10
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = x &gt; 10
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre> <span class='red'>x - 1</span>:
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x + 1;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> return 0;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>}
// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// after
// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-45]]' href='#L[[@LINE-45]]'><pre>[[@LINE-45]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// after
// HTML-WHOLE-FILE: <td class='line-number'><a name='L4' href='#L4'><pre>4</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// before
// HTML-FILTER-NOT: <td class='line-number'><a name='L4' href='#L4'><pre>4</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// before
// HTML: <td class='line-number'><a name='L6' href='#L6'><pre>6</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
// HTML-WHOLE-FILE: <td class='line-number'><a name='L26' href='#L26'><pre>26</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// after
// HTML-FILTER-NOT: <td class='line-number'><a name='L26' href='#L26'><pre>26</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// after
//
// Test index creation.
// RUN: FileCheck -check-prefix=TEXT-INDEX -input-file %t.dir/index.txt %s
Expand Down
13 changes: 13 additions & 0 deletions test/tools/llvm-profdata/Inputs/counter-mismatch-1.proftext
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
foo
1024
1
0

foo
1024
5
0
0
0
0
0
5 changes: 5 additions & 0 deletions test/tools/llvm-profdata/Inputs/counter-mismatch-2.proftext
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
foo
1024
2
0
0
6 changes: 6 additions & 0 deletions test/tools/llvm-profdata/Inputs/counter-mismatch-3.proftext
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
foo
1024
3
0
0
0
7 changes: 7 additions & 0 deletions test/tools/llvm-profdata/Inputs/counter-mismatch-4.proftext
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
foo
1024
4
0
0
0
0
1 change: 1 addition & 0 deletions test/tools/llvm-profdata/compat.proftext
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ large_numbers
# FORMATV2-NEXT: Counters: 4
# FORMATV2-NEXT: Function count: 1
# FORMATV2-NEXT: Block counts: [1000, 1000000, 499500]
# FORMATV2-NEXT: Instrumentation level: Front-end
# FORMATV2-NEXT: Functions shown: 2
# FORMATV2-NEXT: Total functions: 2
# FORMATV2-NEXT: Maximum function count: 499500
Expand Down
7 changes: 7 additions & 0 deletions test/tools/llvm-profdata/show-instr-level.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
RUN: llvm-profdata merge -o %t_clang.profdata %p/Inputs/clang_profile.proftext
RUN: llvm-profdata show %t_clang.profdata | FileCheck %s -check-prefix=FE
FE: Instrumentation level: Front-end

RUN: llvm-profdata merge -o %t_ir.profdata %p/Inputs/IR_profile.proftext
RUN: llvm-profdata show %t_ir.profdata | FileCheck %s -check-prefix=IR
IR: Instrumentation level: IR
10 changes: 10 additions & 0 deletions test/tools/llvm-profdata/threaded-count-mismatch.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Test multithreaded error reporting.

RUN: llvm-profdata merge -j 4 -o %t.profdata \
RUN: %S/Inputs/counter-mismatch-1.proftext \
RUN: %S/Inputs/counter-mismatch-2.proftext \
RUN: %S/Inputs/counter-mismatch-3.proftext \
RUN: %S/Inputs/counter-mismatch-4.proftext \
RUN: 2>&1 | FileCheck %s

CHECK: Function basic block count change detected (counter mismatch)
5 changes: 5 additions & 0 deletions tools/llvm-cov/CodeCoverage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,10 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
"show-instantiation-summary", cl::Optional,
cl::desc("Show instantiation statistics in summary table"));

cl::opt<bool> SummaryOnly(
"summary-only", cl::Optional,
cl::desc("Export only summary information for each source file"));

auto commandLineParser = [&, this](int argc, const char **argv) -> int {
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
ViewOpts.Debug = DebugDump;
Expand Down Expand Up @@ -746,6 +750,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {

ViewOpts.ShowRegionSummary = RegionSummary;
ViewOpts.ShowInstantiationSummary = InstantiationSummary;
ViewOpts.ExportSummaryOnly = SummaryOnly;

return 0;
};
Expand Down
39 changes: 23 additions & 16 deletions tools/llvm-cov/CoverageExporterJson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,11 @@ class CoverageExporterJson {
SourceFiles, Options);
renderFiles(SourceFiles, FileReports);

emitDictKey("functions");
renderFunctions(Coverage.getCoveredFunctions());
// Skip functions-level information for summary-only export mode.
if (!Options.ExportSummaryOnly) {
emitDictKey("functions");
renderFunctions(Coverage.getCoveredFunctions());
}

emitDictKey("totals");
renderSummary(Totals);
Expand Down Expand Up @@ -254,27 +257,31 @@ class CoverageExporterJson {
emitDictStart();

emitDictElement("filename", FileCoverage.getFilename());
emitDictKey("segments");

// Start List of Segments.
emitArrayStart();
// Skip segments and expansions for summary-only export mode.
if (!Options.ExportSummaryOnly) {
emitDictKey("segments");

for (const auto &Segment : FileCoverage)
renderSegment(Segment);
// Start List of Segments.
emitArrayStart();

// End List of Segments.
emitArrayEnd();
for (const auto &Segment : FileCoverage)
renderSegment(Segment);

// End List of Segments.
emitArrayEnd();

emitDictKey("expansions");
emitDictKey("expansions");

// Start List of Expansions.
emitArrayStart();
// Start List of Expansions.
emitArrayStart();

for (const auto &Expansion : FileCoverage.getExpansions())
renderExpansion(Expansion);
for (const auto &Expansion : FileCoverage.getExpansions())
renderExpansion(Expansion);

// End List of Expansions.
emitArrayEnd();
// End List of Expansions.
emitArrayEnd();
}

emitDictKey("summary");
renderSummary(FileReport);
Expand Down
1 change: 1 addition & 0 deletions tools/llvm-cov/CoverageViewOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct CoverageViewOptions {
bool ShowFullFilenames;
bool ShowRegionSummary;
bool ShowInstantiationSummary;
bool ExportSummaryOnly;
OutputFormat Format;
std::string ShowOutputDirectory;
std::vector<std::string> DemanglerOpts;
Expand Down
4 changes: 2 additions & 2 deletions tools/llvm-cov/SourceCoverageView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,

// We need the expansions and instantiations sorted so we can go through them
// while we iterate lines.
std::sort(ExpansionSubViews.begin(), ExpansionSubViews.end());
std::sort(InstantiationSubViews.begin(), InstantiationSubViews.end());
std::stable_sort(ExpansionSubViews.begin(), ExpansionSubViews.end());
std::stable_sort(InstantiationSubViews.begin(), InstantiationSubViews.end());
auto NextESV = ExpansionSubViews.begin();
auto EndESV = ExpansionSubViews.end();
auto NextISV = InstantiationSubViews.begin();
Expand Down
2 changes: 1 addition & 1 deletion tools/llvm-cov/gcov.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/ProfileData/GCOV.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GCOV.h"
#include "llvm/Support/Path.h"
#include <system_error>
using namespace llvm;
Expand Down
Loading