Hi! This is something that happened to work in 4.4 and earlier, before DECL_GIMPLE_FORMAL_TEMP_P removal. If use_pointer_for_field needs to return true because something is shared in a nested parallel and thus in-out wouldn't work, as each thread would have its own location, and that var isn't addressable, before DECL_GIMPLE_FORMAL_TEMP_P removal .omp_data_2.o.y = &y; would be gimplified as is and nothing complained about the missing TREE_ADDRESSABLE on y, supposedly because ompexp cleaned it up. But after that change, i.e. in 4.5+, the above is gimplified into y.3 = y; .omp_data_2.o.y = &y.3; and thus the inner parallel modifies a wrong variable. Fixed by treating it like the other case where we need to make the var addressable for tasks.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk and 4.6. 2011-07-29 Jakub Jelinek <ja...@redhat.com> PR middle-end/49897 PR middle-end/49898 * omp-low.c (use_pointer_for_field): If disallowing copy-in/out in nested parallel and outer is a gimple_reg, mark it as addressable and set its bit in task_shared_vars bitmap too. * testsuite/libgomp.c/pr49897-1.c: New test. * testsuite/libgomp.c/pr49897-2.c: New test. * testsuite/libgomp.c/pr49898-1.c: New test. * testsuite/libgomp.c/pr49898-2.c: New test. --- gcc/omp-low.c.jj 2011-07-21 09:54:49.000000000 +0200 +++ gcc/omp-low.c 2011-07-29 16:31:08.000000000 +0200 @@ -781,7 +781,7 @@ use_pointer_for_field (tree decl, omp_co break; if (c) - return true; + goto maybe_mark_addressable_and_ret; } } @@ -791,7 +791,9 @@ use_pointer_for_field (tree decl, omp_co returns, the task hasn't necessarily terminated. */ if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx)) { - tree outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx); + tree outer; + maybe_mark_addressable_and_ret: + outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx); if (is_gimple_reg (outer)) { /* Taking address of OUTER in lower_send_shared_vars --- libgomp/testsuite/libgomp.c/pr49897-1.c.jj 2011-07-29 17:03:07.000000000 +0200 +++ libgomp/testsuite/libgomp.c/pr49897-1.c 2011-07-29 17:00:23.000000000 +0200 @@ -0,0 +1,31 @@ +/* PR middle-end/49897 */ +/* { dg-do run } */ + +extern void abort (void); + +int +main () +{ + int i, j, x = 0, y, sum = 0; +#pragma omp parallel reduction(+:sum) + { + #pragma omp for firstprivate(x) lastprivate(x, y) + for (i = 0; i < 10; i++) + { + x = i; + y = 0; + #pragma omp parallel reduction(+:sum) + { + #pragma omp for firstprivate(y) lastprivate(y) + for (j = 0; j < 10; j++) + { + y = j; + sum += y; + } + } + } + } + if (x != 9 || y != 9 || sum != 450) + abort (); + return 0; +} --- libgomp/testsuite/libgomp.c/pr49897-2.c.jj 2011-07-29 17:03:07.000000000 +0200 +++ libgomp/testsuite/libgomp.c/pr49897-2.c 2011-07-29 17:00:07.000000000 +0200 @@ -0,0 +1,25 @@ +/* PR middle-end/49897 */ +/* { dg-do run } */ + +extern void abort (void); + +int +main () +{ + int i, j, x = 0, y, sum = 0; +#pragma omp parallel for reduction(+:sum) firstprivate(x) lastprivate(x, y) + for (i = 0; i < 10; i++) + { + x = i; + y = 0; + #pragma omp parallel for reduction(+:sum) firstprivate(y) lastprivate(y) + for (j = 0; j < 10; j++) + { + y = j; + sum += y; + } + } + if (x != 9 || y != 9 || sum != 450) + abort (); + return 0; +} --- libgomp/testsuite/libgomp.c/pr49898-1.c.jj 2011-07-29 17:03:07.000000000 +0200 +++ libgomp/testsuite/libgomp.c/pr49898-1.c 2011-07-29 17:01:44.000000000 +0200 @@ -0,0 +1,26 @@ +/* PR middle-end/49898 */ +/* { dg-do run } */ + +extern void abort (void); + +int +main () +{ + int i, j, sum = 0; +#pragma omp parallel + { + #pragma omp for reduction(+:sum) + for (i = 0; i < 10; i++) + { + #pragma omp parallel + { + #pragma omp for reduction(+:sum) + for (j = 0; j < 10; j++) + sum += j; + } + } + } + if (sum != 450) + abort (); + return 0; +} --- libgomp/testsuite/libgomp.c/pr49898-2.c.jj 2011-07-29 17:03:07.000000000 +0200 +++ libgomp/testsuite/libgomp.c/pr49898-2.c 2011-07-29 17:02:28.000000000 +0200 @@ -0,0 +1,18 @@ +/* PR middle-end/49898 */ +/* { dg-do run } */ + +extern void abort (void); + +int +main () +{ + int i, j, sum = 0; +#pragma omp parallel for reduction(+:sum) + for (i = 0; i < 10; i++) + #pragma omp parallel for reduction(+:sum) + for (j = 0; j < 10; j++) + sum += j; + if (sum != 450) + abort (); + return 0; +} Jakub