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]

[gomp] Fix find_outermost_region_in_block (PR middle-end/26823)


Hi!

On the attached testcases, there are two (resp. 3) separate EH regions
which have a common outer region (the OpenMP maybe_catch_exception
region).
Say    A [ maybe_catch_exception region ]
      / \
     B   C [ 2 inner regions ]
But, given that there are no statements that are only in
the A region except those in the B resp. C regions
and find_outermost_region_in_block only ever returns what
lookup_stmt_eh_region_fn returned for some statement in the SESE
basic-blocks, find_outermost_region_in_block computes B as the
outermost region.  That's obviously incorrect and soon after this
we ICE or segfault, when we attempt to work with statements in the
C region (since we assume it was duplicated, but it was not).

The following patch fixes this by creating a new function in except.c
that finds the outermost region (find_outermost_region_in_block
assumes there is one and as OpenMP is the only user of
move_sese_region_to_fn that should be correct assumption).

Tested with make check RUNTESTFLAGS=gomp.exp and make check-target-libgomp
on x86_64-linux, ok for trunk?

2006-04-13  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/26823
	* except.h (eh_region_outermost): New prototype.
	* except.c (eh_region_outermost): New function.
	* tree-cfg.c (find_outermost_region_in_block): Use it.

	* g++.dg/gomp/pr26823-1.C: New test.
	* g++.dg/gomp/pr26823-2.C: New test.

--- gcc/except.h.jj	2006-03-24 17:07:23.000000000 +0100
+++ gcc/except.h	2006-04-13 15:24:47.000000000 +0200
@@ -108,6 +108,7 @@ extern void expand_resx_expr (tree);
 extern void verify_eh_tree (struct function *);
 extern void dump_eh_tree (FILE *, struct function *);
 extern bool eh_region_outer_p (struct function *, int, int);
+extern int eh_region_outermost (struct function *, int, int);
 
 /* tree-eh.c */
 extern void add_stmt_to_eh_region_fn (struct function *, tree, int);
--- gcc/tree-cfg.c.jj	2006-04-01 13:14:58.000000000 +0200
+++ gcc/tree-cfg.c	2006-04-13 15:38:15.000000000 +0200
@@ -4733,9 +4733,16 @@ find_outermost_region_in_block (struct f
       int stmt_region;
 
       stmt_region = lookup_stmt_eh_region_fn (src_cfun, stmt);
-      if (stmt_region > 0
-	  && (region < 0 || eh_region_outer_p (src_cfun, stmt_region, region)))
-	region = stmt_region;
+      if (stmt_region > 0)
+	{
+	  if (region < 0)
+	    region = stmt_region;
+	  else if (stmt_region != region)
+	    {
+	      region = eh_region_outermost (src_cfun, stmt_region, region);
+	      gcc_assert (region != -1);
+	    }
+	}
     }
 
   return region;
--- gcc/except.c.jj	2006-04-10 13:54:18.000000000 +0200
+++ gcc/except.c	2006-04-13 15:35:53.000000000 +0200
@@ -1078,6 +1078,48 @@ eh_region_outer_p (struct function *ifun
 
   return false;
 }
+
+/* Return region number of region that is outer to both if REGION_A and
+   REGION_B in IFUN.  */
+
+int
+eh_region_outermost (struct function *ifun, int region_a, int region_b)
+{
+  struct eh_region *rp_a, *rp_b;
+  sbitmap b_outer;
+
+  gcc_assert (ifun->eh->last_region_number > 0);
+  gcc_assert (ifun->eh->region_tree);
+
+  rp_a = VEC_index (eh_region, ifun->eh->region_array, region_a);
+  rp_b = VEC_index (eh_region, ifun->eh->region_array, region_b);
+  gcc_assert (rp_a != NULL);
+  gcc_assert (rp_b != NULL);
+
+  b_outer = sbitmap_alloc (ifun->eh->last_region_number + 1);
+  sbitmap_zero (b_outer);
+
+  do
+    {
+      SET_BIT (b_outer, rp_b->region_number);
+      rp_b = rp_b->outer;
+    }
+  while (rp_b);
+
+  do
+    {
+      if (TEST_BIT (b_outer, rp_a->region_number))
+	{
+	  sbitmap_free (b_outer);
+	  return rp_a->region_number;
+	}
+      rp_a = rp_a->outer;
+    }
+  while (rp_a);
+
+  sbitmap_free (b_outer);
+  return -1;
+}
 
 static int
 t2r_eq (const void *pentry, const void *pdata)
--- gcc/testsuite/g++.dg/gomp/pr26823-1.C.jj	2006-04-13 15:42:27.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr26823-1.C	2006-04-13 15:42:15.000000000 +0200
@@ -0,0 +1,23 @@
+// PR middle-end/26823
+// { dg-do compile }
+
+struct A
+{
+  ~A () {}
+};
+
+struct B
+{
+  A a;
+  B ();
+};
+
+void
+foo ()
+{
+#pragma omp parallel
+  {
+    B b[1];
+    new int;
+  }
+}
--- gcc/testsuite/g++.dg/gomp/pr26823-2.C.jj	2006-04-13 15:42:35.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr26823-2.C	2006-04-13 15:43:05.000000000 +0200
@@ -0,0 +1,29 @@
+// PR middle-end/26823
+// { dg-do compile }
+
+struct A
+{
+  ~A () {}
+};
+
+extern void bar ();
+
+void
+foo ()
+{
+#pragma omp parallel
+  {
+    {
+      A a;
+      bar ();
+    }
+    {
+      A a;
+      bar ();
+    }
+    {
+      A a;
+      bar ();
+    }
+  }
+}

	Jakub


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