Index: gcc/tree-ssa-tail-merge.c
===================================================================
--- gcc/tree-ssa-tail-merge.c (revision 183325)
+++ gcc/tree-ssa-tail-merge.c (working copy)
@@ -269,6 +269,88 @@ struct aux_bb_info
 #define BB_VOP_AT_EXIT(bb) (((struct aux_bb_info *)bb->aux)->vop_at_exit)
 #define BB_DEP_BB(bb) (((struct aux_bb_info *)bb->aux)->dep_bb)
 
+/* Returns whether VAL is used in the same bb as in which it is defined, or
+   in the phi of a successor bb.  */
+
+static bool
+local_def (tree val)
+{
+  gimple stmt, def_stmt;
+  basic_block bb, def_bb;
+  imm_use_iterator iter;
+  bool res;
+
+  if (TREE_CODE (val) != SSA_NAME)
+    return false;
+  def_stmt = SSA_NAME_DEF_STMT (val);
+  def_bb = gimple_bb (def_stmt);
+
+  res = true;
+  FOR_EACH_IMM_USE_STMT (stmt, iter, val)
+    {
+      bb = gimple_bb (stmt);
+      if (bb == def_bb)
+	continue;
+      if (gimple_code (stmt) == GIMPLE_PHI
+	  && find_edge (def_bb, bb))
+	continue;
+      res = false;
+      BREAK_FROM_IMM_USE_STMT (iter);
+    }
+  return res;
+}
+
+/* Returns true if the only effect a statement STMT has, is too define a locally
+   used SSA_NAME.  */
+
+static bool
+stmt_local_def (gimple stmt)
+{
+  if (gimple_has_lhs (stmt)
+      && local_def (gimple_get_lhs (stmt))
+      && !gimple_has_side_effects (stmt))
+    return true;
+
+  return false;
+}     
+
+/* Let GSI skip forwards over local defs, forward if FORWARD or backwards.  */
+
+static void
+gsi_advance_nondebug_nonlocal (gimple_stmt_iterator *gsi, bool forward)
+{
+  gimple stmt;
+
+  while (true)
+    {
+      if (gsi_end_p (*gsi))
+	return;
+      stmt = gsi_stmt (*gsi);
+      if (!stmt_local_def (stmt))
+	return;
+      if (forward)
+	gsi_next_nondebug (gsi);
+      else
+	gsi_prev_nondebug (gsi);	
+    }
+}
+
+/* Let GSI skip forwards over local defs.  */
+
+static void
+gsi_advance_fw_nondebug_nonlocal (gimple_stmt_iterator *gsi)
+{
+  gsi_advance_nondebug_nonlocal (gsi, true);
+}
+
+/* Let GSI skip backwards over local defs.  */
+
+static void
+gsi_advance_bw_nondebug_nonlocal (gimple_stmt_iterator *gsi)
+{
+  gsi_advance_nondebug_nonlocal (gsi, false);
+}
+
 /* VAL1 and VAL2 are either:
    - uses in BB1 and BB2, or
    - phi alternatives for BB1 and BB2.
@@ -352,37 +434,6 @@ stmt_update_dep_bb (gimple stmt)
     update_dep_bb (gimple_bb (stmt), USE_FROM_PTR (use));
 }
 
-/* Returns whether VAL is used in the same bb as in which it is defined, or
-   in the phi of a successor bb.  */
-
-static bool
-local_def (tree val)
-{
-  gimple stmt, def_stmt;
-  basic_block bb, def_bb;
-  imm_use_iterator iter;
-  bool res;
-
-  if (TREE_CODE (val) != SSA_NAME)
-    return false;
-  def_stmt = SSA_NAME_DEF_STMT (val);
-  def_bb = gimple_bb (def_stmt);
-
-  res = true;
-  FOR_EACH_IMM_USE_STMT (stmt, iter, val)
-    {
-      bb = gimple_bb (stmt);
-      if (bb == def_bb)
-	continue;
-      if (gimple_code (stmt) == GIMPLE_PHI
-	  && find_edge (def_bb, bb))
-	continue;
-      res = false;
-      BREAK_FROM_IMM_USE_STMT (iter);
-    }
-  return res;
-}
-
 /* Calculates hash value for same_succ VE.  */
 
 static hashval_t
@@ -406,8 +457,7 @@ same_succ_hash (const void *ve)
     {
       stmt = gsi_stmt (gsi);
       stmt_update_dep_bb (stmt);
-      if (is_gimple_assign (stmt) && local_def (gimple_get_lhs (stmt))
-	  && !gimple_has_side_effects (stmt))
+      if (stmt_local_def (stmt))
 	continue;
       size++;
 
@@ -523,6 +573,8 @@ same_succ_equal (const void *ve1, const
 
   gsi1 = gsi_start_nondebug_bb (bb1);
   gsi2 = gsi_start_nondebug_bb (bb2);
+  gsi_advance_fw_nondebug_nonlocal (&gsi1);
+  gsi_advance_fw_nondebug_nonlocal (&gsi2);
   while (!(gsi_end_p (gsi1) || gsi_end_p (gsi2)))
     {
       s1 = gsi_stmt (gsi1);
@@ -533,6 +585,8 @@ same_succ_equal (const void *ve1, const
 	return 0;
       gsi_next_nondebug (&gsi1);
       gsi_next_nondebug (&gsi2);
+      gsi_advance_fw_nondebug_nonlocal (&gsi1);
+      gsi_advance_fw_nondebug_nonlocal (&gsi2);
     }
 
   return 1;
@@ -1121,25 +1175,6 @@ gimple_equal_p (same_succ same_succ, gim
     }
 }
 
-/* Let GSI skip backwards over local defs.  */
-
-static void
-gsi_advance_bw_nondebug_nonlocal (gimple_stmt_iterator *gsi)
-{
-  gimple stmt;
-
-  while (true)
-    {
-      if (gsi_end_p (*gsi))
-	return;
-      stmt = gsi_stmt (*gsi);
-      if (!(is_gimple_assign (stmt) && local_def (gimple_get_lhs (stmt))
-	    && !gimple_has_side_effects (stmt)))
-	return;
-      gsi_prev_nondebug (gsi);
-    }
-}
-
 /* Determines whether BB1 and BB2 (members of same_succ) are duplicates.  If so,
    clusters them.  */
 
Index: gcc/testsuite/gcc.dg/pr51879-12.c
===================================================================
--- /dev/null (new file)
+++ gcc/testsuite/gcc.dg/pr51879-12.c (revision 0)
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre" } */
+
+__attribute__((pure)) int bar (int);
+__attribute__((pure)) int bar2 (int);
+void baz (int);
+
+int x, z;
+
+void
+foo (int y)
+{
+  int a = 0;
+  if (y == 6)
+    {
+      a += bar (7);
+      a += bar2 (6);
+    }
+  else
+    {
+      a += bar2 (6);
+      a += bar (7);
+    }
+  baz (a);
+}
+
+/* { dg-final { scan-tree-dump-times "bar \\(" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "bar2 \\(" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
