public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix PR tree-optimization/17724
@ 2004-10-07 20:13 Jakub Jelinek
  2004-10-07 22:16 ` Kazu Hirata
  2004-10-08 23:48 ` Diego Novillo
  0 siblings, 2 replies; 9+ messages in thread
From: Jakub Jelinek @ 2004-10-07 20:13 UTC (permalink / raw)
  To: Richard Henderson, Diego Novillo; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1900 bytes --]

Hi!

The fold_all_builtin patch to gimplify results of ccp_fold_builtin
uncovered what it seems to be a latent problem - some basic block removals
don't recompute dominators of their neighbouring basic blocks.
Particularly in one of the attached testcases bb1->bb3, bb1->bb4 and
bb3->bb4 are EH edges:
         +---+
         |bb0|
         +---+
          / \
        /    \
       /      \
      v        v
    +---+    +---+
    |bb1|--->|bb2|
    +---+    +---+
     / \       |
    /   \      |
   /     \     |
  v       v    |
+---+   +---+  |
|bb3|-->|bb4|  |
+---+   +---+  |
  \            |
   \         +---+
    -------->|bb5|
             +---+
               |
              ---
               -
strcpy which due to the missing throw () in the testcase can throw
is replaced by code that can't throw, thus the EH edges are removed
(by tree_purge_dead_eh_edges) and in the end cleanup_tree_cfg
kicks in.  This in turn calls delete_unreachable_blocks that deletes
bb3 and bb4 basic blocks.
The problem is that immediate dominator of bb5 before all of this was
bb0, but after bb3 and bb4 basic blocks are removed, immediate dominator
is bb2; there is nothing that updates the dominator info of bb5 though.

Attached are 3 patches, first and third patch were bootstrapped and
regtested on i386-redhat-linux, the second one doesn't work but is
included for completeness what I tried.

The first patch calls free_dominance_info in cleanup_tree_cfg whenever
delete_unreachable_blocks deleted some basic blocks.  It should be safe, but
might be expensive.

The second patch tried to recompute dominators in a routine called
from delete_basic_block, but apparently some callers of delete_basic_block
don't expect the recomputation.

The third one recomputes dominators (and post-dominators) of neighbours
of unreachable basic blocks after they are deleted by
delete_unreachable_blocks.

	Jakub

[-- Attachment #2: delete-unreachable-blocks1.patch --]
[-- Type: text/plain, Size: 5463 bytes --]

2004-10-07  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/17724
	* tree-cfg.c (tree_purge_dead_eh_edges): Recompute dominator for the
	EH block.
	(cleanup_tree_cfg): Free dominators if any delete_unreachable_blocks
	deleted some basic block.

	* g++.dg/opt/pr17724-1.C: New test.
	* g++.dg/opt/pr17724-2.C: New test.
	* g++.dg/opt/pr17724-3.C: New test.
	* g++.dg/opt/pr17724-4.C: New test.
	* g++.dg/opt/pr17724-5.C: New test.
	* g++.dg/opt/pr17724-6.C: New test.

--- gcc/tree-cfg.c.jj	2004-10-02 10:46:07.000000000 +0200
+++ gcc/tree-cfg.c	2004-10-02 11:19:53.042030301 +0200
@@ -713,11 +713,13 @@ bool
 cleanup_tree_cfg (void)
 {
-  bool retval = false;
+  bool retval;
+  bool blocks_deleted;
 
   timevar_push (TV_TREE_CLEANUP_CFG);
 
   retval = cleanup_control_flow ();
-  retval |= delete_unreachable_blocks ();
+  blocks_deleted = delete_unreachable_blocks ();
+  retval |= blocks_deleted;
 
   /* thread_jumps() sometimes leaves further transformation
      opportunities for itself, so iterate on it until nothing
@@ -743,6 +745,13 @@ cleanup_tree_cfg (void)
     }
 #endif
 
+  /* If blocks were deleted, the dominance info might be outdated.  */
+  if (blocks_deleted)
+    {
+      free_dominance_info (CDI_DOMINATORS);
+      free_dominance_info (CDI_POST_DOMINATORS);
+    }
+
   /* Merging the blocks creates no new opportunities for the other
      optimizations, so do it here.  */
   merge_seq_blocks ();
@@ -5089,7 +5098,11 @@ tree_purge_dead_eh_edges (basic_block bb
     {
       if (e->flags & EDGE_EH)
 	{
+	  basic_block dest = e->dest, dom;
+
 	  ssa_remove_edge (e);
+	  dom = recount_dominator (CDI_DOMINATORS, dest);
+	  set_immediate_dominator (CDI_DOMINATORS, dest, dom);
 	  changed = true;
 	}
       else
--- gcc/testsuite/g++.dg/opt/pr17724-4.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-4.C	2004-10-02 11:29:21.803990546 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "C" char *strcpy (char* d, const char* s);
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-6.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-6.C	2004-10-02 11:28:39.000000000 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern char *strcpy (char* d, const char* s);
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-1.C.jj	2004-10-02 11:13:45.797278812 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-1.C	2004-10-02 11:13:45.797278812 +0200
@@ -0,0 +1,23 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+namespace N { char *strcpy (char *, const char *); }
+extern "C" char *strcpy (char *, const char *) throw ();
+inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); }
+
+struct S { ~S (); };
+int foo ();
+
+int
+main ()
+{
+  S s;
+  int a;
+  char b[64];
+  N::strcpy (b, "ABCDEFGHIJKLM");
+  while ((a = foo ()) != -1)
+    if (a)
+      return -1;
+  return 0;
+}
--- gcc/testsuite/g++.dg/opt/pr17724-2.C.jj	2004-10-02 11:13:45.797278812 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-2.C	2004-10-02 11:13:45.797278812 +0200
@@ -0,0 +1,23 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+namespace N { char *strcpy (char *, const char *); }
+extern "C" char *strcpy (char *, const char *);
+inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); }
+
+struct S { ~S (); };
+int foo ();
+
+int
+main ()
+{
+  S s;
+  int a;
+  char b[64];
+  N::strcpy (b, "ABCDEFGHIJKLM");
+  while ((a = foo ()) != -1)
+    if (a)
+      return -1;
+  return 0;
+}
--- gcc/testsuite/g++.dg/opt/pr17724-3.C.jj	2004-10-02 11:27:29.650919752 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-3.C	2004-10-02 11:29:13.933389195 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "C" char *strcpy (char* d, const char* s) throw ();
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-5.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-5.C	2004-10-02 11:29:29.275662780 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern char *strcpy (char* d, const char* s) throw ();
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}

[-- Attachment #3: delete-unreachable-blocks2.patch --]
[-- Type: text/plain, Size: 5738 bytes --]

2004-10-07  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/17724
	* tree-cfg.c (tree_purge_dead_eh_edges): Recompute dominator for the
	EH block.
	(remove_phi_nodes_and_edges_for_unreachab): Recompute dominators
	and post-dominators for predecessors and successors.

	* g++.dg/opt/pr17724-1.C: New test.
	* g++.dg/opt/pr17724-2.C: New test.
	* g++.dg/opt/pr17724-3.C: New test.
	* g++.dg/opt/pr17724-4.C: New test.
	* g++.dg/opt/pr17724-5.C: New test.
	* g++.dg/opt/pr17724-6.C: New test.

--- gcc/tree-cfg.c	2004-10-02 11:19:53.042030301 +0200
+++ gcc/tree-cfg.c	2004-10-02 23:17:12.229321933 +0200
@@ -1784,6 +1784,8 @@
 remove_phi_nodes_and_edges_for_unreachable_block (basic_block bb)
 {
   tree phi;
+  basic_block *succs = NULL;
+  int nsuccs = 0;
 
   /* Since this block is no longer reachable, we can just delete all
      of its PHI nodes.  */
@@ -1795,9 +1797,32 @@
       phi = next;
     }
 
+  if (dom_computed[CDI_DOMINATORS])
+    succs = xmalloc (sizeof (basic_block *) * EDGE_COUNT (bb->succs));
+
   /* Remove edges to BB's successors.  */
   while (EDGE_COUNT (bb->succs) > 0)
-    ssa_remove_edge (EDGE_SUCC (bb, 0));
+    {
+      if (succs != NULL
+	  && EDGE_SUCC (bb, 0)->dest != bb
+	  && EDGE_COUNT (EDGE_SUCC (bb, 0)->dest->preds) > 1)
+	succs[nsuccs++] = EDGE_SUCC (bb, 0)->dest;
+      ssa_remove_edge (EDGE_SUCC (bb, 0));
+    }
+
+  if (succs)
+    {
+      int i;
+
+      for (i = 0; i < nsuccs; ++i)
+	{
+	  basic_block dom = recount_dominator (CDI_DOMINATORS, succs[i]);
+
+	  if (dom != get_immediate_dominator (CDI_DOMINATORS, succs[i]))
+	    set_immediate_dominator (CDI_DOMINATORS, succs[i], dom);
+	}
+      free (succs);
+    }
 }
 
 
@@ -5089,7 +5114,12 @@
     {
       if (e->flags & EDGE_EH)
 	{
+	  basic_block dest = e->dest, dom;
+
 	  ssa_remove_edge (e);
+	  dom = recount_dominator (CDI_DOMINATORS, dest);
+	  if (dom != get_immediate_dominator (CDI_DOMINATORS, dest))
+	    set_immediate_dominator (CDI_DOMINATORS, dest, dom);
 	  changed = true;
 	}
       else
--- gcc/testsuite/g++.dg/opt/pr17724-4.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-4.C	2004-10-02 11:29:21.803990546 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "C" char *strcpy (char* d, const char* s);
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-6.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-6.C	2004-10-02 11:28:39.000000000 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern char *strcpy (char* d, const char* s);
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-1.C.jj	2004-10-02 11:13:45.797278812 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-1.C	2004-10-02 11:13:45.797278812 +0200
@@ -0,0 +1,23 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+namespace N { char *strcpy (char *, const char *); }
+extern "C" char *strcpy (char *, const char *) throw ();
+inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); }
+
+struct S { ~S (); };
+int foo ();
+
+int
+main ()
+{
+  S s;
+  int a;
+  char b[64];
+  N::strcpy (b, "ABCDEFGHIJKLM");
+  while ((a = foo ()) != -1)
+    if (a)
+      return -1;
+  return 0;
+}
--- gcc/testsuite/g++.dg/opt/pr17724-2.C.jj	2004-10-02 11:13:45.797278812 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-2.C	2004-10-02 11:13:45.797278812 +0200
@@ -0,0 +1,23 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+namespace N { char *strcpy (char *, const char *); }
+extern "C" char *strcpy (char *, const char *);
+inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); }
+
+struct S { ~S (); };
+int foo ();
+
+int
+main ()
+{
+  S s;
+  int a;
+  char b[64];
+  N::strcpy (b, "ABCDEFGHIJKLM");
+  while ((a = foo ()) != -1)
+    if (a)
+      return -1;
+  return 0;
+}
--- gcc/testsuite/g++.dg/opt/pr17724-3.C.jj	2004-10-02 11:27:29.650919752 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-3.C	2004-10-02 11:29:13.933389195 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "C" char *strcpy (char* d, const char* s) throw ();
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-5.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-5.C	2004-10-02 11:29:29.275662780 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern char *strcpy (char* d, const char* s) throw ();
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}

[-- Attachment #4: delete-unreachable-blocks3.patch --]
[-- Type: text/plain, Size: 7084 bytes --]

2004-10-07  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/17724
	* tree-cfg.c (tree_purge_dead_eh_edges): Recompute dominator for the
	EH block.
	(cleanup_tree_cfg): Remove unnecessary retval initialization.
	* cfgcleanup.c (delete_unreachable_blocks): Recompute dominators
	and post-dominators for predecessors and successors of deleted
	unreachable basic blocks.

	* g++.dg/opt/pr17724-1.C: New test.
	* g++.dg/opt/pr17724-2.C: New test.
	* g++.dg/opt/pr17724-3.C: New test.
	* g++.dg/opt/pr17724-4.C: New test.
	* g++.dg/opt/pr17724-5.C: New test.
	* g++.dg/opt/pr17724-6.C: New test.

--- gcc/cfgcleanup.c.jj	2004-09-28 04:19:43.000000000 -0400
+++ gcc/cfgcleanup.c	2004-10-07 12:30:11.000000000 -0400
@@ -2029,9 +2029,18 @@ delete_unreachable_blocks (void)
 {
   bool changed = false;
   basic_block b, next_bb;
+  basic_block *succs = NULL, *preds = NULL;
+  int nsuccs = 0, npreds = 0, i;
+  edge_iterator ei;
+  edge e;
 
   find_unreachable_blocks ();
 
+  if (dom_computed[CDI_DOMINATORS])
+    succs = xmalloc (sizeof (basic_block *) * n_basic_blocks);
+  if (dom_computed[CDI_POST_DOMINATORS])
+    preds = xmalloc (sizeof (basic_block *) * n_basic_blocks);
+
   /* Delete all unreachable basic blocks.  */
 
   for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR; b = next_bb)
@@ -2040,6 +2049,22 @@ delete_unreachable_blocks (void)
 
       if (!(b->flags & BB_REACHABLE))
 	{
+	  if (succs)
+	    FOR_EACH_EDGE (e, ei, b->succs)
+	      if ((e->dest->flags & (BB_REACHABLE | BB_VISITED))
+	          == BB_REACHABLE)
+                {
+	          succs[nsuccs++] = e->dest;
+	          e->dest->flags |= BB_VISITED;
+                }
+	  if (preds)
+	    FOR_EACH_EDGE (e, ei, b->preds)
+	      if ((e->src->flags & (BB_REACHABLE | BB_VISITED))
+	          == BB_REACHABLE)
+                {
+	          preds[npreds++] = e->src;
+	          e->src->flags |= BB_VISITED;
+                }
 	  delete_basic_block (b);
 	  changed = true;
 	}
@@ -2047,6 +2072,33 @@ delete_unreachable_blocks (void)
 
   if (changed)
     tidy_fallthru_edges ();
+
+  if (succs)
+    {
+      for (i = 0; i < nsuccs; ++i)
+        {
+          basic_block dom = recount_dominator (CDI_DOMINATORS, succs[i]);
+
+          succs[i]->flags &= ~BB_VISITED;
+          if (dom != get_immediate_dominator (CDI_DOMINATORS, succs[i]))
+            set_immediate_dominator (CDI_DOMINATORS, succs[i], dom);
+        }
+      free (succs);        
+    }
+
+  if (preds)
+    {
+      for (i = 0; i < npreds; ++i)
+        {
+          basic_block dom = recount_dominator (CDI_POST_DOMINATORS, preds[i]);
+
+          preds[i]->flags &= ~BB_VISITED;
+          if (dom != get_immediate_dominator (CDI_POST_DOMINATORS, preds[i]))
+            set_immediate_dominator (CDI_POST_DOMINATORS, preds[i], dom);
+        }
+      free (preds);        
+    }
+
   return changed;
 }
 
--- gcc/tree-cfg.c.jj	2004-10-02 04:46:07.000000000 -0400
+++ gcc/tree-cfg.c	2004-10-07 12:28:44.000000000 -0400
@@ -5089,7 +5089,12 @@ tree_purge_dead_eh_edges (basic_block bb
     {
       if (e->flags & EDGE_EH)
 	{
+	  basic_block dest = e->dest, dom;
+
 	  ssa_remove_edge (e);
+	  dom = recount_dominator (CDI_DOMINATORS, dest);
+	  if (dom != get_immediate_dominator (CDI_DOMINATORS, dest))
+	    set_immediate_dominator (CDI_DOMINATORS, dest, dom);
 	  changed = true;
 	}
       else
--- gcc/testsuite/g++.dg/opt/pr17724-4.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-4.C	2004-10-02 11:29:21.803990546 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "C" char *strcpy (char* d, const char* s);
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-6.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-6.C	2004-10-02 11:28:39.000000000 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern char *strcpy (char* d, const char* s);
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-1.C.jj	2004-10-02 11:13:45.797278812 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-1.C	2004-10-02 11:13:45.797278812 +0200
@@ -0,0 +1,23 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+namespace N { char *strcpy (char *, const char *); }
+extern "C" char *strcpy (char *, const char *) throw ();
+inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); }
+
+struct S { ~S (); };
+int foo ();
+
+int
+main ()
+{
+  S s;
+  int a;
+  char b[64];
+  N::strcpy (b, "ABCDEFGHIJKLM");
+  while ((a = foo ()) != -1)
+    if (a)
+      return -1;
+  return 0;
+}
--- gcc/testsuite/g++.dg/opt/pr17724-2.C.jj	2004-10-02 11:13:45.797278812 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-2.C	2004-10-02 11:13:45.797278812 +0200
@@ -0,0 +1,23 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+namespace N { char *strcpy (char *, const char *); }
+extern "C" char *strcpy (char *, const char *);
+inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); }
+
+struct S { ~S (); };
+int foo ();
+
+int
+main ()
+{
+  S s;
+  int a;
+  char b[64];
+  N::strcpy (b, "ABCDEFGHIJKLM");
+  while ((a = foo ()) != -1)
+    if (a)
+      return -1;
+  return 0;
+}
--- gcc/testsuite/g++.dg/opt/pr17724-3.C.jj	2004-10-02 11:27:29.650919752 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-3.C	2004-10-02 11:29:13.933389195 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "C" char *strcpy (char* d, const char* s) throw ();
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}
--- gcc/testsuite/g++.dg/opt/pr17724-5.C.jj	2004-10-02 11:27:29.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-5.C	2004-10-02 11:29:29.275662780 +0200
@@ -0,0 +1,24 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern char *strcpy (char* d, const char* s) throw ();
+
+class A { public: A (); ~A (); };
+
+inline char * B (char *s, const char *t)
+{ return ::strcpy (s, t); }
+
+class C { int D (void); int E; };
+
+int C::D (void)
+{
+  A a;
+  try
+    {
+      char z[22];
+      if (this->E) B (z, "");
+      return 0;
+    }
+  catch (int &f) { return -1; }
+}

^ permalink raw reply	[flat|nested] 9+ messages in thread
[parent not found: <20041009082440.GB22455@atrey.karlin.mff.cuni.cz>]
* [PATCH] Fix PR tree-optimization/17724
@ 2004-09-30  1:05 Jakub Jelinek
  0 siblings, 0 replies; 9+ messages in thread
From: Jakub Jelinek @ 2004-09-30  1:05 UTC (permalink / raw)
  To: Diego Novillo; +Cc: gcc-patches

Hi!

This patch seems to fix the testcase (bootstrap/regtest still pending),
though I'm not sure if it is the right thing or the dominator should be
recomputed somewhere else (either at lower level, e.g. in remove_edge
or ssa_remove_edge, or in tree_purge_dead_eh_edges callers, or in
cleanup_tree_cfg).

2004-09-30  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/17724
	* tree-cfg.c (tree_purge_dead_eh_edges): Recompute dominator for the
	EH block.

	* g++.dg/opt/pr17724-1.C: New test.
	* g++.dg/opt/pr17724-2.C: New test.

--- gcc/tree-cfg.c.jj	2004-09-28 10:19:49.000000000 +0200
+++ gcc/tree-cfg.c	2004-09-30 00:16:27.722706542 +0200
@@ -5067,7 +5067,11 @@ tree_purge_dead_eh_edges (basic_block bb
     {
       if (e->flags & EDGE_EH)
 	{
+	  basic_block dest = e->dest, dom;
+
 	  ssa_remove_edge (e);
+	  dom = recount_dominator (CDI_DOMINATORS, dest);
+	  set_immediate_dominator (CDI_DOMINATORS, dest, dom);
 	  changed = true;
 	}
       else
--- gcc/testsuite/g++.dg/opt/pr17724-1.C.jj	2004-09-30 00:20:11.520994862 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-1.C	2004-09-30 00:20:24.014777890 +0200
@@ -0,0 +1,23 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+namespace N { char *strcpy (char *, const char *); }
+extern "C" char *strcpy (char *, const char *) throw ();
+inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); }
+
+struct S { ~S (); };
+int foo ();
+
+int
+main ()
+{
+  S s;
+  int a;
+  char b[64];
+  N::strcpy (b, "ABCDEFGHIJKLM");
+  while ((a = foo ()) != -1)
+    if (a)
+      return -1;
+  return 0;
+}
--- gcc/testsuite/g++.dg/opt/pr17724-2.C.jj	2004-09-30 00:20:11.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr17724-2.C	2004-09-30 00:20:04.000000000 +0200
@@ -0,0 +1,23 @@
+// PR tree-optimization/17724
+// { dg-do compile }
+// { dg-options "-O2" }
+
+namespace N { char *strcpy (char *, const char *); }
+extern "C" char *strcpy (char *, const char *);
+inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); }
+
+struct S { ~S (); };
+int foo ();
+
+int
+main ()
+{
+  S s;
+  int a;
+  char b[64];
+  N::strcpy (b, "ABCDEFGHIJKLM");
+  while ((a = foo ()) != -1)
+    if (a)
+      return -1;
+  return 0;
+}

	Jakub

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2004-10-09  9:00 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-07 20:13 [PATCH] Fix PR tree-optimization/17724 Jakub Jelinek
2004-10-07 22:16 ` Kazu Hirata
2004-10-08  7:05   ` Jakub Jelinek
2004-10-08 19:32     ` Jeffrey A Law
2004-10-08 20:25       ` Andrew Pinski
2004-10-08 23:48 ` Diego Novillo
2004-10-09  8:24   ` Zdenek Dvorak
     [not found] <20041009082440.GB22455@atrey.karlin.mff.cuni.cz>
2004-10-09  9:23 ` Zdenek Dvorak
  -- strict thread matches above, loose matches on Subject: below --
2004-09-30  1:05 Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).