This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Fix PR rtl-optimization/20017.


Hi,

Attached is a patch to fix PR rtl-optimization/20017, a fall-out from
one of my speed-up patches.

Consider the testcase.  Here is what happens.

1. CSE folds the switch statement into an unconditional jump (but does
   not remove the dead jump table).  This new unconditoinal jump
   happens to jump to the next block.  Since CFG clean up makes no
   change to CFG, it does not call delete_dead_jumptables.

2. When we go out of the CFG layout mode, the CFG layout code thinks
   that the basic block that ends with the unconditonal jump has an
   outgoing fall-through edge because it's a jump to the next block.

3. However, we have the dead jump table stuck between two adacent
   blocks.

4. rtl_verify_flow_info complains about this inconsistency and causes
   an ICE.

We have several options.

1. Revert my previous patch to remove delete_dead_jumptables and
   cleanup_cfg from the beginning of rest_of_handle_loop_optimize.

2. Run delete_dead_jumptables after every pass potentially changes a
   conditional jump to an unconditional one.

3. Run delete_dead_jumptables in cleanup_cfg regardless of whether we
   optimize CFG.

Solution 1 would only make this missed jump-table deletion opportunity
latent.  If we remove the old jump optimizer in 4.1, we would
presumably remove rest_of_handle_loop_optimize.  Then we wouldn't call
delete_jump_deadtables unconditonally, so a dead jump table could
possibly survive for a very long time.

Solution 2 isn't too bad, but we have so many RTL passes that still
discover constants and thus fold conditional jumps into unconditional
ones.  We would end up calling delete_dead_jumptables everywhere in
passes.c.

So I am going for the easiest solution, Solution 3.

Tested on i686-pc-linux-gnu.  OK to apply?

Kazu Hirata

2005-02-17  Kazu Hirata  <kazu@cs.umass.edu>

	PR rtl-optimization/20017.
	* cfgcleanup.c (cleanup_cfg): Call delete_dead_jumptables.

2005-02-17  Kazu Hirata  <kazu@cs.umass.edu>

	PR rtl-optimization/20017.
	* gcc.dg/pr20017.c: New.

Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgcleanup.c,v
retrieving revision 1.140
diff -u -d -p -r1.140 cfgcleanup.c
--- cfgcleanup.c	7 Feb 2005 15:53:25 -0000	1.140
+++ cfgcleanup.c	17 Feb 2005 03:34:10 -0000
@@ -2109,6 +2109,10 @@ cleanup_cfg (int mode)
 
   compact_blocks ();
 
+  /* Removing dead jump tables may create an opportunity for two
+     adjacent blocks to be merged.  */
+  delete_dead_jumptables ();
+
   while (try_optimize_cfg (mode))
     {
       delete_unreachable_blocks (), changed = true;
--- /dev/null	2005-02-18 20:13:08.537291064 -0500
+++ pr20017.c	2005-02-19 10:28:17.000000000 -0500
@@ -0,0 +1,40 @@
+/* PR rtl-optimization/20017
+
+   After CSE/GCSE folds a switch statement to an unconditonal jump,
+   cfg_cleanup did not remove a dead jump table, confusing the CFG
+   layout code later on.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=i386" } */
+
+int
+foo (int *buf, int *p)
+{
+  int result;
+  const int *tmp;
+
+  if (*buf)
+    return 1;
+
+  result = 2;
+  *buf = 2;
+  tmp = buf;
+  switch (*tmp)
+    {
+    case 3:
+    case 4:
+    case 6:
+    case 14:
+      return 1;
+
+    case 0:
+      result = *p;
+
+      /* Fall through.  */
+    default:
+      if (result)
+	return 1;
+    }
+
+  return 0;
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]