[PATCH] CSE path following fixes for non-call exceptions

Steven Bosscher stevenb.gcc@gmail.com
Sun Dec 17 18:14:00 GMT 2006


After this fix, I've addressed all the problems that I'm aware of
with the CSE path following changes.

This patch should fix the Ada failure.  I've chosen to clean up
dead EH edges from cse_extended_basic_block, because, as Eric said,
it's quite likely that there are still some other cases in cse_insn
where we should purge dead edges but don't.  This way, we play safe
and I suppose it's not too ugly...

I removed purge_all_dead_edges asserts from rest_of_handle_cse{,2}
because we can now be fairly sure that we remove all dead edges in
cse_extended_basic_block.  Any remaining cfg problems will still be
caught in verify_flow_info.

Bootstrapped all including java and ada on x86_64-suse-linux-gnu.
For acats I now get:

                === acats Summary ===
# of expected passes            2313
# of unexpected failures        2
*** FAILURES: cdd2a02 cxh1001

I have no reference results, but this looks pretty good to me.

OK for the trunk?


	* cse.c (have_eh_succ_edges): New function.
	(cse_insn): Don't remove dead EH edges here
	(cse_extended_basic_block): Do it here.
	(rest_of_handle_cse, rest_of_handle_cse2): Don't assert
	that we have removed all dead edges.

Index: cse.c
--- cse.c	(revision 119985)
+++ cse.c	(working copy)
@@ -4858,13 +4858,6 @@ cse_insn (rtx insn, rtx libcall_insn)
 	      validate_change (insn, &SET_SRC (sets[i].rtl), new, 1);
 	      apply_change_group ();
-	      /* With non-call exceptions, if this was an insn that could
-		 trap, we may have made it non-throwing now.  For example
-		 we may have replaced a load with a register.  */
-	      if (flag_non_call_exceptions
-		  && insn == BB_END (BLOCK_FOR_INSN (insn)))
-		purge_dead_edges (BLOCK_FOR_INSN (insn));
@@ -5939,6 +5932,22 @@ cse_dump_path (struct cse_basic_block_da

+/* Return true if BB has exception handling successor edges.  */
+static bool
+have_eh_succ_edges (basic_block bb)
+  edge e;
+  edge_iterator ei;
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    if (e->flags & EDGE_EH)
+      return true;
+  return false;

 /* Scan to the end of the path described by DATA.  Return an estimate of
    the total number of SETs, and the lowest and highest insn CUID, of all
    insns in the path.  */
@@ -6109,6 +6118,12 @@ cse_extended_basic_block (struct cse_bas
       /* Make sure that libcalls don't span multiple basic blocks.  */
       gcc_assert (libcall_insn == NULL_RTX);
+      /* With non-call exceptions, we are not always able to update
+	 the CFG properly inside cse_insn.  So clean up possibly
+	 redundant EH edges here.  */
+      if (flag_non_call_exceptions && have_eh_succ_edges (bb))
+	purge_dead_edges (bb);
       /* If we changed a conditional jump, we may have terminated
 	 the path we are following.  Check that by verifying that
 	 the edge we would take still exists.  If the edge does
@@ -6988,10 +7003,6 @@ rest_of_handle_cse (void)
      expecting CSE to be run.  But always rerun it in a cheap mode.  */
   cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
-  /* If there are dead edges to purge, we haven't properly updated
-     the CFG incrementally.  */
-  gcc_assert (!purge_all_dead_edges ());
   if (tem)
     rebuild_jump_labels (get_insns ());
@@ -7044,10 +7055,6 @@ rest_of_handle_cse2 (void)
      bypassed safely.  */
   cse_condition_code_reg ();
-  /* If there are dead edges to purge, we haven't properly updated
-     the CFG incrementally.  */
-  gcc_assert (!purge_all_dead_edges ());
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
   if (tem)

More information about the Gcc-patches mailing list