This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix !$omp workshare (PR fortran/49792)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, fortran at gcc dot gnu dot org
- Date: Fri, 19 Aug 2011 15:32:47 +0200
- Subject: [PATCH] Fix !$omp workshare (PR fortran/49792)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
As the first testcase shows, if we need a temporary for array assignment,
we can't easily parallelize it (we'd have to emit the temporary allocation
into a OMP_SINGLE, then copyprivate the result to all the other threads, then
do the OMP_FOR and afterwards OMP_SINGLE again to free it).
Similarly, if for f03 we need lhs reallocation.
And lastly, if workshare has empty body, but no NOWAIT clause, we want to
emit a barrier.
Regtested on x86_64-linux, committed to trunk and 4.6 so far.
2011-08-19 Jakub Jelinek <jakub@redhat.com>
PR fortran/49792
* trans-expr.c (gfc_trans_assignment_1): Set OMPWS_SCALARIZER_WS
bit in ompws_flags only if loop.temp_ss is NULL, and clear it if
lhs needs reallocation.
* trans-openmp.c (gfc_trans_omp_workshare): Don't return early if
code is NULL, emit a barrier if workshare emitted no code at all
and NOWAIT clause isn't present.
* testsuite/libgomp.fortran/pr49792-1.f90: New test.
* testsuite/libgomp.fortran/pr49792-2.f90: New test.
--- gcc/fortran/trans-expr.c.jj 2011-07-27 23:25:33.000000000 +0200
+++ gcc/fortran/trans-expr.c 2011-08-19 14:12:46.000000000 +0200
@@ -6137,10 +6137,6 @@ gfc_trans_assignment_1 (gfc_expr * expr1
rss = NULL;
if (lss != gfc_ss_terminator)
{
- /* Allow the scalarizer to workshare array assignments. */
- if (ompws_flags & OMPWS_WORKSHARE_FLAG)
- ompws_flags |= OMPWS_SCALARIZER_WS;
-
/* The assignment needs scalarization. */
lss_section = lss;
@@ -6196,6 +6192,10 @@ gfc_trans_assignment_1 (gfc_expr * expr1
gfc_mark_ss_chain_used (loop.temp_ss, 3);
}
+ /* Allow the scalarizer to workshare array assignments. */
+ if ((ompws_flags & OMPWS_WORKSHARE_FLAG) && loop.temp_ss == NULL)
+ ompws_flags |= OMPWS_SCALARIZER_WS;
+
/* Start the scalarized loop body. */
gfc_start_scalarized_body (&loop, &body);
}
@@ -6304,6 +6304,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1
&& !gfc_expr_attr (expr1).codimension
&& !gfc_is_coindexed (expr1))
{
+ ompws_flags &= ~OMPWS_SCALARIZER_WS;
tmp = gfc_alloc_allocatable_for_assignment (&loop, expr1, expr2);
if (tmp != NULL_TREE)
gfc_add_expr_to_block (&loop.code[expr1->rank - 1], tmp);
--- gcc/fortran/trans-openmp.c.jj 2011-08-03 18:41:01.000000000 +0200
+++ gcc/fortran/trans-openmp.c 2011-08-19 13:58:02.000000000 +0200
@@ -1764,9 +1764,6 @@ gfc_trans_omp_workshare (gfc_code *code,
pushlevel (0);
- if (!code)
- return build_empty_stmt (input_location);
-
gfc_start_block (&block);
pblock = █
@@ -1903,6 +1900,9 @@ gfc_trans_omp_workshare (gfc_code *code,
else
poplevel (0, 0, 0);
+ if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
+ stmt = gfc_trans_omp_barrier ();
+
ompws_flags = 0;
return stmt;
}
--- libgomp/testsuite/libgomp.fortran/pr49792-1.f90.jj 2011-08-19 14:14:53.000000000 +0200
+++ libgomp/testsuite/libgomp.fortran/pr49792-1.f90 2011-08-19 14:16:20.000000000 +0200
@@ -0,0 +1,18 @@
+! PR fortran/49792
+! { dg-do run }
+
+subroutine reverse(n, a)
+ integer :: n
+ real(kind=8) :: a(n)
+!$omp parallel workshare
+ a(:) = a(n:1:-1)
+!$omp end parallel workshare
+end subroutine reverse
+
+program pr49792
+ real(kind=8) :: a(16) = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
+ real(kind=8) :: b(16)
+ b(:) = a(16:1:-1)
+ call reverse (16,a)
+ if (any (a.ne.b)) call abort
+end program pr49792
--- libgomp/testsuite/libgomp.fortran/pr49792-2.f90.jj 2011-08-19 14:16:00.000000000 +0200
+++ libgomp/testsuite/libgomp.fortran/pr49792-2.f90 2011-08-19 14:28:25.000000000 +0200
@@ -0,0 +1,22 @@
+! PR fortran/49792
+! { dg-do run }
+! { dg-options "-std=f2003 -fall-intrinsics" }
+
+subroutine reverse(n, a)
+ integer :: n
+ real(kind=8) :: a(n)
+!$omp parallel workshare
+ a(:) = a(n:1:-1)
+!$omp end parallel workshare
+end subroutine reverse
+
+program pr49792
+ integer :: b(16)
+ integer, allocatable :: a(:)
+ b = 1
+!$omp parallel workshare
+ a = b
+!$omp end parallel workshare
+ if (size(a).ne.size(b)) call abort()
+ if (any (a.ne.b)) call abort()
+end program pr49792
Jakub