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] Call purge_dead_edges when needed in fwprop (PR rtl-optimization/47366)


Hi!

This testcase ICEs during checking, because fwprop turned
a MEM that was conservatively considered to potentially trap
(-fnon-call-exceptions) into one that clearly can't trap (frame based),
but doesn't clean up the EH edges for it, and then DSE removes
the dead stores and doesn't think about EH cleanup because
frame based stores (or any other that can be DSEd) really shouldn't
ever trap.

Fixed by calling purge_dead_edges in fwprop.  Bootstrapped/regtested on
x86_64-linux and i686-linux, ok for trunk?

2011-01-20  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/47366
	* fwprop.c (forward_propagate_into): Return bool.  If
	any changes are made, -fnon-call-exceptions is used and
	REG_EH_REGION note is present, call purge_dead_edges
	and return true if it purged anything.
	(fwprop_addr): Adjust callers, call cleanup_cfg (0) if
	any EH edges were purged.

	* g++.dg/opt/pr47366.C: New test.

--- gcc/fwprop.c.jj	2010-12-02 11:51:31.000000000 +0100
+++ gcc/fwprop.c	2011-01-20 13:48:25.000000000 +0100
@@ -1315,9 +1315,10 @@ forward_propagate_and_simplify (df_ref u
 
 
 /* Given a use USE of an insn, if it has a single reaching
-   definition, try to forward propagate it into that insn.  */
+   definition, try to forward propagate it into that insn.
+   Return true if cfg cleanup will be needed.  */
 
-static void
+static bool
 forward_propagate_into (df_ref use)
 {
   df_ref def;
@@ -1325,22 +1326,22 @@ forward_propagate_into (df_ref use)
   rtx parent;
 
   if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
-    return;
+    return false;
   if (DF_REF_IS_ARTIFICIAL (use))
-    return;
+    return false;
 
   /* Only consider uses that have a single definition.  */
   def = get_def_for_use (use);
   if (!def)
-    return;
+    return false;
   if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
-    return;
+    return false;
   if (DF_REF_IS_ARTIFICIAL (def))
-    return;
+    return false;
 
   /* Do not propagate loop invariant definitions inside the loop.  */
   if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father)
-    return;
+    return false;
 
   /* Check if the use is still present in the insn!  */
   use_insn = DF_REF_INSN (use);
@@ -1350,19 +1351,26 @@ forward_propagate_into (df_ref use)
     parent = PATTERN (use_insn);
 
   if (!reg_mentioned_p (DF_REF_REG (use), parent))
-    return;
+    return false;
 
   def_insn = DF_REF_INSN (def);
   if (multiple_sets (def_insn))
-    return;
+    return false;
   def_set = single_set (def_insn);
   if (!def_set)
-    return;
+    return false;
 
   /* Only try one kind of propagation.  If two are possible, we'll
      do it on the following iterations.  */
-  if (!forward_propagate_and_simplify (use, def_insn, def_set))
-    forward_propagate_subreg (use, def_insn, def_set);
+  if (forward_propagate_and_simplify (use, def_insn, def_set)
+      || forward_propagate_subreg (use, def_insn, def_set))
+    {
+      if (cfun->can_throw_non_call_exceptions
+	  && find_reg_note (use_insn, REG_EH_REGION, NULL_RTX)
+	  && purge_dead_edges (DF_REF_BB (use)))
+	return true;
+    }
+  return false;
 }
 
 
@@ -1421,6 +1429,7 @@ static unsigned int
 fwprop (void)
 {
   unsigned i;
+  bool need_cleanup = false;
 
   fwprop_init ();
 
@@ -1438,10 +1447,12 @@ fwprop (void)
 	    || DF_REF_BB (use)->loop_father == NULL
 	    /* The outer most loop is not really a loop.  */
 	    || loop_outer (DF_REF_BB (use)->loop_father) == NULL)
-	  forward_propagate_into (use);
+	  need_cleanup |= forward_propagate_into (use);
     }
 
   fwprop_done ();
+  if (need_cleanup)
+    cleanup_cfg (0);
   return 0;
 }
 
@@ -1469,6 +1480,8 @@ static unsigned int
 fwprop_addr (void)
 {
   unsigned i;
+  bool need_cleanup = false;
+
   fwprop_init ();
 
   /* Go through all the uses.  df_uses_create will create new ones at the
@@ -1481,11 +1494,13 @@ fwprop_addr (void)
 	    && DF_REF_BB (use)->loop_father != NULL
 	    /* The outer most loop is not really a loop.  */
 	    && loop_outer (DF_REF_BB (use)->loop_father) != NULL)
-	  forward_propagate_into (use);
+	  need_cleanup |= forward_propagate_into (use);
     }
 
   fwprop_done ();
 
+  if (need_cleanup)
+    cleanup_cfg (0);
   return 0;
 }
 
--- gcc/testsuite/g++.dg/opt/pr47366.C.jj	2011-01-20 13:51:25.000000000 +0100
+++ gcc/testsuite/g++.dg/opt/pr47366.C	2011-01-20 13:51:01.000000000 +0100
@@ -0,0 +1,22 @@
+// PR rtl-optimization/47366
+// { dg-do compile }
+// { dg-options "-O -fnon-call-exceptions -fno-tree-ccp -fno-tree-forwprop" }
+
+struct A
+{
+  int i;
+  virtual ~A ();
+};
+
+struct B : virtual A
+{};
+
+struct C : B
+{
+  void bar () {}
+};
+
+void foo ()
+{
+  C ().bar ();
+}

	Jakub


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