diff --git a/docs/CommandGuide/llvm-cov.rst b/docs/CommandGuide/llvm-cov.rst
index 6ee05ee1a0a..478ba0fb15e 100644
--- a/docs/CommandGuide/llvm-cov.rst
+++ b/docs/CommandGuide/llvm-cov.rst
@@ -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.
diff --git a/include/llvm/Support/GCOV.h b/include/llvm/ProfileData/GCOV.h
similarity index 99%
rename from include/llvm/Support/GCOV.h
rename to include/llvm/ProfileData/GCOV.h
index 02016e7dbd6..497f80b87b2 100644
--- a/include/llvm/Support/GCOV.h
+++ b/include/llvm/ProfileData/GCOV.h
@@ -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"
diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h
index ac3f057ec2f..b08b78cd593 100644
--- a/include/llvm/ProfileData/InstrProf.h
+++ b/include/llvm/ProfileData/InstrProf.h
@@ -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;
diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc
index 66d63a462a0..6a98dc7b9b8 100644
--- a/include/llvm/ProfileData/InstrProfData.inc
+++ b/include/llvm/ProfileData/InstrProfData.inc
@@ -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
 
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h
index 7fc258831be..ecc2ea5d894 100644
--- a/include/llvm/ProfileData/SampleProf.h
+++ b/include/llvm/ProfileData/SampleProf.h
@@ -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.
@@ -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;
@@ -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;
   }
diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h
index 9c1f357cbbd..0e9ab2dc60e 100644
--- a/include/llvm/ProfileData/SampleProfReader.h
+++ b/include/llvm/ProfileData/SampleProfReader.h
@@ -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>
diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt
index eb4b9143090..17822bbbb5c 100644
--- a/lib/IR/CMakeLists.txt
+++ b/lib/IR/CMakeLists.txt
@@ -22,7 +22,6 @@ add_llvm_library(LLVMCore
   DiagnosticPrinter.cpp
   Dominators.cpp
   Function.cpp
-  GCOV.cpp
   GVMaterializer.cpp
   Globals.cpp
   IRBuilder.cpp
diff --git a/lib/ProfileData/CMakeLists.txt b/lib/ProfileData/CMakeLists.txt
index cd65762ae6a..3a981d8acf4 100644
--- a/lib/ProfileData/CMakeLists.txt
+++ b/lib/ProfileData/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_llvm_library(LLVMProfileData
+  GCOV.cpp
   InstrProf.cpp
   InstrProfReader.cpp
   InstrProfWriter.cpp
diff --git a/lib/ProfileData/Coverage/CoverageMapping.cpp b/lib/ProfileData/Coverage/CoverageMapping.cpp
index 9df37a47408..ccc8cc56eb0 100644
--- a/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -33,6 +33,7 @@
 #include <cassert>
 #include <cstdint>
 #include <iterator>
+#include <map>
 #include <memory>
 #include <string>
 #include <system_error>
@@ -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:
@@ -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);
     }
 
diff --git a/lib/IR/GCOV.cpp b/lib/ProfileData/GCOV.cpp
similarity index 99%
rename from lib/IR/GCOV.cpp
rename to lib/ProfileData/GCOV.cpp
index d4b45522822..d6e44389f2b 100644
--- a/lib/IR/GCOV.cpp
+++ b/lib/ProfileData/GCOV.cpp
@@ -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"
diff --git a/test/tools/llvm-cov/deferred-region.cpp b/test/tools/llvm-cov/deferred-region.cpp
index 38090fbb498..3bc675d66e7 100644
--- a/test/tools/llvm-cov/deferred-region.cpp
+++ b/test/tools/llvm-cov/deferred-region.cpp
@@ -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|
@@ -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
diff --git a/test/tools/llvm-cov/showLineExecutionCounts.cpp b/test/tools/llvm-cov/showLineExecutionCounts.cpp
index c4b76824aac..c18afedf034 100644
--- a/test/tools/llvm-cov/showLineExecutionCounts.cpp
+++ b/test/tools/llvm-cov/showLineExecutionCounts.cpp
@@ -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
diff --git a/test/tools/llvm-profdata/Inputs/counter-mismatch-1.proftext b/test/tools/llvm-profdata/Inputs/counter-mismatch-1.proftext
new file mode 100644
index 00000000000..45d028e1ad0
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/counter-mismatch-1.proftext
@@ -0,0 +1,13 @@
+foo
+1024
+1
+0
+
+foo
+1024
+5
+0
+0
+0
+0
+0
diff --git a/test/tools/llvm-profdata/Inputs/counter-mismatch-2.proftext b/test/tools/llvm-profdata/Inputs/counter-mismatch-2.proftext
new file mode 100644
index 00000000000..261bfdde595
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/counter-mismatch-2.proftext
@@ -0,0 +1,5 @@
+foo
+1024
+2
+0
+0
diff --git a/test/tools/llvm-profdata/Inputs/counter-mismatch-3.proftext b/test/tools/llvm-profdata/Inputs/counter-mismatch-3.proftext
new file mode 100644
index 00000000000..ca70a71a923
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/counter-mismatch-3.proftext
@@ -0,0 +1,6 @@
+foo
+1024
+3
+0
+0
+0
diff --git a/test/tools/llvm-profdata/Inputs/counter-mismatch-4.proftext b/test/tools/llvm-profdata/Inputs/counter-mismatch-4.proftext
new file mode 100644
index 00000000000..f403382e913
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/counter-mismatch-4.proftext
@@ -0,0 +1,7 @@
+foo
+1024
+4
+0
+0
+0
+0
diff --git a/test/tools/llvm-profdata/compat.proftext b/test/tools/llvm-profdata/compat.proftext
index 17855a7f0f9..73321cc5e66 100644
--- a/test/tools/llvm-profdata/compat.proftext
+++ b/test/tools/llvm-profdata/compat.proftext
@@ -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
diff --git a/test/tools/llvm-profdata/show-instr-level.test b/test/tools/llvm-profdata/show-instr-level.test
new file mode 100644
index 00000000000..ed003265e38
--- /dev/null
+++ b/test/tools/llvm-profdata/show-instr-level.test
@@ -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
diff --git a/test/tools/llvm-profdata/threaded-count-mismatch.test b/test/tools/llvm-profdata/threaded-count-mismatch.test
new file mode 100644
index 00000000000..8e704cf85a6
--- /dev/null
+++ b/test/tools/llvm-profdata/threaded-count-mismatch.test
@@ -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)
diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp
index d2cc21b4e26..73de07c8887 100644
--- a/tools/llvm-cov/CodeCoverage.cpp
+++ b/tools/llvm-cov/CodeCoverage.cpp
@@ -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;
@@ -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;
   };
diff --git a/tools/llvm-cov/CoverageExporterJson.cpp b/tools/llvm-cov/CoverageExporterJson.cpp
index 5b6b09f048e..7b700908968 100644
--- a/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/tools/llvm-cov/CoverageExporterJson.cpp
@@ -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);
@@ -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);
diff --git a/tools/llvm-cov/CoverageViewOptions.h b/tools/llvm-cov/CoverageViewOptions.h
index a071c0aca9e..17614c4e9ba 100644
--- a/tools/llvm-cov/CoverageViewOptions.h
+++ b/tools/llvm-cov/CoverageViewOptions.h
@@ -32,6 +32,7 @@ struct CoverageViewOptions {
   bool ShowFullFilenames;
   bool ShowRegionSummary;
   bool ShowInstantiationSummary;
+  bool ExportSummaryOnly;
   OutputFormat Format;
   std::string ShowOutputDirectory;
   std::vector<std::string> DemanglerOpts;
diff --git a/tools/llvm-cov/SourceCoverageView.cpp b/tools/llvm-cov/SourceCoverageView.cpp
index 0572968b8b4..8c39dab580d 100644
--- a/tools/llvm-cov/SourceCoverageView.cpp
+++ b/tools/llvm-cov/SourceCoverageView.cpp
@@ -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();
diff --git a/tools/llvm-cov/gcov.cpp b/tools/llvm-cov/gcov.cpp
index 4df7f015fd1..7776f2aa9a6 100644
--- a/tools/llvm-cov/gcov.cpp
+++ b/tools/llvm-cov/gcov.cpp
@@ -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;
diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp
index eee242107da..6049933b7de 100644
--- a/tools/llvm-profdata/llvm-profdata.cpp
+++ b/tools/llvm-profdata/llvm-profdata.cpp
@@ -37,14 +37,19 @@ using namespace llvm;
 
 enum ProfileFormat { PF_None = 0, PF_Text, PF_Binary, PF_GCC };
 
-static void exitWithError(const Twine &Message, StringRef Whence = "",
-                          StringRef Hint = "") {
-  errs() << "error: ";
+static void warn(StringRef Prefix, Twine Message, std::string Whence = "",
+                 std::string Hint = "") {
+  errs() << Prefix;
   if (!Whence.empty())
     errs() << Whence << ": ";
   errs() << Message << "\n";
   if (!Hint.empty())
     errs() << Hint << "\n";
+}
+
+static void exitWithError(Twine Message, std::string Whence = "",
+                          std::string Hint = "") {
+  warn("error: ", Message, Whence, Hint);
   ::exit(1);
 }
 
@@ -119,7 +124,7 @@ struct WriterContext {
   std::mutex Lock;
   InstrProfWriter Writer;
   Error Err;
-  StringRef ErrWhence;
+  std::string ErrWhence;
   std::mutex &ErrLock;
   SmallSet<instrprof_error, 4> &WriterErrorCodes;
 
@@ -129,6 +134,22 @@ struct WriterContext {
         ErrLock(ErrLock), WriterErrorCodes(WriterErrorCodes) {}
 };
 
+/// Determine whether an error is fatal for profile merging.
+static bool isFatalError(instrprof_error IPE) {
+  switch (IPE) {
+  default:
+    return true;
+  case instrprof_error::success:
+  case instrprof_error::eof:
+  case instrprof_error::unknown_function:
+  case instrprof_error::hash_mismatch:
+  case instrprof_error::count_mismatch:
+  case instrprof_error::counter_overflow:
+  case instrprof_error::value_site_count_mismatch:
+    return false;
+  }
+}
+
 /// Load an input into a writer context.
 static void loadInput(const WeightedFile &Input, WriterContext *WC) {
   std::unique_lock<std::mutex> CtxGuard{WC->Lock};
@@ -137,6 +158,9 @@ static void loadInput(const WeightedFile &Input, WriterContext *WC) {
   if (WC->Err)
     return;
 
+  // Copy the filename, because llvm::ThreadPool copied the input "const
+  // WeightedFile &" by value, making a reference to the filename within it
+  // invalid outside of this packaged task.
   WC->ErrWhence = Input.Filename;
 
   auto ReaderOrErr = InstrProfReader::create(Input.Filename);
@@ -174,12 +198,22 @@ static void loadInput(const WeightedFile &Input, WriterContext *WC) {
                              FuncName, firstTime);
     });
   }
-  if (Reader->hasError())
-    WC->Err = Reader->getError();
+  if (Reader->hasError()) {
+    if (Error E = Reader->getError()) {
+      instrprof_error IPE = InstrProfError::take(std::move(E));
+      if (isFatalError(IPE))
+        WC->Err = make_error<InstrProfError>(IPE);
+    }
+  }
 }
 
 /// Merge the \p Src writer context into \p Dst.
 static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {
+  // If we've already seen a hard error, continuing with the merge would
+  // clobber it.
+  if (Dst->Err || Src->Err)
+    return;
+
   bool Reported = false;
   Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) {
     if (Reported) {
@@ -254,10 +288,20 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
   }
 
   // Handle deferred hard errors encountered during merging.
-  for (std::unique_ptr<WriterContext> &WC : Contexts)
-    if (WC->Err)
+  for (std::unique_ptr<WriterContext> &WC : Contexts) {
+    if (!WC->Err)
+      continue;
+    if (!WC->Err.isA<InstrProfError>())
       exitWithError(std::move(WC->Err), WC->ErrWhence);
 
+    instrprof_error IPE = InstrProfError::take(std::move(WC->Err));
+    if (isFatalError(IPE))
+      exitWithError(make_error<InstrProfError>(IPE), WC->ErrWhence);
+    else
+      warn("warning: ", toString(make_error<InstrProfError>(IPE)),
+           WC->ErrWhence);
+  }
+
   InstrProfWriter &Writer = Contexts[0]->Writer;
   if (OutputFormat == PF_Text) {
     if (Error E = Writer.writeText(Output))
@@ -625,6 +669,8 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
   if (ShowCounts && TextFormat)
     return 0;
   std::unique_ptr<ProfileSummary> PS(Builder.getSummary());
+  OS << "Instrumentation level: "
+     << (Reader->isIRLevelProfile() ? "IR" : "Front-end") << "\n";
   if (ShowAllFunctions || !ShowFunction.empty())
     OS << "Functions shown: " << ShownFunctions << "\n";
   OS << "Total functions: " << PS->getNumFunctions() << "\n";
diff --git a/unittests/ProfileData/CoverageMappingTest.cpp b/unittests/ProfileData/CoverageMappingTest.cpp
index 74c515e5777..ded364c40d1 100644
--- a/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/unittests/ProfileData/CoverageMappingTest.cpp
@@ -466,6 +466,34 @@ TEST_P(CoverageMappingTest, multiple_regions_end_after_parent_ends) {
   EXPECT_EQ(CoverageSegment(9, 9, false), Segments[7]);
 }
 
+TEST_P(CoverageMappingTest, multiple_completed_segments_at_same_loc) {
+  ProfileWriter.addRecord({"func1", 0x1234, {0, 1, 2}}, Err);
+  startFunction("func1", 0x1234);
+
+  // PR35495
+  addCMR(Counter::getCounter(1), "file1", 2, 1, 18, 2);
+  addCMR(Counter::getCounter(0), "file1", 8, 10, 14, 6);
+  addCMR(Counter::getCounter(0), "file1", 8, 12, 14, 6);
+  addCMR(Counter::getCounter(1), "file1", 9, 1, 14, 6);
+  addCMR(Counter::getCounter(2), "file1", 11, 13, 11, 14);
+
+  EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
+  const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
+  const auto &FunctionRecord = *FunctionRecords.begin();
+  CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
+  std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
+
+  ASSERT_EQ(7U, Segments.size());
+  EXPECT_EQ(CoverageSegment(2, 1, 1, true), Segments[0]);
+  EXPECT_EQ(CoverageSegment(8, 10, 0, true), Segments[1]);
+  EXPECT_EQ(CoverageSegment(8, 12, 0, true), Segments[2]);
+  EXPECT_EQ(CoverageSegment(9, 1, 1, true), Segments[3]);
+  EXPECT_EQ(CoverageSegment(11, 13, 2, true), Segments[4]);
+  // Use count=1 (from 9:1 -> 14:6), not count=0 (from 8:12 -> 14:6).
+  EXPECT_EQ(CoverageSegment(11, 14, 1, false), Segments[5]);
+  EXPECT_EQ(CoverageSegment(18, 2, false), Segments[6]);
+}
+
 TEST_P(CoverageMappingTest, dont_emit_redundant_segments) {
   ProfileWriter.addRecord({"func1", 0x1234, {1, 1}}, Err);
   startFunction("func1", 0x1234);