@@ -1075,6 +1075,38 @@ set_cluster (basic_block bb1, basic_block bb2)
gcc_unreachable ();
}
+/* Return true if tail-merge should refrain from merging STMT with another
+ stmt. */
+
+static bool
+gimple_dont_merge_p (gimple stmt)
+{
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_CALL:
+ /* Eventually, we'll significantly complicate the CFG by adding
+ back edges to properly model the effects of transaction restart.
+ For the bulk of optimization this does not matter, but what we
+ cannot recover from is tail merging blocks between two separate
+ transactions. Avoid that by making commit not match. */
+ if (gimple_call_builtin_p (stmt, BUILT_IN_TM_COMMIT))
+ return true;
+
+ /* We cannot tail-merge the builtins that end transactions.
+ ??? The alternative being unsharing of BBs in the tm_init pass. */
+ if (flag_tm
+ && (gimple_call_flags (stmt) & ECF_TM_BUILTIN)
+ && is_tm_ending_fndecl (gimple_call_fndecl (stmt)))
+ return true;
+
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
/* Return true if gimple statements S1 and S2 are equal. Gimple_bb (s1) and
gimple_bb (s2) are members of SAME_SUCC. */
@@ -1099,14 +1131,6 @@ gimple_equal_p (same_succ same_succ, gimple s1, gimple s2)
if (!gimple_call_same_target_p (s1, s2))
return false;
- /* Eventually, we'll significantly complicate the CFG by adding
- back edges to properly model the effects of transaction restart.
- For the bulk of optimization this does not matter, but what we
- cannot recover from is tail merging blocks between two separate
- transactions. Avoid that by making commit not match. */
- if (gimple_call_builtin_p (s1, BUILT_IN_TM_COMMIT))
- return false;
-
for (i = 0; i < gimple_call_num_args (s1); ++i)
{
t1 = gimple_call_arg (s1, i);
@@ -1220,15 +1244,15 @@ find_duplicate (same_succ same_succ, basic_block bb1, basic_block bb2)
gimple stmt1 = gsi_stmt (gsi1);
gimple stmt2 = gsi_stmt (gsi2);
- if (!gimple_equal_p (same_succ, stmt1, stmt2))
+ /* This should be tested also on local statements, but given the current
+ content of gimple_dont_merge_p, that's not necessary atm. What could
+ be better is to blacklist the bb containing the stmt, when encountering
+ the stmt f.i. in same_succ_hash. */
+ if (gimple_dont_merge_p (stmt1)
+ || gimple_dont_merge_p (stmt2))
return;
- // We cannot tail-merge the builtins that end transactions.
- // ??? The alternative being unsharing of BBs in the tm_init pass.
- if (flag_tm
- && is_gimple_call (stmt1)
- && (gimple_call_flags (stmt1) & ECF_TM_BUILTIN)
- && is_tm_ending_fndecl (gimple_call_fndecl (stmt1)))
+ if (!gimple_equal_p (same_succ, stmt1, stmt2))
return;
gsi_prev_nondebug (&gsi1);