This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp] Fix find_outermost_region_in_block (PR middle-end/26823)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, Diego Novillo <dnovillo at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 13 Apr 2006 10:02:29 -0400
- Subject: [gomp] Fix find_outermost_region_in_block (PR middle-end/26823)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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