diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index a9fcc7fd050..0f8efcf4aa3 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -164,7 +164,7 @@ static edge gimple_redirect_edge_and_branch (edge, basic_block);
  static edge gimple_try_redirect_by_replacing_jump (edge, basic_block);
  
  /* Various helpers.  */
-static inline bool stmt_starts_bb_p (gimple *, gimple *);
+static inline bool stmt_starts_bb_p (gimple *, gimple *, hash_set<tree> *);
  static int gimple_verify_flow_info (void);
  static void gimple_make_forwarder_block (edge);
  static gimple *first_non_label_stmt (basic_block);
@@ -521,6 +521,59 @@ gimple_call_initialize_ctrl_altering (gimple *stmt)
      gimple_call_set_ctrl_altering (stmt, false);
  }
  
+/* Compute target labels to save useful labels.  */
+static void
+compute_target_labels (gimple_seq seq, hash_set<tree> *target_labels)
+{
+  gimple *stmt = NULL;
+  gimple_stmt_iterator j = gsi_start (seq);
+
+  while (!gsi_end_p (j))
+  {
+      stmt = gsi_stmt (j);
+
+      switch (gimple_code (stmt))
+      {
+	case GIMPLE_COND:
+	  {
+	    gcond *cstmt = as_a <gcond *> (stmt);
+	    tree true_label = gimple_cond_true_label (cstmt);
+	    tree false_label = gimple_cond_false_label (cstmt);
+	    target_labels->add (true_label);
+	    target_labels->add (false_label);
+	  }
+	  break;
+	case GIMPLE_SWITCH:
+	  {
+	    gswitch *gstmt = as_a <gswitch *> (stmt);
+	    size_t i, n = gimple_switch_num_labels (gstmt);
+	    tree elt, label;
+	    for (i = 0; i < n; i++)
+	    {
+	      elt = gimple_switch_label (gstmt, i);
+	      label = CASE_LABEL (elt);
+	      target_labels->add (label);
+	    }
+	  }
+	  break;
+	case GIMPLE_GOTO:
+#if 0
+	  if (!computed_goto_p (stmt))
+	    {
+	      tree dest = gimple_goto_dest (stmt);
+	      target_labels->add (dest);
+	    }
+#endif
+	  break;
+
+	default:
+	  break;
+      }
+
+      gsi_next (&j);
+  }
+}
+
  
  /* Insert SEQ after BB and build a flowgraph.  */
  
@@ -532,6 +585,10 @@ make_blocks_1 (gimple_seq seq, basic_block bb)
    gimple *prev_stmt = NULL;
    bool start_new_block = true;
    bool first_stmt_of_seq = true;
+  hash_set<tree> target_labels;
+
+  if (!optimize)
+    compute_target_labels (seq, &target_labels);
  
    while (!gsi_end_p (i))
      {
@@ -553,7 +610,7 @@ make_blocks_1 (gimple_seq seq, basic_block bb)
        /* If the statement starts a new basic block or if we have determined
  	 in a previous pass that we need to create a new block for STMT, do
  	 so now.  */
-      if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt))
+      if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt, &target_labels))
  	{
  	  if (!first_stmt_of_seq)
  	    gsi_split_seq_before (&i, &seq);
@@ -2832,7 +2889,8 @@ simple_goto_p (gimple *t)
     label.  */
  
  static inline bool
-stmt_starts_bb_p (gimple *stmt, gimple *prev_stmt)
+stmt_starts_bb_p (gimple *stmt, gimple *prev_stmt,
+		  hash_set<tree> *target_labels)
  {
    if (stmt == NULL)
      return false;
@@ -2860,6 +2918,10 @@ stmt_starts_bb_p (gimple *stmt, gimple *prev_stmt)
  	      || !DECL_ARTIFICIAL (gimple_label_label (plabel)))
  	    return true;
  
+	  if (!optimize
+	      && target_labels->contains (gimple_label_label (label_stmt)))
+	    return true;
+
  	  cfg_stats.num_merged_labels++;
  	  return false;
  	}
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-1.C b/gcc/testsuite/g++.dg/gcov/gcov-1.C
index ee383b480a8..01e7084fb03 100644
--- a/gcc/testsuite/g++.dg/gcov/gcov-1.C
+++ b/gcc/testsuite/g++.dg/gcov/gcov-1.C
@@ -263,7 +263,7 @@ test_switch (int i, int j)
        case 2:
          result = do_something (1024);
          break;
-      case 3:				/* count(3) */
+      case 3:				/* count(2) */
        case 4:
  					/* branch(67) */
          if (j == 2)			/* count(3) */
diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-4.c b/gcc/testsuite/gcc.dg/analyzer/paths-4.c
index b72e658739e..fdf33e68d0c 100644
--- a/gcc/testsuite/gcc.dg/analyzer/paths-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/paths-4.c
@@ -35,18 +35,18 @@ int test_2 (struct state *s)
  	  do_stuff (s, 0);
  	  break;
  	case 1:
-	  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+	  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */
  	  do_stuff (s, 17);
  	  break;
  	case 2:
-	  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+	  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */
  	  do_stuff (s, 5);
  	  break;
  	case 3:
-	  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+	  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */
  	  return 42;
  	case 4:
-	  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+	  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */
  	  return -3;
  	}
      }
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr85332.c b/gcc/testsuite/gcc.misc-tests/gcov-pr85332.c
index 73e50b19fc7..b37e760910c 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-pr85332.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-pr85332.c
@@ -7,7 +7,7 @@ int doit(int sel, int n, void *p)
  
    switch (sel)
    {
-    case 0: /* count(3) */
+    case 0: /* count(1) */
        do {*p0 += *p0;} while (--n); /* count(3) */
        return *p0 == 0; /* count(1) */
  
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr93680.c b/gcc/testsuite/gcc.misc-tests/gcov-pr93680.c
new file mode 100644
index 00000000000..2fe340c4011
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/gcov-pr93680.c
@@ -0,0 +1,24 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+int f(int s, int n)
+{
+  int p = 0;
+
+  switch (s)
+  {
+    case 0: /* count(1) */
+      do { p++; } while (--n); /* count(5) */
+      return p; /* count(1) */
+
+    case 1: /* count(1) */
+      do { p++; } while (--n); /* count(5) */
+      return p; /* count(1) */
+  }
+
+  return 0;
+}
+
+int main() { f(0, 5); f(1, 5); return 0; }
+
+/* { dg-final { run-gcov gcov-pr93680.c } } */
diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp
index 80e74aeb220..07e1978d25d 100644
--- a/gcc/testsuite/lib/gcov.exp
+++ b/gcc/testsuite/lib/gcov.exp
@@ -424,9 +424,7 @@ proc run-gcov { args } {
      }
      if { $tfailed > 0 } {
  	fail "$testname gcov: $lfailed failures in line counts, $bfailed in branch percentages, $cfailed in return percentages, $ifailed in intermediate format"
-	if { $xfailed } {
-	    clean-gcov $testcase
-	}
+	clean-gcov $testcase
      } else {
  	pass "$testname gcov"
  	clean-gcov $testcase
