[llvm] 9f2967b - [Coverage] Add support for Branch Coverage in LLVM Source-Based Code Coverage

Alan Phipps via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 5 07:52:51 PST 2021


Author: Alan Phipps
Date: 2021-01-05T09:51:51-06:00
New Revision: 9f2967bcfe2f7d1fc02281f0098306c90c2c10a5

URL: https://github.com/llvm/llvm-project/commit/9f2967bcfe2f7d1fc02281f0098306c90c2c10a5
DIFF: https://github.com/llvm/llvm-project/commit/9f2967bcfe2f7d1fc02281f0098306c90c2c10a5.diff

LOG: [Coverage] Add support for Branch Coverage in LLVM Source-Based Code Coverage

This is an enhancement to LLVM Source-Based Code Coverage in clang to track how
many times individual branch-generating conditions are taken (evaluate to TRUE)
and not taken (evaluate to FALSE).  Individual conditions may comprise larger
boolean expressions using boolean logical operators.  This functionality is
very similar to what is supported by GCOV except that it is very closely
anchored to the ASTs.

Differential Revision: https://reviews.llvm.org/D84467

Added: 
    clang/test/CoverageMapping/branch-constfolded.cpp
    clang/test/CoverageMapping/branch-logical-mixed.cpp
    clang/test/CoverageMapping/branch-macros.cpp
    clang/test/CoverageMapping/branch-mincounters.cpp
    clang/test/CoverageMapping/branch-templates.cpp
    clang/test/Profile/branch-logical-mixed.cpp
    clang/test/Profile/branch-profdup.cpp
    llvm/test/tools/llvm-cov/Inputs/branch-c-general.o32l
    llvm/test/tools/llvm-cov/Inputs/branch-c-general.proftext
    llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.o32l
    llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.proftext
    llvm/test/tools/llvm-cov/Inputs/branch-macros.o32l
    llvm/test/tools/llvm-cov/Inputs/branch-macros.proftext
    llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.o32l
    llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.proftext
    llvm/test/tools/llvm-cov/Inputs/branch-templates.o32l
    llvm/test/tools/llvm-cov/Inputs/branch-templates.proftext
    llvm/test/tools/llvm-cov/branch-c-general.c
    llvm/test/tools/llvm-cov/branch-export-json.test
    llvm/test/tools/llvm-cov/branch-export-lcov.test
    llvm/test/tools/llvm-cov/branch-logical-mixed.cpp
    llvm/test/tools/llvm-cov/branch-macros.cpp
    llvm/test/tools/llvm-cov/branch-noShowBranch.test
    llvm/test/tools/llvm-cov/branch-showBranchPercentage.c
    llvm/test/tools/llvm-cov/branch-templates.cpp

Modified: 
    clang/docs/SourceBasedCodeCoverage.rst
    clang/lib/CodeGen/CGExprScalar.cpp
    clang/lib/CodeGen/CGStmt.cpp
    clang/lib/CodeGen/CodeGenFunction.cpp
    clang/lib/CodeGen/CodeGenFunction.h
    clang/lib/CodeGen/CodeGenPGO.cpp
    clang/lib/CodeGen/CoverageMappingGen.cpp
    clang/lib/CodeGen/CoverageMappingGen.h
    clang/test/CoverageMapping/continue.c
    clang/test/CoverageMapping/coroutine.cpp
    clang/test/CoverageMapping/if.cpp
    clang/test/CoverageMapping/label.cpp
    clang/test/CoverageMapping/logical.cpp
    clang/test/CoverageMapping/loopmacro.c
    clang/test/CoverageMapping/loops.cpp
    clang/test/CoverageMapping/macro-expansion.c
    clang/test/CoverageMapping/macro-expressions.cpp
    clang/test/CoverageMapping/macros.c
    clang/test/CoverageMapping/macroscopes.cpp
    clang/test/CoverageMapping/moremacros.c
    clang/test/CoverageMapping/return.c
    clang/test/CoverageMapping/switch.cpp
    clang/test/CoverageMapping/switchmacro.c
    clang/test/CoverageMapping/test.c
    clang/test/CoverageMapping/unreachable-macro.c
    clang/test/CoverageMapping/while.c
    clang/test/Profile/Inputs/c-general.proftext
    clang/test/Profile/c-general.c
    clang/test/Profile/cxx-lambda.cpp
    compiler-rt/include/profile/InstrProfData.inc
    llvm/docs/CommandGuide/llvm-cov.rst
    llvm/docs/CoverageMappingFormat.rst
    llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
    llvm/include/llvm/ProfileData/InstrProf.h
    llvm/include/llvm/ProfileData/InstrProfData.inc
    llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
    llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
    llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
    llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
    llvm/test/tools/llvm-cov/Inputs/showExpansions.json
    llvm/test/tools/llvm-cov/ignore-filename-regex.test
    llvm/tools/llvm-cov/CodeCoverage.cpp
    llvm/tools/llvm-cov/CoverageExporterJson.cpp
    llvm/tools/llvm-cov/CoverageExporterLcov.cpp
    llvm/tools/llvm-cov/CoverageReport.cpp
    llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
    llvm/tools/llvm-cov/CoverageSummaryInfo.h
    llvm/tools/llvm-cov/CoverageViewOptions.h
    llvm/tools/llvm-cov/SourceCoverageView.cpp
    llvm/tools/llvm-cov/SourceCoverageView.h
    llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
    llvm/tools/llvm-cov/SourceCoverageViewHTML.h
    llvm/tools/llvm-cov/SourceCoverageViewText.cpp
    llvm/tools/llvm-cov/SourceCoverageViewText.h

Removed: 
    


################################################################################
diff  --git a/clang/docs/SourceBasedCodeCoverage.rst b/clang/docs/SourceBasedCodeCoverage.rst
index f5b3d05262e9..90feb41b0a3f 100644
--- a/clang/docs/SourceBasedCodeCoverage.rst
+++ b/clang/docs/SourceBasedCodeCoverage.rst
@@ -179,6 +179,31 @@ region counts (even in macro expansions):
     |      4|    1|}
     ------------------
 
+If ``--show-branches=count`` and ``--show-expansions`` are also enabled, the
+sub-views will show detailed branch coverage information in addition to the
+region counts:
+
+.. code-block:: none
+
+    ------------------
+    | void foo<float>(int):
+    |      2|    1|template <typename T> void foo(T x) {
+    |      3|   11|  for (unsigned I = 0; I < 10; ++I) { BAR(I); }
+    |                                     ^11     ^10  ^10^10
+    |  ------------------
+    |  |  |    1|     10|#define BAR(x) ((x) || (x))
+    |  |  |                             ^10     ^1
+    |  |  |  ------------------
+    |  |  |  |  Branch (1:17): [True: 9, False: 1]
+    |  |  |  |  Branch (1:24): [True: 0, False: 1]
+    |  |  |  ------------------
+    |  ------------------
+    |  |  Branch (3:23): [True: 10, False: 1]
+    |  ------------------
+    |      4|    1|}
+    ------------------
+
+
 To generate a file-level summary of coverage statistics instead of a
 line-oriented report, try:
 
@@ -186,11 +211,11 @@ line-oriented report, try:
 
     # Step 3(c): Create a coverage summary.
     % llvm-cov report ./foo -instr-profile=foo.profdata
-    Filename           Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover
-    --------------------------------------------------------------------------------------------------------------------------------------
-    /tmp/foo.cc             13                 0   100.00%           3                 0   100.00%          13                 0   100.00%
-    --------------------------------------------------------------------------------------------------------------------------------------
-    TOTAL                   13                 0   100.00%           3                 0   100.00%          13                 0   100.00%
+    Filename           Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover     Branches    Missed Branches     Cover
+    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+    /tmp/foo.cc             13                 0   100.00%           3                 0   100.00%          13                 0   100.00%           12                  2    83.33%
+    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+    TOTAL                   13                 0   100.00%           3                 0   100.00%          13                 0   100.00%           12                  2    83.33%
 
 The ``llvm-cov`` tool supports specifying a custom demangler, writing out
 reports in a directory structure, and generating html reports. For the full
@@ -246,8 +271,17 @@ There are four statistics tracked in a coverage summary:
   body with no control flow). However, it's also possible for a single line to
   contain multiple code regions (e.g in "return x || y && z").
 
-Of these four statistics, function coverage is usually the least granular while
-region coverage is the most granular. The project-wide totals for each
+* Branch coverage is the percentage of "true" and "false" branches that have
+  been taken at least once. Each branch is tied to individual conditions in the
+  source code that may each evaluate to either "true" or "false".  These
+  conditions may comprise larger boolean expressions linked by boolean logical
+  operators. For example, "x = (y == 2) || (z < 10)" is a boolean expression
+  that is comprised of two individual conditions, each of which evaluates to
+  either true or false, producing four total branch outcomes.
+
+Of these five statistics, function coverage is usually the least granular while
+branch coverage is the most granular. 100% branch coverage for a function
+implies 100% region coverage for a function. The project-wide totals for each
 statistic are listed in the summary.
 
 Format compatibility guarantees
@@ -351,6 +385,25 @@ as red "unexecuted" highlights present at the end of an otherwise covered line,
 or blue "executed" highlights present at the start of a line that is otherwise
 not executed.
 
+Branch regions
+--------------
+When viewing branch coverage details in source-based file-level sub-views using
+``--show-branches``, it is recommended that users show all macro expansions
+(using option ``--show-expansions``) since macros may contain hidden branch
+conditions.  The coverage summary report will always include these macro-based
+boolean expressions in the overall branch coverage count for a function or
+source file.
+
+Branch coverage is not tracked for constant folded branch conditions since
+branches are not generated for these cases.  In the source-based file-level
+sub-view, these branches will simply be shown as ``[Folded - Ignored]`` so that
+users are informed about what happened.
+
+Branch coverage is tied directly to branch-generating conditions in the source
+code.  Users should not see hidden branches that aren't actually tied to the
+source code.
+
+
 Switch statements
 -----------------
 
@@ -366,3 +419,10 @@ which the switch body and the single case share a count.
 
 For switches with ``CompoundStmt`` bodies, a new region is created at the start
 of each switch case.
+
+Branch regions are also generated for each switch case, including the default
+case. If there is no explicitly defined default case in the source code, a
+branch region is generated to correspond to the implicit default case that is
+generated by the compiler.  The implicit branch region is tied to the line and
+column number of the switch statement condition since no source code for the
+implicit case exists.

diff  --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index afb03774132e..d6d5ec544c08 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4191,6 +4191,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
     return Builder.CreateSExt(And, ConvertType(E->getType()), "sext");
   }
 
+  bool InstrumentRegions = CGF.CGM.getCodeGenOpts().hasProfileClangInstr();
   llvm::Type *ResTy = ConvertType(E->getType());
 
   // If we have 0 && RHS, see if we can elide RHS, if so, just return 0.
@@ -4201,6 +4202,22 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
       CGF.incrementProfileCounter(E);
 
       Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
+
+      // If we're generating for profiling or coverage, generate a branch to a
+      // block that increments the RHS counter needed to track branch condition
+      // coverage. In this case, use "FBlock" as both the final "TrueBlock" and
+      // "FalseBlock" after the increment is done.
+      if (InstrumentRegions &&
+          CodeGenFunction::isInstrumentedCondition(E->getRHS())) {
+        llvm::BasicBlock *FBlock = CGF.createBasicBlock("land.end");
+        llvm::BasicBlock *RHSBlockCnt = CGF.createBasicBlock("land.rhscnt");
+        Builder.CreateCondBr(RHSCond, RHSBlockCnt, FBlock);
+        CGF.EmitBlock(RHSBlockCnt);
+        CGF.incrementProfileCounter(E->getRHS());
+        CGF.EmitBranch(FBlock);
+        CGF.EmitBlock(FBlock);
+      }
+
       // ZExt result to int or bool.
       return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext");
     }
@@ -4237,6 +4254,19 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
   // Reaquire the RHS block, as there may be subblocks inserted.
   RHSBlock = Builder.GetInsertBlock();
 
+  // If we're generating for profiling or coverage, generate a branch on the
+  // RHS to a block that increments the RHS true counter needed to track branch
+  // condition coverage.
+  if (InstrumentRegions &&
+      CodeGenFunction::isInstrumentedCondition(E->getRHS())) {
+    llvm::BasicBlock *RHSBlockCnt = CGF.createBasicBlock("land.rhscnt");
+    Builder.CreateCondBr(RHSCond, RHSBlockCnt, ContBlock);
+    CGF.EmitBlock(RHSBlockCnt);
+    CGF.incrementProfileCounter(E->getRHS());
+    CGF.EmitBranch(ContBlock);
+    PN->addIncoming(RHSCond, RHSBlockCnt);
+  }
+
   // Emit an unconditional branch from this block to ContBlock.
   {
     // There is no need to emit line number for unconditional branch.
@@ -4277,6 +4307,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
     return Builder.CreateSExt(Or, ConvertType(E->getType()), "sext");
   }
 
+  bool InstrumentRegions = CGF.CGM.getCodeGenOpts().hasProfileClangInstr();
   llvm::Type *ResTy = ConvertType(E->getType());
 
   // If we have 1 || RHS, see if we can elide RHS, if so, just return 1.
@@ -4287,6 +4318,22 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
       CGF.incrementProfileCounter(E);
 
       Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
+
+      // If we're generating for profiling or coverage, generate a branch to a
+      // block that increments the RHS counter need to track branch condition
+      // coverage. In this case, use "FBlock" as both the final "TrueBlock" and
+      // "FalseBlock" after the increment is done.
+      if (InstrumentRegions &&
+          CodeGenFunction::isInstrumentedCondition(E->getRHS())) {
+        llvm::BasicBlock *FBlock = CGF.createBasicBlock("lor.end");
+        llvm::BasicBlock *RHSBlockCnt = CGF.createBasicBlock("lor.rhscnt");
+        Builder.CreateCondBr(RHSCond, FBlock, RHSBlockCnt);
+        CGF.EmitBlock(RHSBlockCnt);
+        CGF.incrementProfileCounter(E->getRHS());
+        CGF.EmitBranch(FBlock);
+        CGF.EmitBlock(FBlock);
+      }
+
       // ZExt result to int or bool.
       return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext");
     }
@@ -4327,6 +4374,19 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
   // Reaquire the RHS block, as there may be subblocks inserted.
   RHSBlock = Builder.GetInsertBlock();
 
+  // If we're generating for profiling or coverage, generate a branch on the
+  // RHS to a block that increments the RHS true counter needed to track branch
+  // condition coverage.
+  if (InstrumentRegions &&
+      CodeGenFunction::isInstrumentedCondition(E->getRHS())) {
+    llvm::BasicBlock *RHSBlockCnt = CGF.createBasicBlock("lor.rhscnt");
+    Builder.CreateCondBr(RHSCond, ContBlock, RHSBlockCnt);
+    CGF.EmitBlock(RHSBlockCnt);
+    CGF.incrementProfileCounter(E->getRHS());
+    CGF.EmitBranch(ContBlock);
+    PN->addIncoming(RHSCond, RHSBlockCnt);
+  }
+
   // Emit an unconditional branch from this block to ContBlock.  Insert an entry
   // into the phi node for the edge with the value of RHSCond.
   CGF.EmitBlock(ContBlock);

diff  --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index d67e73a2ec3b..a1a72a9f668d 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1441,7 +1441,7 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S,
       SwitchWeights->push_back(getProfileCount(NextCase));
     if (CGM.getCodeGenOpts().hasProfileClangInstr()) {
       CaseDest = createBasicBlock("sw.bb");
-      EmitBlockWithFallThrough(CaseDest, &S);
+      EmitBlockWithFallThrough(CaseDest, CurCase);
     }
     // Since this loop is only executed when the CaseStmt has no attributes
     // use a hard-coded value.

diff  --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a8a91c59ff2d..49f13323297c 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1501,6 +1501,90 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
   return true;
 }
 
+/// Determine whether the given condition is an instrumentable condition
+/// (i.e. no "&&" or "||").
+bool CodeGenFunction::isInstrumentedCondition(const Expr *C) {
+  // Bypass simplistic logical-NOT operator before determining whether the
+  // condition contains any other logical operator.
+  if (const UnaryOperator *UnOp = dyn_cast<UnaryOperator>(C->IgnoreParens()))
+    if (UnOp->getOpcode() == UO_LNot)
+      C = UnOp->getSubExpr();
+
+  const BinaryOperator *BOp = dyn_cast<BinaryOperator>(C->IgnoreParens());
+  return (!BOp || !BOp->isLogicalOp());
+}
+
+/// EmitBranchToCounterBlock - Emit a conditional branch to a new block that
+/// increments a profile counter based on the semantics of the given logical
+/// operator opcode.  This is used to instrument branch condition coverage for
+/// logical operators.
+void CodeGenFunction::EmitBranchToCounterBlock(
+    const Expr *Cond, BinaryOperator::Opcode LOp, llvm::BasicBlock *TrueBlock,
+    llvm::BasicBlock *FalseBlock, uint64_t TrueCount /* = 0 */,
+    Stmt::Likelihood LH /* =None */, const Expr *CntrIdx /* = nullptr */) {
+  // If not instrumenting, just emit a branch.
+  bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
+  if (!InstrumentRegions || !isInstrumentedCondition(Cond))
+    return EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount, LH);
+
+  llvm::BasicBlock *ThenBlock = NULL;
+  llvm::BasicBlock *ElseBlock = NULL;
+  llvm::BasicBlock *NextBlock = NULL;
+
+  // Create the block we'll use to increment the appropriate counter.
+  llvm::BasicBlock *CounterIncrBlock = createBasicBlock("lop.rhscnt");
+
+  // Set block pointers according to Logical-AND (BO_LAnd) semantics. This
+  // means we need to evaluate the condition and increment the counter on TRUE:
+  //
+  // if (Cond)
+  //   goto CounterIncrBlock;
+  // else
+  //   goto FalseBlock;
+  //
+  // CounterIncrBlock:
+  //   Counter++;
+  //   goto TrueBlock;
+
+  if (LOp == BO_LAnd) {
+    ThenBlock = CounterIncrBlock;
+    ElseBlock = FalseBlock;
+    NextBlock = TrueBlock;
+  }
+
+  // Set block pointers according to Logical-OR (BO_LOr) semantics. This means
+  // we need to evaluate the condition and increment the counter on FALSE:
+  //
+  // if (Cond)
+  //   goto TrueBlock;
+  // else
+  //   goto CounterIncrBlock;
+  //
+  // CounterIncrBlock:
+  //   Counter++;
+  //   goto FalseBlock;
+
+  else if (LOp == BO_LOr) {
+    ThenBlock = TrueBlock;
+    ElseBlock = CounterIncrBlock;
+    NextBlock = FalseBlock;
+  } else {
+    llvm_unreachable("Expected Opcode must be that of a Logical Operator");
+  }
+
+  // Emit Branch based on condition.
+  EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, TrueCount, LH);
+
+  // Emit the block containing the counter increment(s).
+  EmitBlock(CounterIncrBlock);
+
+  // Increment corresponding counter; if index not provided, use Cond as index.
+  incrementProfileCounter(CntrIdx ? CntrIdx : Cond);
+
+  // Go to the next block.
+  EmitBranch(NextBlock);
+}
+
 /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if
 /// statement) to the specified blocks.  Based on the condition, this might try
 /// to simplify the codegen of the conditional based on the branch.
@@ -1523,8 +1607,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
           ConstantBool) {
         // br(1 && X) -> br(X).
         incrementProfileCounter(CondBOp);
-        return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
-                                    TrueCount, LH);
+        return EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LAnd, TrueBlock,
+                                        FalseBlock, TrueCount, LH);
       }
 
       // If we have "X && 1", simplify the code to use an uncond branch.
@@ -1532,8 +1616,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
       if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) &&
           ConstantBool) {
         // br(X && 1) -> br(X).
-        return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock,
-                                    TrueCount, LH);
+        return EmitBranchToCounterBlock(CondBOp->getLHS(), BO_LAnd, TrueBlock,
+                                        FalseBlock, TrueCount, LH, CondBOp);
       }
 
       // Emit the LHS as a conditional.  If the LHS conditional is false, we
@@ -1559,8 +1643,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
 
       // Any temporaries created here are conditional.
       eval.begin(*this);
-      EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount,
-                           LH);
+      EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LAnd, TrueBlock,
+                               FalseBlock, TrueCount, LH);
       eval.end(*this);
 
       return;
@@ -1574,8 +1658,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
           !ConstantBool) {
         // br(0 || X) -> br(X).
         incrementProfileCounter(CondBOp);
-        return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
-                                    TrueCount, LH);
+        return EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LOr, TrueBlock,
+                                        FalseBlock, TrueCount, LH);
       }
 
       // If we have "X || 0", simplify the code to use an uncond branch.
@@ -1583,8 +1667,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
       if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) &&
           !ConstantBool) {
         // br(X || 0) -> br(X).
-        return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock,
-                                    TrueCount, LH);
+        return EmitBranchToCounterBlock(CondBOp->getLHS(), BO_LOr, TrueBlock,
+                                        FalseBlock, TrueCount, LH, CondBOp);
       }
 
       // Emit the LHS as a conditional.  If the LHS conditional is true, we
@@ -1613,8 +1697,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
 
       // Any temporaries created here are conditional.
       eval.begin(*this);
-      EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount,
-                           LH);
+      EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LOr, TrueBlock, FalseBlock,
+                               RHSCount, LH);
 
       eval.end(*this);
 

diff  --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 142cf5d83273..9d11466f69ce 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4394,6 +4394,21 @@ class CodeGenFunction : public CodeGenTypeCache {
   bool ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APSInt &Result,
                                     bool AllowLabels = false);
 
+  /// isInstrumentedCondition - Determine whether the given condition is an
+  /// instrumentable condition (i.e. no "&&" or "||").
+  static bool isInstrumentedCondition(const Expr *C);
+
+  /// EmitBranchToCounterBlock - Emit a conditional branch to a new block that
+  /// increments a profile counter based on the semantics of the given logical
+  /// operator opcode.  This is used to instrument branch condition coverage
+  /// for logical operators.
+  void EmitBranchToCounterBlock(const Expr *Cond, BinaryOperator::Opcode LOp,
+                                llvm::BasicBlock *TrueBlock,
+                                llvm::BasicBlock *FalseBlock,
+                                uint64_t TrueCount = 0,
+                                Stmt::Likelihood LH = Stmt::LH_None,
+                                const Expr *CntrIdx = nullptr);
+
   /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an
   /// if statement) to the specified blocks.  Based on the condition, this might
   /// try to simplify the codegen of the conditional based on the branch.

diff  --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index c11d99a348d1..052d58a04a14 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -160,10 +160,13 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
   PGOHash Hash;
   /// The map of statements to counters.
   llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
+  /// The profile version.
+  uint64_t ProfileVersion;
 
-  MapRegionCounters(PGOHashVersion HashVersion,
+  MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion,
                     llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
-      : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap) {}
+      : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
+        ProfileVersion(ProfileVersion) {}
 
   // Blocks and lambdas are handled as separate functions, so we need not
   // traverse them in the parent context.
@@ -203,6 +206,18 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
     return Type;
   }
 
+  /// The RHS of all logical operators gets a fresh counter in order to count
+  /// how many times the RHS evaluates to true or false, depending on the
+  /// semantics of the operator. This is only valid for ">= v7" of the profile
+  /// version so that we facilitate backward compatibility.
+  bool VisitBinaryOperator(BinaryOperator *S) {
+    if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
+      if (S->isLogicalOp() &&
+          CodeGenFunction::isInstrumentedCondition(S->getRHS()))
+        CounterMap[S->getRHS()] = NextCounter++;
+    return Base::VisitBinaryOperator(S);
+  }
+
   /// Include \p S in the function hash.
   bool VisitStmt(Stmt *S) {
     auto Type = updateCounterMappings(S);
@@ -814,11 +829,14 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
   // Use the latest hash version when inserting instrumentation, but use the
   // version in the indexed profile if we're reading PGO data.
   PGOHashVersion HashVersion = PGO_HASH_LATEST;
-  if (auto *PGOReader = CGM.getPGOReader())
+  uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
+  if (auto *PGOReader = CGM.getPGOReader()) {
     HashVersion = getPGOHashVersion(PGOReader, CGM);
+    ProfileVersion = PGOReader->getVersion();
+  }
 
   RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
-  MapRegionCounters Walker(HashVersion, *RegionCounterMap);
+  MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap);
   if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
     Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
   else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))

diff  --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8d9c1979d87c..c474546d4abf 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -92,8 +92,12 @@ namespace {
 
 /// A region of source code that can be mapped to a counter.
 class SourceMappingRegion {
+  /// Primary Counter that is also used for Branch Regions for "True" branches.
   Counter Count;
 
+  /// Secondary Counter used for Branch Regions for "False" branches.
+  Optional<Counter> FalseCount;
+
   /// The region's starting location.
   Optional<SourceLocation> LocStart;
 
@@ -114,8 +118,20 @@ class SourceMappingRegion {
       : Count(Count), LocStart(LocStart), LocEnd(LocEnd),
         DeferRegion(DeferRegion), GapRegion(GapRegion) {}
 
+  SourceMappingRegion(Counter Count, Optional<Counter> FalseCount,
+                      Optional<SourceLocation> LocStart,
+                      Optional<SourceLocation> LocEnd, bool DeferRegion = false,
+                      bool GapRegion = false)
+      : Count(Count), FalseCount(FalseCount), LocStart(LocStart),
+        LocEnd(LocEnd), DeferRegion(DeferRegion), GapRegion(GapRegion) {}
+
   const Counter &getCounter() const { return Count; }
 
+  const Counter &getFalseCounter() const {
+    assert(FalseCount && "Region has no alternate counter");
+    return *FalseCount;
+  }
+
   void setCounter(Counter C) { Count = C; }
 
   bool hasStartLoc() const { return LocStart.hasValue(); }
@@ -146,6 +162,8 @@ class SourceMappingRegion {
   bool isGap() const { return GapRegion; }
 
   void setGap(bool Gap) { GapRegion = Gap; }
+
+  bool isBranch() const { return FalseCount.hasValue(); }
 };
 
 /// Spelling locations for the start and end of a source region.
@@ -425,6 +443,10 @@ class CoverageMappingBuilder {
         MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
             Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
             SR.LineEnd, SR.ColumnEnd));
+      } else if (Region.isBranch()) {
+        MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
+            Region.getCounter(), Region.getFalseCounter(), *CovFileID,
+            SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd));
       } else {
         MappingRegions.push_back(CounterMappingRegion::makeRegion(
             Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
@@ -563,12 +585,16 @@ struct CounterCoverageMappingBuilder
   /// Returns the index on the stack where the region was pushed. This can be
   /// used with popRegions to exit a "scope", ending the region that was pushed.
   size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None,
-                    Optional<SourceLocation> EndLoc = None) {
-    if (StartLoc) {
+                    Optional<SourceLocation> EndLoc = None,
+                    Optional<Counter> FalseCount = None) {
+
+    if (StartLoc && !FalseCount.hasValue()) {
       MostRecentLocation = *StartLoc;
       completeDeferred(Count, MostRecentLocation);
     }
-    RegionStack.emplace_back(Count, StartLoc, EndLoc);
+
+    RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc,
+                             FalseCount.hasValue());
 
     return RegionStack.size() - 1;
   }
@@ -658,49 +684,64 @@ struct CounterCoverageMappingBuilder
         SourceLocation EndLoc = Region.hasEndLoc()
                                     ? Region.getEndLoc()
                                     : RegionStack[ParentIndex].getEndLoc();
+        bool isBranch = Region.isBranch();
         size_t StartDepth = locationDepth(StartLoc);
         size_t EndDepth = locationDepth(EndLoc);
         while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
           bool UnnestStart = StartDepth >= EndDepth;
           bool UnnestEnd = EndDepth >= StartDepth;
           if (UnnestEnd) {
-            // The region ends in a nested file or macro expansion. Create a
-            // separate region for each expansion.
+            // The region ends in a nested file or macro expansion. If the
+            // region is not a branch region, create a separate region for each
+            // expansion, and for all regions, update the EndLoc. Branch
+            // regions should not be split in order to keep a straightforward
+            // correspondance between the region and its associated branch
+            // condition, even if the condition spans multiple depths.
             SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
             assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
 
-            if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
-              SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
+            if (!isBranch && !isRegionAlreadyAdded(NestedLoc, EndLoc))
+              SourceRegions.emplace_back(Region.getCounter(), NestedLoc,
+                                         EndLoc);
 
             EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
             if (EndLoc.isInvalid())
-              llvm::report_fatal_error("File exit not handled before popRegions");
+              llvm::report_fatal_error(
+                  "File exit not handled before popRegions");
             EndDepth--;
           }
           if (UnnestStart) {
-            // The region begins in a nested file or macro expansion. Create a
-            // separate region for each expansion.
+            // The region ends in a nested file or macro expansion. If the
+            // region is not a branch region, create a separate region for each
+            // expansion, and for all regions, update the StartLoc. Branch
+            // regions should not be split in order to keep a straightforward
+            // correspondance between the region and its associated branch
+            // condition, even if the condition spans multiple depths.
             SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
             assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
 
-            if (!isRegionAlreadyAdded(StartLoc, NestedLoc))
-              SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc);
+            if (!isBranch && !isRegionAlreadyAdded(StartLoc, NestedLoc))
+              SourceRegions.emplace_back(Region.getCounter(), StartLoc,
+                                         NestedLoc);
 
             StartLoc = getIncludeOrExpansionLoc(StartLoc);
             if (StartLoc.isInvalid())
-              llvm::report_fatal_error("File exit not handled before popRegions");
+              llvm::report_fatal_error(
+                  "File exit not handled before popRegions");
             StartDepth--;
           }
         }
         Region.setStartLoc(StartLoc);
         Region.setEndLoc(EndLoc);
 
-        MostRecentLocation = EndLoc;
-        // If this region happens to span an entire expansion, we need to make
-        // sure we don't overlap the parent region with it.
-        if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
-            EndLoc == getEndOfFileOrMacro(EndLoc))
-          MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
+        if (!isBranch) {
+          MostRecentLocation = EndLoc;
+          // If this region happens to span an entire expansion, we need to
+          // make sure we don't overlap the parent region with it.
+          if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
+              EndLoc == getEndOfFileOrMacro(EndLoc))
+            MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
+        }
 
         assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
         assert(SpellingRegion(SM, Region).isInSourceOrder());
@@ -759,14 +800,61 @@ struct CounterCoverageMappingBuilder
     return ExitCount;
   }
 
+  /// Determine whether the given condition can be constant folded.
+  bool ConditionFoldsToBool(const Expr *Cond) {
+    Expr::EvalResult Result;
+    return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext()));
+  }
+
+  /// Create a Branch Region around an instrumentable condition for coverage
+  /// and add it to the function's SourceRegions.  A branch region tracks a
+  /// "True" counter and a "False" counter for boolean expressions that
+  /// result in the generation of a branch.
+  void createBranchRegion(const Expr *C, Counter TrueCnt, Counter FalseCnt) {
+    // Check for NULL conditions.
+    if (!C)
+      return;
+
+    // Ensure we are an instrumentable condition (i.e. no "&&" or "||").  Push
+    // region onto RegionStack but immediately pop it (which adds it to the
+    // function's SourceRegions) because it doesn't apply to any other source
+    // code other than the Condition.
+    if (CodeGenFunction::isInstrumentedCondition(C)) {
+      // If a condition can fold to true or false, the corresponding branch
+      // will be removed.  Create a region with both counters hard-coded to
+      // zero. This allows us to visualize them in a special way.
+      // Alternatively, we can prevent any optimization done via
+      // constant-folding by ensuring that ConstantFoldsToSimpleInteger() in
+      // CodeGenFunction.c always returns false, but that is very heavy-handed.
+      if (ConditionFoldsToBool(C))
+        popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C),
+                              Counter::getZero()));
+      else
+        // Otherwise, create a region with the True counter and False counter.
+        popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt));
+    }
+  }
+
+  /// Create a Branch Region around a SwitchCase for code coverage
+  /// and add it to the function's SourceRegions.
+  void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt,
+                              Counter FalseCnt) {
+    // Push region onto RegionStack but immediately pop it (which adds it to
+    // the function's SourceRegions) because it doesn't apply to any other
+    // source other than the SwitchCase.
+    popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt));
+  }
+
   /// Check whether a region with bounds \c StartLoc and \c EndLoc
   /// is already added to \c SourceRegions.
-  bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc) {
+  bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc,
+                            bool isBranch = false) {
     return SourceRegions.rend() !=
            std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
                         [&](const SourceMappingRegion &Region) {
                           return Region.getBeginLoc() == StartLoc &&
-                                 Region.getEndLoc() == EndLoc;
+                                 Region.getEndLoc() == EndLoc &&
+                                 Region.isBranch() == isBranch;
                         });
   }
 
@@ -783,7 +871,7 @@ struct CounterCoverageMappingBuilder
     if (getRegion().hasEndLoc() &&
         MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
         isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
-                             MostRecentLocation))
+                             MostRecentLocation, getRegion().isBranch()))
       MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
   }
 
@@ -827,9 +915,14 @@ struct CounterCoverageMappingBuilder
         // The most nested region for each start location is the one with the
         // correct count. We avoid creating redundant regions by stopping once
         // we've seen this region.
-        if (StartLocs.insert(Loc).second)
-          SourceRegions.emplace_back(I.getCounter(), Loc,
-                                     getEndOfFileOrMacro(Loc));
+        if (StartLocs.insert(Loc).second) {
+          if (I.isBranch())
+            SourceRegions.emplace_back(I.getCounter(), I.getFalseCounter(), Loc,
+                                       getEndOfFileOrMacro(Loc), I.isBranch());
+          else
+            SourceRegions.emplace_back(I.getCounter(), Loc,
+                                       getEndOfFileOrMacro(Loc));
+        }
         Loc = getIncludeOrExpansionLoc(Loc);
       }
       I.setStartLoc(getPreciseTokenLocEnd(Loc));
@@ -1070,6 +1163,10 @@ struct CounterCoverageMappingBuilder
         addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
     if (OutCount != ParentCount)
       pushRegion(OutCount);
+
+    // Create Branch Region around condition.
+    createBranchRegion(S->getCond(), BodyCount,
+                       subtractCounters(CondCount, BodyCount));
   }
 
   void VisitDoStmt(const DoStmt *S) {
@@ -1091,6 +1188,10 @@ struct CounterCoverageMappingBuilder
         addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
     if (OutCount != ParentCount)
       pushRegion(OutCount);
+
+    // Create Branch Region around condition.
+    createBranchRegion(S->getCond(), BodyCount,
+                       subtractCounters(CondCount, BodyCount));
   }
 
   void VisitForStmt(const ForStmt *S) {
@@ -1138,6 +1239,10 @@ struct CounterCoverageMappingBuilder
                                    subtractCounters(CondCount, BodyCount));
     if (OutCount != ParentCount)
       pushRegion(OutCount);
+
+    // Create Branch Region around condition.
+    createBranchRegion(S->getCond(), BodyCount,
+                       subtractCounters(CondCount, BodyCount));
   }
 
   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
@@ -1167,6 +1272,10 @@ struct CounterCoverageMappingBuilder
         addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
     if (OutCount != ParentCount)
       pushRegion(OutCount);
+
+    // Create Branch Region around condition.
+    createBranchRegion(S->getCond(), BodyCount,
+                       subtractCounters(LoopCount, BodyCount));
   }
 
   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
@@ -1231,6 +1340,7 @@ struct CounterCoverageMappingBuilder
       BreakContinueStack.back().ContinueCount = addCounters(
           BreakContinueStack.back().ContinueCount, BC.ContinueCount);
 
+    Counter ParentCount = getRegion().getCounter();
     Counter ExitCount = getRegionCounter(S);
     SourceLocation ExitLoc = getEnd(S);
     pushRegion(ExitCount);
@@ -1239,6 +1349,28 @@ struct CounterCoverageMappingBuilder
     // in a 
diff erent file.
     MostRecentLocation = getStart(S);
     handleFileExit(ExitLoc);
+
+    // Create a Branch Region around each Case. Subtract the case's
+    // counter from the Parent counter to track the "False" branch count.
+    Counter CaseCountSum;
+    bool HasDefaultCase = false;
+    const SwitchCase *Case = S->getSwitchCaseList();
+    for (; Case; Case = Case->getNextSwitchCase()) {
+      HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
+      CaseCountSum = addCounters(CaseCountSum, getRegionCounter(Case));
+      createSwitchCaseRegion(
+          Case, getRegionCounter(Case),
+          subtractCounters(ParentCount, getRegionCounter(Case)));
+    }
+
+    // If no explicit default case exists, create a branch region to represent
+    // the hidden branch, which will be added later by the CodeGen. This region
+    // will be associated with the switch statement's condition.
+    if (!HasDefaultCase) {
+      Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum);
+      Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue);
+      createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse);
+    }
   }
 
   void VisitSwitchCase(const SwitchCase *S) {
@@ -1299,6 +1431,10 @@ struct CounterCoverageMappingBuilder
 
     if (OutCount != ParentCount)
       pushRegion(OutCount);
+
+    // Create Branch Region around condition.
+    createBranchRegion(S->getCond(), ThenCount,
+                       subtractCounters(ParentCount, ThenCount));
   }
 
   void VisitCXXTryStmt(const CXXTryStmt *S) {
@@ -1342,6 +1478,10 @@ struct CounterCoverageMappingBuilder
     extendRegion(E->getFalseExpr());
     propagateCounts(subtractCounters(ParentCount, TrueCount),
                     E->getFalseExpr());
+
+    // Create Branch Region around condition.
+    createBranchRegion(E->getCond(), TrueCount,
+                       subtractCounters(ParentCount, TrueCount));
   }
 
   void VisitBinLAnd(const BinaryOperator *E) {
@@ -1349,8 +1489,26 @@ struct CounterCoverageMappingBuilder
     propagateCounts(getRegion().getCounter(), E->getLHS());
     handleFileExit(getEnd(E->getLHS()));
 
+    // Counter tracks the right hand side of a logical and operator.
     extendRegion(E->getRHS());
     propagateCounts(getRegionCounter(E), E->getRHS());
+
+    // Extract the RHS's Execution Counter.
+    Counter RHSExecCnt = getRegionCounter(E);
+
+    // Extract the RHS's "True" Instance Counter.
+    Counter RHSTrueCnt = getRegionCounter(E->getRHS());
+
+    // Extract the Parent Region Counter.
+    Counter ParentCnt = getRegion().getCounter();
+
+    // Create Branch Region around LHS condition.
+    createBranchRegion(E->getLHS(), RHSExecCnt,
+                       subtractCounters(ParentCnt, RHSExecCnt));
+
+    // Create Branch Region around RHS condition.
+    createBranchRegion(E->getRHS(), RHSTrueCnt,
+                       subtractCounters(RHSExecCnt, RHSTrueCnt));
   }
 
   void VisitBinLOr(const BinaryOperator *E) {
@@ -1358,8 +1516,26 @@ struct CounterCoverageMappingBuilder
     propagateCounts(getRegion().getCounter(), E->getLHS());
     handleFileExit(getEnd(E->getLHS()));
 
+    // Counter tracks the right hand side of a logical or operator.
     extendRegion(E->getRHS());
     propagateCounts(getRegionCounter(E), E->getRHS());
+
+    // Extract the RHS's Execution Counter.
+    Counter RHSExecCnt = getRegionCounter(E);
+
+    // Extract the RHS's "False" Instance Counter.
+    Counter RHSFalseCnt = getRegionCounter(E->getRHS());
+
+    // Extract the Parent Region Counter.
+    Counter ParentCnt = getRegion().getCounter();
+
+    // Create Branch Region around LHS condition.
+    createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
+                       RHSExecCnt);
+
+    // Create Branch Region around RHS condition.
+    createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
+                       RHSFalseCnt);
   }
 
   void VisitLambdaExpr(const LambdaExpr *LE) {
@@ -1396,11 +1572,20 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
     case CounterMappingRegion::GapRegion:
       OS << "Gap,";
       break;
+    case CounterMappingRegion::BranchRegion:
+      OS << "Branch,";
+      break;
     }
 
     OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
        << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = ";
     Ctx.dump(R.Count, OS);
+
+    if (R.Kind == CounterMappingRegion::BranchRegion) {
+      OS << ", ";
+      Ctx.dump(R.FalseCount, OS);
+    }
+
     if (R.Kind == CounterMappingRegion::ExpansionRegion)
       OS << " (Expanded file = " << R.ExpandedFileID << ")";
     OS << "\n";

diff  --git a/clang/lib/CodeGen/CoverageMappingGen.h b/clang/lib/CodeGen/CoverageMappingGen.h
index 645ad23a9ccd..9d0aa3b9cad1 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.h
+++ b/clang/lib/CodeGen/CoverageMappingGen.h
@@ -122,6 +122,9 @@ class CoverageMappingModuleGen {
   /// Return the coverage mapping translation unit file id
   /// for the given file.
   unsigned getFileID(const FileEntry *File);
+
+  /// Return an interface into CodeGenModule.
+  CodeGenModule &getCodeGenModule() { return CGM; }
 };
 
 /// Organizes the per-function state that is used while generating

diff  --git a/clang/test/CoverageMapping/branch-constfolded.cpp b/clang/test/CoverageMapping/branch-constfolded.cpp
new file mode 100644
index 000000000000..bb7c675e3ef7
--- /dev/null
+++ b/clang/test/CoverageMapping/branch-constfolded.cpp
@@ -0,0 +1,90 @@
+// Test that branch regions are not generated for constant-folded conditions.
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name branch-constfolded.cpp %s | FileCheck %s
+
+// CHECK-LABEL: _Z6fand_0b:
+bool fand_0(bool a) {
+  return false && a;       // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #2, (#1 - #2)
+
+// CHECK-LABEL: _Z6fand_1b:
+bool fand_1(bool a) {
+  return a && true;        // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1)
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
+
+// CHECK-LABEL: _Z6fand_2bb:
+bool fand_2(bool a, bool b) {
+  return false && a && b;  // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #4, (#3 - #4)
+                           // CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = #2, (#1 - #2)
+
+// CHECK-LABEL: _Z6fand_3bb:
+bool fand_3(bool a, bool b) {
+  return a && true && b;   // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3)
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
+                           // CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = #2, (#1 - #2)
+
+// CHECK-LABEL: _Z6fand_4bb:
+bool fand_4(bool a, bool b) {
+  return a && b && false;  // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3)
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = #4, (#3 - #4)
+                           // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:25 = 0, 0
+
+// CHECK-LABEL: _Z6fand_5b:
+bool fand_5(bool a) {
+  return false && true;    // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:23 = 0, 0
+
+// CHECK-LABEL: _Z6fand_6b:
+bool fand_6(bool a) {
+  return true && a;        // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = #2, (#1 - #2)
+
+// CHECK-LABEL: _Z6fand_7b:
+bool fand_7(bool a) {
+  return a && false;       // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1)
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
+
+// CHECK-LABEL: _Z5for_0b:
+bool for_0(bool a) {
+  return true || a;        // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#1 - #2), #2
+
+// CHECK-LABEL: _Z5for_1b:
+bool for_1(bool a) {
+  return a || false;       // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
+
+// CHECK-LABEL: _Z5for_2bb:
+bool for_2(bool a, bool b) {
+  return true || a || b;   // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#3 - #4), #4
+                           // CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = (#1 - #2), #2
+
+// CHECK-LABEL: _Z5for_3bb:
+bool for_3(bool a, bool b) {
+  return a || false || b;  // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
+                           // CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = (#1 - #2), #2
+
+// CHECK-LABEL: _Z5for_4bb:
+bool for_4(bool a, bool b) {
+  return a || b || true;   // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = (#3 - #4), #4
+                           // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:24 = 0, 0
+
+// CHECK-LABEL: _Z5for_5b:
+bool for_5(bool a) {
+  return true || false;    // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:23 = 0, 0
+
+// CHECK-LABEL: _Z5for_6b:
+bool for_6(bool a) {
+  return false || a;       // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = (#1 - #2), #2
+
+// CHECK-LABEL: _Z5for_7b:
+bool for_7(bool a) {
+  return a || true;        // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1
+}                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
+

diff  --git a/clang/test/CoverageMapping/branch-logical-mixed.cpp b/clang/test/CoverageMapping/branch-logical-mixed.cpp
new file mode 100644
index 000000000000..2f9277790acd
--- /dev/null
+++ b/clang/test/CoverageMapping/branch-logical-mixed.cpp
@@ -0,0 +1,64 @@
+// Test to ensure that each branch condition has an associated branch region
+// with expected True/False counters.
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name branch-logical-mixed.cpp %s | FileCheck %s
+
+
+
+
+bool func() {                        // CHECK: File 0, [[@LINE]]:13 -> [[@LINE+55]]:2 = #0
+  bool bt0 = true;
+  bool bt1 = true;
+  bool bt2 = true;
+  bool bt3 = true;
+  bool bt4 = true;
+  bool bt5 = true;
+  bool bf0 = false;
+  bool bf1 = false;
+  bool bf2 = false;
+  bool bf3 = false;
+  bool bf4 = false;
+  bool bf5 = false;
+
+  bool a = bt0 &&                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = #9, (#0 - #9)
+           bf0 &&                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = #10, (#9 - #10)
+           bt1 &&                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = #8, (#7 - #8)
+           bf1 &&                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = #6, (#5 - #6)
+           bt2 &&                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = #4, (#3 - #4)
+           bf2;                     // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = #2, (#1 - #2)
+
+  bool b = bt0 ||                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = (#0 - #19), #19
+           bf0 ||                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = (#19 - #20), #20
+           bt1 ||                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = (#17 - #18), #18
+           bf1 ||                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = (#15 - #16), #16
+           bt2 ||                   // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = (#13 - #14), #14
+           bf2;                     // CHECK: Branch,File 0, [[@LINE]]:12 -> [[@LINE]]:15 = (#11 - #12), #12
+
+  bool c = (bt0  &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #26, (#0 - #26)
+            bf0) ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #27, (#26 - #27)
+           (bt1  &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #28, (#25 - #28)
+            bf1) ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #29, (#28 - #29)
+           (bt2  &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #30, (#24 - #30)
+            bf2) ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #31, (#30 - #31)
+           (bt3  &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #32, (#23 - #32)
+            bf3) ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #33, (#32 - #33)
+           (bt4  &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #34, (#22 - #34)
+            bf4) ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #35, (#34 - #35)
+           (bf5  &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #36, (#21 - #36)
+            bf5);                   // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = #37, (#36 - #37)
+
+  bool d = (bt0  ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#0 - #43), #43
+            bf0) &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#43 - #44), #44
+           (bt1  ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#42 - #45), #45
+            bf1) &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#45 - #46), #46
+           (bt2  ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#41 - #47), #47
+            bf2) &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#47 - #48), #48
+           (bt3  ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#40 - #49), #49
+            bf3) &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#49 - #50), #50
+           (bt4  ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#39 - #51), #51
+            bf4) &&                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#51 - #52), #52
+           (bt5  ||                 // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#38 - #53), #53
+            bf5);                   // CHECK: Branch,File 0, [[@LINE]]:13 -> [[@LINE]]:16 = (#53 - #54), #54
+
+  return a && b && c && d;
+}

diff  --git a/clang/test/CoverageMapping/branch-macros.cpp b/clang/test/CoverageMapping/branch-macros.cpp
new file mode 100644
index 000000000000..d5bc47fbef76
--- /dev/null
+++ b/clang/test/CoverageMapping/branch-macros.cpp
@@ -0,0 +1,43 @@
+// Test that branch regions are generated for conditions in nested macro
+// expansions.
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name branch-macros.cpp %s | FileCheck %s
+
+#define COND1 (a == b)
+#define COND2 (a != b)
+#define COND3 (COND1 && COND2)
+#define COND4 (COND3 ? COND2 : COND1)
+#define MACRO1 COND3
+#define MACRO2 MACRO1
+#define MACRO3 MACRO2
+
+
+// CHECK-LABEL: _Z4funcii:
+bool func(int a, int b) {
+                             // CHECK: Branch,File 0, [[@LINE+15]]:12 -> [[@LINE+15]]:13 = #17, (#0 - #17)
+                             // CHECK: Branch,File 0, [[@LINE+14]]:17 -> [[@LINE+14]]:18 = #18, (#17 - #18)
+                             // CHECK: Branch,File 0, [[@LINE+13]]:22 -> [[@LINE+13]]:23 = #16, (#15 - #16)
+                             // CHECK: Branch,File 0, [[@LINE+12]]:27 -> [[@LINE+12]]:28 = #14, (#13 - #14)
+                             // CHECK: Branch,File 0, [[@LINE+11]]:32 -> [[@LINE+11]]:33 = #12, (#11 - #12)
+    bool c = COND1 && COND2; // CHECK: Branch,File 1, [[@LINE-16]]:15 -> [[@LINE-16]]:23 = #1, (#0 - #1)
+                             // CHECK: Branch,File 2, [[@LINE-16]]:15 -> [[@LINE-16]]:23 = #2, (#1 - #2)
+    bool d = COND3;          // CHECK: Branch,File 7, [[@LINE-18]]:15 -> [[@LINE-18]]:23 = #3, (#0 - #3)
+                             // CHECK: Branch,File 8, [[@LINE-18]]:15 -> [[@LINE-18]]:23 = #4, (#3 - #4)
+    bool e = MACRO1;         // CHECK: Branch,File 12, [[@LINE-20]]:15 -> [[@LINE-20]]:23 = #5, (#0 - #5)
+                             // CHECK: Branch,File 13, [[@LINE-20]]:15 -> [[@LINE-20]]:23 = #6, (#5 - #6)
+    bool f = MACRO2;         // CHECK: Branch,File 16, [[@LINE-22]]:15 -> [[@LINE-22]]:23 = #7, (#0 - #7)
+                             // CHECK: Branch,File 17, [[@LINE-22]]:15 -> [[@LINE-22]]:23 = #8, (#7 - #8)
+    bool g = MACRO3;         // CHECK: Branch,File 19, [[@LINE-24]]:15 -> [[@LINE-24]]:23 = #9, (#0 - #9)
+                             // CHECK: Branch,File 20, [[@LINE-24]]:15 -> [[@LINE-24]]:23 = #10, (#9 - #10)
+    return c && d && e && f && g;
+}
+
+// CHECK-LABEL: _Z5func2ii:
+bool func2(int a, int b) {
+    bool h = MACRO3 || COND4;// CHECK: Branch,File 2, [[@LINE-28]]:15 -> [[@LINE-28]]:38 = (#1 - #2), #2
+                             // CHECK: Branch,File 8, [[@LINE-32]]:15 -> [[@LINE-32]]:23 = #6, (#1 - #6)
+                             // CHECK: Branch,File 9, [[@LINE-32]]:15 -> [[@LINE-32]]:23 = #7, (#6 - #7)
+                             // CHECK: Branch,File 11, [[@LINE-34]]:15 -> [[@LINE-34]]:23 = #3, (#0 - #3)
+                             // CHECK: Branch,File 12, [[@LINE-34]]:15 -> [[@LINE-34]]:23 = #4, (#3 - #4)
+    return h;
+}

diff  --git a/clang/test/CoverageMapping/branch-mincounters.cpp b/clang/test/CoverageMapping/branch-mincounters.cpp
new file mode 100644
index 000000000000..68e691684970
--- /dev/null
+++ b/clang/test/CoverageMapping/branch-mincounters.cpp
@@ -0,0 +1,54 @@
+// Test to ensure right number of counters are allocated and used for nested
+// logical operators on branch conditions for branch coverage.
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name branch-logical-mixed.cpp %s | FileCheck %s
+
+
+// CHECK-LABEL: _Z5func1ii:
+bool func1(int a, int b) {
+  bool b0 = a <= b;
+  bool b1 = a == b;
+  bool b2 = a >= b;
+
+  // This should allocate a RHS branch counter on b2 (counter #3).
+  bool c = b0 && (b1 || b2);
+  // CHECK: Branch,File 0, [[@LINE-1]]:12 -> [[@LINE-1]]:14 = #1, (#0 - #1)
+  // CHECK: Branch,File 0, [[@LINE-2]]:19 -> [[@LINE-2]]:21 = (#1 - #2), #2
+  // CHECK: Branch,File 0, [[@LINE-3]]:25 -> [[@LINE-3]]:27 = (#2 - #3), #3
+
+  return c;
+}
+
+// CHECK-LABEL: _Z5func2ii:
+bool func2(int a, int b) {
+  bool b0 = a <= b;
+  bool b1 = a == b;
+  bool b2 = a >= b;
+
+  // This should allocate a RHS branch counter on b1 and b2 (counters #2, #4)
+  // This could possibly be further optimized through counter reuse (future).
+  bool c = (b0 && b1) || b2;
+  // CHECK: Branch,File 0, [[@LINE-1]]:13 -> [[@LINE-1]]:15 = #3, (#0 - #3)
+  // CHECK: Branch,File 0, [[@LINE-2]]:19 -> [[@LINE-2]]:21 = #4, (#3 - #4)
+  // CHECK: Branch,File 0, [[@LINE-3]]:26 -> [[@LINE-3]]:28 = (#1 - #2), #2
+
+  return c;
+}
+
+// CHECK-LABEL: _Z5func3ii:
+bool func3(int a, int b) {
+  bool b0 = a <= b;
+  bool b1 = a == b;
+  bool b2 = a >= b;
+  bool b3 = a < b;
+
+  // This should allocate a RHS branch counter on b1 and b3 (counters #3, #5)
+  // This could possibly be further optimized through counter reuse (future).
+  bool c = (b0 || b1) && (b2 || b3);
+  // CHECK: Branch,File 0, [[@LINE-1]]:13 -> [[@LINE-1]]:15 = (#0 - #2), #2
+  // CHECK: Branch,File 0, [[@LINE-2]]:19 -> [[@LINE-2]]:21 = (#2 - #3), #3
+  // CHECK: Branch,File 0, [[@LINE-3]]:27 -> [[@LINE-3]]:29 = (#1 - #4), #4
+  // CHECK: Branch,File 0, [[@LINE-4]]:33 -> [[@LINE-4]]:35 = (#4 - #5), #5
+
+  return c;
+}

diff  --git a/clang/test/CoverageMapping/branch-templates.cpp b/clang/test/CoverageMapping/branch-templates.cpp
new file mode 100644
index 000000000000..9e312df9b2de
--- /dev/null
+++ b/clang/test/CoverageMapping/branch-templates.cpp
@@ -0,0 +1,32 @@
+// Test that branch regions are generated for conditions in function template
+// instantiations.
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name branch-templates.cpp %s | FileCheck %s
+
+template<typename T>
+void unused(T x) {
+  return;
+}
+
+template<typename T>
+int func(T x) {
+  if(x)
+    return 0;
+  else
+    return 1;
+  int j = 1;
+}
+
+int main() {
+  func<int>(0);
+  func<bool>(true);
+  func<float>(0.0);
+  return 0;
+}
+
+// CHECK-LABEL: _Z4funcIiEiT_:
+// CHECK: Branch,File 0, [[@LINE-15]]:6 -> [[@LINE-15]]:7 = #1, (#0 - #1)
+// CHECK-LABEL: _Z4funcIbEiT_:
+// CHECK: Branch,File 0, [[@LINE-17]]:6 -> [[@LINE-17]]:7 = #1, (#0 - #1)
+// CHECK-LABEL: _Z4funcIfEiT_:
+// CHECK: Branch,File 0, [[@LINE-19]]:6 -> [[@LINE-19]]:7 = #1, (#0 - #1)

diff  --git a/clang/test/CoverageMapping/continue.c b/clang/test/CoverageMapping/continue.c
index 2c3eec07de2f..9bbbdab64fe8 100644
--- a/clang/test/CoverageMapping/continue.c
+++ b/clang/test/CoverageMapping/continue.c
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name continue.c %s | FileCheck %s
 
-int main() {                    // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+21]]:2 = #0
-  int j = 0;                    // CHECK-NEXT: File 0, [[@LINE+2]]:18 -> [[@LINE+2]]:24 = (#0 + #1)
+int main() {                    // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+22]]:2 = #0
+  int j = 0;                    // CHECK-NEXT: File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:24 = (#0 + #1)
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:18 -> [[@LINE+2]]:24 = #1, #0
                                 // CHECK-NEXT: File 0, [[@LINE+1]]:26 -> [[@LINE+1]]:29 = #1
   for(int i = 0; i < 20; ++i) { // CHECK: File 0, [[@LINE]]:31 -> [[@LINE+17]]:4 = #1
     if(i < 10) {                // CHECK: File 0, [[@LINE]]:16 -> [[@LINE+13]]:6 = #2

diff  --git a/clang/test/CoverageMapping/coroutine.cpp b/clang/test/CoverageMapping/coroutine.cpp
index 8eac751e309e..ac17eed59f1f 100644
--- a/clang/test/CoverageMapping/coroutine.cpp
+++ b/clang/test/CoverageMapping/coroutine.cpp
@@ -37,10 +37,11 @@ struct std::experimental::coroutine_traits<int, int> {
 };
 
 // CHECK-LABEL: _Z2f1i:
-int f1(int x) {       // CHECK-NEXT: File 0, [[@LINE]]:15 -> [[@LINE+7]]:2 = #0
+int f1(int x) {       // CHECK-NEXT: File 0, [[@LINE]]:15 -> [[@LINE+8]]:2 = #0
   if (x > 42) {       // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:13 = #0
-    ++x;              // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE-1]]:15 = #1
-  } else {            // CHECK-NEXT: File 0, [[@LINE-2]]:15 -> [[@LINE]]:4 = #1
+                      // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:13 = #1, (#0 - #1)
+    ++x;              // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:14 -> [[@LINE-2]]:15 = #1
+  } else {            // CHECK-NEXT: File 0, [[@LINE-3]]:15 -> [[@LINE]]:4 = #1
     co_return x + 42; // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE-1]]:10 = (#0 - #1)
   }                   // CHECK-NEXT: File 0, [[@LINE-2]]:10 -> [[@LINE]]:4 = (#0 - #1)
   co_return x;        // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = #1

diff  --git a/clang/test/CoverageMapping/if.cpp b/clang/test/CoverageMapping/if.cpp
index 1734f7baf07c..0dd9b016a5ac 100644
--- a/clang/test/CoverageMapping/if.cpp
+++ b/clang/test/CoverageMapping/if.cpp
@@ -3,40 +3,47 @@
 int nop() { return 0; }
 
 // CHECK-LABEL: _Z3foov:
-                                // CHECK-NEXT: [[@LINE+1]]:12 -> [[@LINE+6]]:2 = #0
+                                // CHECK-NEXT: [[@LINE+2]]:12 -> [[@LINE+7]]:2 = #0
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = 0, 0
 void foo() {                    // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:20 -> [[@LINE+1]]:22 = #2
   if (int j = true ? nop()      // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = #2
                    : nop();     // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = (#0 - #2)
       j)                        // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:8 = #0
-    ++j;                        // CHECK-NEXT: [[@LINE-1]]:9 -> [[@LINE]]:5 = #1
-}                               // CHECK-NEXT: [[@LINE-1]]:5 -> [[@LINE-1]]:8 = #1
-
+    ++j;                        // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:8 = #1, (#0 - #1)
+}                               // CHECK-NEXT: [[@LINE-2]]:9 -> [[@LINE-1]]:5 = #1
+                                // CHECK-NEXT: [[@LINE-2]]:5 -> [[@LINE-2]]:8 = #1
 // CHECK-LABEL: main:
 int main() {                    // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = #0
   int i = 0;
-                                // CHECK-NEXT: File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:12 = #0
+                                // CHECK-NEXT: File 0, [[@LINE+3]]:6 -> [[@LINE+3]]:12 = #0
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:12 = #1, (#0 - #1)
                                 // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:13 -> [[@LINE+1]]:14 = #1
   if(i == 0) i = 1;             // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE]]:19 = #1
 
-                                // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #0
+                                // CHECK-NEXT: File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:12 = #0
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #2, (#0 - #2)
   if(i == 1)                    // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+1]]:5 = #2
     i = 2;                      // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:10 = #2
 
-                                // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #0
+                                // CHECK-NEXT: File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:12 = #0
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #3, (#0 - #3)
   if(i == 0) { i = 1;           // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE]]:14 = #3
     i = 2;                      // CHECK-NEXT: File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:4 = #3
   }
-                                // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #0
+                                // CHECK-NEXT: File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:12 = #0
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #4, (#0 - #4)
   if(i != 0) {                  // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE]]:14 = #4
     i = 1;                      // CHECK-NEXT: File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:4 = #4
   } else {                      // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10 = (#0 - #4)
     i = 3;                      // CHECK-NEXT: File 0, [[@LINE-1]]:10 -> [[@LINE+1]]:4 = (#0 - #4)
   }
 
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:13 = #5, (#0 - #5)
   i = i == 0?                   // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+1]]:9 = #5
         i + 1 :                 // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:14 = #5
         i + 2;                  // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:14 = (#0 - #5)
 
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:13 = #6, (#0 - #6)
                                 // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:13 -> [[@LINE+2]]:14 = #6
                                 // CHECK-NEXT: File 0, [[@LINE+1]]:14 -> [[@LINE+1]]:20 = #6
   i = i == 0?i + 12:i + 10;     // CHECK-NEXT: File 0, [[@LINE]]:21 -> [[@LINE]]:27 = (#0 - #6)

diff  --git a/clang/test/CoverageMapping/label.cpp b/clang/test/CoverageMapping/label.cpp
index 385fbc0f6046..71524d21248c 100644
--- a/clang/test/CoverageMapping/label.cpp
+++ b/clang/test/CoverageMapping/label.cpp
@@ -2,7 +2,8 @@
 
 // CHECK: func
 void func() {                // CHECK-NEXT: File 0, [[@LINE]]:13 -> {{[0-9]+}}:2 = #0
-  int i = 0;                 // CHECK-NEXT: File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = (#0 + #3)
+  int i = 0;                 // CHECK-NEXT: File 0, [[@LINE+3]]:14 -> [[@LINE+3]]:20 = (#0 + #3)
+                             // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #1, ((#0 + #3) - #1)
                              // CHECK-NEXT: File 0, [[@LINE+1]]:22 -> [[@LINE+1]]:25 = #3
   for(i = 0; i < 10; ++i) {  // CHECK: File 0, [[@LINE]]:27 -> [[@LINE+11]]:4 = #1
                              // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> [[@LINE+1]]:13 = #1

diff  --git a/clang/test/CoverageMapping/logical.cpp b/clang/test/CoverageMapping/logical.cpp
index 143256668549..cd1a388ec4c2 100644
--- a/clang/test/CoverageMapping/logical.cpp
+++ b/clang/test/CoverageMapping/logical.cpp
@@ -1,18 +1,25 @@
 // RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name logical.cpp %s | FileCheck %s
 
-int main() {                        // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+15]]:2 = #0
+int main() {                        // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+22]]:2 = #0
   bool bt = true;
   bool bf = false;
   bool a = bt && bf;                // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE]]:14 = #0
-                                    // CHECK-NEXT: File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:20 = #1
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:12 -> [[@LINE-1]]:14 = #1, (#0 - #1)
+                                    // CHECK-NEXT: File 0, [[@LINE-2]]:18 -> [[@LINE-2]]:20 = #1
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE-3]]:18 -> [[@LINE-3]]:20 = #2, (#1 - #2)
 
   a = bt &&                         // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
-      bf;                           // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #2
-
+      bf;                           // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #3, (#0 - #3)
+                                    // CHECK-NEXT: File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #3
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:7 -> [[@LINE-2]]:9 = #4, (#3 - #4)
   a = bf || bt;                     // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
-                                    // CHECK-NEXT: File 0, [[@LINE-1]]:13 -> [[@LINE-1]]:15 = #3
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = (#0 - #5), #5
+                                    // CHECK-NEXT: File 0, [[@LINE-2]]:13 -> [[@LINE-2]]:15 = #5
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE-3]]:13 -> [[@LINE-3]]:15 = (#5 - #6), #6
 
   a = bf ||                         // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
-      bt;                           // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #4
+      bt;                           // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = (#0 - #7), #7
+                                    // CHECK-NEXT: File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #7
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:7 -> [[@LINE-2]]:9 = (#7 - #8), #8
   return 0;
 }

diff  --git a/clang/test/CoverageMapping/loopmacro.c b/clang/test/CoverageMapping/loopmacro.c
index 069740ea7f84..8a57eb66bcd4 100644
--- a/clang/test/CoverageMapping/loopmacro.c
+++ b/clang/test/CoverageMapping/loopmacro.c
@@ -6,6 +6,7 @@
 // CHECK-NEXT: Expansion,File 0, {{[0-9]+}}:7 -> {{[0-9]+}}:20 = (#0 + #1)
 // CHECK-NEXT: File 0, {{[0-9]+}}:12 -> {{[0-9]+}}:30 = (#0 + #1)
 
+// CHECK-NEXT: Branch,File 0, {{[0-9]+}}:12 -> {{[0-9]+}}:30 = #1, #0
 // CHECK-NEXT: File 1, [[@LINE+4]]:4 -> [[@LINE+6]]:23 = (#0 + #1)
 // CHECK-NEXT: Expansion,File 1, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = (#0 + #1)
 // CHECK-NEXT: Expansion,File 1, [[@LINE+3]]:16 -> [[@LINE+3]]:21 = (#0 + #1)

diff  --git a/clang/test/CoverageMapping/loops.cpp b/clang/test/CoverageMapping/loops.cpp
index bc391583c5ff..60bb2a5fbd8d 100644
--- a/clang/test/CoverageMapping/loops.cpp
+++ b/clang/test/CoverageMapping/loops.cpp
@@ -3,7 +3,8 @@
 // CHECK: rangedFor
 void rangedFor() {                  // CHECK-NEXT: File 0, [[@LINE]]:18 -> {{[0-9]+}}:2 = #0
   int arr[] = { 1, 2, 3, 4, 5 };
-  int sum = 0;                      // CHECK: Gap,File 0, [[@LINE+1]]:20 -> [[@LINE+1]]:21 = #1
+  int sum = 0;                      // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:15 = #1, (#0 - #3)
+                                    // CHECK: Gap,File 0, [[@LINE+1]]:20 -> [[@LINE+1]]:21 = #1
   for(auto i : arr) {               // CHECK: File 0, [[@LINE]]:21 -> [[@LINE+6]]:4 = #1
     if (i == 3)
       continue;                     // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = #2
@@ -19,29 +20,34 @@ void rangedFor() {                  // CHECK-NEXT: File 0, [[@LINE]]:18 -> {{[0-
                                     // CHECK: main:
 int main() {                        // CHECK-NEXT: File 0, [[@LINE]]:12 -> {{.*}}:2 = #0
                                     // CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+1]]:24 = (#0 + #1)
-  for(int i = 0; i < 10; ++i)       // CHECK-NEXT: File 0, [[@LINE]]:26 -> [[@LINE]]:29 = #1
-     ;                              // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:30 -> [[@LINE]]:6 = #1
-                                    // CHECK-NEXT: File 0, [[@LINE-1]]:6 -> [[@LINE-1]]:7 = #1
+  for(int i = 0; i < 10; ++i)       // CHECK-NEXT: Branch,File 0, [[@LINE]]:18 -> [[@LINE]]:24 = #1, #0
+     ;                              // CHECK-NEXT: File 0, [[@LINE-1]]:26 -> [[@LINE-1]]:29 = #1
+                                    // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:30 -> [[@LINE-1]]:6 = #1
+                                    // CHECK-NEXT: File 0, [[@LINE-2]]:6 -> [[@LINE-2]]:7 = #1
   for(int i = 0;
       i < 10;                       // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:13 = (#0 + #2)
-      ++i)                          // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:10 = #2
-  {                                 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE]]:3 = #2
+      ++i)                          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:13 = #2, #0
+                                    // CHECK-NEXT: File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:10 = #2
+  {                                 // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:11 -> [[@LINE]]:3 = #2
     int x = 0;                      // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE+1]]:4 = #2
   }
-  int j = 0;                        // CHECK-NEXT: File 0, [[@LINE+1]]:9 -> [[@LINE+1]]:14 = (#0 + #3)
+  int j = 0;                        // CHECK-NEXT: File 0, [[@LINE+2]]:9 -> [[@LINE+2]]:14 = (#0 + #3)
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:9 -> [[@LINE+1]]:14 = #3, #0
   while(j < 5) ++j;                 // CHECK-NEXT: Gap,File 0, [[@LINE]]:15 -> [[@LINE]]:16 = #3
                                     // CHECK-NEXT: File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:19 = #3
 
   do {                              // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE+2]]:4 = (#0 + #4)
     ++j;
   } while(j < 10);                  // CHECK-NEXT: File 0, [[@LINE]]:11 -> [[@LINE]]:17 = (#0 + #4)
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:17 = #4, #0
   j = 0;
   while                             // CHECK-NEXT: File 0, [[@LINE+1]]:5 -> [[@LINE+1]]:10 = (#0 + #5)
-   (j < 5)                          // CHECK-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:6 = #5
-     ++j;                           // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE]]:9 = #5
-  do
+   (j < 5)                          // CHECK-NEXT: Branch,File 0, [[@LINE]]:5 -> [[@LINE]]:10 = #5, #0
+     ++j;                           // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE]]:6 = #5
+  do                                // CHECK-NEXT: File 0, [[@LINE-1]]:6 -> [[@LINE-1]]:9 = #5
     ++j;                            // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:8 = (#0 + #6)
   while(j < 10);                    // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:15 = (#0 + #6)
+                                    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:15 = #6, #0
   rangedFor();
   return 0;
 }

diff  --git a/clang/test/CoverageMapping/macro-expansion.c b/clang/test/CoverageMapping/macro-expansion.c
index b0a00e40f59b..ad71fb15eda4 100644
--- a/clang/test/CoverageMapping/macro-expansion.c
+++ b/clang/test/CoverageMapping/macro-expansion.c
@@ -1,42 +1,53 @@
 // RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name macro-expansion.c %s | FileCheck %s
 
 // CHECK: func
-// CHECK:      File 1, [[@LINE+5]]:12 -> [[@LINE+5]]:38 = #0
-// CHECK-NEXT: File 1, [[@LINE+4]]:15 -> [[@LINE+4]]:28 = (#0 + #2)
-// CHECK-NEXT: File 1, [[@LINE+3]]:21 -> [[@LINE+3]]:22 = (#0 + #2)
-// CHECK: File 1, [[@LINE+2]]:24 -> [[@LINE+2]]:26 = #3
-// CHECK-NEXT: File 1, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = (#0 + #2)
+// CHECK:      File 1, [[@LINE+7]]:12 -> [[@LINE+7]]:38 = #0
+// CHECK-NEXT: File 1, [[@LINE+6]]:15 -> [[@LINE+6]]:28 = (#0 + #2)
+// CHECK-NEXT: File 1, [[@LINE+5]]:21 -> [[@LINE+5]]:22 = (#0 + #2)
+// CHECK: Branch,File 1, [[@LINE+4]]:21 -> [[@LINE+4]]:22 = 0, 0
+// CHECK-NEXT: File 1, [[@LINE+3]]:24 -> [[@LINE+3]]:26 = #3
+// CHECK-NEXT: File 1, [[@LINE+2]]:36 -> [[@LINE+2]]:37 = (#0 + #2)
+// CHECK-NEXT: Branch,File 1, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, 0
 #define M1 do { if (0) {} } while (0)
-// CHECK-NEXT: File 2, [[@LINE+10]]:15 -> [[@LINE+10]]:41 = #0
-// CHECK-NEXT: File 2, [[@LINE+9]]:18 -> [[@LINE+9]]:31 = (#0 + #4)
-// CHECK-NEXT: File 2, [[@LINE+8]]:24 -> [[@LINE+8]]:25 = (#0 + #4)
-// CHECK: File 2, [[@LINE+7]]:27 -> [[@LINE+7]]:29 = #5
-// CHECK-NEXT: File 2, [[@LINE+6]]:39 -> [[@LINE+6]]:40 = (#0 + #4)
-// CHECK-NEXT: File 3, [[@LINE+5]]:15 -> [[@LINE+5]]:41 = #0
-// CHECK-NEXT: File 3, [[@LINE+4]]:18 -> [[@LINE+4]]:31 = (#0 + #6)
-// CHECK-NEXT: File 3, [[@LINE+3]]:24 -> [[@LINE+3]]:25 = (#0 + #6)
-// CHECK: File 3, [[@LINE+2]]:27 -> [[@LINE+2]]:29 = #7
-// CHECK-NEXT: File 3, [[@LINE+1]]:39 -> [[@LINE+1]]:40 = (#0 + #6)
+// CHECK-NEXT: File 2, [[@LINE+12]]:15 -> [[@LINE+12]]:41 = #0
+// CHECK-NEXT: File 2, [[@LINE+11]]:18 -> [[@LINE+11]]:31 = (#0 + #4)
+// CHECK-NEXT: File 2, [[@LINE+10]]:24 -> [[@LINE+10]]:25 = (#0 + #4)
+// CHECK: File 2, [[@LINE+9]]:27 -> [[@LINE+9]]:29 = #5
+// CHECK-NEXT: File 2, [[@LINE+8]]:39 -> [[@LINE+8]]:40 = (#0 + #4)
+// CHECK-NEXT: Branch,File 2, [[@LINE+7]]:39 -> [[@LINE+7]]:40 = 0, 0
+// CHECK-NEXT: File 3, [[@LINE+6]]:15 -> [[@LINE+6]]:41 = #0
+// CHECK-NEXT: File 3, [[@LINE+5]]:18 -> [[@LINE+5]]:31 = (#0 + #6)
+// CHECK-NEXT: File 3, [[@LINE+4]]:24 -> [[@LINE+4]]:25 = (#0 + #6)
+// CHECK: File 3, [[@LINE+3]]:27 -> [[@LINE+3]]:29 = #7
+// CHECK-NEXT: File 3, [[@LINE+2]]:39 -> [[@LINE+2]]:40 = (#0 + #6)
+// CHECK-NEXT: Branch,File 3, [[@LINE+1]]:39 -> [[@LINE+1]]:40 = 0, 0
 #define M2(x) do { if (x) {} } while (0)
-// CHECK-NEXT: File 4, [[@LINE+4]]:15 -> [[@LINE+4]]:38 = #0
-// CHECK-NEXT: File 4, [[@LINE+3]]:18 -> [[@LINE+3]]:28 = (#0 + #8)
-// CHECK-NEXT: Expansion,File 4, [[@LINE+2]]:20 -> [[@LINE+2]]:22 = (#0 + #8)
-// CHECK-NEXT: File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = (#0 + #8)
+// CHECK-NEXT: File 4, [[@LINE+5]]:15 -> [[@LINE+5]]:38 = #0
+// CHECK-NEXT: File 4, [[@LINE+4]]:18 -> [[@LINE+4]]:28 = (#0 + #8)
+// CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:22 = (#0 + #8)
+// CHECK-NEXT: File 4, [[@LINE+2]]:36 -> [[@LINE+2]]:37 = (#0 + #8)
+// CHECK-NEXT: Branch,File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, 0
 #define M3(x) do { M2(x); } while (0)
-// CHECK-NEXT: File 5, [[@LINE+3]]:15 -> [[@LINE+3]]:27 = #0
-// CHECK-NEXT: File 5, [[@LINE+2]]:16 -> [[@LINE+2]]:19 = #0
+// CHECK-NEXT: File 5, [[@LINE+4]]:15 -> [[@LINE+4]]:27 = #0
+// CHECK-NEXT: File 5, [[@LINE+3]]:16 -> [[@LINE+3]]:19 = #0
+// CHECK-NEXT: Branch,File 5, [[@LINE+2]]:16 -> [[@LINE+2]]:19 = #12, (#0 - #12)
 // CHECK-NEXT: File 5, [[@LINE+1]]:23 -> [[@LINE+1]]:26 = #12
 #define M4(x) ((x) && (x))
-// CHECK-NEXT: File 6, [[@LINE+3]]:15 -> [[@LINE+3]]:27 = #0
-// CHECK-NEXT: File 6, [[@LINE+2]]:16 -> [[@LINE+2]]:19 = #0
-// CHECK-NEXT: File 6, [[@LINE+1]]:23 -> [[@LINE+1]]:26 = #14
+// CHECK-NEXT: Branch,File 5, [[@LINE-1]]:23 -> [[@LINE-1]]:26 = #13, (#12 - #13)
+// CHECK-NEXT: File 6, [[@LINE+4]]:15 -> [[@LINE+4]]:27 = #0
+// CHECK-NEXT: File 6, [[@LINE+3]]:16 -> [[@LINE+3]]:19 = #0
+// CHECK-NEXT: Branch,File 6, [[@LINE+2]]:16 -> [[@LINE+2]]:19 = (#0 - #15), #15
+// CHECK-NEXT: File 6, [[@LINE+1]]:23 -> [[@LINE+1]]:26 = #15
 #define M5(x) ((x) || (x))
+// CHECK-NEXT: Branch,File 6, [[@LINE-1]]:23 -> [[@LINE-1]]:26 = (#15 - #16), #16
 // CHECK-NEXT: File 7, [[@LINE+1]]:15 -> [[@LINE+1]]:26 = #0
 #define M6(x) ((x) + (x))
+// CHECK-NEXT: Branch,File 7, [[@LINE-1]]:15 -> [[@LINE-1]]:26 = #17, (#0 - #17)
 // CHECK-NEXT: File 8, [[@LINE+1]]:15 -> [[@LINE+1]]:18 = #0
 #define M7(x) (x)
 
 // Check for the expansion of M2 within M3.
+// CHECK-NEXT: Branch,File 8, [[@LINE-3]]:15 -> [[@LINE-3]]:18 = #18, (#0 - #18)
 // CHECK-NEXT: File 9, {{[0-9]+}}:15 -> {{[0-9]+}}:41 = (#0 + #8)
 // CHECK-NEXT: File 9, {{[0-9]+}}:18 -> {{[0-9]+}}:31 = ((#0 + #8) + #9)
 // CHECK-NEXT: File 9, {{[0-9]+}}:24 -> {{[0-9]+}}:25 = ((#0 + #8) + #9)

diff  --git a/clang/test/CoverageMapping/macro-expressions.cpp b/clang/test/CoverageMapping/macro-expressions.cpp
index c45549721342..18c2a7fa8e3a 100644
--- a/clang/test/CoverageMapping/macro-expressions.cpp
+++ b/clang/test/CoverageMapping/macro-expressions.cpp
@@ -77,11 +77,13 @@ void foo(int i) {
   // CHECK-NEXT: File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:8 = (#0 + #6)
   // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:21 = (#0 + #6)
   do {} while (NEXPR(i));
-  // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:8 -> [[@LINE+3]]:12 = #0
+  // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:8 -> [[@LINE+4]]:12 = #0
+  // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:21 -> [[@LINE+3]]:22 = #7, #0
   // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:26 = #0
   // CHECK: File 0, [[@LINE+1]]:42 -> [[@LINE+1]]:44 = #7
   for (DECL(int, j) : ARR(int, 1, 2, 3)) {}
 
+  // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:10 -> [[@LINE+3]]:11 = #8, (#0 - #8)
   // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #0
   // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:23 -> [[@LINE+1]]:29 = #0
   (void)(i ? PRIo64 : PRIu64);
@@ -92,6 +94,7 @@ void foo(int i) {
   // CHECK: File 0, [[@LINE+2]]:28 -> [[@LINE+2]]:29 = #10
   // CHECK-NEXT: File 0, [[@LINE+1]]:32 -> [[@LINE+1]]:33 = ((#0 - #9) - #10)
   (void)(i ? i : EXPR(i) ? i : 0);
+  // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #11, (#0 - #11)
   // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:15 -> [[@LINE+3]]:19 = (#0 - #11)
   // CHECK-NEXT: File 0, [[@LINE+2]]:19 -> [[@LINE+2]]:27 = (#0 - #11)
   // CHECK-NEXT: File 0, [[@LINE+1]]:26 -> [[@LINE+1]]:27 = ((#0 - #11) - #12)
@@ -99,14 +102,19 @@ void foo(int i) {
 }
 
 // CHECK-NEXT: File {{[0-9]+}}, 3:17 -> 3:20 = #0
+// CHECK-NEXT: Branch,File {{[0-9]+}}, 3:17 -> 3:20 = #2, (#0 - #2)
 // CHECK-NEXT: File {{[0-9]+}}, 4:18 -> 4:22 = (#0 + #3)
+// CHECK-NEXT: Branch,File {{[0-9]+}}, 4:18 -> 4:22 = #3, #0
 // CHECK-NEXT: File {{[0-9]+}}, 6:22 -> 6:27 = #0
 // CHECK-NEXT: File {{[0-9]+}}, 8:16 -> 8:19 = #4
 // CHECK-NEXT: File {{[0-9]+}}, 7:18 -> 7:23 = (#0 + #4)
+// CHECK-NEXT: Branch,File {{[0-9]+}}, 7:18 -> 7:23 = #4, #0
 // CHECK-NEXT: File {{[0-9]+}}, 6:22 -> 6:27 = #0
 // CHECK-NEXT: File {{[0-9]+}}, 8:16 -> 8:19 = #5
 // CHECK-NEXT: File {{[0-9]+}}, 7:18 -> 7:23 = (#0 + #5)
+// CHECK-NEXT: Branch,File {{[0-9]+}}, 7:18 -> 7:23 = #5, #0
 // CHECK-NEXT: File {{[0-9]+}}, 4:18 -> 4:22 = (#0 + #6)
+// CHECK-NEXT: Branch,File {{[0-9]+}}, 4:18 -> 4:22 = #6, #0
 // CHECK-NEXT: File {{[0-9]+}}, 5:20 -> 5:23 = #0
 // CHECK-NEXT: File {{[0-9]+}}, 9:25 -> 9:40 = #0
 // CHECK-NEXT: File {{[0-9]+}}, 12:16 -> 12:42 = #0
@@ -116,7 +124,9 @@ void foo(int i) {
 // CHECK-NEXT: Expansion,File {{[0-9]+}}, 13:16 -> 13:38 = (#0 - #8)
 // CHECK-NEXT: File {{[0-9]+}}, 13:38 -> 13:42 = (#0 - #8)
 // CHECK-NEXT: File {{[0-9]+}}, 3:17 -> 3:20 = (#0 - #9)
+// CHECK-NEXT: Branch,File {{[0-9]+}}, 3:17 -> 3:20 = #10, ((#0 - #9) - #10)
 // CHECK-NEXT: File {{[0-9]+}}, 3:17 -> 3:20 = (#0 - #11)
+// CHECK-NEXT: Branch,File {{[0-9]+}}, 3:17 -> 3:20 = #12, ((#0 - #11) - #12)
 // CHECK-NEXT: File {{[0-9]+}}, 11:32 -> 11:36 = #8
 // CHECK-NEXT: File {{[0-9]+}}, 11:32 -> 11:36 = (#0 - #8)
 

diff  --git a/clang/test/CoverageMapping/macros.c b/clang/test/CoverageMapping/macros.c
index 93bc2a100fc0..e7fb92e5931c 100644
--- a/clang/test/CoverageMapping/macros.c
+++ b/clang/test/CoverageMapping/macros.c
@@ -38,29 +38,32 @@ void func3() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+3]]:2 = #0
 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #0
 
 // CHECK-NEXT: func4
-void func4() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+6]]:2 = #0
+void func4() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+7]]:2 = #0
   int i = 0;
   while (i++ < 10) // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE]]:18 = (#0 + #1)
-    if (i < 5) // CHECK: File 0, [[@LINE]]:5 -> [[@LINE+2]]:14 = #1
+    if (i < 5) // CHECK: File 0, [[@LINE]]:5 -> [[@LINE+3]]:14 = #1
                // CHECK-NEXT: File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:14 = #1
+               // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:14 = #2, (#1 - #2)
       MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:7 -> [[@LINE]]:14 = #2
 }
 // CHECK-NEXT: File 1, 4:17 -> 4:22 = #2
 // CHECK-NOT: File 1
 
 // CHECK-NEXT: func5
-void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+4]]:2 = #0
+void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+5]]:2 = #0
   int i = 0;
   if (i > 5) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = #0
+             // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:12 = #1, (#0 - #1)
     MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = #1
 }
 // CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1
 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #1
 
 // CHECK-NEXT: func6
-void func6(unsigned count) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+4]]:2 = #0
-begin:                       // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+3]]:2 = #1
+void func6(unsigned count) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+5]]:2 = #0
+begin:                       // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+4]]:2 = #1
     if (count--)             // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:16 = #1
+                             // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:16 = #2, (#1 - #2)
         GOTO begin;          // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:19 = #2
 }
 // CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:13 = #2

diff  --git a/clang/test/CoverageMapping/macroscopes.cpp b/clang/test/CoverageMapping/macroscopes.cpp
index 8353321dfcc6..9a2134b26577 100644
--- a/clang/test/CoverageMapping/macroscopes.cpp
+++ b/clang/test/CoverageMapping/macroscopes.cpp
@@ -85,6 +85,7 @@ int main() {
 
 // CHECK-NEXT: File 1, 3:24 -> 3:53 = #0
 // CHECK-NEXT: File 1, 3:40 -> 3:45 = (#0 + #1)
+// CHECK-NEXT: Branch,File 1, 3:40 -> 3:45 = #1, #0
 // CHECK-NEXT: File 1, 3:47 -> 3:50 = #1
 // CHECK-NEXT: File 1, 3:52 -> 3:53 = #1
 // CHECK-NEXT: File 2, 10:3 -> 20:4 = #1
@@ -97,6 +98,7 @@ int main() {
 // CHECK-NEXT: File 3, 6:3 -> 7:4 = #1
 // CHECK-NEXT: File 4, 3:24 -> 3:53 = #0
 // CHECK-NEXT: File 4, 3:40 -> 3:45 = (#0 + #4)
+// CHECK-NEXT: Branch,File 4, 3:40 -> 3:45 = #4, #0
 // CHECK-NEXT: File 4, 3:47 -> 3:50 = #4
 // CHECK-NEXT: File 4, 3:52 -> 3:53 = #4
 // CHECK-NEXT: File 5, 10:3 -> 20:4 = #4
@@ -109,20 +111,25 @@ int main() {
 // CHECK-NEXT: File 6, 6:3 -> 7:4 = #4
 // CHECK-NEXT: File 7, 3:24 -> 3:53 = #0
 // CHECK-NEXT: File 7, 3:40 -> 3:45 = (#0 + #7)
+// CHECK-NEXT: Branch,File 7, 3:40 -> 3:45 = #7, #0
 // CHECK-NEXT: File 7, 3:47 -> 3:50 = #7
 // CHECK-NEXT: File 7, 3:52 -> 3:53 = #7
 // CHECK-NEXT: File 8, 6:3 -> 7:4 = #7
 // CHECK-NEXT: File 9, 22:24 -> 22:37 = #0
 // CHECK-NEXT: File 9, 22:31 -> 22:36 = (#0 + #8)
+// CHECK-NEXT: Branch,File 9, 22:31 -> 22:36 = #8, #0
 // CHECK-NEXT: File 10, 23:21 -> 23:24 = #8
 // CHECK-NEXT: File 11, 22:24 -> 22:37 = #0
 // CHECK-NEXT: File 11, 22:31 -> 22:36 = (#0 + #9)
+// CHECK-NEXT: Branch,File 11, 22:31 -> 22:36 = #9, #0
 // CHECK-NEXT: File 12, 23:21 -> 23:24 = #9
 // CHECK-NEXT: File 13, 6:3 -> 7:4 = #9
 // CHECK-NEXT: File 14, 26:3 -> 28:4 = #0
 // CHECK-NEXT: File 14, 27:19 -> 27:24 = (#0 + #10)
+// CHECK-NEXT: Branch,File 14, 27:19 -> 27:24 = #10, #0
 // CHECK-NEXT: File 14, 27:26 -> 27:29 = #10
 // CHECK-NEXT: File 14, 27:31 -> 28:4 = #10
 // CHECK-NEXT: File 15, 31:3 -> 34:4 = #0
 // CHECK-NEXT: File 15, 32:10 -> 32:15 = (#0 + #11)
+// CHECK-NEXT: Branch,File 15, 32:10 -> 32:15 = #11, #0
 // CHECK-NEXT: File 15, 32:17 -> 34:4 = #11

diff  --git a/clang/test/CoverageMapping/moremacros.c b/clang/test/CoverageMapping/moremacros.c
index 05f3ffdc4095..6da10075e34e 100644
--- a/clang/test/CoverageMapping/moremacros.c
+++ b/clang/test/CoverageMapping/moremacros.c
@@ -9,16 +9,18 @@ int main(int argc, const char *argv[]) {
   // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:12 = #0
   if (!argc) {} // CHECK: File 0, [[@LINE]]:14 -> [[@LINE]]:16 = #1
 
-  // CHECK-NEXT: File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #0
+  // CHECK-NEXT: File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = #0
+  // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #2, (#0 - #2)
   // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #2
   // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+4]]:8 = #2
   if (!argc) LBRAC
     return 0;
   // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #2
-  RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+6]]:3 = (#0 - #2)
+  RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+7]]:3 = (#0 - #2)
 
-  // CHECK-NEXT: File 0, [[@LINE+4]]:3 -> [[@LINE+15]]:2 = (#0 - #2)
-  // CHECK-NEXT: File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = (#0 - #2)
+  // CHECK-NEXT: File 0, [[@LINE+5]]:3 -> [[@LINE+16]]:2 = (#0 - #2)
+  // CHECK-NEXT: File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = (#0 - #2)
+  // CHECK-NEXT: Branch,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #3, ((#0 - #2) - #3)
   // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #3
   // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+3]]:4 = #3
   if (!argc) LBRAC

diff  --git a/clang/test/CoverageMapping/return.c b/clang/test/CoverageMapping/return.c
index cc7b462a9b03..cc5159b79880 100644
--- a/clang/test/CoverageMapping/return.c
+++ b/clang/test/CoverageMapping/return.c
@@ -8,7 +8,8 @@ void func() {                   // CHECK: File 0, [[@LINE]]:13 -> [[@LINE+3]]:2
 
                                 // CHECK-NEXT: func2
 void func2() {                  // CHECK-NEXT: File 0, [[@LINE]]:14 -> {{[0-9]+}}:2 = #0
-                                // CHECK-NEXT: File 0, [[@LINE+2]]:18 -> [[@LINE+2]]:24 = ((#0 + #1) - #2)
+                                // CHECK-NEXT: File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:24 = ((#0 + #1) - #2)
+                                // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:18 -> [[@LINE+2]]:24 = #1, (#0 - #2)
                                 // CHECK-NEXT: File 0, [[@LINE+1]]:26 -> [[@LINE+1]]:29 = (#1 - #2)
   for(int i = 0; i < 10; ++i) { // CHECK: File 0, [[@LINE]]:31 -> {{[0-9]+}}:4 = #1
                                 // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> [[@LINE+1]]:13 = #1

diff  --git a/clang/test/CoverageMapping/switch.cpp b/clang/test/CoverageMapping/switch.cpp
index 61b639f6eb2b..93a5540c0ad6 100644
--- a/clang/test/CoverageMapping/switch.cpp
+++ b/clang/test/CoverageMapping/switch.cpp
@@ -1,37 +1,39 @@
 // RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++1z -triple %itanium_abi_triple -main-file-name switch.cpp %s | FileCheck %s
 
 // CHECK: foo
-void foo(int i) {   // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+8]]:2 = #0
-  switch(i) {       // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+4]]:10 = 0
+void foo(int i) {   // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+9]]:2 = #0
+  switch(i) {       // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = ((#0 - #2) - #3), (#2 + #3)
+                    // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+4]]:10 = 0
   case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:11 = #2
-    return;
+    return;         // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2)
   case 2:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #3
-    break;          // CHECK-NEXT: Gap,File 0, [[@LINE]]:10 -> [[@LINE+2]]:3 = #1
-  }
+    break;          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3)
+  }                 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:10 -> [[@LINE+1]]:3 = #1
   int x = 0;        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #1
 }
 
 int nop() { return 0; }
 
                     // CHECK: bar
-void bar(int i) {   // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+20]]:2 = #0
-  switch (i)
+void bar(int i) {   // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+21]]:2 = #0
+  switch (i)        // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = #0, 0
     ;               // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:6 = 0
 
-  switch (i) {      // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+16]]:2 = #1
-  }
-
-  switch (i)        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+13]]:2 = #2
-    nop();          // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:10 = 0
-
-  switch (i)        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+10]]:2 = #3
-  case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #5
-    nop();
-
-  switch (i) {      // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+6]]:2 = #4
+  switch (i) {      // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+17]]:2 = #1
+  }                 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = #1, 0
+
+  switch (i)        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+14]]:2 = #2
+    nop();          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = #2, 0
+                    // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:10 = 0
+  switch (i)        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+11]]:2 = #3
+  case 1:           // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = (#3 - #5), #5
+                    // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE+1]]:10 = #5
+    nop();          // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #5, (#3 - #5)
+                    // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> [[@LINE+7]]:2 = #4
+  switch (i) {      // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = (#4 - #7), #7
     nop();          // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+2]]:10 = 0
   case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #7
-    nop();
+    nop();          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, (#4 - #7)
   }
   nop();            // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #6
 }
@@ -40,40 +42,43 @@ void bar(int i) {   // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+20]]:2 = #0
 void baz() {        // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+5]]:2 = #0
   switch (int i = true ? nop()  // CHECK: [[@LINE]]:26 -> [[@LINE]]:31 = #2
                        : nop(); // CHECK-NEXT: [[@LINE]]:26 -> [[@LINE]]:31 = (#0 - #2)
-          i) {}
+          i) {}     // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = #0, 0
   nop();            // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:2 = #1
 }
 
                     // CHECK-NEXT: main
-int main() {        // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+35]]:2 = #0
+int main() {        // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+38]]:2 = #0
   int i = 0;
   switch(i) {       // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+8]]:10 = 0
   case 0:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = #2
-    i = 1;
+    i = 1;          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2)
     break;
   case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = #3
-    i = 2;
+    i = 2;          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3)
     break;
   default:          // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #4
-    break;          // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE+2]]:3 = #1
-  }
-  switch(i) {       // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+23]]:2 = #1
+    break;          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #4, (#0 - #4)
+  }                 // CHECK-NEXT: File 0, [[@LINE-1]]:10 -> [[@LINE+1]]:3 = #1
+  switch(i) {       // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+26]]:2 = #1
   case 0:           // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+6]]:10 = 0
     i = 1;          // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE+1]]:10 = #6
-    break;
+    break;          // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #6, (#1 - #6)
   case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:10 = #7
-    i = 2;
+    i = 2;          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, (#1 - #7)
   default:          // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = (#7 + #8)
-    break;          // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE+3]]:3 = #5
-  }
-                    // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> [[@LINE+14]]:2 = #5
-  switch(i) {       // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+6]]:11 = 0
-  case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:11 = #10
-  case 2:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:11 = (#10 + #11)
-    i = 11;
-  case 3:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:11 = ((#10 + #11) + #12)
+    break;          // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #8, (#1 - #8)
+  }                 // CHECK-NEXT: File 0, [[@LINE-1]]:10 -> [[@LINE+2]]:3 = #5
+                    // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> [[@LINE+17]]:2 = #5
+  switch(i) {       // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = ((((#5 - #10) - #11) - #12) - #13), (((#10 + #11) + #12) + #13)
+                    // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+8]]:11 = 0
+  case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+7]]:11 = #10
+                    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #10, (#5 - #10)
+  case 2:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:11 = (#10 + #11)
+    i = 11;         // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #11, (#5 - #11)
+  case 3:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:11 = ((#10 + #11) + #12)
+                    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #12, (#5 - #12)
   case 4:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:11 = (((#10 + #11) + #12) + #13)
-    i = 99;
+    i = 99;         // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #13, (#5 - #13)
   }
 
   foo(1);           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:11 = #9
@@ -87,26 +92,28 @@ int pr44011(int i) { // CHECK-NEXT: File 0, [[@LINE]]:20 -> {{.*}}:2 = #0
   switch (i) {       // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+6]]:13 = 0
 
   case 1:            // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = #2
-    return 0;
+    return 0;        // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2)
 
   default:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = #3
-    return 1;
+    return 1;        // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #3, (#0 - #3)
   }
 } // A region for counter #1 is missing due to the missing return.
 
 
 // FIXME: End location for "case 1" shouldn't point at the end of the switch.
                          // CHECK: fallthrough
-int fallthrough(int i) { // CHECK-NEXT: File 0, [[@LINE]]:24 -> [[@LINE+12]]:2 = #0
-  switch(i) {       // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+9]]:10 = 0
-  case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+8]]:10 = #2
-    i = 23;
+int fallthrough(int i) { // CHECK-NEXT: File 0, [[@LINE]]:24 -> [[@LINE+14]]:2 = #0
+                    // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:11 = ((((#0 - #2) - #3) - #4) - #5), (((#2 + #3) + #4) + #5)
+  switch(i) {       // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+10]]:10 = 0
+  case 1:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+9]]:10 = #2
+    i = 23;         // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2)
   case 2:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = (#2 + #3)
-    i = 11;
+    i = 11;         // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3)
     break;
-  case 3:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:10 = #4
+  case 3:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:10 = #4
+                    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4)
   case 4:           // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = (#4 + #5)
-    i = 99;
+    i = 99;         // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #5, (#0 - #5)
     break;
   }
 }
@@ -116,10 +123,10 @@ void abort(void) __attribute((noreturn));
 int noret(int x) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+9]]:2
   switch (x) {     // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+6]]:14 = 0
   default:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:12
-    abort();
+    abort();      // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, (#0 - #2)
   case 1:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13
-    return 5;
+    return 5;     // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3)
   case 2:         // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:14
-    return 10;
+    return 10;    // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4)
   }
 }

diff  --git a/clang/test/CoverageMapping/switchmacro.c b/clang/test/CoverageMapping/switchmacro.c
index 72a9a2b96e33..565eeffb2cea 100644
--- a/clang/test/CoverageMapping/switchmacro.c
+++ b/clang/test/CoverageMapping/switchmacro.c
@@ -6,13 +6,16 @@
 int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> {{[0-9]+}}:2 = #0
   switch (i) {   // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> {{[0-9]+}}:11 = 0
   default:       // CHECK-NEXT: File 0, [[@LINE]]:3 -> {{[0-9]+}}:11 = #2
+                 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, (#0 - #2)
     if (i == 1)  // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:15 = #2
+                 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:15 = #3, (#2 - #3)
       return 0;  // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = #3
                  // CHECK-NEXT: File 0, [[@LINE-1]]:15 -> [[@LINE+3]]:5 = (#2 - #3)
     // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:8 = (#2 - #3) (Expanded file = 1)
     // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> {{[0-9]+}}:11 = (#2 - #3)
     FOO(1);
-  case 0:        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = ((#2 + #4) - #3)
+  case 0:        // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:13 = ((#2 + #4) - #3)
+                 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4)
     return 2;    // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+6]]:3 = #5
 
   // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = 0

diff  --git a/clang/test/CoverageMapping/test.c b/clang/test/CoverageMapping/test.c
index 6080ed47d696..e0c01986fb2b 100644
--- a/clang/test/CoverageMapping/test.c
+++ b/clang/test/CoverageMapping/test.c
@@ -4,8 +4,9 @@ void bar();
 static void static_func();
 
                                  // CHECK: main
-int main() {                     // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+7]]:2 = #0
-                                 // CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+1]]:24 = (#0 + #1)
+int main() {                     // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+8]]:2 = #0
+                                 // CHECK-NEXT: File 0, [[@LINE+2]]:18 -> [[@LINE+2]]:24 = (#0 + #1)
+                                 // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:18 -> [[@LINE+1]]:24 = #1, #0
   for(int i = 0; i < 10; ++i) {  // CHECK-NEXT: File 0, [[@LINE]]:26 -> [[@LINE]]:29 = #1
     bar();                       // CHECK: File 0, [[@LINE-1]]:31 -> [[@LINE+1]]:4 = #1
   }

diff  --git a/clang/test/CoverageMapping/unreachable-macro.c b/clang/test/CoverageMapping/unreachable-macro.c
index 30cc8880c7b6..f2be352668b7 100644
--- a/clang/test/CoverageMapping/unreachable-macro.c
+++ b/clang/test/CoverageMapping/unreachable-macro.c
@@ -12,4 +12,5 @@ void counters_in_macro_following_unreachable() {
 }
 // CHECK-NEXT: File 1, 3:15 -> 3:27 = 0
 // CHECK-NEXT: File 1, 3:22 -> 3:23 = #1
+// CHECK-NEXT: Branch,File 1, 3:22 -> 3:23 = 0, 0
 // CHECK-NEXT: File 1, 3:25 -> 3:27 = #1

diff  --git a/clang/test/CoverageMapping/while.c b/clang/test/CoverageMapping/while.c
index 538ac9408422..f62b0cefe21a 100644
--- a/clang/test/CoverageMapping/while.c
+++ b/clang/test/CoverageMapping/while.c
@@ -1,12 +1,14 @@
 // RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name loops.cpp %s | FileCheck %s
 
 // CHECK: main
-int main() {                        // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+8]]:2 = #0
+int main() {                        // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+10]]:2 = #0
   int j = 0;                        // CHECK-NEXT: File 0, [[@LINE+1]]:9 -> [[@LINE+1]]:14 = (#0 + #1)
-  while(j < 5) ++j;                 // CHECK-NEXT: File 0, [[@LINE]]:15 -> [[@LINE]]:16 = #1
-  j = 0;                            // CHECK-NEXT: File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:19 = #1
+  while(j < 5) ++j;                 // CHECK-NEXT: Branch,File 0, [[@LINE]]:9 -> [[@LINE]]:14 = #1, #0
+                                    // CHECK-NEXT: File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = #1
+  j = 0;                            // CHECK-NEXT: File 0, [[@LINE-2]]:16 -> [[@LINE-2]]:19 = #1
   while                             // CHECK-NEXT: File 0, [[@LINE+1]]:5 -> [[@LINE+1]]:10 = (#0 + #2)
-   (j < 5)                          // CHECK-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:6 = #2
-     ++j;                           // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE]]:9 = #2
+   (j < 5)                          // CHECK-NEXT: Branch,File 0, [[@LINE]]:5 -> [[@LINE]]:10 = #2, #0
+     ++j;                           // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE]]:6 = #2
+                                    // CHECK-NEXT: File 0, [[@LINE-1]]:6 -> [[@LINE-1]]:9 = #2
   return 0;
 }

diff  --git a/clang/test/Profile/Inputs/c-general.proftext b/clang/test/Profile/Inputs/c-general.proftext
index 18ad2050fe1a..08280ef39a89 100644
--- a/clang/test/Profile/Inputs/c-general.proftext
+++ b/clang/test/Profile/Inputs/c-general.proftext
@@ -8,7 +8,7 @@ simple_loops
 
 conditionals
 4904767535850050386
-11
+13
 1
 100
 50
@@ -19,7 +19,9 @@ conditionals
 99
 100
 99
+99
 100
+1
 
 early_exits
 2880354649761471549
@@ -106,28 +108,38 @@ big_switch
 
 boolean_operators
 1245693242827665
-8
+14
 1
 100
 34
+1
+66
 66
 17
+1
 34
+17
+33
 33
 50
+33
 
 boolop_loops
 12402604614320574815
-9
+13
 1
 50
 51
 50
+50
 26
+1
 50
 51
 50
+50
 26
+1
 
 conditional_operator
 54992

diff  --git a/clang/test/Profile/branch-logical-mixed.cpp b/clang/test/Profile/branch-logical-mixed.cpp
new file mode 100644
index 000000000000..e6f546d3ac4b
--- /dev/null
+++ b/clang/test/Profile/branch-logical-mixed.cpp
@@ -0,0 +1,66 @@
+// Test to ensure instrumentation of logical operator RHS True/False counters
+// are being instrumented for branch coverage
+
+// RUN: %clang_cc1 -main-file-name branch-logical-mixed.cpp %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -allow-deprecated-dag-overlap %s
+
+
+// CHECK: @[[FUNC:__profc__Z4funcv]] = private global [61 x i64] zeroinitializer
+
+
+// CHECK-LABEL: @_Z4funcv()
+bool func() {
+  bool bt0 = true;
+  bool bt1 = true;
+  bool bt2 = true;
+  bool bt3 = true;
+  bool bt4 = true;
+  bool bt5 = true;
+  bool bf0 = false;
+  bool bf1 = false;
+  bool bf2 = false;
+  bool bf3 = false;
+  bool bf4 = false;
+  bool bf5 = false;
+
+  bool a = bt0 &&
+           bf0 &&                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 10
+           bt1 &&                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 8
+           bf1 &&                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 6
+           bt2 &&                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 4
+           bf2;                     // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 2
+
+  bool b = bt0 ||
+           bf0 ||                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 20
+           bt1 ||                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 18
+           bf1 ||                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 16
+           bt2 ||                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 14
+           bf2;                     // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 12
+
+  bool c = (bt0  &&
+            bf0) ||                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 27
+           (bt1  &&
+            bf1) ||                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 29
+           (bt2  &&
+            bf2) ||                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 31
+           (bt3  &&
+            bf3) ||                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 33
+           (bt4  &&
+            bf4) ||                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 35
+           (bf5  &&
+            bf5);                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 37
+
+  bool d = (bt0  ||
+            bf0) &&                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 44
+           (bt1  ||
+            bf1) &&                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 46
+           (bt2  ||
+            bf2) &&                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 48
+           (bt3  ||
+            bf3) &&                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 50
+           (bt4  ||
+            bf4) &&                 // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 52
+           (bt5  ||
+            bf5);                   // CHECK: store {{.*}} @[[FUNC]], i64 0, i64 54
+
+  return a && b && c && d;
+}

diff  --git a/clang/test/Profile/branch-profdup.cpp b/clang/test/Profile/branch-profdup.cpp
new file mode 100644
index 000000000000..09c08c59d015
--- /dev/null
+++ b/clang/test/Profile/branch-profdup.cpp
@@ -0,0 +1,76 @@
+// Test to ensure RHS condition of logical operators isn't evaluated more than
+// one time when instrumenting RHS counter blocks for branch coverage.
+
+// RUN: %clang_cc1 -main-file-name branch-profdup.cpp %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -allow-deprecated-dag-overlap %s
+
+// CHECK-LABEL: define {{.*}}@_Z5test1b
+// CHECK-COUNT-1: = call {{.*}}@_Z5fval1v()
+// CHECK-NOT: = call {{.*}}@_Z5fval1v()
+extern bool fval1();
+bool test1(bool a) {
+  return (a && fval1());
+}
+
+// CHECK-LABEL: define {{.*}}@_Z5test2b
+// CHECK-COUNT-1: call {{.*}}_Z5fval2v()
+// CHECK-NOT: call {{.*}}_Z5fval2v()
+extern bool fval2();
+bool test2(bool a) {
+  return (a || fval2());
+}
+
+// CHECK-LABEL: define {{.*}}@_Z5test3v
+// CHECK-COUNT-1: call {{.*}}_Z5fval3v()
+// CHECK-NOT: call {{.*}}_Z5fval3v()
+extern bool fval3();
+bool test3() {
+  return (1 && fval3());
+}
+
+// CHECK-LABEL: define {{.*}}@_Z5test4v
+// CHECK-COUNT-1: call {{.*}}_Z5fval4v()
+// CHECK-NOT: call {{.*}}_Z5fval4v()
+extern bool fval4();
+bool test4() {
+  return (0 || fval4());
+}
+
+// CHECK-LABEL: define {{.*}}@_Z5test5b
+// CHECK-COUNT-1: call {{.*}}_Z5fval5v()
+// CHECK-NOT: call {{.*}}_Z5fval5v()
+extern bool fval5();
+bool test5(bool a) {
+  if (a && fval5())
+    return true;
+  return false;
+}
+
+// CHECK-LABEL: define {{.*}}@_Z5test6b
+// CHECK-COUNT-1: call {{.*}}_Z5fval6v()
+// CHECK-NOT: call {{.*}}_Z5fval6v()
+extern bool fval6();
+bool test6(bool a) {
+  if (a || fval6())
+    return true;
+  return false;
+}
+
+// CHECK-LABEL: define {{.*}}@_Z5test7v
+// CHECK-COUNT-1: call {{.*}}_Z5fval7v()
+// CHECK-NOT: call {{.*}}_Z5fval7v()
+extern bool fval7();
+bool test7() {
+  if (1 && fval7())
+    return true;
+  return false;
+}
+
+// CHECK-LABEL: define {{.*}}@_Z5test8v
+// CHECK-COUNT-1: call {{.*}}_Z5fval8v()
+// CHECK-NOT: call {{.*}}_Z5fval8v()
+extern bool fval8();
+bool test8() {
+  if (0 || fval8())
+    return true;
+  return false;
+}

diff  --git a/clang/test/Profile/c-general.c b/clang/test/Profile/c-general.c
index a7f03e872881..d77301d83cd5 100644
--- a/clang/test/Profile/c-general.c
+++ b/clang/test/Profile/c-general.c
@@ -10,13 +10,13 @@
 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v1 | FileCheck -allow-deprecated-dag-overlap  -check-prefix=PGOUSE %s
 
 // PGOGEN: @[[SLC:__profc_simple_loops]] = private global [4 x i64] zeroinitializer
-// PGOGEN: @[[IFC:__profc_conditionals]] = private global [11 x i64] zeroinitializer
+// PGOGEN: @[[IFC:__profc_conditionals]] = private global [13 x i64] zeroinitializer
 // PGOGEN: @[[EEC:__profc_early_exits]] = private global [9 x i64] zeroinitializer
 // PGOGEN: @[[JMC:__profc_jumps]] = private global [22 x i64] zeroinitializer
 // PGOGEN: @[[SWC:__profc_switches]] = private global [19 x i64] zeroinitializer
 // PGOGEN: @[[BSC:__profc_big_switch]] = private global [17 x i64] zeroinitializer
-// PGOGEN: @[[BOC:__profc_boolean_operators]] = private global [8 x i64] zeroinitializer
-// PGOGEN: @[[BLC:__profc_boolop_loops]] = private global [9 x i64] zeroinitializer
+// PGOGEN: @[[BOC:__profc_boolean_operators]] = private global [14 x i64] zeroinitializer
+// PGOGEN: @[[BLC:__profc_boolop_loops]] = private global [13 x i64] zeroinitializer
 // PGOGEN: @[[COC:__profc_conditional_operator]] = private global [3 x i64] zeroinitializer
 // PGOGEN: @[[DFC:__profc_do_fallthrough]] = private global [4 x i64] zeroinitializer
 // PGOGEN: @[[MAC:__profc_main]] = private global [1 x i64] zeroinitializer
@@ -69,11 +69,13 @@ void conditionals() {
     }
 
     // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 8
+    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 9
     // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 7
     // PGOUSE: br {{.*}} !prof ![[IF7:[0-9]+]]
     if (1 && i) {}
+    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 11
+    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 12
     // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 10
-    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 9
     // PGOUSE: br {{.*}} !prof ![[IF8:[0-9]+]]
     if (0 || i) {}
   }
@@ -360,21 +362,27 @@ void boolean_operators() {
   // PGOUSE: br {{.*}} !prof ![[BO1:[0-9]+]]
   for (int i = 0; i < 100; ++i) {
     // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 2
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 3
     // PGOUSE: br {{.*}} !prof ![[BO2:[0-9]+]]
     v = i % 3 || i;
 
-    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 3
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 4
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 5
     // PGOUSE: br {{.*}} !prof ![[BO3:[0-9]+]]
     v = i % 3 && i;
 
-    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 5
-    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 4
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 8
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 9
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 6
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 7
     // PGOUSE: br {{.*}} !prof ![[BO4:[0-9]+]]
     // PGOUSE: br {{.*}} !prof ![[BO5:[0-9]+]]
     v = i % 3 || i % 2 || i;
 
-    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 7
-    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 6
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 12
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 13
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 10
+    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 11
     // PGOUSE: br {{.*}} !prof ![[BO6:[0-9]+]]
     // PGOUSE: br {{.*}} !prof ![[BO7:[0-9]+]]
     v = i % 2 && i % 3 && i;
@@ -391,27 +399,31 @@ void boolop_loops() {
   int i = 100;
 
   // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 2
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 3
   // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 1
   // PGOUSE: br {{.*}} !prof ![[BL1:[0-9]+]]
   // PGOUSE: br {{.*}} !prof ![[BL2:[0-9]+]]
   while (i && i > 50)
     i--;
 
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 5
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 6
   // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 4
-  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 3
   // PGOUSE: br {{.*}} !prof ![[BL3:[0-9]+]]
   // PGOUSE: br {{.*}} !prof ![[BL4:[0-9]+]]
   while ((i % 2) || (i > 0))
     i--;
 
-  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 6
-  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 5
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 8
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 9
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 7
   // PGOUSE: br {{.*}} !prof ![[BL5:[0-9]+]]
   // PGOUSE: br {{.*}} !prof ![[BL6:[0-9]+]]
   for (i = 100; i && i > 50; --i);
 
-  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 8
-  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 7
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 11
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 12
+  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 10
   // PGOUSE: br {{.*}} !prof ![[BL7:[0-9]+]]
   // PGOUSE: br {{.*}} !prof ![[BL8:[0-9]+]]
   for (; (i % 2) || (i > 0); --i);

diff  --git a/clang/test/Profile/cxx-lambda.cpp b/clang/test/Profile/cxx-lambda.cpp
index 08d78da40348..4512f23e0849 100644
--- a/clang/test/Profile/cxx-lambda.cpp
+++ b/clang/test/Profile/cxx-lambda.cpp
@@ -11,7 +11,7 @@
 
 // PGOGEN: @[[LWC:__profc__Z7lambdasv]] = {{(private|internal)}} global [4 x i64] zeroinitializer
 // PGOGEN: @[[MAC:__profc_main]] = {{(private|internal)}} global [1 x i64] zeroinitializer
-// LMBGEN: @[[LFC:"__profc_cxx_lambda.cpp__ZZ7lambdasvENK3\$_0clEi"]] = {{(private|internal)}} global [3 x i64] zeroinitializer
+// LMBGEN: @[[LFC:"__profc_cxx_lambda.cpp__ZZ7lambdasvENK3\$_0clEi"]] = {{(private|internal)}} global [4 x i64] zeroinitializer
 
 // PGOGEN-LABEL: define {{.*}}void @_Z7lambdasv()
 // PGOUSE-LABEL: define {{.*}}void @_Z7lambdasv()

diff  --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc
index af74a752dde0..f715505ba5e1 100644
--- a/compiler-rt/include/profile/InstrProfData.inc
+++ b/compiler-rt/include/profile/InstrProfData.inc
@@ -647,9 +647,9 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
 /* Raw profile format version (start from 1). */
 #define INSTR_PROF_RAW_VERSION 5
 /* Indexed profile format version (start from 1). */
-#define INSTR_PROF_INDEX_VERSION 6
+#define INSTR_PROF_INDEX_VERSION 7
 /* Coverage mapping format version (start from 0). */
-#define INSTR_PROF_COVMAP_VERSION 3
+#define INSTR_PROF_COVMAP_VERSION 4
 
 /* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
  * version for other variants of profile. We set the lowest bit of the upper 8

diff  --git a/llvm/docs/CommandGuide/llvm-cov.rst b/llvm/docs/CommandGuide/llvm-cov.rst
index 08123e8cb788..288d41b3ff70 100644
--- a/llvm/docs/CommandGuide/llvm-cov.rst
+++ b/llvm/docs/CommandGuide/llvm-cov.rst
@@ -202,6 +202,11 @@ tool.
 OPTIONS
 ^^^^^^^
 
+.. option:: -show-branches=<VIEW>
+
+ Show coverage for branch conditions in terms of either count or percentage.
+ The supported views are: "count", "percent".
+
 .. option:: -show-line-counts
 
  Show the execution counts for each line. Defaults to true, unless another
@@ -359,6 +364,10 @@ OPTIONS
  universal binary or to use an architecture that does not match a
  non-universal binary.
 
+.. option:: -show-branch-summary
+
+ Show statistics for all branch conditions. Defaults to true.
+
 .. option:: -show-functions
 
  Show coverage summaries for each function. Defaults to false.
@@ -390,9 +399,9 @@ The :program:`llvm-cov export` command exports coverage data of the binaries
 *BIN*,... using the profile data *PROFILE* in either JSON or lcov trace file
 format.
 
-When exporting JSON, the regions, functions, expansions, and summaries of the
-coverage data will be exported. When exporting an lcov trace file, the
-line-based coverage and summaries will be exported.
+When exporting JSON, the regions, functions, branches, expansions, and
+summaries of the coverage data will be exported. When exporting an lcov trace
+file, the line-based coverage, branch coverage, and summaries will be exported.
 
 The exported data can optionally be filtered to only export the coverage
 for the files listed in *SOURCES*.

diff  --git a/llvm/docs/CoverageMappingFormat.rst b/llvm/docs/CoverageMappingFormat.rst
index 2267265f0bc9..4dc9dc380b98 100644
--- a/llvm/docs/CoverageMappingFormat.rst
+++ b/llvm/docs/CoverageMappingFormat.rst
@@ -126,6 +126,25 @@ There are several kinds of mapping regions:
   <span style='background-color:#4A789C'>  return </span><span style='background-color:#7FCA9F'>MAX</span><span style='background-color:#4A789C'>(x, 42);                          </span> <span class='c1'>// Expansion Region from 3:10 to 3:13</span>
   <span style='background-color:#4A789C'>}</span>
   </pre>`
+* Branch regions associate instrumentable branch conditions in the source code
+  with a `coverage mapping counter`_ to track how many times an individual
+  condition evaluated to 'true' and another `coverage mapping counter`_ to
+  track how many times that condition evaluated to false.  Instrumentable
+  branch conditions may comprise larger boolean expressions using boolean
+  logical operators.  The 'true' and 'false' cases reflect unique branch paths
+  that can be traced back to the source code.
+  For example:
+
+  :raw-html:`<pre class='highlight' style='line-height:initial;'><span>int func(int x, int y) {
+  <span>  if (<span style='background-color:#4A789C'>(x > 1)</span> || <span style='background-color:#4A789C'>(y > 3)</span>) {</span>  <span class='c1'>// Branch Region from 3:6 to 3:12</span>
+  <span>                             </span><span class='c1'>// Branch Region from 3:17 to 3:23</span>
+  <span>    printf("%d\n", x);              </span>
+  <span>  } else {                                </span>
+  <span>    printf("\n");                         </span>
+  <span>  }</span>
+  <span>  return 0;                                 </span>
+  <span>}</span>
+  </pre>`
 
 .. _source code range:
 
@@ -198,6 +217,11 @@ counts for the unreachable lines and highlight the unreachable code.
 Without them, the tool would think that those lines and regions were still
 executed, as it doesn't possess the frontend's knowledge.
 
+Note that branch regions are created to track branch conditions in the source
+code and refer to two coverage mapping counters, one to track the number of
+times the branch condition evaluated to "true", and one to track the number of
+times the branch condition evaluated to "false".
+
 LLVM IR Representation
 ======================
 
@@ -242,7 +266,14 @@ too deeply).
    [32 x i8] c"..." ; Encoded data (dissected later)
   }, section "__llvm_covmap", align 8
 
-The current version of the format is version 4. There are two 
diff erences from version 3:
+The current version of the format is version 5. There is one 
diff erence from version 4:
+
+* The notion of branch region has been introduced along with a corresponding
+  region kind.  Branch regions encode two counters, one to track how many
+  times a "true" branch condition is taken, and one to track how many times a
+  "false" branch condition is taken.
+
+There are two 
diff erences between versions 4 and 3:
 
 * Function records are now named symbols, and are marked *linkonce_odr*. This
   allows linkers to merge duplicate function records. Merging of duplicate
@@ -511,7 +542,8 @@ or
 
 ``[pseudo-counter]``
 
-The header encodes the region's counter and the region's kind.
+The header encodes the region's counter and the region's kind. A branch region
+will encode two counters.
 
 The value of the counter's tag distinguishes between the counters and
 pseudo-counters --- if the tag is zero, than this header contains a
@@ -544,6 +576,7 @@ the ordinary counter. It has the following interpretation:
 
   * 0 - This mapping region is a code region with a counter of zero.
   * 2 - This mapping region is a skipped region.
+  * 4 - This mapping region is a branch region.
 
 .. _source range:
 

diff  --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 2f285bf54a6a..09f21677ec54 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -90,6 +90,8 @@ class CoverageMapError : public ErrorInfo<CoverageMapError> {
 /// A Counter is an abstract value that describes how to compute the
 /// execution count for a region of code using the collected profile count data.
 struct Counter {
+  /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to
+  /// the CounterKind. This means CounterKind has to leave bit 0 free.
   enum CounterKind { Zero, CounterValueReference, Expression };
   static const unsigned EncodingTagBits = 2;
   static const unsigned EncodingTagMask = 0x3;
@@ -219,10 +221,20 @@ struct CounterMappingRegion {
 
     /// A GapRegion is like a CodeRegion, but its count is only set as the
     /// line execution count when its the only region in the line.
-    GapRegion
+    GapRegion,
+
+    /// A BranchRegion represents leaf-level boolean expressions and is
+    /// associated with two counters, each representing the number of times the
+    /// expression evaluates to true or false.
+    BranchRegion
   };
 
+  /// Primary Counter that is also used for Branch Regions (TrueCount).
   Counter Count;
+
+  /// Secondary Counter used for Branch Regions (FalseCount).
+  Counter FalseCount;
+
   unsigned FileID, ExpandedFileID;
   unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
   RegionKind Kind;
@@ -234,6 +246,15 @@ struct CounterMappingRegion {
         LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd),
         ColumnEnd(ColumnEnd), Kind(Kind) {}
 
+  CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID,
+                       unsigned ExpandedFileID, unsigned LineStart,
+                       unsigned ColumnStart, unsigned LineEnd,
+                       unsigned ColumnEnd, RegionKind Kind)
+      : Count(Count), FalseCount(FalseCount), FileID(FileID),
+        ExpandedFileID(ExpandedFileID), LineStart(LineStart),
+        ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
+        Kind(Kind) {}
+
   static CounterMappingRegion
   makeRegion(Counter Count, unsigned FileID, unsigned LineStart,
              unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
@@ -263,6 +284,14 @@ struct CounterMappingRegion {
                                 LineEnd, (1U << 31) | ColumnEnd, GapRegion);
   }
 
+  static CounterMappingRegion
+  makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID,
+                   unsigned LineStart, unsigned ColumnStart, unsigned LineEnd,
+                   unsigned ColumnEnd) {
+    return CounterMappingRegion(Count, FalseCount, FileID, 0, LineStart,
+                                ColumnStart, LineEnd, ColumnEnd, BranchRegion);
+  }
+
   inline LineColPair startLoc() const {
     return LineColPair(LineStart, ColumnStart);
   }
@@ -273,9 +302,17 @@ struct CounterMappingRegion {
 /// Associates a source range with an execution count.
 struct CountedRegion : public CounterMappingRegion {
   uint64_t ExecutionCount;
+  uint64_t FalseExecutionCount;
+  bool Folded;
 
   CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
-      : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {}
+      : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
+        FalseExecutionCount(0), Folded(false) {}
+
+  CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
+                uint64_t FalseExecutionCount)
+      : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
+        FalseExecutionCount(FalseExecutionCount), Folded(false) {}
 };
 
 /// A Counter mapping context is used to connect the counters, expressions
@@ -312,6 +349,8 @@ struct FunctionRecord {
   std::vector<std::string> Filenames;
   /// Regions in the function along with their counts.
   std::vector<CountedRegion> CountedRegions;
+  /// Branch Regions in the function along with their counts.
+  std::vector<CountedRegion> CountedBranchRegions;
   /// The number of times this function was executed.
   uint64_t ExecutionCount = 0;
 
@@ -321,10 +360,19 @@ struct FunctionRecord {
   FunctionRecord(FunctionRecord &&FR) = default;
   FunctionRecord &operator=(FunctionRecord &&) = default;
 
-  void pushRegion(CounterMappingRegion Region, uint64_t Count) {
+  void pushRegion(CounterMappingRegion Region, uint64_t Count,
+                  uint64_t FalseCount) {
+    if (Region.Kind == CounterMappingRegion::BranchRegion) {
+      CountedBranchRegions.emplace_back(Region, Count, FalseCount);
+      // If both counters are hard-coded to zero, then this region represents a
+      // constant-folded branch.
+      if (Region.Count.isZero() && Region.FalseCount.isZero())
+        CountedBranchRegions.back().Folded = true;
+      return;
+    }
     if (CountedRegions.empty())
       ExecutionCount = Count;
-    CountedRegions.emplace_back(Region, Count);
+    CountedRegions.emplace_back(Region, Count, FalseCount);
   }
 };
 
@@ -403,7 +451,8 @@ struct CoverageSegment {
         IsRegionEntry(IsRegionEntry), IsGapRegion(false) {}
 
   CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
-                  bool IsRegionEntry, bool IsGapRegion = false)
+                  bool IsRegionEntry, bool IsGapRegion = false,
+                  bool IsBranchRegion = false)
       : Line(Line), Col(Col), Count(Count), HasCount(true),
         IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {}
 
@@ -483,6 +532,7 @@ class CoverageData {
   std::string Filename;
   std::vector<CoverageSegment> Segments;
   std::vector<ExpansionRecord> Expansions;
+  std::vector<CountedRegion> BranchRegions;
 
 public:
   CoverageData() = default;
@@ -506,6 +556,9 @@ class CoverageData {
 
   /// Expansions that can be further processed.
   ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; }
+
+  /// Branches that can be further processed.
+  ArrayRef<CountedRegion> getBranches() const { return BranchRegions; }
 };
 
 /// The mapping of profile information to coverage data.
@@ -941,7 +994,9 @@ enum CovMapVersion {
   Version3 = 2,
   // Function records are named, uniqued, and moved to a dedicated section.
   Version4 = 3,
-  // The current version is Version4.
+  // Branch regions referring to two counters are added
+  Version5 = 4,
+  // The current version is Version5.
   CurrentVersion = INSTR_PROF_COVMAP_VERSION
 };
 

diff  --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index f3805828f1a3..899abf564f3a 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -983,7 +983,9 @@ enum ProfVersion {
   // In this version, the frontend PGO stable hash algorithm got fixed and
   // may produce hashes 
diff erent from Version5.
   Version6 = 6,
-  // The current version is 5.
+  // An additional counter is added around logical operators.
+  Version7 = 7,
+  // The current version is 7.
   CurrentVersion = INSTR_PROF_INDEX_VERSION
 };
 const uint64_t Version = ProfVersion::CurrentVersion;

diff  --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc
index af74a752dde0..f715505ba5e1 100644
--- a/llvm/include/llvm/ProfileData/InstrProfData.inc
+++ b/llvm/include/llvm/ProfileData/InstrProfData.inc
@@ -647,9 +647,9 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
 /* Raw profile format version (start from 1). */
 #define INSTR_PROF_RAW_VERSION 5
 /* Indexed profile format version (start from 1). */
-#define INSTR_PROF_INDEX_VERSION 6
+#define INSTR_PROF_INDEX_VERSION 7
 /* Coverage mapping format version (start from 0). */
-#define INSTR_PROF_COVMAP_VERSION 3
+#define INSTR_PROF_COVMAP_VERSION 4
 
 /* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
  * version for other variants of profile. We set the lowest bit of the upper 8

diff  --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 87dab212bdcd..4c90eaafcc36 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -249,7 +249,12 @@ Error CoverageMapping::loadFunctionRecord(
       consumeError(std::move(E));
       return Error::success();
     }
-    Function.pushRegion(Region, *ExecutionCount);
+    Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
+    if (auto E = AltExecutionCount.takeError()) {
+      consumeError(std::move(E));
+      return Error::success();
+    }
+    Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
   }
 
   // Don't create records for (filenames, function) pairs we've already seen.
@@ -672,6 +677,10 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
         if (MainFileID && isExpansion(CR, *MainFileID))
           FileCoverage.Expansions.emplace_back(CR, Function);
       }
+    // Capture branch regions specific to the function (excluding expansions).
+    for (const auto &CR : Function.CountedBranchRegions)
+      if (FileIDs.test(CR.FileID) && (CR.FileID == CR.ExpandedFileID))
+        FileCoverage.BranchRegions.push_back(CR);
   }
 
   LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
@@ -719,6 +728,10 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
       if (isExpansion(CR, *MainFileID))
         FunctionCoverage.Expansions.emplace_back(CR, Function);
     }
+  // Capture branch regions specific to the function (excluding expansions).
+  for (const auto &CR : Function.CountedBranchRegions)
+    if (CR.FileID == *MainFileID)
+      FunctionCoverage.BranchRegions.push_back(CR);
 
   LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
                     << "\n");
@@ -738,6 +751,10 @@ CoverageData CoverageMapping::getCoverageForExpansion(
       if (isExpansion(CR, Expansion.FileID))
         ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
     }
+  for (const auto &CR : Expansion.Function.CountedBranchRegions)
+    // Capture branch regions that only pertain to the corresponding expansion.
+    if (CR.FileID == Expansion.FileID)
+      ExpansionCoverage.BranchRegions.push_back(CR);
 
   LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
                     << Expansion.FileID << "\n");

diff  --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index 4936638c61cc..1acdcb4bebb9 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -213,7 +213,7 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
     return Err;
   unsigned LineStart = 0;
   for (size_t I = 0; I < NumRegions; ++I) {
-    Counter C;
+    Counter C, C2;
     CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
 
     // Read the combined counter + region kind.
@@ -223,6 +223,18 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
       return Err;
     unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
     uint64_t ExpandedFileID = 0;
+
+    // If Tag does not represent a ZeroCounter, then it is understood to refer
+    // to a counter or counter expression with region kind assumed to be
+    // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the
+    // referenced counter or counter expression (and nothing else).
+    //
+    // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,
+    // then EncodedCounterAndRegion is interpreted to represent an
+    // ExpansionRegion. In all other cases, EncodedCounterAndRegion is
+    // interpreted to refer to a specific region kind, after which additional
+    // fields may be read (e.g. BranchRegions have two encoded counters that
+    // follow an encoded region kind value).
     if (Tag != Counter::Zero) {
       if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
         return Err;
@@ -243,6 +255,14 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
         case CounterMappingRegion::SkippedRegion:
           Kind = CounterMappingRegion::SkippedRegion;
           break;
+        case CounterMappingRegion::BranchRegion:
+          // For a Branch Region, read two successive counters.
+          Kind = CounterMappingRegion::BranchRegion;
+          if (auto Err = readCounter(C))
+            return Err;
+          if (auto Err = readCounter(C2))
+            return Err;
+          break;
         default:
           return make_error<CoverageMapError>(coveragemap_error::malformed);
         }
@@ -294,7 +314,7 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
       dbgs() << "\n";
     });
 
-    auto CMR = CounterMappingRegion(C, InferredFileID, ExpandedFileID,
+    auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID,
                                     LineStart, ColumnStart,
                                     LineStart + NumLines, ColumnEnd, Kind);
     if (CMR.startLoc() > CMR.endLoc())
@@ -600,7 +620,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
     CovBuf += FilenamesSize;
     FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
 
-    if (Version == CovMapVersion::Version4) {
+    if (Version >= CovMapVersion::Version4) {
       // Map a hash of the filenames region to the filename range associated
       // with this coverage header.
       int64_t FilenamesRef =
@@ -628,7 +648,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
     // This is a no-op in Version4 (coverage mappings are not affixed to the
     // coverage header).
     const char *MappingBuf = CovBuf;
-    if (Version == CovMapVersion::Version4 && CoverageSize != 0)
+    if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
       return make_error<CoverageMapError>(coveragemap_error::malformed);
     CovBuf += CoverageSize;
     const char *MappingEnd = CovBuf;
@@ -682,7 +702,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
       if (FileRange && !FileRange->isInvalid()) {
         StringRef Mapping =
             CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
-        if (Version == CovMapVersion::Version4 &&
+        if (Version >= CovMapVersion::Version4 &&
             Mapping.data() + Mapping.size() > FuncRecBufEnd)
           return make_error<CoverageMapError>(coveragemap_error::malformed);
         if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
@@ -711,6 +731,7 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
   case CovMapVersion::Version2:
   case CovMapVersion::Version3:
   case CovMapVersion::Version4:
+  case CovMapVersion::Version5:
     // Decompress the name data.
     if (Error E = P.create(P.getNameData()))
       return std::move(E);
@@ -723,6 +744,9 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
     else if (Version == CovMapVersion::Version4)
       return std::make_unique<VersionedCovMapFuncRecordReader<
           CovMapVersion::Version4, IntPtrT, Endian>>(P, R, F);
+    else if (Version == CovMapVersion::Version5)
+      return std::make_unique<VersionedCovMapFuncRecordReader<
+          CovMapVersion::Version5, IntPtrT, Endian>>(P, R, F);
   }
   llvm_unreachable("Unsupported version");
 }
@@ -766,7 +790,7 @@ static Error readCoverageMappingData(
   }
   // In Version4, function records are not affixed to coverage headers. Read
   // the records from their dedicated section.
-  if (Version == CovMapVersion::Version4)
+  if (Version >= CovMapVersion::Version4)
     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr,
                                        nullptr);
   return Error::success();

diff  --git a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
index 8d3c429c4484..65b83d1f4197 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
@@ -80,10 +80,14 @@ class CounterExpressionsMinimizer {
                               ArrayRef<CounterMappingRegion> MappingRegions)
       : Expressions(Expressions) {
     AdjustedExpressionIDs.resize(Expressions.size(), 0);
-    for (const auto &I : MappingRegions)
+    for (const auto &I : MappingRegions) {
       mark(I.Count);
-    for (const auto &I : MappingRegions)
+      mark(I.FalseCount);
+    }
+    for (const auto &I : MappingRegions) {
       gatherUsed(I.Count);
+      gatherUsed(I.FalseCount);
+    }
   }
 
   void mark(Counter C) {
@@ -201,6 +205,7 @@ void CoverageMappingWriter::write(raw_ostream &OS) {
       PrevLineStart = 0;
     }
     Counter Count = Minimizer.adjust(I->Count);
+    Counter FalseCount = Minimizer.adjust(I->FalseCount);
     switch (I->Kind) {
     case CounterMappingRegion::CodeRegion:
     case CounterMappingRegion::GapRegion:
@@ -226,6 +231,13 @@ void CoverageMappingWriter::write(raw_ostream &OS) {
                         << Counter::EncodingCounterTagAndExpansionRegionTagBits,
                     OS);
       break;
+    case CounterMappingRegion::BranchRegion:
+      encodeULEB128(unsigned(I->Kind)
+                        << Counter::EncodingCounterTagAndExpansionRegionTagBits,
+                    OS);
+      writeCounter(MinExpressions, Count, OS);
+      writeCounter(MinExpressions, FalseCount, OS);
+      break;
     }
     assert(I->LineStart >= PrevLineStart);
     encodeULEB128(I->LineStart - PrevLineStart, OS);

diff  --git a/llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json b/llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
index e6eb0bd3fba0..a30411a84b23 100644
--- a/llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
+++ b/llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
@@ -1,24 +1,28 @@
 CHECK: {"data":
 CHECK-SAME: [{
 CHECK-SAME:  "files":[
-CHECK-SAME:    {"expansions":[],
+CHECK-SAME:    {"branches":[],
+CHECK-SAME:     "expansions":[],
 CHECK-SAME:     "filename":"/tmp/binary-formats.c",
 CHECK-SAME:     "segments":
 CHECK-SAME:        4,40,100,true,true,false
 CHECK-SAME:        4,42,0,false,false,false
-CHECK-SAME:     "summary":{"functions":{"count":1,"covered":1,"percent":100},
+CHECK-SAME:     "summary":{"branches":{"count":0,"covered":0,"notcovered":0,"percent":0},
+CHECK-SAME:                "functions":{"count":1,"covered":1,"percent":100},
 CHECK-SAME:                "instantiations":{"count":1,"covered":1,"percent":100},
 CHECK-SAME:                "lines":{"count":1,"covered":1,"percent":100},
 CHECK-SAME:                "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}}
 CHECK-SAME:  ],
 CHECK-SAME:  "functions":[
-CHECK-SAME:    {"count":100,"filenames":["/tmp/binary-formats.c"],"name":"main",
+CHECK-SAME:    {"branches":[],
+CHECK-SAME:     "count":100,"filenames":["/tmp/binary-formats.c"],"name":"main",
 CHECK-SAME:     "regions":
 CHECK-SAME:        4,40,4,42,100,0,0,0
 CHECK-SAME:    }
 CHECK-SAME:  ],
 CHECK-SAME:  "totals":
-CHECK-SAME:    {"functions":{"count":1,"covered":1,"percent":100},
+CHECK-SAME:    {"branches":{"count":0,"covered":0,"notcovered":0,"percent":0},
+CHECK-SAME:     "functions":{"count":1,"covered":1,"percent":100},
 CHECK-SAME:     "instantiations":{"count":1,"covered":1,"percent":100},
 CHECK-SAME:     "lines":{"count":1,"covered":1,"percent":100},
 CHECK-SAME:     "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}}

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-c-general.o32l b/llvm/test/tools/llvm-cov/Inputs/branch-c-general.o32l
new file mode 100644
index 000000000000..7b3151184817
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/branch-c-general.o32l 
diff er

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-c-general.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-c-general.proftext
new file mode 100644
index 000000000000..508b0fef94a0
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-c-general.proftext
@@ -0,0 +1,206 @@
+big_switch
+# Func Hash:
+13144136522122330070
+# Num Counters:
+17
+# Counter Values:
+1
+32
+32
+1
+0
+1
+1
+11
+11
+1
+1
+15
+15
+1
+1
+2
+2
+
+boolean_operators
+# Func Hash:
+1245693242827665
+# Num Counters:
+14
+# Counter Values:
+1
+100
+34
+1
+66
+66
+17
+1
+34
+17
+33
+33
+50
+33
+
+boolop_loops
+# Func Hash:
+12402604614320574815
+# Num Counters:
+13
+# Counter Values:
+1
+50
+51
+50
+50
+26
+1
+50
+51
+50
+50
+26
+1
+
+branch-c-general.c:static_func
+# Func Hash:
+18129
+# Num Counters:
+2
+# Counter Values:
+1
+10
+
+conditional_operator
+# Func Hash:
+54992
+# Num Counters:
+3
+# Counter Values:
+1
+0
+1
+
+conditionals
+# Func Hash:
+4904767535850050386
+# Num Counters:
+13
+# Counter Values:
+1
+100
+50
+50
+33
+33
+16
+99
+100
+99
+99
+100
+1
+
+do_fallthrough
+# Func Hash:
+8714614136504380050
+# Num Counters:
+4
+# Counter Values:
+1
+10
+2
+8
+
+early_exits
+# Func Hash:
+2880354649761471549
+# Num Counters:
+9
+# Counter Values:
+1
+0
+51
+1
+25
+1
+25
+1
+0
+
+jumps
+# Func Hash:
+15051420506203462683
+# Num Counters:
+22
+# Counter Values:
+1
+1
+0
+1
+0
+0
+1
+0
+1
+2
+3
+2
+0
+3
+0
+1
+1
+1
+10
+0
+10
+9
+
+main
+# Func Hash:
+24
+# Num Counters:
+2
+# Counter Values:
+1
+0
+
+simple_loops
+# Func Hash:
+1245818015463121
+# Num Counters:
+4
+# Counter Values:
+1
+100
+100
+75
+
+switches
+# Func Hash:
+43242458792028222
+# Num Counters:
+19
+# Counter Values:
+1
+1
+1
+15
+7
+1
+0
+2
+2
+3
+3
+4
+4
+0
+4
+4
+5
+1
+0
+

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.o32l b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.o32l
new file mode 100644
index 000000000000..a50099716bce
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.o32l 
diff er

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.proftext
new file mode 100644
index 000000000000..e5c67dd21a04
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.proftext
@@ -0,0 +1,84 @@
+_Z4funcii
+# Func Hash:
+9495997393973228792
+# Num Counters:
+69
+# Counter Values:
+4
+0
+0
+0
+0
+2
+0
+2
+2
+3
+2
+0
+0
+0
+0
+0
+0
+1
+0
+1
+1
+3
+3
+3
+3
+3
+3
+3
+3
+3
+3
+3
+1
+2
+0
+3
+0
+0
+0
+1
+0
+1
+0
+3
+3
+3
+3
+3
+3
+3
+3
+4
+3
+1
+0
+2
+1
+0
+0
+3
+0
+2
+0
+2
+0
+0
+4
+1
+3
+
+main
+# Func Hash:
+24
+# Num Counters:
+1
+# Counter Values:
+4
+

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-macros.o32l b/llvm/test/tools/llvm-cov/Inputs/branch-macros.o32l
new file mode 100644
index 000000000000..bb4c85adeb4d
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/branch-macros.o32l 
diff er

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-macros.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-macros.proftext
new file mode 100644
index 000000000000..3b42e4121c94
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-macros.proftext
@@ -0,0 +1,49 @@
+_Z4funcii
+# Func Hash:
+2263559805428111017
+# Num Counters:
+19
+# Counter Values:
+3
+1
+0
+1
+0
+1
+0
+1
+0
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+
+_Z5func2ii
+# Func Hash:
+5552544297182115648
+# Num Counters:
+8
+# Counter Values:
+3
+3
+2
+1
+0
+0
+1
+0
+
+main
+# Func Hash:
+24
+# Num Counters:
+1
+# Counter Values:
+3
+

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.o32l b/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.o32l
new file mode 100644
index 000000000000..5f8b9fa10582
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.o32l 
diff er

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.proftext
new file mode 100644
index 000000000000..9bb07479e863
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.proftext
@@ -0,0 +1,28 @@
+main
+# Func Hash:
+3890582504168513655
+# Num Counters:
+21
+# Counter Values:
+6
+1
+2
+5
+3
+5
+5
+1
+0
+4
+1
+1
+4
+1
+1
+5
+1
+1
+0
+3
+50
+

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-templates.o32l b/llvm/test/tools/llvm-cov/Inputs/branch-templates.o32l
new file mode 100644
index 000000000000..d611727170d9
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/branch-templates.o32l 
diff er

diff  --git a/llvm/test/tools/llvm-cov/Inputs/branch-templates.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-templates.proftext
new file mode 100644
index 000000000000..66e1e4ebfe0b
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-templates.proftext
@@ -0,0 +1,38 @@
+_Z4funcIbEiT_
+# Func Hash:
+11045778961
+# Num Counters:
+2
+# Counter Values:
+1
+1
+
+_Z4funcIfEiT_
+# Func Hash:
+11045778961
+# Num Counters:
+2
+# Counter Values:
+1
+0
+
+_Z4funcIiEiT_
+# Func Hash:
+11045778961
+# Num Counters:
+2
+# Counter Values:
+1
+0
+
+main
+# Func Hash:
+185286008276329560
+# Num Counters:
+4
+# Counter Values:
+1
+1
+0
+1
+

diff  --git a/llvm/test/tools/llvm-cov/Inputs/showExpansions.json b/llvm/test/tools/llvm-cov/Inputs/showExpansions.json
index 9c1fc73c0af2..a13467f0db06 100644
--- a/llvm/test/tools/llvm-cov/Inputs/showExpansions.json
+++ b/llvm/test/tools/llvm-cov/Inputs/showExpansions.json
@@ -1,4 +1,4 @@
-CHECK: {"expansions":
+CHECK: {"branches":[],"expansions":
 CHECK:    "filenames":["{{[^"]+}}showExpansions.cpp",
 CHECK:    "source_region":[24,5,24,17,100,0,1,1],
 CHECK:    "filename":"{{[^"]+}}showExpansions.cpp",

diff  --git a/llvm/test/tools/llvm-cov/branch-c-general.c b/llvm/test/tools/llvm-cov/branch-c-general.c
new file mode 100644
index 000000000000..ffbbd12bf161
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-c-general.c
@@ -0,0 +1,311 @@
+// Test visualization of general branch constructs in C.
+
+// RUN: llvm-profdata merge %S/Inputs/branch-c-general.proftext -o %t.profdata
+// RUN: llvm-cov show --show-branches=count %S/Inputs/branch-c-general.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-c-general.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORT
+
+void simple_loops() {
+  int i;
+  for (i = 0; i < 100; ++i) {    // CHECK: Branch ([[@LINE]]:15): [True: 100, False: 1]
+  }
+  while (i > 0)                  // CHECK: Branch ([[@LINE]]:10): [True: 100, False: 1]
+    i--;
+  do {} while (i++ < 75);        // CHECK: Branch ([[@LINE]]:16): [True: 75, False: 1]
+
+}
+
+void conditionals() {
+  for (int i = 0; i < 100; ++i) {// CHECK: Branch ([[@LINE]]:19): [True: 100, False: 1]
+    if (i % 2) {                 // CHECK: Branch ([[@LINE]]:9): [True: 50, False: 50]
+      if (i) {}                  // CHECK: Branch ([[@LINE]]:11): [True: 50, False: 0]
+    } else if (i % 3) {          // CHECK: Branch ([[@LINE]]:16): [True: 33, False: 17]
+      if (i) {}                  // CHECK: Branch ([[@LINE]]:11): [True: 33, False: 0]
+    } else {
+      if (i) {}                  // CHECK: Branch ([[@LINE]]:11): [True: 16, False: 1]
+    }
+                                 // CHECK: Branch ([[@LINE+1]]:9): [Folded - Ignored]
+    if (1 && i) {}               // CHECK: Branch ([[@LINE]]:14): [True: 99, False: 1]
+    if (0 || i) {}               // CHECK: Branch ([[@LINE]]:9): [Folded - Ignored]
+  }                              // CHECK: Branch ([[@LINE-1]]:14): [True: 99, False: 1]
+
+}
+
+void early_exits() {
+  int i = 0;
+
+  if (i) {}                     // CHECK: Branch ([[@LINE]]:7): [True: 0, False: 1]
+
+  while (i < 100) {             // CHECK: Branch ([[@LINE]]:10): [True: 51, False: 0]
+    i++;
+    if (i > 50)                 // CHECK: Branch ([[@LINE]]:9): [True: 1, False: 50]
+      break;
+    if (i % 2)                  // CHECK: Branch ([[@LINE]]:9): [True: 25, False: 25]
+      continue;
+  }
+
+  if (i) {}                     // CHECK: Branch ([[@LINE]]:7): [True: 1, False: 0]
+
+  do {
+    if (i > 75)                 // CHECK: Branch ([[@LINE]]:9): [True: 1, False: 25]
+      return;
+    else
+      i++;
+  } while (i < 100);            // CHECK: Branch ([[@LINE]]:12): [True: 25, False: 0]
+
+  if (i) {}                     // CHECK: Branch ([[@LINE]]:7): [True: 0, False: 0]
+
+}
+
+void jumps() {
+  int i;
+
+  for (i = 0; i < 2; ++i) {     // CHECK: Branch ([[@LINE]]:15): [True: 1, False: 0]
+    goto outofloop;
+    // Never reached -> no weights
+    if (i) {}                   // CHECK: Branch ([[@LINE]]:9): [True: 0, False: 0]
+  }
+
+outofloop:
+  if (i) {}                     // CHECK: Branch ([[@LINE]]:7): [True: 0, False: 1]
+
+  goto loop1;
+
+  while (i) {                   // CHECK: Branch ([[@LINE]]:10): [True: 0, False: 1]
+  loop1:
+    if (i) {}                   // CHECK: Branch ([[@LINE]]:9): [True: 0, False: 1]
+  }
+
+  goto loop2;
+first:
+second:
+third:
+  i++;
+  if (i < 3)                    // CHECK: Branch ([[@LINE]]:7): [True: 2, False: 1]
+    goto loop2;
+
+  while (i < 3) {               // CHECK: Branch ([[@LINE]]:10): [True: 0, False: 1]
+  loop2:
+    switch (i) {
+    case 0:                     // CHECK: Branch ([[@LINE]]:5): [True: 1, False: 2]
+      goto first;
+    case 1:                     // CHECK: Branch ([[@LINE]]:5): [True: 1, False: 2]
+      goto second;
+    case 2:                     // CHECK: Branch ([[@LINE]]:5): [True: 1, False: 2]
+      goto third;
+    }
+  }
+
+  for (i = 0; i < 10; ++i) {    // CHECK: Branch ([[@LINE]]:15): [True: 10, False: 1]
+    goto withinloop;
+    // never reached -> no weights
+    if (i) {}                   // CHECK: Branch ([[@LINE]]:9): [True: 0, False: 0]
+  withinloop:
+    if (i) {}                   // CHECK: Branch ([[@LINE]]:9): [True: 9, False: 1]
+  }
+
+}
+
+void switches() {
+  static int weights[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5};
+
+  // No cases -> no weights
+  switch (weights[0]) {
+  default:                      // CHECK: Branch ([[@LINE]]:3): [True: 1, False: 0]
+    break;
+  }
+                                // CHECK: Branch ([[@LINE+1]]:63): [True: 15, False: 0]
+  for (int i = 0, len = sizeof(weights) / sizeof(weights[0]); i < len; ++i) {
+    switch (i[weights]) {
+    case 1:                     // CHECK: Branch ([[@LINE]]:5): [True: 1, False: 14]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 0, False: 1]
+      // fallthrough
+    case 2:                     // CHECK: Branch ([[@LINE]]:5): [True: 2, False: 13]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 2, False: 1]
+      break;
+    case 3:                     // CHECK: Branch ([[@LINE]]:5): [True: 3, False: 12]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 3, False: 0]
+      continue;
+    case 4:                     // CHECK: Branch ([[@LINE]]:5): [True: 4, False: 11]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 4, False: 0]
+      switch (i) {
+      case 6 ... 9:             // CHECK: Branch ([[@LINE]]:7): [True: 4, False: 0]
+        if (i) {}               // CHECK: Branch ([[@LINE]]:13): [True: 4, False: 0]
+        continue;
+      }
+
+    default:                    // CHECK: Branch ([[@LINE]]:5): [True: 5, False: 10]
+      if (i == len - 1)         // CHECK: Branch ([[@LINE]]:11): [True: 1, False: 4]
+        return;
+    }
+  }
+
+  // Never reached -> no weights
+  if (weights[0]) {}            // CHECK: Branch ([[@LINE]]:7): [True: 0, False: 0]
+
+}
+
+void big_switch() {
+  for (int i = 0; i < 32; ++i) {// CHECK: Branch ([[@LINE]]:19): [True: 32, False: 1]
+    switch (1 << i) {
+    case (1 << 0):              // CHECK: Branch ([[@LINE]]:5): [True: 1, False: 31]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 0, False: 1]
+      // fallthrough
+    case (1 << 1):              // CHECK: Branch ([[@LINE]]:5): [True: 1, False: 31]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 1, False: 1]
+      break;
+    case (1 << 2) ... (1 << 12):// CHECK: Branch ([[@LINE]]:5): [True: 11, False: 21]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 11, False: 0]
+      break;
+      // The branch for the large case range above appears after the case body.
+
+    case (1 << 13):             // CHECK: Branch ([[@LINE]]:5): [True: 1, False: 31]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 1, False: 0]
+      break;
+    case (1 << 14) ... (1 << 28):// CHECK: Branch ([[@LINE]]:5): [True: 15, False: 17]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 15, False: 0]
+      break;
+    // The branch for the large case range above appears after the case body.
+    // CHECK: Branch ([[@LINE+1]]:5): [True: 1, False: 31]
+    case (1 << 29) ... ((1 << 29) + 1):
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 1, False: 0]
+      break;
+    default:                    // CHECK: Branch ([[@LINE]]:5): [True: 2, False: 30]
+      if (i) {}                 // CHECK: Branch ([[@LINE]]:11): [True: 2, False: 0]
+      break;
+    }
+  }
+
+}
+
+void boolean_operators() {
+  int v;                        // CHECK: Branch ([[@LINE+1]]:19): [True: 100, False: 1]
+  for (int i = 0; i < 100; ++i) {
+    v = i % 3 || i;             // CHECK: Branch ([[@LINE]]:9): [True: 66, False: 34]
+                                // CHECK: Branch ([[@LINE-1]]:18): [True: 33, False: 1]
+    v = i % 3 && i;             // CHECK: Branch ([[@LINE]]:9): [True: 66, False: 34]
+                                // CHECK: Branch ([[@LINE-1]]:18): [True: 66, False: 0]
+    v = i % 3 || i % 2 || i;    // CHECK: Branch ([[@LINE]]:9): [True: 66, False: 34]
+                                // CHECK: Branch ([[@LINE-1]]:18): [True: 17, False: 17]
+    v = i % 2 && i % 3 && i;    // CHECK: Branch ([[@LINE-2]]:27): [True: 16, False: 1]
+  }                             // CHECK: Branch ([[@LINE-1]]:9): [True: 50, False: 50]
+                                // CHECK: Branch ([[@LINE-2]]:18): [True: 33, False: 17]
+}                               // CHECK: Branch ([[@LINE-3]]:27): [True: 33, False: 0]
+
+void boolop_loops() {
+  int i = 100;
+
+  while (i && i > 50)           // CHECK: Branch ([[@LINE]]:10): [True: 51, False: 0]
+    i--;                        // CHECK: Branch ([[@LINE-1]]:15): [True: 50, False: 1]
+
+  while ((i % 2) || (i > 0))    // CHECK: Branch ([[@LINE]]:10): [True: 25, False: 26]
+    i--;                        // CHECK: Branch ([[@LINE-1]]:21): [True: 25, False: 1]
+
+  for (i = 100; i && i > 50; --i); // CHECK: Branch ([[@LINE]]:17): [True: 51, False: 0]
+                                   // CHECK: Branch ([[@LINE-1]]:22): [True: 50, False: 1]
+  for (; (i % 2) || (i > 0); --i); // CHECK: Branch ([[@LINE]]:10): [True: 25, False: 26]
+                                   // CHECK: Branch ([[@LINE-1]]:21): [True: 25, False: 1]
+}
+
+void conditional_operator() {
+  int i = 100;
+
+  int j = i < 50 ? i : 1;       // CHECK: Branch ([[@LINE]]:11): [True: 0, False: 1]
+
+  int k = i ?: 0;               // CHECK: Branch ([[@LINE]]:11): [True: 1, False: 0]
+
+}
+
+void do_fallthrough() {
+  for (int i = 0; i < 10; ++i) {// CHECK: Branch ([[@LINE]]:19): [True: 10, False: 1]
+    int j = 0;
+    do {
+      // The number of exits out of this do-loop via the break statement
+      // exceeds the counter value for the loop (which does not include the
+      // fallthrough count). Make sure that does not violate any assertions.
+      if (i < 8) break;         // CHECK: Branch ([[@LINE]]:11): [True: 8, False: 4]
+      j++;
+    } while (j < 2);            // CHECK: Branch ([[@LINE]]:14): [True: 2, False: 2]
+  }
+}
+
+static void static_func() {
+  for (int i = 0; i < 10; ++i) {// CHECK: Branch ([[@LINE]]:19): [True: 10, False: 1]
+  }
+}
+
+
+
+
+
+
+
+
+
+
+int main(int argc, const char *argv[]) {
+  simple_loops();
+  conditionals();
+  early_exits();
+  jumps();
+  switches();
+  big_switch();
+  boolean_operators();
+  boolop_loops();
+  conditional_operator();
+  do_fallthrough();
+  static_func();
+  extern void __llvm_profile_write_file();
+  __llvm_profile_write_file();
+  return 0;
+}
+
+// REPORT: Name                        Regions    Miss   Cover     Lines    Miss   Cover  Branches    Miss   Cover
+// REPORT-NEXT: ---
+// REPORT-NEXT: simple_loops                      8       0 100.00%         9       0 100.00%         6       0 100.00%
+// REPORT-NEXT: conditionals                     24       0 100.00%        15       0 100.00%        16       2  87.50%
+// REPORT-NEXT: early_exits                      20       4  80.00%        25       3  88.00%        16       6  62.50%
+// REPORT-NEXT: jumps                            39      12  69.23%        48       4  91.67%        26       9  65.38%
+// REPORT-NEXT: switches                         28       5  82.14%        38       5  86.84%        30       9  70.00%
+// REPORT-NEXT: big_switch                       25       1  96.00%        32       0 100.00%        30       6  80.00%
+// REPORT-NEXT: boolean_operators                16       0 100.00%        13       0 100.00%        22       2  90.91%
+// REPORT-NEXT: boolop_loops                     19       0 100.00%        14       0 100.00%        16       2  87.50%
+// REPORT-NEXT: conditional_operator              4       2  50.00%         8       1  87.50%         4       2  50.00%
+// REPORT-NEXT: do_fallthrough                    9       0 100.00%        12       0 100.00%         6       0 100.00%
+// REPORT-NEXT: main                              1       0 100.00%        16       0 100.00%         0       0   0.00%
+// REPORT-NEXT: c-general.c:static_func           4       0 100.00%         4       0 100.00%         2       0 100.00%
+// REPORT-NEXT: ---
+// REPORT-NEXT: TOTAL                           197      24  87.82%       234      13 94.44%       174      38  78.16%
+
+// Test file-level report.
+// RUN: llvm-profdata merge %S/Inputs/branch-c-general.proftext -o %t.profdata
+// RUN: llvm-cov report %S/Inputs/branch-c-general.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=FILEREPORT
+// FILEREPORT: TOTAL{{.*}}174                38    78.16%
+
+// Test color True/False output.
+// RUN: llvm-cov show --use-color --show-branches=count %S/Inputs/branch-c-general.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=USECOLOR
+// USECOLOR: Branch ({{[0-9]+}}:7): {{.*}}: 0, {{.*}}0]
+
+// Test html output.
+// RUN: llvm-cov show --show-branch-summary --show-branches=count %S/Inputs/branch-c-general.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -format html -o %t.html.dir
+// RUN: FileCheck -check-prefix=HTML -input-file=%t.html.dir/coverage/tmp/branch-c-general.c.html %s
+// HTML-COUNT-89: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>
+// HTML-NOT: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>
+
+// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
+// HTML-INDEX-LABEL: <table>
+// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
+// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
+// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
+// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
+// HTML-INDEX: <td class='column-entry-bold'>Branch Coverage</td>
+// HTML-INDEX: <a href='coverage{{.*}}branch-c-general.c.html'{{.*}}branch-c-general.c</a>
+// HTML-INDEX: <td class='column-entry-green'>
+// HTML-INDEX: 100.00% (12/12)
+// HTML-INDEX: <td class='column-entry-yellow'>
+// HTML-INDEX: 94.44% (221/234)
+// HTML-INDEX: <td class='column-entry-yellow'>
+// HTML-INDEX: 87.82% (173/197)
+// HTML-INDEX: <td class='column-entry-red'>
+// HTML-INDEX: 78.16% (136/174)
+// HTML-INDEX: <tr class='light-row-bold'>
+// HTML-INDEX: Totals

diff  --git a/llvm/test/tools/llvm-cov/branch-export-json.test b/llvm/test/tools/llvm-cov/branch-export-json.test
new file mode 100644
index 000000000000..7f3e8e024d25
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-export-json.test
@@ -0,0 +1,49 @@
+
+// RUN: llvm-profdata merge %S/Inputs/branch-showBranchPercentage.proftext -o %t.profdata
+// RUN: llvm-cov export --format=text %S/Inputs/branch-showBranchPercentage.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/branch-showBranchPercentage.c | FileCheck %s
+
+// CHECK: "branches":
+// CHECK: 14,7,14,15,1,5,0,0,4
+// CHECK: 27,8,27,14,1,4,0,0,4
+// CHECK: 27,18,27,24,0,1,0,0,4
+// CHECK: 27,29,27,36,0,5,0,0,4
+// CHECK: 27,40,27,46,2,3,0,0,4
+// CHECK: 30,8,30,14,4,1,0,0,4
+// CHECK: 30,18,30,24,0,1,0,0,4
+// CHECK: 32,8,32,14,4,1,0,0,4
+// CHECK: 32,18,32,24,1,3,0,0,4
+// CHECK: 34,15,34,20,1,5,0,0,4
+// CHECK: 41,5,41,11,1,4,0,0,4
+// CHECK: 43,5,43,11,1,4,0,0,4
+// CHECK: 45,5,45,11,0,5,0,0,4
+// CHECK: 47,5,47,12,3,2,0,0,4
+// CHECK: 53,12,53,20,50,5,0,0,4
+// CHECK: {"count":30,"covered":26,"notcovered":4,"percent":86.666666666666671}
+
+// Check recursive macro-expansions.
+// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
+// RUN: llvm-cov export --format=text %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/branch-macros.c | FileCheck %s -check-prefix=MACROS
+
+// MACROS: "branches":
+// MACROS: 27,10,27,11,0,3,0,0,4
+// MACROS: 27,15,27,16,0,0,0,0,4
+// MACROS: 27,20,27,21,0,0,0,0,4
+// MACROS: 27,25,27,26,0,0,0,0,4
+// MACROS: 27,30,27,31,0,0,0,0,4
+
+// MACROS: 15,5,23,1,2,1,0,4
+// MACROS: 6,15,6,23,0,1,2,0,4
+// MACROS: 5,15,5,23,1,2,7,0,4
+// MACROS: 6,15,6,23,0,1,8,0,4
+// MACROS: 5,15,5,23,1,2,12,0,4
+// MACROS: 6,15,6,23,0,1,13,0,4
+// MACROS: 5,15,5,23,1,2,16,0,4
+// MACROS: 6,15,6,23,0,1,17,0,4
+// MACROS: 5,15,5,23,1,2,19,0,4
+// MACROS: 6,15,6,23,0,1,20,0,4
+// MACROS: 5,15,5,23,1,2,11,0,4
+// MACROS: 6,15,6,23,0,1,12,0,4
+// MACROS: 5,15,5,23,1,2,8,0,4
+// MACROS: 6,15,6,23,0,1,9,0,4
+// MACROS: 8,15,8,38,1,2,2,0,4
+// MACROS: {"count":40,"covered":24,"notcovered":16,"percent":60}

diff  --git a/llvm/test/tools/llvm-cov/branch-export-lcov.test b/llvm/test/tools/llvm-cov/branch-export-lcov.test
new file mode 100644
index 000000000000..c13c54e67e02
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-export-lcov.test
@@ -0,0 +1,73 @@
+
+// RUN: llvm-profdata merge %S/Inputs/branch-showBranchPercentage.proftext -o %t.profdata
+// RUN: llvm-cov export --format=lcov %S/Inputs/branch-showBranchPercentage.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/branch-showBranchPercentage.c | FileCheck %s
+
+// CHECK-DAG: BRDA:14,0,0,1
+// CHECK-DAG: BRDA:14,0,1,5
+// CHECK-DAG: BRDA:27,0,0,1
+// CHECK-DAG: BRDA:27,0,1,4
+// CHECK-DAG: BRDA:27,1,2,0
+// CHECK-DAG: BRDA:27,1,3,1
+// CHECK-DAG: BRDA:27,2,4,0
+// CHECK-DAG: BRDA:27,2,5,5
+// CHECK-DAG: BRDA:27,3,6,2
+// CHECK-DAG: BRDA:27,3,7,3
+// CHECK-DAG: BRDA:30,0,0,4
+// CHECK-DAG: BRDA:30,0,1,1
+// CHECK-DAG: BRDA:30,1,2,0
+// CHECK-DAG: BRDA:30,1,3,1
+// CHECK-DAG: BRDA:32,0,0,4
+// CHECK-DAG: BRDA:32,0,1,1
+// CHECK-DAG: BRDA:32,1,2,1
+// CHECK-DAG: BRDA:32,1,3,3
+// CHECK-DAG: BRDA:34,0,0,1
+// CHECK-DAG: BRDA:34,0,1,5
+// CHECK-DAG: BRDA:41,0,0,1
+// CHECK-DAG: BRDA:41,0,1,4
+// CHECK-DAG: BRDA:43,0,0,1
+// CHECK-DAG: BRDA:43,0,1,4
+// CHECK-DAG: BRDA:45,0,0,0
+// CHECK-DAG: BRDA:45,0,1,5
+// CHECK-DAG: BRDA:47,0,0,3
+// CHECK-DAG: BRDA:47,0,1,2
+// CHECK-DAG: BRDA:53,0,0,50
+// CHECK-DAG: BRDA:53,0,1,5
+// CHECK-NOT: BRDA
+// CHECK: BRF:30
+// CHECK: BFH:26
+
+// Check recursive macro-expansions.
+// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
+// RUN: llvm-cov export --format=lcov %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/branch-macros.cpp | FileCheck %s -check-prefix=MACROS
+
+// MACROS-COUNT-4: BRDA:17
+// MACROS-NOT: BRDA:17
+
+// MACROS-COUNT-4: BRDA:19
+// MACROS-NOT: BRDA:19
+
+// MACROS-COUNT-4: BRDA:21
+// MACROS-NOT: BRDA:21
+
+// MACROS-COUNT-4: BRDA:23
+// MACROS-NOT: BRDA:23
+
+// MACROS-COUNT-4: BRDA:25
+// MACROS-NOT: BRDA:25
+
+// MACROS: BRDA:27,0,0,0
+// MACROS: BRDA:27,0,1,3
+// MACROS: BRDA:27,1,2,-
+// MACROS: BRDA:27,1,3,-
+// MACROS: BRDA:27,2,4,-
+// MACROS: BRDA:27,2,5,-
+// MACROS: BRDA:27,3,6,-
+// MACROS: BRDA:27,3,7,-
+// MACROS: BRDA:27,4,8,-
+// MACROS: BRDA:27,4,9,-
+
+// MACROS-COUNT-10: BRDA:37
+// MACROS-NOT: BRDA:37
+// MACROS-NOT: BRDA
+// MACROS: BRF:40
+// MACROS: BFH:24

diff  --git a/llvm/test/tools/llvm-cov/branch-logical-mixed.cpp b/llvm/test/tools/llvm-cov/branch-logical-mixed.cpp
new file mode 100644
index 000000000000..107ed7778015
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-logical-mixed.cpp
@@ -0,0 +1,90 @@
+// RUN: llvm-profdata merge %S/Inputs/branch-logical-mixed.proftext -o %t.profdata
+// RUN: llvm-cov show --show-branches=count %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORT
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void func(int a, int b) {
+  bool b0 = a <= b;
+  bool b1 = a == b;
+  bool b2 = a >= b;
+  bool b3 = a < b;
+  bool b4 = a > b;
+  bool b5 = a != b;
+
+  bool c = b0 &&           // CHECK: Branch ([[@LINE]]:12): [True: 3, False: 1]
+           b1 &&           // CHECK: Branch ([[@LINE]]:12): [True: 2, False: 1]
+           b2 &&           // CHECK: Branch ([[@LINE]]:12): [True: 2, False: 0]
+           b3 &&           // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 2]
+           b4 &&           // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
+           b5;             // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
+
+  bool d = b0 ||           // CHECK: Branch ([[@LINE]]:12): [True: 3, False: 1]
+           b1 ||           // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 1]
+           b2 ||           // CHECK: Branch ([[@LINE]]:12): [True: 1, False: 0]
+           b3 ||           // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
+           b4 ||           // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
+           b5;             // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
+
+  bool e = (b0  &&         // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 1]
+            b5) ||         // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
+           (b1  &&         // CHECK: Branch ([[@LINE]]:13): [True: 2, False: 1]
+            b4) ||         // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 2]
+           (b2  &&         // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 0]
+            b3) ||         // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 3]
+           (b3  &&         // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 3]
+            b2) ||         // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 0]
+           (b4  &&         // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
+            b1) ||         // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 1]
+           (b5  &&         // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
+            b0);           // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 1]
+
+  bool f = (b0  ||         // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 1]
+            b5) &&         // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 0]
+           (b1  ||         // CHECK: Branch ([[@LINE]]:13): [True: 2, False: 2]
+            b4) &&         // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 1]
+           (b2  ||         // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 0]
+            b3) &&         // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 0]
+           (b3  ||         // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 3]
+            b2) &&         // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 0]
+           (b4  ||         // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
+            b1) &&         // CHECK: Branch ([[@LINE]]:13): [True: 2, False: 0]
+           (b5  ||         // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
+            b0);           // CHECK: Branch ([[@LINE]]:13): [True: 2, False: 0]
+
+  if (c)                   // CHECK: Branch ([[@LINE]]:7): [True: 0, False: 4]
+    printf("case0\n");
+  else
+    printf("case1\n");
+
+  if (d)                   // CHECK: Branch ([[@LINE]]:7): [True: 4, False: 0]
+    printf("case2\n");
+  else
+    printf("case3\n");
+
+  if (e)                   // CHECK: Branch ([[@LINE]]:7): [True: 1, False: 3]
+    printf("case4\n");
+  else
+    printf("case5\n");
+
+  if (f)                   // CHECK: Branch ([[@LINE]]:7): [True: 3, False: 1]
+    printf("case6\n");
+  else
+    printf("case7\n");
+}
+
+extern "C" { extern void __llvm_profile_write_file(void); }
+int main(int argc, char *argv[])
+{
+  func(atoi(argv[1]), atoi(argv[2]));
+  __llvm_profile_write_file();
+  return 0;
+}
+
+// REPORT: Name                        Regions    Miss   Cover     Lines    Miss   Cover  Branches    Miss   Cover
+// REPORT-NEXT: ---
+// REPORT-NEXT: _Z4funcii                        77       9  88.31%        68       10  85.29%        80      32  60.00%
+// REPORT-NEXT: main                              1       0 100.00%         5       0 100.00%         0       0   0.00%
+// REPORT-NEXT: ---
+// REPORT-NEXT: TOTAL                            78       9  88.46%        73       10  86.30%        80      32  60.00%

diff  --git a/llvm/test/tools/llvm-cov/branch-macros.cpp b/llvm/test/tools/llvm-cov/branch-macros.cpp
new file mode 100644
index 000000000000..73042ac397d4
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-macros.cpp
@@ -0,0 +1,60 @@
+// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
+// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORT
+
+#define COND1 (a == b)
+#define COND2 (a != b)
+#define COND3 (COND1 && COND2)
+#define COND4 (COND3 ? COND2 : COND1)
+#define MACRO1 COND3
+#define MACRO2 MACRO1
+#define MACRO3 MACRO2
+
+#include <stdlib.h>
+
+
+bool func(int a, int b) {
+  bool c = COND1 && COND2; // CHECK: |  |  |  Branch ([[@LINE-12]]:15): [True: 1, False: 2]
+                           // CHECK: |  |  |  Branch ([[@LINE-12]]:15): [True: 0, False: 1]
+  bool d = COND3;          // CHECK: |  |  |  |  |  Branch ([[@LINE-14]]:15): [True: 1, False: 2]
+                           // CHECK: |  |  |  |  |  Branch ([[@LINE-14]]:15): [True: 0, False: 1]
+  bool e = MACRO1;         // CHECK: |  |  |  |  |  |  |  Branch ([[@LINE-16]]:15): [True: 1, False: 2]
+                           // CHECK: |  |  |  |  |  |  |  Branch ([[@LINE-16]]:15): [True: 0, False: 1]
+  bool f = MACRO2;         // CHECK: |  |  |  |  |  |  |  |  |  Branch ([[@LINE-18]]:15): [True: 1, False: 2]
+                           // CHECK: |  |  |  |  |  |  |  |  |  Branch ([[@LINE-18]]:15): [True: 0, False: 1]
+  bool g = MACRO3;         // CHECK: |  |  |  |  |  |  |  |  |  |  |  Branch ([[@LINE-20]]:15): [True: 1, False: 2]
+                           // CHECK: |  |  |  |  |  |  |  |  |  |  |  Branch ([[@LINE-20]]:15): [True: 0, False: 1]
+  return c && d && e && f && g;
+                           // CHECK: |  Branch ([[@LINE-1]]:10): [True: 0, False: 3]
+                           // CHECK: |  Branch ([[@LINE-2]]:15): [True: 0, False: 0]
+                           // CHECK: |  Branch ([[@LINE-3]]:20): [True: 0, False: 0]
+                           // CHECK: |  Branch ([[@LINE-4]]:25): [True: 0, False: 0]
+                           // CHECK: |  Branch ([[@LINE-5]]:30): [True: 0, False: 0]
+}
+
+
+bool func2(int a, int b) {
+    bool h = MACRO3 || COND4;  // CHECK: |  |  |  |  |  |  |  |  |  |  |  Branch ([[@LINE-32]]:15): [True: 1, False: 2]
+                               // CHECK: |  |  |  |  |  |  |  |  |  |  |  Branch ([[@LINE-32]]:15): [True: 0, False: 1]
+                               // CHECK: |  |  |  |  |  |  |  Branch ([[@LINE-34]]:15): [True: 1, False: 2]
+                               // CHECK: |  |  |  |  |  |  |  Branch ([[@LINE-34]]:15): [True: 0, False: 1]
+                               // CHECK: |  |  |  Branch ([[@LINE-33]]:15): [True: 1, False: 2]
+  return h;
+}
+
+extern "C" { extern void __llvm_profile_write_file(void); }
+int main(int argc, char *argv[])
+{
+  func(atoi(argv[1]), atoi(argv[2]));
+  func2(atoi(argv[1]), atoi(argv[2]));
+  __llvm_profile_write_file();
+  return 0;
+}
+
+// REPORT: Name                        Regions    Miss   Cover     Lines    Miss   Cover  Branches    Miss   Cover
+// REPORT-NEXT: ---
+// REPORT-NEXT: _Z4funcii                        28       4  85.71%        18       0 100.00%        30      14  53.33%
+// REPORT-NEXT: _Z5func2ii                       13       1  92.31%         8       0 100.00%        10       2  80.00%
+// REPORT-NEXT: main                              1       0 100.00%         6       0 100.00%         0       0   0.00%
+// REPORT-NEXT: ---
+// REPORT-NEXT: TOTAL                            42       5  88.10%        32       0 100.00% 40      16  60.00%

diff  --git a/llvm/test/tools/llvm-cov/branch-noShowBranch.test b/llvm/test/tools/llvm-cov/branch-noShowBranch.test
new file mode 100644
index 000000000000..63b9f5218004
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-noShowBranch.test
@@ -0,0 +1,25 @@
+
+// RUN: llvm-profdata merge %S/Inputs/branch-c-general.proftext -o %t.profdata
+// RUN: llvm-cov show %S/Inputs/branch-c-general.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/branch-c-general.c | FileCheck %s
+// RUN: llvm-cov report %S/Inputs/branch-c-general.o32l --show-branch-summary=false -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %S/branch-c-general.c | FileCheck %s -check-prefix=REPORT
+
+// CHECK-NOT: | Branch
+
+// REPORT: Name                        Regions    Miss   Cover     Lines    Miss   Cover
+// REPORT-NOT: Name                        Regions    Miss   Cover     Lines    Miss   Cover  Branches    Miss   Cover
+// REPORT: ---
+// REPORT-NOT: simple_loops                      8       0 100.00%         9       0 100.00%         6       0 100.00%
+// REPORT-NOT: conditionals                     24       0 100.00%        15       0 100.00%        16       2  87.50%
+// REPORT-NOT: early_exits                      20       4  80.00%        25       2  92.00%        16       6  62.50%
+// REPORT-NOT: jumps                            39      12  69.23%        48       2  95.83%        26       9  65.38%
+// REPORT-NOT: switches                         28       5  82.14%        38       4  89.47%        30       9  70.00%
+// REPORT-NOT: big_switch                       25       1  96.00%        32       0 100.00%        30       6  80.00%
+// REPORT-NOT: boolean_operators                16       0 100.00%        13       0 100.00%        22       2  90.91%
+// REPORT-NOT: boolop_loops                     19       0 100.00%        14       0 100.00%        16       2  87.50%
+// REPORT-NOT: conditional_operator              4       2  50.00%         8       0 100.00%         4       2  50.00%
+// REPORT-NOT: do_fallthrough                    9       0 100.00%        12       0 100.00%         6       0 100.00%
+// REPORT-NOT: main                              1       0 100.00%        16       0 100.00%         0       0   0.00%
+// REPORT-NOT: c-general.c:static_func           4       0 100.00%         4       0 100.00%         2       0 100.00%
+// REPORT: TOTAL                           197      24  87.82%       234       13  94.44%
+// REPORT-NOT: TOTAL                           197      24  87.82%       234       13  94.44%       174      38  78.16%
+

diff  --git a/llvm/test/tools/llvm-cov/branch-showBranchPercentage.c b/llvm/test/tools/llvm-cov/branch-showBranchPercentage.c
new file mode 100644
index 000000000000..a649462116a0
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-showBranchPercentage.c
@@ -0,0 +1,77 @@
+// Test visualization of branch taken percentages
+
+// RUN: llvm-profdata merge %S/Inputs/branch-showBranchPercentage.proftext -o %t.profdata
+// RUN: llvm-cov show --show-branches=percent %S/Inputs/branch-showBranchPercentage.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern void __llvm_profile_write_file(void);
+
+int main(int argc, char *argv[])
+{
+  int i = 0;
+  if (argc < 3)                       // CHECK: Branch ([[@LINE]]:7): [True: 16.67%, False: 83.33%]
+  {
+    __llvm_profile_write_file();
+    return 0;
+  }
+
+  int a = atoi(argv[1]);
+  int b = atoi(argv[2]);
+
+                                      // CHECK: Branch ([[@LINE+4]]:8): [True: 20.00%, False: 80.00%]
+                                      // CHECK: Branch ([[@LINE+3]]:18): [True: 0.00%, False: 100.00%]
+                                      // CHECK: Branch ([[@LINE+2]]:29): [True: 0.00%, False: 100.00%]
+                                      // CHECK: Branch ([[@LINE+1]]:40): [True: 40.00%, False: 60.00%]
+  if ((a == 0 && b == 2) || b == 34 || a == b)
+    printf("case1\n");
+
+  b = (a != 0 || a == 2) ? b : b+2;   // CHECK: Branch ([[@LINE]]:8): [True: 80.00%, False: 20.00%]
+                                      // CHECK: Branch ([[@LINE-1]]:18): [True: 0.00%, False: 100.00%]
+  b = (a != 0 && a == 1);             // CHECK: Branch ([[@LINE]]:8): [True: 80.00%, False: 20.00%]
+                                      // CHECK: Branch ([[@LINE-1]]:18): [True: 25.00%, False: 75.00%]
+  for (i = 0; i < b; i++) { a = 2 + b + b; }
+                                      // CHECK: Branch ([[@LINE-1]]:15): [True: 16.67%, False: 83.33%]
+
+  b = a;
+
+  switch (a)
+  {
+    case 0:                           // CHECK: Branch ([[@LINE]]:5): [True: 20.00%, False: 80.00%]
+      printf("case0\n");
+    case 2:                           // CHECK: Branch ([[@LINE]]:5): [True: 20.00%, False: 80.00%]
+      printf("case2\n");
+    case 3:                           // CHECK: Branch ([[@LINE]]:5): [True: 0.00%, False: 100.00%]
+      printf("case3\n");
+    default: break;                   // CHECK: Branch ([[@LINE]]:5): [True: 60.00%, False: 40.00%]
+  }
+
+  i = 0;
+  do {
+    printf("loop\n");
+  } while (i++ < 10);                 // CHECK: Branch ([[@LINE]]:12): [True: 90.91%, False: 9.09%]
+
+  __llvm_profile_write_file();
+
+  return b;
+}
+// RUN: llvm-profdata merge %S/Inputs/branch-showBranchPercentage.proftext -o %t.profdata
+// RUN: llvm-cov show --show-branches=percent %S/Inputs/branch-showBranchPercentage.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -format html -o %t.html.dir
+
+// Test html output.
+// RUN: FileCheck -check-prefix=HTML -input-file=%t.html.dir/coverage/tmp/branch-showBranchPercentage.c.html %s
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}16.67%,{{.*}}83.33%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}20.00%,{{.*}}80.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}0.00%,{{.*}}100.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}0.00%,{{.*}}100.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}40.00%,{{.*}}60.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}80.00%,{{.*}}20.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}0.00%,{{.*}}100.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}80.00%,{{.*}}20.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}25.00%,{{.*}}75.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}16.67%,{{.*}}83.33%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}20.00%,{{.*}}80.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}20.00%,{{.*}}80.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}0.00%,{{.*}}100.00%]
+// HTML: Branch (<span class='line-number'><a name='L{{[0-9]+}}' href='#L{{[0-9]+}}'><span>{{.*}}60.00%,{{.*}}40.00%]

diff  --git a/llvm/test/tools/llvm-cov/branch-templates.cpp b/llvm/test/tools/llvm-cov/branch-templates.cpp
new file mode 100644
index 000000000000..750dc7bd58f2
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-templates.cpp
@@ -0,0 +1,47 @@
+// RUN: llvm-profdata merge %S/Inputs/branch-templates.proftext -o %t.profdata
+// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORT
+
+#include <stdio.h>
+
+template<typename T>
+void unused(T x) {
+  return;
+}
+
+template<typename T>
+int func(T x) {
+  if(x)       // CHECK: |  Branch ([[@LINE]]:6): [True: 0, False: 1]
+    return 0; // CHECK: |  Branch ([[@LINE-1]]:6): [True: 1, False: 0]
+  else        // CHECK: |  Branch ([[@LINE-2]]:6): [True: 0, False: 1]
+    return 1;
+  int j = 1;
+}
+
+              // CHECK-LABEL: _Z4funcIiEiT_:
+              // CHECK: |  |  Branch ([[@LINE-8]]:6): [True: 0, False: 1]
+              // CHECK-LABEL: _Z4funcIbEiT_:
+              // CHECK: |  |  Branch ([[@LINE-10]]:6): [True: 1, False: 0]
+              // CHECK-LABEL: _Z4funcIfEiT_:
+              // CHECK: |  |  Branch ([[@LINE-12]]:6): [True: 0, False: 1]
+
+extern "C" { extern void __llvm_profile_write_file(void); }
+int main() {
+  if (func<int>(0))      // CHECK: |  Branch ([[@LINE]]:7): [True: 1, False: 0]
+    printf("case1\n");
+  if (func<bool>(true))  // CHECK: |  Branch ([[@LINE]]:7): [True: 0, False: 1]
+    printf("case2\n");
+  if (func<float>(0.0))  // CHECK: |  Branch ([[@LINE]]:7): [True: 1, False: 0]
+    printf("case3\n");
+  __llvm_profile_write_file();
+  return 0;
+}
+
+// REPORT: Name                        Regions    Miss   Cover     Lines    Miss   Cover  Branches    Miss   Cover
+// REPORT-NEXT: ---
+// REPORT-NEXT: main                              7       1  85.71%        10       1  90.00%         6       3  50.00%
+// REPORT-NEXT: _Z4funcIiEiT_                     5       2  60.00%         7       3  57.14%         2       1  50.00%
+// REPORT-NEXT: _Z4funcIbEiT_                     5       2  60.00%         7       4  42.86%         2       1  50.00%
+// REPORT-NEXT: _Z4funcIfEiT_                     5       2  60.00%         7       3  57.14%         2       1  50.00%
+// REPORT-NEXT: ---
+// REPORT-NEXT: TOTAL                            22       7  68.18%        31      11  64.52%        12       6  50.00%

diff  --git a/llvm/test/tools/llvm-cov/ignore-filename-regex.test b/llvm/test/tools/llvm-cov/ignore-filename-regex.test
index 0824645b5082..efc4cda4abc0 100644
--- a/llvm/test/tools/llvm-cov/ignore-filename-regex.test
+++ b/llvm/test/tools/llvm-cov/ignore-filename-regex.test
@@ -4,7 +4,7 @@
 # Ignore all header files.
 RUN: llvm-cov report -instr-profile %S/Inputs/sources_specified/main.profdata \
 RUN:   -path-equivalence=/tmp,%S/Inputs -ignore-filename-regex='.*\.h$' \
-RUN:   %S/Inputs/sources_specified/main.covmapping \
+RUN:   %S/Inputs/sources_specified/main.covmapping --show-branch-summary=false \
 RUN:   | FileCheck -check-prefix=REPORT_IGNORE_HEADERS %s
 
 REPORT_IGNORE_HEADERS-NOT: {{.*}}dec.h{{.*}}
@@ -15,7 +15,7 @@ REPORT_IGNORE_HEADERS: {{^}}TOTAL 1{{.*}}100.00%{{$}}
 # Ignore all files from "extra" directory.
 RUN: llvm-cov report -instr-profile %S/Inputs/sources_specified/main.profdata \
 RUN:   -path-equivalence=/tmp,%S/Inputs -ignore-filename-regex='.*extra[/\\].*' \
-RUN:   %S/Inputs/sources_specified/main.covmapping \
+RUN:   %S/Inputs/sources_specified/main.covmapping --show-branch-summary=false \
 RUN:   | FileCheck -check-prefix=REPORT_IGNORE_DIR %s
 
 REPORT_IGNORE_DIR-NOT: {{.*}}extra{{[/\\]}}dec.h{{.*}}
@@ -27,7 +27,7 @@ REPORT_IGNORE_DIR: {{^}}TOTAL 5{{.*}}90.00%{{$}}
 # Ignore all files from "extra" directory even when SOURCES specified.
 RUN: llvm-cov report -instr-profile %S/Inputs/sources_specified/main.profdata \
 RUN:   -path-equivalence=/tmp,%S/Inputs -ignore-filename-regex='.*extra[/\\].*' \
-RUN:   %S/Inputs/sources_specified/main.covmapping \
+RUN:   %S/Inputs/sources_specified/main.covmapping --show-branch-summary=false \
 RUN:   %S/Inputs/sources_specified/extra %S/Inputs/sources_specified/abs.h \
 RUN:   | FileCheck -check-prefix=REPORT_IGNORE_DIR_WITH_SOURCES %s
 

diff  --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index a453e975fca9..baa968820b63 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -88,6 +88,12 @@ class CodeCoverageTool {
                                ArrayRef<ExpansionRecord> Expansions,
                                const CoverageMapping &Coverage);
 
+  /// Create source views for the branches of the view.
+  void attachBranchSubViews(SourceCoverageView &View, StringRef SourceName,
+                            ArrayRef<CountedRegion> Branches,
+                            const MemoryBuffer &File,
+                            CoverageData &CoverageInfo);
+
   /// Create the source view of a particular function.
   std::unique_ptr<SourceCoverageView>
   createFunctionView(const FunctionRecord &Function,
@@ -268,15 +274,45 @@ void CodeCoverageTool::attachExpansionSubViews(
     if (!SourceBuffer)
       continue;
 
+    auto SubViewBranches = ExpansionCoverage.getBranches();
     auto SubViewExpansions = ExpansionCoverage.getExpansions();
     auto SubView =
         SourceCoverageView::create(Expansion.Function.Name, SourceBuffer.get(),
                                    ViewOpts, std::move(ExpansionCoverage));
     attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
+    attachBranchSubViews(*SubView, Expansion.Function.Name, SubViewBranches,
+                         SourceBuffer.get(), ExpansionCoverage);
     View.addExpansion(Expansion.Region, std::move(SubView));
   }
 }
 
+void CodeCoverageTool::attachBranchSubViews(SourceCoverageView &View,
+                                            StringRef SourceName,
+                                            ArrayRef<CountedRegion> Branches,
+                                            const MemoryBuffer &File,
+                                            CoverageData &CoverageInfo) {
+  if (!ViewOpts.ShowBranchCounts && !ViewOpts.ShowBranchPercents)
+    return;
+
+  const auto *NextBranch = Branches.begin();
+  const auto *EndBranch = Branches.end();
+
+  // Group branches that have the same line number into the same subview.
+  while (NextBranch != EndBranch) {
+    std::vector<CountedRegion> ViewBranches;
+    unsigned CurrentLine = NextBranch->LineStart;
+
+    while (NextBranch != EndBranch && CurrentLine == NextBranch->LineStart)
+      ViewBranches.push_back(*NextBranch++);
+
+    if (!ViewBranches.empty()) {
+      auto SubView = SourceCoverageView::create(SourceName, File, ViewOpts,
+                                                std::move(CoverageInfo));
+      View.addBranch(CurrentLine, ViewBranches, std::move(SubView));
+    }
+  }
+}
+
 std::unique_ptr<SourceCoverageView>
 CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
                                      const CoverageMapping &Coverage) {
@@ -287,11 +323,14 @@ CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
   if (!SourceBuffer)
     return nullptr;
 
+  auto Branches = FunctionCoverage.getBranches();
   auto Expansions = FunctionCoverage.getExpansions();
   auto View = SourceCoverageView::create(DC.demangle(Function.Name),
                                          SourceBuffer.get(), ViewOpts,
                                          std::move(FunctionCoverage));
   attachExpansionSubViews(*View, Expansions, Coverage);
+  attachBranchSubViews(*View, DC.demangle(Function.Name), Branches,
+                       SourceBuffer.get(), FunctionCoverage);
 
   return View;
 }
@@ -306,10 +345,13 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
   if (FileCoverage.empty())
     return nullptr;
 
+  auto Branches = FileCoverage.getBranches();
   auto Expansions = FileCoverage.getExpansions();
   auto View = SourceCoverageView::create(SourceFile, SourceBuffer.get(),
                                          ViewOpts, std::move(FileCoverage));
   attachExpansionSubViews(*View, Expansions, Coverage);
+  attachBranchSubViews(*View, SourceFile, Branches, SourceBuffer.get(),
+                       FileCoverage);
   if (!ViewOpts.ShowFunctionInstantiations)
     return View;
 
@@ -326,9 +368,12 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
       if (Function->ExecutionCount > 0) {
         auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);
         auto SubViewExpansions = SubViewCoverage.getExpansions();
+        auto SubViewBranches = SubViewCoverage.getBranches();
         SubView = SourceCoverageView::create(
             Funcname, SourceBuffer.get(), ViewOpts, std::move(SubViewCoverage));
         attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
+        attachBranchSubViews(*SubView, SourceFile, SubViewBranches,
+                             SourceBuffer.get(), SubViewCoverage);
       }
 
       unsigned FileID = Function->CountedRegions.front().FileID;
@@ -645,6 +690,11 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
       cl::desc("Show region statistics in summary table"),
       cl::init(true));
 
+  cl::opt<bool> BranchSummary(
+      "show-branch-summary", cl::Optional,
+      cl::desc("Show branch condition statistics in summary table"),
+      cl::init(true));
+
   cl::opt<bool> InstantiationSummary(
       "show-instantiation-summary", cl::Optional,
       cl::desc("Show instantiation statistics in summary table"));
@@ -788,6 +838,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
       ::exit(0);
     }
 
+    ViewOpts.ShowBranchSummary = BranchSummary;
     ViewOpts.ShowRegionSummary = RegionSummary;
     ViewOpts.ShowInstantiationSummary = InstantiationSummary;
     ViewOpts.ExportSummaryOnly = SummaryOnly;
@@ -822,6 +873,15 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
       cl::desc("Show the execution counts for each region"),
       cl::cat(ViewCategory));
 
+  cl::opt<CoverageViewOptions::BranchOutputType> ShowBranches(
+      "show-branches", cl::Optional,
+      cl::desc("Show coverage for branch conditions"), cl::cat(ViewCategory),
+      cl::values(clEnumValN(CoverageViewOptions::BranchOutputType::Count,
+                            "count", "Show True/False counts"),
+                 clEnumValN(CoverageViewOptions::BranchOutputType::Percent,
+                            "percent", "Show True/False percent")),
+      cl::init(CoverageViewOptions::BranchOutputType::Off));
+
   cl::opt<bool> ShowBestLineRegionsCounts(
       "show-line-counts-or-regions", cl::Optional,
       cl::desc("Show the execution counts for each line, or the execution "
@@ -865,6 +925,10 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
                            !ShowRegions || ShowBestLineRegionsCounts;
   ViewOpts.ShowRegionMarkers = ShowRegions || ShowBestLineRegionsCounts;
   ViewOpts.ShowExpandedRegions = ShowExpansions;
+  ViewOpts.ShowBranchCounts =
+      ShowBranches == CoverageViewOptions::BranchOutputType::Count;
+  ViewOpts.ShowBranchPercents =
+      ShowBranches == CoverageViewOptions::BranchOutputType::Percent;
   ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
   ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
   ViewOpts.TabSize = TabSize;

diff  --git a/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index c8bb1aa5b6ea..0a47dd2b88c7 100644
--- a/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -18,6 +18,8 @@
 //   -- Export: dict => Json representation of one CoverageMapping
 //     -- Files: array => List of objects describing coverage for files
 //       -- File: dict => Coverage for a single file
+//         -- Branches: array => List of Branches in the file
+//           -- Branch: dict => Describes a branch of the file with counters
 //         -- Segments: array => List of Segments contained in the file
 //           -- Segment: dict => Describes a segment of the file with a counter
 //         -- Expansions: array => List of expansion records
@@ -25,10 +27,13 @@
 //             -- CountedRegion: dict => The region to be expanded
 //             -- TargetRegions: array => List of Regions in the expansion
 //               -- CountedRegion: dict => Single Region in the expansion
+//             -- Branches: array => List of Branches in the expansion
+//               -- Branch: dict => Describes a branch in expansion and counters
 //         -- Summary: dict => Object summarizing the coverage for this file
 //           -- LineCoverage: dict => Object summarizing line coverage
 //           -- FunctionCoverage: dict => Object summarizing function coverage
 //           -- RegionCoverage: dict => Object summarizing region coverage
+//           -- BranchCoverage: dict => Object summarizing branch coverage
 //     -- Functions: array => List of objects describing coverage for functions
 //       -- Function: dict => Coverage info for a single function
 //         -- Filenames: array => List of filenames that the function relates to
@@ -37,6 +42,7 @@
 //     -- FunctionCoverage: dict => Object summarizing function coverage
 //     -- InstantiationCoverage: dict => Object summarizing inst. coverage
 //     -- RegionCoverage: dict => Object summarizing region coverage
+//     -- BranchCoverage: dict => Object summarizing branch coverage
 //
 //===----------------------------------------------------------------------===//
 
@@ -84,6 +90,14 @@ json::Array renderRegion(const coverage::CountedRegion &Region) {
                       int64_t(Region.Kind)});
 }
 
+json::Array renderBranch(const coverage::CountedRegion &Region) {
+  return json::Array(
+      {Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
+       clamp_uint64_to_int64(Region.ExecutionCount),
+       clamp_uint64_to_int64(Region.FalseExecutionCount), Region.FileID,
+       Region.ExpandedFileID, int64_t(Region.Kind)});
+}
+
 json::Array renderRegions(ArrayRef<coverage::CountedRegion> Regions) {
   json::Array RegionArray;
   for (const auto &Region : Regions)
@@ -91,13 +105,49 @@ json::Array renderRegions(ArrayRef<coverage::CountedRegion> Regions) {
   return RegionArray;
 }
 
-json::Object renderExpansion(const coverage::ExpansionRecord &Expansion) {
+json::Array renderBranchRegions(ArrayRef<coverage::CountedRegion> Regions) {
+  json::Array RegionArray;
+  for (const auto &Region : Regions)
+    if (!Region.Folded)
+      RegionArray.push_back(renderBranch(Region));
+  return RegionArray;
+}
+
+std::vector<llvm::coverage::CountedRegion>
+collectNestedBranches(const coverage::CoverageMapping &Coverage,
+                      ArrayRef<llvm::coverage::ExpansionRecord> Expansions) {
+  std::vector<llvm::coverage::CountedRegion> Branches;
+  for (const auto &Expansion : Expansions) {
+    auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion);
+
+    // Recursively collect branches from nested expansions.
+    auto NestedExpansions = ExpansionCoverage.getExpansions();
+    auto NestedExBranches = collectNestedBranches(Coverage, NestedExpansions);
+    Branches.insert(Branches.end(), NestedExBranches.begin(),
+                    NestedExBranches.end());
+
+    // Add branches from this level of expansion.
+    auto ExBranches = ExpansionCoverage.getBranches();
+    for (auto B : ExBranches)
+      if (B.FileID == Expansion.FileID)
+        Branches.push_back(B);
+  }
+
+  return Branches;
+}
+
+json::Object renderExpansion(const coverage::CoverageMapping &Coverage,
+                             const coverage::ExpansionRecord &Expansion) {
+  std::vector<llvm::coverage::ExpansionRecord> Expansions = {Expansion};
   return json::Object(
       {{"filenames", json::Array(Expansion.Function.Filenames)},
        // Mark the beginning and end of this expansion in the source file.
        {"source_region", renderRegion(Expansion.Region)},
        // Enumerate the coverage information for the expansion.
-       {"target_regions", renderRegions(Expansion.Function.CountedRegions)}});
+       {"target_regions", renderRegions(Expansion.Function.CountedRegions)},
+       // Enumerate the branch coverage information for the expansion.
+       {"branches",
+        renderBranchRegions(collectNestedBranches(Coverage, Expansions))}});
 }
 
 json::Object renderSummary(const FileCoverageSummary &Summary) {
@@ -123,14 +173,22 @@ json::Object renderSummary(const FileCoverageSummary &Summary) {
              {"covered", int64_t(Summary.RegionCoverage.getCovered())},
              {"notcovered", int64_t(Summary.RegionCoverage.getNumRegions() -
                                     Summary.RegionCoverage.getCovered())},
-             {"percent", Summary.RegionCoverage.getPercentCovered()}})}});
+             {"percent", Summary.RegionCoverage.getPercentCovered()}})},
+       {"branches",
+        json::Object(
+            {{"count", int64_t(Summary.BranchCoverage.getNumBranches())},
+             {"covered", int64_t(Summary.BranchCoverage.getCovered())},
+             {"notcovered", int64_t(Summary.BranchCoverage.getNumBranches() -
+                                    Summary.BranchCoverage.getCovered())},
+             {"percent", Summary.BranchCoverage.getPercentCovered()}})}});
 }
 
-json::Array renderFileExpansions(const coverage::CoverageData &FileCoverage,
+json::Array renderFileExpansions(const coverage::CoverageMapping &Coverage,
+                                 const coverage::CoverageData &FileCoverage,
                                  const FileCoverageSummary &FileReport) {
   json::Array ExpansionArray;
   for (const auto &Expansion : FileCoverage.getExpansions())
-    ExpansionArray.push_back(renderExpansion(Expansion));
+    ExpansionArray.push_back(renderExpansion(Coverage, Expansion));
   return ExpansionArray;
 }
 
@@ -142,6 +200,14 @@ json::Array renderFileSegments(const coverage::CoverageData &FileCoverage,
   return SegmentArray;
 }
 
+json::Array renderFileBranches(const coverage::CoverageData &FileCoverage,
+                               const FileCoverageSummary &FileReport) {
+  json::Array BranchArray;
+  for (const auto &Branch : FileCoverage.getBranches())
+    BranchArray.push_back(renderBranch(Branch));
+  return BranchArray;
+}
+
 json::Object renderFile(const coverage::CoverageMapping &Coverage,
                         const std::string &Filename,
                         const FileCoverageSummary &FileReport,
@@ -151,8 +217,10 @@ json::Object renderFile(const coverage::CoverageMapping &Coverage,
     // Calculate and render detailed coverage information for given file.
     auto FileCoverage = Coverage.getCoverageForFile(Filename);
     File["segments"] = renderFileSegments(FileCoverage, FileReport);
+    File["branches"] = renderFileBranches(FileCoverage, FileReport);
     if (!Options.SkipExpansions) {
-      File["expansions"] = renderFileExpansions(FileCoverage, FileReport);
+      File["expansions"] =
+          renderFileExpansions(Coverage, FileCoverage, FileReport);
     }
   }
   File["summary"] = renderSummary(FileReport);
@@ -197,6 +265,7 @@ json::Array renderFunctions(
         json::Object({{"name", F.Name},
                       {"count", clamp_uint64_to_int64(F.ExecutionCount)},
                       {"regions", renderRegions(F.CountedRegions)},
+                      {"branches", renderBranchRegions(F.CountedBranchRegions)},
                       {"filenames", json::Array(F.Filenames)}}));
   return FunctionArray;
 }

diff  --git a/llvm/tools/llvm-cov/CoverageExporterLcov.cpp b/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
index 46c6b493ea80..08115e0494b0 100644
--- a/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
+++ b/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
@@ -26,6 +26,10 @@
 //   - "FNH:<number of functions hit>"
 //   - for each instrumented line:
 //     - "DA:<line number>,<execution count>[,<checksum>]
+//   - for each branch:
+//     - "BRDA:<line number>,<branch pair id>,<branch id>,<count>"
+//   - "BRF:<number of branches found>"
+//   - "BRH:<number of branches hit>"
 //   - "LH:<number of lines with non-zero execution count>"
 //   - "LF:<number of instrumented lines>"
 //   - "end_of_record"
@@ -71,11 +75,102 @@ void renderLineExecutionCounts(raw_ostream &OS,
   }
 }
 
+std::vector<llvm::coverage::CountedRegion>
+collectNestedBranches(const coverage::CoverageMapping &Coverage,
+                      ArrayRef<llvm::coverage::ExpansionRecord> Expansions,
+                      int ViewDepth = 0, int SrcLine = 0) {
+  std::vector<llvm::coverage::CountedRegion> Branches;
+  for (const auto &Expansion : Expansions) {
+    auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion);
+
+    // If we're at the top level, set the corresponding source line.
+    if (ViewDepth == 0)
+      SrcLine = Expansion.Region.LineStart;
+
+    // Recursively collect branches from nested expansions.
+    auto NestedExpansions = ExpansionCoverage.getExpansions();
+    auto NestedExBranches = collectNestedBranches(Coverage, NestedExpansions,
+                                                  ViewDepth + 1, SrcLine);
+    Branches.insert(Branches.end(), NestedExBranches.begin(),
+                    NestedExBranches.end());
+
+    // Add branches from this level of expansion.
+    auto ExBranches = ExpansionCoverage.getBranches();
+    for (auto B : ExBranches)
+      if (B.FileID == Expansion.FileID) {
+        B.LineStart = SrcLine;
+        Branches.push_back(B);
+      }
+  }
+
+  return Branches;
+}
+
+bool sortLine(llvm::coverage::CountedRegion I,
+              llvm::coverage::CountedRegion J) {
+  return (I.LineStart < J.LineStart) ||
+         ((I.LineStart == J.LineStart) && (I.ColumnStart < J.ColumnStart));
+}
+
+void renderBranchExecutionCounts(raw_ostream &OS,
+                                 const coverage::CoverageMapping &Coverage,
+                                 const coverage::CoverageData &FileCoverage) {
+  std::vector<llvm::coverage::CountedRegion> Branches =
+      FileCoverage.getBranches();
+
+  // Recursively collect branches for all file expansions.
+  std::vector<llvm::coverage::CountedRegion> ExBranches =
+      collectNestedBranches(Coverage, FileCoverage.getExpansions());
+
+  // Append Expansion Branches to Source Branches.
+  Branches.insert(Branches.end(), ExBranches.begin(), ExBranches.end());
+
+  // Sort branches based on line number to ensure branches corresponding to the
+  // same source line are counted together.
+  std::sort(Branches.begin(), Branches.end(), sortLine);
+
+  auto NextBranch = Branches.begin();
+  auto EndBranch = Branches.end();
+
+  // Branches with the same source line are enumerated individually
+  // (BranchIndex) as well as based on True/False pairs (PairIndex).
+  while (NextBranch != EndBranch) {
+    unsigned CurrentLine = NextBranch->LineStart;
+    unsigned PairIndex = 0;
+    unsigned BranchIndex = 0;
+
+    while (NextBranch != EndBranch && CurrentLine == NextBranch->LineStart) {
+      if (!NextBranch->Folded) {
+        unsigned BC1 = NextBranch->ExecutionCount;
+        unsigned BC2 = NextBranch->FalseExecutionCount;
+        bool BranchNotExecuted = (BC1 == 0 && BC2 == 0);
+
+        for (int I = 0; I < 2; I++, BranchIndex++) {
+          OS << "BRDA:" << CurrentLine << ',' << PairIndex << ','
+             << BranchIndex;
+          if (BranchNotExecuted)
+            OS << ',' << '-' << '\n';
+          else
+            OS << ',' << (I == 0 ? BC1 : BC2) << '\n';
+        }
+
+        PairIndex++;
+      }
+      NextBranch++;
+    }
+  }
+}
+
 void renderLineSummary(raw_ostream &OS, const FileCoverageSummary &Summary) {
   OS << "LF:" << Summary.LineCoverage.getNumLines() << '\n'
      << "LH:" << Summary.LineCoverage.getCovered() << '\n';
 }
 
+void renderBranchSummary(raw_ostream &OS, const FileCoverageSummary &Summary) {
+  OS << "BRF:" << Summary.BranchCoverage.getNumBranches() << '\n'
+     << "BFH:" << Summary.BranchCoverage.getCovered() << '\n';
+}
+
 void renderFile(raw_ostream &OS, const coverage::CoverageMapping &Coverage,
                 const std::string &Filename,
                 const FileCoverageSummary &FileReport, bool ExportSummaryOnly,
@@ -91,7 +186,9 @@ void renderFile(raw_ostream &OS, const coverage::CoverageMapping &Coverage,
     // Calculate and render detailed coverage information for given file.
     auto FileCoverage = Coverage.getCoverageForFile(Filename);
     renderLineExecutionCounts(OS, FileCoverage);
+    renderBranchExecutionCounts(OS, Coverage, FileCoverage);
   }
+  renderBranchSummary(OS, FileReport);
   renderLineSummary(OS, FileReport);
 
   OS << "end_of_record\n";

diff  --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp
index 8509710032d1..2c08f5309494 100644
--- a/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -86,9 +86,9 @@ Column column(StringRef Str, unsigned Width, const T &Value) {
 }
 
 // Specify the default column widths.
-size_t FileReportColumns[] = {25, 12, 18, 10, 12, 18, 10,
-                              16, 16, 10, 12, 18, 10};
-size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};
+size_t FileReportColumns[] = {25, 12, 18, 10, 12, 18, 10, 16,
+                              16, 10, 12, 18, 10, 12, 18, 10};
+size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8, 10, 8, 8};
 
 /// Adjust column widths to fit long file paths and function names.
 void adjustColumnWidths(ArrayRef<StringRef> Files,
@@ -239,6 +239,23 @@ void CoverageReport::render(const FileCoverageSummary &File,
         << '%';
   else
     OS << column("-", FileReportColumns[12], Column::RightAlignment);
+
+  if (Options.ShowBranchSummary) {
+    OS << format("%*u", FileReportColumns[13],
+                 (unsigned)File.BranchCoverage.getNumBranches());
+    Options.colored_ostream(OS, LineCoverageColor)
+        << format("%*u", FileReportColumns[14],
+                  (unsigned)(File.BranchCoverage.getNumBranches() -
+                             File.BranchCoverage.getCovered()));
+    if (File.BranchCoverage.getNumBranches())
+      Options.colored_ostream(OS, LineCoverageColor)
+          << format("%*.2f", FileReportColumns[15] - 1,
+                    File.BranchCoverage.getPercentCovered())
+          << '%';
+    else
+      OS << column("-", FileReportColumns[15], Column::RightAlignment);
+  }
+
   OS << "\n";
 }
 
@@ -273,6 +290,19 @@ void CoverageReport::render(const FunctionCoverageSummary &Function,
       << format("%*.2f", FunctionReportColumns[6] - 1,
                 Function.LineCoverage.getPercentCovered())
       << '%';
+  if (Options.ShowBranchSummary) {
+    OS << format("%*u", FunctionReportColumns[7],
+                 (unsigned)Function.BranchCoverage.getNumBranches());
+    Options.colored_ostream(OS, LineCoverageColor)
+        << format("%*u", FunctionReportColumns[8],
+                  (unsigned)(Function.BranchCoverage.getNumBranches() -
+                             Function.BranchCoverage.getCovered()));
+    Options.colored_ostream(
+        OS, determineCoveragePercentageColor(Function.BranchCoverage))
+        << format("%*.2f", FunctionReportColumns[9] - 1,
+                  Function.BranchCoverage.getPercentCovered())
+        << '%';
+  }
   OS << "\n";
 }
 
@@ -301,6 +331,10 @@ void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
        << column("Lines", FunctionReportColumns[4], Column::RightAlignment)
        << column("Miss", FunctionReportColumns[5], Column::RightAlignment)
        << column("Cover", FunctionReportColumns[6], Column::RightAlignment);
+    if (Options.ShowBranchSummary)
+      OS << column("Branches", FunctionReportColumns[7], Column::RightAlignment)
+         << column("Miss", FunctionReportColumns[8], Column::RightAlignment)
+         << column("Cover", FunctionReportColumns[9], Column::RightAlignment);
     OS << "\n";
     renderDivider(FunctionReportColumns, OS);
     OS << "\n";
@@ -310,6 +344,7 @@ void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
       ++Totals.ExecutionCount;
       Totals.RegionCoverage += Function.RegionCoverage;
       Totals.LineCoverage += Function.LineCoverage;
+      Totals.BranchCoverage += Function.BranchCoverage;
       render(Function, DC, OS);
     }
     if (Totals.ExecutionCount) {
@@ -420,7 +455,13 @@ void CoverageReport::renderFileReports(
        << column("Executed", FileReportColumns[9], Column::RightAlignment);
   OS << column("Lines", FileReportColumns[10], Column::RightAlignment)
      << column("Missed Lines", FileReportColumns[11], Column::RightAlignment)
-     << column("Cover", FileReportColumns[12], Column::RightAlignment) << "\n";
+     << column("Cover", FileReportColumns[12], Column::RightAlignment);
+  if (Options.ShowBranchSummary)
+    OS << column("Branches", FileReportColumns[13], Column::RightAlignment)
+       << column("Missed Branches", FileReportColumns[14],
+                 Column::RightAlignment)
+       << column("Cover", FileReportColumns[15], Column::RightAlignment);
+  OS << "\n";
   renderDivider(FileReportColumns, OS);
   OS << "\n";
 

diff  --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
index 929529c27b6e..4a0a86168908 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
@@ -16,6 +16,34 @@
 using namespace llvm;
 using namespace coverage;
 
+static void sumBranches(size_t &NumBranches, size_t &CoveredBranches,
+                        const ArrayRef<CountedRegion> &Branches) {
+  for (const auto &BR : Branches) {
+    // Skip folded branches.
+    if (BR.Folded)
+      continue;
+
+    // "True" Condition Branches.
+    ++NumBranches;
+    if (BR.ExecutionCount > 0)
+      ++CoveredBranches;
+    // "False" Condition Branches.
+    ++NumBranches;
+    if (BR.FalseExecutionCount > 0)
+      ++CoveredBranches;
+  }
+}
+
+static void sumBranchExpansions(size_t &NumBranches, size_t &CoveredBranches,
+                                const CoverageMapping &CM,
+                                ArrayRef<ExpansionRecord> Expansions) {
+  for (const auto &Expansion : Expansions) {
+    auto CE = CM.getCoverageForExpansion(Expansion);
+    sumBranches(NumBranches, CoveredBranches, CE.getBranches());
+    sumBranchExpansions(NumBranches, CoveredBranches, CM, CE.getExpansions());
+  }
+}
+
 FunctionCoverageSummary
 FunctionCoverageSummary::get(const CoverageMapping &CM,
                              const coverage::FunctionRecord &Function) {
@@ -40,10 +68,16 @@ FunctionCoverageSummary::get(const CoverageMapping &CM,
       ++CoveredLines;
   }
 
+  // Compute the branch coverage, including branches from expansions.
+  size_t NumBranches = 0, CoveredBranches = 0;
+  sumBranches(NumBranches, CoveredBranches, CD.getBranches());
+  sumBranchExpansions(NumBranches, CoveredBranches, CM, CD.getExpansions());
+
   return FunctionCoverageSummary(
       Function.Name, Function.ExecutionCount,
       RegionCoverageInfo(CoveredRegions, NumCodeRegions),
-      LineCoverageInfo(CoveredLines, NumLines));
+      LineCoverageInfo(CoveredLines, NumLines),
+      BranchCoverageInfo(CoveredBranches, NumBranches));
 }
 
 FunctionCoverageSummary
@@ -62,9 +96,15 @@ FunctionCoverageSummary::get(const InstantiationGroup &Group,
   Summary.ExecutionCount = Group.getTotalExecutionCount();
   Summary.RegionCoverage = Summaries[0].RegionCoverage;
   Summary.LineCoverage = Summaries[0].LineCoverage;
+  Summary.BranchCoverage = Summaries[0].BranchCoverage;
   for (const auto &FCS : Summaries.drop_front()) {
     Summary.RegionCoverage.merge(FCS.RegionCoverage);
     Summary.LineCoverage.merge(FCS.LineCoverage);
+
+    // Sum branch coverage across instantiation groups for the summary rather
+    // than "merge" the maximum count. This is a clearer view into whether all
+    // created branches are covered.
+    Summary.BranchCoverage += FCS.BranchCoverage;
   }
   return Summary;
 }

diff  --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index 97beacb26d07..4bc1c24a079f 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -101,6 +101,42 @@ class LineCoverageInfo {
   }
 };
 
+/// Provides information about branches coverage for a function/file.
+class BranchCoverageInfo {
+  /// The number of branches that were executed at least once.
+  size_t Covered;
+
+  /// The total number of branches in a function/file.
+  size_t NumBranches;
+
+public:
+  BranchCoverageInfo() : Covered(0), NumBranches(0) {}
+
+  BranchCoverageInfo(size_t Covered, size_t NumBranches)
+      : Covered(Covered), NumBranches(NumBranches) {
+    assert(Covered <= NumBranches && "Covered branches over-counted");
+  }
+
+  BranchCoverageInfo &operator+=(const BranchCoverageInfo &RHS) {
+    Covered += RHS.Covered;
+    NumBranches += RHS.NumBranches;
+    return *this;
+  }
+
+  size_t getCovered() const { return Covered; }
+
+  size_t getNumBranches() const { return NumBranches; }
+
+  bool isFullyCovered() const { return Covered == NumBranches; }
+
+  double getPercentCovered() const {
+    assert(Covered <= NumBranches && "Covered branches over-counted");
+    if (NumBranches == 0)
+      return 0.0;
+    return double(Covered) / double(NumBranches) * 100.0;
+  }
+};
+
 /// Provides information about function coverage for a file.
 class FunctionCoverageInfo {
   /// The number of functions that were executed.
@@ -147,15 +183,19 @@ struct FunctionCoverageSummary {
   uint64_t ExecutionCount;
   RegionCoverageInfo RegionCoverage;
   LineCoverageInfo LineCoverage;
+  BranchCoverageInfo BranchCoverage;
 
   FunctionCoverageSummary(const std::string &Name)
-      : Name(Name), ExecutionCount(0), RegionCoverage(), LineCoverage() {}
+      : Name(Name), ExecutionCount(0), RegionCoverage(), LineCoverage(),
+        BranchCoverage() {}
 
   FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount,
                           const RegionCoverageInfo &RegionCoverage,
-                          const LineCoverageInfo &LineCoverage)
+                          const LineCoverageInfo &LineCoverage,
+                          const BranchCoverageInfo &BranchCoverage)
       : Name(Name), ExecutionCount(ExecutionCount),
-        RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) {}
+        RegionCoverage(RegionCoverage), LineCoverage(LineCoverage),
+        BranchCoverage(BranchCoverage) {}
 
   /// Compute the code coverage summary for the given function coverage
   /// mapping record.
@@ -174,6 +214,7 @@ struct FileCoverageSummary {
   StringRef Name;
   RegionCoverageInfo RegionCoverage;
   LineCoverageInfo LineCoverage;
+  BranchCoverageInfo BranchCoverage;
   FunctionCoverageInfo FunctionCoverage;
   FunctionCoverageInfo InstantiationCoverage;
 
@@ -185,6 +226,7 @@ struct FileCoverageSummary {
     RegionCoverage += RHS.RegionCoverage;
     LineCoverage += RHS.LineCoverage;
     FunctionCoverage += RHS.FunctionCoverage;
+    BranchCoverage += RHS.BranchCoverage;
     InstantiationCoverage += RHS.InstantiationCoverage;
     return *this;
   }
@@ -192,6 +234,7 @@ struct FileCoverageSummary {
   void addFunction(const FunctionCoverageSummary &Function) {
     RegionCoverage += Function.RegionCoverage;
     LineCoverage += Function.LineCoverage;
+    BranchCoverage += Function.BranchCoverage;
     FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
   }
 

diff  --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h
index dde0c692ab05..eee4ba74e165 100644
--- a/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -23,20 +23,26 @@ struct CoverageViewOptions {
     Lcov
   };
 
+  enum class BranchOutputType { Count, Percent, Off };
+
   bool Debug;
   bool Colors;
   bool ShowLineNumbers;
   bool ShowLineStats;
   bool ShowRegionMarkers;
+  bool ShowBranchCounts;
+  bool ShowBranchPercents;
   bool ShowExpandedRegions;
   bool ShowFunctionInstantiations;
   bool ShowFullFilenames;
+  bool ShowBranchSummary;
   bool ShowRegionSummary;
   bool ShowInstantiationSummary;
   bool ExportSummaryOnly;
   bool SkipExpansions;
   bool SkipFunctions;
   OutputFormat Format;
+  BranchOutputType ShowBranches;
   std::string ShowOutputDirectory;
   std::vector<std::string> DemanglerOpts;
   uint32_t TabSize;

diff  --git a/llvm/tools/llvm-cov/SourceCoverageView.cpp b/llvm/tools/llvm-cov/SourceCoverageView.cpp
index cd7395a1a87d..aca58a07f250 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageView.cpp
@@ -132,7 +132,8 @@ bool SourceCoverageView::shouldRenderRegionMarkers(
 }
 
 bool SourceCoverageView::hasSubViews() const {
-  return !ExpansionSubViews.empty() || !InstantiationSubViews.empty();
+  return !ExpansionSubViews.empty() || !InstantiationSubViews.empty() ||
+         !BranchSubViews.empty();
 }
 
 std::unique_ptr<SourceCoverageView>
@@ -167,6 +168,12 @@ void SourceCoverageView::addExpansion(
   ExpansionSubViews.emplace_back(Region, std::move(View));
 }
 
+void SourceCoverageView::addBranch(unsigned Line,
+                                   ArrayRef<CountedRegion> Regions,
+                                   std::unique_ptr<SourceCoverageView> View) {
+  BranchSubViews.emplace_back(Line, Regions, std::move(View));
+}
+
 void SourceCoverageView::addInstantiation(
     StringRef FunctionName, unsigned Line,
     std::unique_ptr<SourceCoverageView> View) {
@@ -187,14 +194,17 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
   renderTableHeader(OS, (ViewDepth > 0) ? 0 : getFirstUncoveredLineNo(),
                     ViewDepth);
 
-  // We need the expansions and instantiations sorted so we can go through them
-  // while we iterate lines.
+  // We need the expansions, instantiations, and branches sorted so we can go
+  // through them while we iterate lines.
   llvm::stable_sort(ExpansionSubViews);
   llvm::stable_sort(InstantiationSubViews);
+  llvm::stable_sort(BranchSubViews);
   auto NextESV = ExpansionSubViews.begin();
   auto EndESV = ExpansionSubViews.end();
   auto NextISV = InstantiationSubViews.begin();
   auto EndISV = InstantiationSubViews.end();
+  auto NextBRV = BranchSubViews.begin();
+  auto EndBRV = BranchSubViews.end();
 
   // Get the coverage information for the file.
   auto StartSegment = CoverageInfo.begin();
@@ -234,7 +244,7 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
     if (shouldRenderRegionMarkers(*LCI))
       renderRegionMarkers(OS, *LCI, ViewDepth);
 
-    // Show the expansions and instantiations for this line.
+    // Show the expansions, instantiations, and branches for this line.
     bool RenderedSubView = false;
     for (; NextESV != EndESV && NextESV->getLine() == LI.line_number();
          ++NextESV) {
@@ -257,6 +267,11 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
       renderInstantiationView(OS, *NextISV, ViewDepth + 1);
       RenderedSubView = true;
     }
+    for (; NextBRV != EndBRV && NextBRV->Line == LI.line_number(); ++NextBRV) {
+      renderViewDivider(OS, ViewDepth + 1);
+      renderBranchView(OS, *NextBRV, ViewDepth + 1);
+      RenderedSubView = true;
+    }
     if (RenderedSubView)
       renderViewDivider(OS, ViewDepth + 1);
     renderLineSuffix(OS, ViewDepth);

diff  --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h
index 9ae928443651..5a9fcdd15761 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -67,6 +67,23 @@ struct InstantiationView {
   }
 };
 
+/// A view that represents one or more branch regions on a given source line.
+struct BranchView {
+  std::vector<CountedRegion> Regions;
+  std::unique_ptr<SourceCoverageView> View;
+  unsigned Line;
+
+  BranchView(unsigned Line, ArrayRef<CountedRegion> Regions,
+             std::unique_ptr<SourceCoverageView> View)
+      : Regions(Regions), View(std::move(View)), Line(Line) {}
+
+  unsigned getLine() const { return Line; }
+
+  friend bool operator<(const BranchView &LHS, const BranchView &RHS) {
+    return LHS.Line < RHS.Line;
+  }
+};
+
 /// A file manager that handles format-aware file creation.
 class CoveragePrinter {
 public:
@@ -140,6 +157,9 @@ class SourceCoverageView {
   /// A container for all expansions (e.g macros) in the source on display.
   std::vector<ExpansionView> ExpansionSubViews;
 
+  /// A container for all branches in the source on display.
+  std::vector<BranchView> BranchSubViews;
+
   /// A container for all instantiations (e.g template functions) in the source
   /// on display.
   std::vector<InstantiationView> InstantiationSubViews;
@@ -209,6 +229,10 @@ class SourceCoverageView {
   virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
                                        unsigned ViewDepth) = 0;
 
+  /// Render a branch view and any nested views.
+  virtual void renderBranchView(raw_ostream &OS, BranchView &BRV,
+                                unsigned ViewDepth) = 0;
+
   /// Render \p Title, a project title if one is available, and the
   /// created time.
   virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
@@ -255,6 +279,10 @@ class SourceCoverageView {
   void addInstantiation(StringRef FunctionName, unsigned Line,
                         std::unique_ptr<SourceCoverageView> View);
 
+  /// Add a branch subview to this view.
+  void addBranch(unsigned Line, ArrayRef<CountedRegion> Regions,
+                 std::unique_ptr<SourceCoverageView> View);
+
   /// Print the code coverage information for a specific portion of a
   /// source file to the output stream.
   void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,

diff  --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index 9d10def0a211..4db5624e34fa 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -313,6 +313,8 @@ static void emitColumnLabelsForIndex(raw_ostream &OS,
   Columns.emplace_back(tag("td", "Line Coverage", "column-entry-bold"));
   if (Opts.ShowRegionSummary)
     Columns.emplace_back(tag("td", "Region Coverage", "column-entry-bold"));
+  if (Opts.ShowBranchSummary)
+    Columns.emplace_back(tag("td", "Branch Coverage", "column-entry-bold"));
   OS << tag("tr", join(Columns.begin(), Columns.end(), ""));
 }
 
@@ -378,6 +380,10 @@ void CoveragePrinterHTML::emitFileSummary(raw_ostream &OS, StringRef SF,
     AddCoverageTripleToColumn(FCS.RegionCoverage.getCovered(),
                               FCS.RegionCoverage.getNumRegions(),
                               FCS.RegionCoverage.getPercentCovered());
+  if (Opts.ShowBranchSummary)
+    AddCoverageTripleToColumn(FCS.BranchCoverage.getCovered(),
+                              FCS.BranchCoverage.getNumBranches(),
+                              FCS.BranchCoverage.getPercentCovered());
 
   if (IsTotals)
     OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row-bold");
@@ -650,6 +656,72 @@ void SourceCoverageViewHTML::renderExpansionView(raw_ostream &OS,
   OS << EndExpansionDiv;
 }
 
+void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV,
+                                              unsigned ViewDepth) {
+  // Render the child subview.
+  if (getOptions().Debug)
+    errs() << "Branch at line " << BRV.getLine() << '\n';
+
+  OS << BeginExpansionDiv;
+  OS << BeginPre;
+  for (const auto &R : BRV.Regions) {
+    // Calculate TruePercent and False Percent.
+    double TruePercent = 0.0;
+    double FalsePercent = 0.0;
+    unsigned Total = R.ExecutionCount + R.FalseExecutionCount;
+
+    if (!getOptions().ShowBranchCounts && Total != 0) {
+      TruePercent = ((double)(R.ExecutionCount) / (double)Total) * 100.0;
+      FalsePercent = ((double)(R.FalseExecutionCount) / (double)Total) * 100.0;
+    }
+
+    // Display Line + Column.
+    std::string LineNoStr = utostr(uint64_t(R.LineStart));
+    std::string ColNoStr = utostr(uint64_t(R.ColumnStart));
+    std::string TargetName = "L" + LineNoStr;
+
+    OS << "  Branch (";
+    OS << tag("span",
+              a("#" + TargetName, tag("span", LineNoStr + ":" + ColNoStr),
+                TargetName),
+              "line-number") +
+              "): [";
+
+    if (R.Folded) {
+      OS << "Folded - Ignored]\n";
+      continue;
+    }
+
+    // Display TrueCount or TruePercent.
+    std::string TrueColor = R.ExecutionCount ? "None" : "red";
+    std::string TrueCovClass =
+        (R.ExecutionCount > 0) ? "covered-line" : "uncovered-line";
+
+    OS << tag("span", "True", TrueColor);
+    OS << ": ";
+    if (getOptions().ShowBranchCounts)
+      OS << tag("span", formatCount(R.ExecutionCount), TrueCovClass) << ", ";
+    else
+      OS << format("%0.2f", TruePercent) << "%, ";
+
+    // Display FalseCount or FalsePercent.
+    std::string FalseColor = R.FalseExecutionCount ? "None" : "red";
+    std::string FalseCovClass =
+        (R.FalseExecutionCount > 0) ? "covered-line" : "uncovered-line";
+
+    OS << tag("span", "False", FalseColor);
+    OS << ": ";
+    if (getOptions().ShowBranchCounts)
+      OS << tag("span", formatCount(R.FalseExecutionCount), FalseCovClass);
+    else
+      OS << format("%0.2f", FalsePercent) << "%";
+
+    OS << "]\n";
+  }
+  OS << EndPre;
+  OS << EndExpansionDiv;
+}
+
 void SourceCoverageViewHTML::renderInstantiationView(raw_ostream &OS,
                                                      InstantiationView &ISV,
                                                      unsigned ViewDepth) {

diff  --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.h b/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
index 9834040008a6..7d94675f4b0b 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
@@ -68,6 +68,9 @@ class SourceCoverageViewHTML : public SourceCoverageView {
   void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
                            unsigned ViewDepth) override;
 
+  void renderBranchView(raw_ostream &OS, BranchView &BRV,
+                        unsigned ViewDepth) override;
+
   void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
                                unsigned ViewDepth) override;
 

diff  --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index fcabee2ee69d..948414a4f995 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -10,11 +10,12 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "CoverageReport.h"
 #include "SourceCoverageViewText.h"
+#include "CoverageReport.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Format.h"
 
 using namespace llvm;
 
@@ -222,6 +223,53 @@ void SourceCoverageViewText::renderExpansionView(raw_ostream &OS,
                   /*ShowTitle=*/false, ViewDepth + 1);
 }
 
+void SourceCoverageViewText::renderBranchView(raw_ostream &OS, BranchView &BRV,
+                                              unsigned ViewDepth) {
+  // Render the child subview.
+  if (getOptions().Debug)
+    errs() << "Branch at line " << BRV.getLine() << '\n';
+
+  for (const auto &R : BRV.Regions) {
+    double TruePercent = 0.0;
+    double FalsePercent = 0.0;
+    unsigned Total = R.ExecutionCount + R.FalseExecutionCount;
+
+    if (!getOptions().ShowBranchCounts && Total != 0) {
+      TruePercent = ((double)(R.ExecutionCount) / (double)Total) * 100.0;
+      FalsePercent = ((double)(R.FalseExecutionCount) / (double)Total) * 100.0;
+    }
+
+    renderLinePrefix(OS, ViewDepth);
+    OS << "  Branch (" << R.LineStart << ":" << R.ColumnStart << "): [";
+
+    if (R.Folded) {
+      OS << "Folded - Ignored]\n";
+      continue;
+    }
+
+    colored_ostream(OS, raw_ostream::RED,
+                    getOptions().Colors && !R.ExecutionCount,
+                    /*Bold=*/false, /*BG=*/true)
+        << "True";
+
+    if (getOptions().ShowBranchCounts)
+      OS << ": " << formatCount(R.ExecutionCount) << ", ";
+    else
+      OS << ": " << format("%0.2f", TruePercent) << "%, ";
+
+    colored_ostream(OS, raw_ostream::RED,
+                    getOptions().Colors && !R.FalseExecutionCount,
+                    /*Bold=*/false, /*BG=*/true)
+        << "False";
+
+    if (getOptions().ShowBranchCounts)
+      OS << ": " << formatCount(R.FalseExecutionCount);
+    else
+      OS << ": " << format("%0.2f", FalsePercent) << "%";
+    OS << "]\n";
+  }
+}
+
 void SourceCoverageViewText::renderInstantiationView(raw_ostream &OS,
                                                      InstantiationView &ISV,
                                                      unsigned ViewDepth) {

diff  --git a/llvm/tools/llvm-cov/SourceCoverageViewText.h b/llvm/tools/llvm-cov/SourceCoverageViewText.h
index c8c4632c3b9d..b2be06039f95 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.h
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.h
@@ -59,6 +59,9 @@ class SourceCoverageViewText : public SourceCoverageView {
   void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
                            unsigned ViewDepth) override;
 
+  void renderBranchView(raw_ostream &OS, BranchView &BRV,
+                        unsigned ViewDepth) override;
+
   void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
                                unsigned ViewDepth) override;
 


        


More information about the llvm-commits mailing list