Hi! On 2019-10-15T23:32:32+0200, Tobias Burnus <tob...@codesourcery.com> wrote: > This OpenACC-only patch extends the support for /common/ blocks.
I'll be quick to note that I don't have any first-hand experience with Fortran common blocks. :-P > [In OpenMP (4.0 to 5.0, unchanged) and gfortran, common blocks are supported > in copyin/copyprivate, in firstprivate/lastprivate/private/shared, in > threadprivate and in declare target.] > > For OpenACC, gfortran already supports common blocks for > device_resident/usedevice/cache/flush/link. > > This patch adds them (for OpenACC only) to copy/copyin/copyout, create/delete, > host, pcopy/pcopy_in/pcopy_out, present_or_copy, present_or_copy_in, > present_or_copy_out, present_or_create and self. > [Of those, only "copy()" is also an OpenMP clause name.] I'm confused: in <http://mid.mail-archive.com/20181204133007.GO12380@tucnak> Jakub stated that "OpenMP doesn't have a copy clause, so I'd expect true here": | @@ -1051,7 +1052,7 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, | if ((mask & OMP_CLAUSE_COPY) | && gfc_match ("copy ( ") == MATCH_YES | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], | - OMP_MAP_TOFROM)) | + OMP_MAP_TOFROM, openacc)) | continue; > [Cf. OpenACC 2.7 in 1.9 (for the p* variants) and 2.13; the latter is new > since OpenACC 2.0.] > > > > I think the Fortran part is obvious, once one agrees on the list of clauses; > and OK from a Fortran's maintainer view. I'll defer to your judgement there, but just one comment: I noticed that OpenACC 2.7 in 2.7. "Data Clauses" states that "For all clauses except 'deviceptr' and 'present', the list argument may include a Fortran _common block_ name enclosed within slashes, if that _common block_ name also appears in a 'declare' directive 'link' clause". Are we already properly handling the aspect that requires that the "that _common block_ name also appears in a 'declare' directive 'link' clause"? The libgomp execution test cases you're adding all state that "This test does not exercise ACC DECLARE", yet they supposedly already do work fine. Or am I understading the OpenACC specification wrongly here? I'm certainly aware of (big) deficiencies in the OpenACC 'declare' handling, so I guess my question here may be whether these test cases are valid after all? > gcc/gimplify.c: oacc_default_clause contains some changes; there are > additionally two lines which only differ for ORT_ACC – Hence, it is an > OpenACC-only change! > The ME change is about privatizing common blocks (I haven't studied this part > closer.) So, please do study that closer. ;-P In <http://mid.mail-archive.com/87efx6haep.fsf@euler.schwinge.homeip.net> I raised some questions, got a bit of an answer, and in <http://mid.mail-archive.com/87bms85kra.fsf@hertz.schwinge.homeip.net> asked further, didn't get an answer. All the rationale from Cesar's original submission email should be transferred into 'gcc/gimplify.c' as much as feasible, to make that "voodoo code" better understandable. > @Jakub, all: comments and approvals are welcome. Indeed. :-) > gcc/ > * gimplify.c (oacc_default_clause): Privatize fortran common blocks. > (omp_notice_variable): Defer the expansion of DECL_VALUE_EXPR for > common block decls. > --- a/gcc/gimplify.c > +++ b/gcc/gimplify.c > @@ -7218,15 +7218,20 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, > tree decl, unsigned flags) > { > const char *rkind; > bool on_device = false; > + bool is_private = false; > bool declared = is_oacc_declared (decl); > tree type = TREE_TYPE (decl); > > if (lang_hooks.decls.omp_privatize_by_reference (decl)) > type = TREE_TYPE (type); > > + if (RECORD_OR_UNION_TYPE_P (type)) > + is_private = lang_hooks.decls.omp_disregard_value_expr (decl, false); > + > if ((ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)) != 0 > && is_global_var (decl) > - && device_resident_p (decl)) > + && device_resident_p (decl) > + && !is_private) > { > on_device = true; > flags |= GOVD_MAP_TO_ONLY; > @@ -7237,7 +7242,9 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, tree > decl, unsigned flags) > case ORT_ACC_KERNELS: > rkind = "kernels"; > > - if (AGGREGATE_TYPE_P (type)) > + if (is_private) > + flags |= GOVD_MAP; > + else if (AGGREGATE_TYPE_P (type)) > { > /* Aggregates default to 'present_or_copy', or 'present'. */ > if (ctx->default_kind != OMP_CLAUSE_DEFAULT_PRESENT) > @@ -7254,7 +7261,9 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, tree > decl, unsigned flags) > case ORT_ACC_PARALLEL: > rkind = "parallel"; > > - if (on_device || declared) > + if (is_private) > + flags |= GOVD_FIRSTPRIVATE; > + else if (on_device || declared) > flags |= GOVD_MAP; > else if (AGGREGATE_TYPE_P (type)) > { > @@ -7320,7 +7329,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree > decl, bool in_code) > { > tree value = get_base_address (DECL_VALUE_EXPR (decl)); > > - if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value)) > + if (!(ctx->region_type & ORT_ACC) > + && value && DECL_P (value) && DECL_THREAD_LOCAL_P (value)) > return omp_notice_threadprivate_variable (ctx, decl, value); > } > > @@ -7352,7 +7362,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree > decl, bool in_code) > n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl); > if ((ctx->region_type & ORT_TARGET) != 0) > { > - ret = lang_hooks.decls.omp_disregard_value_expr (decl, true); > + shared = !(ctx->region_type & ORT_ACC); > + ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared); > if (n == NULL) > { > unsigned nflags = flags; > @@ -7520,6 +7531,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree > decl, bool in_code) > } > > shared = ((flags | n->value) & GOVD_SHARED) != 0; > + if (ctx->region_type & ORT_ACC) > + shared = false; > ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared); > > /* If nothing changed, there's nothing left to do. */ > PS: This patch is the rediffed OG9 (alias OG8) patch > 0793cef408c9937f4c4e2423dd1f7d6a97b9bed3 by Cesar Philippidis from 2016. > (Which was on gomp-4_0-branch as r240165). Due to the wonders of GIT – when > not requiring linear history and due to rebasing with GCC9, it is also part > of the OG9 commit ac6c90812344f4f4cfe4d2f5901c1a9d038a4000 – which in > addition also does some other things like handling OpenACC device pointers. There's no Git magic involved there: somebody just (manually) merged several these patches together into one, for no good reason. ;-\ Grüße Thomas > diff --git a/gcc/testsuite/gfortran.dg/goacc/common-block-1.f90 > b/gcc/testsuite/gfortran.dg/goacc/common-block-1.f90 > new file mode 100644 > index 00000000000..1cbbb49d638 > --- /dev/null > +++ b/gcc/testsuite/gfortran.dg/goacc/common-block-1.f90 > @@ -0,0 +1,69 @@ > +! Test data clauses involving common blocks and common block data. > +! Specifically, validates early matching errors. > + > +subroutine subtest > + implicit none > + integer, parameter :: n = 10 > + integer a(n), b(n), c, d(n), e > + real*4 x(n), y(n), z, w(n), v > + common /blockA/ a, c, x > + common /blockB/ b, y, z > + !$acc declare link(/blockA/, /blockB/, e, v) > +end subroutine subtest > + > +program test > + implicit none > + integer, parameter :: n = 10 > + integer a(n), b(n), c, d(n), e > + real*4 x(n), y(n), z, w(n), v > + common /blockA/ a, c, x > + common /blockB/ b, y, z > + !$acc declare link(/blockA/, /blockB/, e, v) > + > + !$acc data copy(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data copyin(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data copyout(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data create(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data copyout(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data pcopy(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data pcopyin(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data pcopyout(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data pcreate(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data pcopyout(/blockA/, /blockB/, e, v) > + !$acc end data > + > + !$acc data present(/blockA/, /blockB/, e, v) ! { dg-error "Syntax error in > OpenMP variable list" } > + !$acc end data ! { dg-error "Unexpected ..ACC END DATA statement" } > + > + !$acc parallel private(/blockA/, /blockB/, e, v) > + !$acc end parallel > + > + !$acc parallel firstprivate(/blockA/, /blockB/, e, v) > + !$acc end parallel > + > + !$acc exit data delete(/blockA/, /blockB/, e, v) > + > + !$acc data deviceptr(/blockA/, /blockB/, e, v) ! { dg-error "Syntax error > in OpenMP variable list" } > + !$acc end data ! { dg-error "Unexpected ..ACC END DATA statement" } > + > + !$acc data deviceptr(/blockA/, /blockB/, e, v) ! { dg-error "Syntax error > in OpenMP variable list" } > + !$acc end data ! { dg-error "Unexpected ..ACC END DATA statement" } > +end program test > diff --git a/gcc/testsuite/gfortran.dg/goacc/common-block-2.f90 > b/gcc/testsuite/gfortran.dg/goacc/common-block-2.f90 > new file mode 100644 > index 00000000000..b83638918a3 > --- /dev/null > +++ b/gcc/testsuite/gfortran.dg/goacc/common-block-2.f90 > @@ -0,0 +1,49 @@ > +! Test data clauses involving common blocks and common block data. > +! Specifically, resolver errors such as duplicate data clauses. > + > +program test > + implicit none > + integer, parameter :: n = 10 > + integer a(n), b(n), c, d(n), e > + real*4 x(n), y(n), z, w(n), v > + common /blockA/ a, c, x > + common /blockB/ b, y, z > + > + !$acc data copy(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data copyin(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data copyout(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data create(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data copyout(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data pcopy(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data pcopyin(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data pcopyout(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data pcreate(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc data pcopyout(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol .a. > present on multiple clauses" } > + !$acc end data > + > + !$acc parallel private(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol > .a. present on multiple clauses" } > + !$acc end parallel > + > + !$acc parallel firstprivate(/blockA/, /blockB/, e, v, a) ! { dg-error > "Symbol .a. present on multiple clauses" } > + !$acc end parallel > + > + !$acc exit data delete(/blockA/, /blockB/, e, v, a) ! { dg-error "Symbol > .a. present on multiple clauses" } > +end program test > diff --git a/libgomp/testsuite/libgomp.oacc-fortran/common-block-1.f90 > b/libgomp/testsuite/libgomp.oacc-fortran/common-block-1.f90 > new file mode 100644 > index 00000000000..a17a33536f3 > --- /dev/null > +++ b/libgomp/testsuite/libgomp.oacc-fortran/common-block-1.f90 > @@ -0,0 +1,105 @@ > +! Test data located inside common blocks. This test does not exercise > +! ACC DECLARE. > + > +module const > + integer, parameter :: n = 100 > +end module const > + > +subroutine check > + use const > + > + implicit none > + integer i, x(n), y > + common /BLOCK/ x, y > + > + do i = 1, n > + if (x(i) .ne. y) call abort > + end do > +end subroutine check > + > +module m > + use const > + integer a(n), b > + common /BLOCK/ a, b > + > +contains > + subroutine mod_implicit_incr > + implicit none > + integer i > + > + !$acc parallel loop > + do i = 1, n > + a(i) = b > + end do > + !$acc end parallel loop > + > + call check > + end subroutine mod_implicit_incr > + > + subroutine mod_explicit_incr > + implicit none > + integer i > + > + !$acc parallel loop copy(a(1:n)) copyin(b) > + do i = 1, n > + a(i) = b > + end do > + !$acc end parallel loop > + > + call check > + end subroutine mod_explicit_incr > +end module m > + > +subroutine sub_implicit_incr > + use const > + > + implicit none > + integer i, x(n), y > + common /BLOCK/ x, y > + > + !$acc parallel loop > + do i = 1, n > + x(i) = y > + end do > + !$acc end parallel loop > + > + call check > +end subroutine sub_implicit_incr > + > +subroutine sub_explicit_incr > + use const > + > + implicit none > + integer i, x(n), y > + common /BLOCK/ x, y > + > + !$acc parallel loop copy(x(1:n)) copyin(y) > + do i = 1, n > + x(i) = y > + end do > + !$acc end parallel loop > + > + call check > +end subroutine sub_explicit_incr > + > +program main > + use m > + > + implicit none > + > + a(:) = -1 > + b = 5 > + call mod_implicit_incr > + > + a(:) = -2 > + b = 6 > + call mod_explicit_incr > + > + a(:) = -3 > + b = 7 > + call sub_implicit_incr > + > + a(:) = -4 > + b = 8 > + call sub_explicit_incr > +end program main > diff --git a/libgomp/testsuite/libgomp.oacc-fortran/common-block-2.f90 > b/libgomp/testsuite/libgomp.oacc-fortran/common-block-2.f90 > new file mode 100644 > index 00000000000..e27a225a024 > --- /dev/null > +++ b/libgomp/testsuite/libgomp.oacc-fortran/common-block-2.f90 > @@ -0,0 +1,150 @@ > +! Test data located inside common blocks. This test does not exercise > +! ACC DECLARE. All data clauses are explicit. > + > +module consts > + integer, parameter :: n = 100 > +end module consts > + > +subroutine validate > + use consts > + > + implicit none > + integer i, j > + real*4 x(n), y(n), z > + common /BLOCK/ x, y, z, j > + > + do i = 1, n > + if (abs(x(i) - i - z) .ge. 0.0001) call abort > + end do > +end subroutine validate > + > +subroutine incr > + use consts > + > + implicit none > + integer i, j > + real*4 x(n), y(n), z > + common /BLOCK/ x, y, z, j > + > + !$acc parallel loop pcopy(/BLOCK/) > + do i = 1, n > + x(i) = x(i) + z > + end do > + !$acc end parallel loop > +end subroutine incr > + > +program main > + use consts > + > + implicit none > + integer i, j > + real*4 a(n), b(n), c > + common /BLOCK/ a, b, c, j > + > + ! Test copyout, pcopy, device > + > + !$acc data copyout(a, c) > + > + c = 1.0 > + > + !$acc update device(c) > + > + !$acc parallel loop pcopy(a) > + do i = 1, n > + a(i) = i > + end do > + !$acc end parallel loop > + > + call incr > + call incr > + call incr > + !$acc end data > + > + c = 3.0 > + call validate > + > + ! Test pcopy without copyout > + > + c = 2.0 > + call incr > + c = 5.0 > + call validate > + > + ! Test create, delete, host, copyout, copyin > + > + !$acc enter data create(b) > + > + !$acc parallel loop pcopy(b) > + do i = 1, n > + b(i) = i > + end do > + !$acc end parallel loop > + > + !$acc update host (b) > + > + !$acc parallel loop pcopy(b) copyout(a) copyin(c) > + do i = 1, n > + a(i) = b(i) + c > + end do > + !$acc end parallel loop > + > + !$acc exit data delete(b) > + > + call validate > + > + a(:) = b(:) > + c = 0.0 > + call validate > + > + ! Test copy > + > + c = 1.0 > + !$acc parallel loop copy(/BLOCK/) > + do i = 1, n > + a(i) = b(i) + c > + end do > + !$acc end parallel loop > + > + call validate > + > + ! Test pcopyin, pcopyout FIXME > + > + c = 2.0 > + !$acc data copyin(b, c) copyout(a) > + > + !$acc parallel loop pcopyin(b, c) pcopyout(a) > + do i = 1, n > + a(i) = b(i) + c > + end do > + !$acc end parallel loop > + > + !$acc end data > + > + call validate > + > + ! Test reduction, private > + > + j = 0 > + > + !$acc parallel private(i) copy(j) > + !$acc loop reduction(+:j) > + do i = 1, n > + j = j + 1 > + end do > + !$acc end parallel > + > + if (j .ne. n) call abort > + > + ! Test firstprivate, copy > + > + a(:) = 0 > + c = j > + > + !$acc parallel loop firstprivate(c) copyout(a) > + do i = 1, n > + a(i) = i + c > + end do > + !$acc end parallel loop > + > + call validate > +end program main > diff --git a/libgomp/testsuite/libgomp.oacc-fortran/common-block-3.f90 > b/libgomp/testsuite/libgomp.oacc-fortran/common-block-3.f90 > new file mode 100644 > index 00000000000..90448d2da72 > --- /dev/null > +++ b/libgomp/testsuite/libgomp.oacc-fortran/common-block-3.f90 > @@ -0,0 +1,137 @@ > +! Test data located inside common blocks. This test does not exercise > +! ACC DECLARE. Most of the data clauses are implicit. > + > +module consts > + integer, parameter :: n = 100 > +end module consts > + > +subroutine validate > + use consts > + > + implicit none > + integer i, j > + real*4 x(n), y(n), z > + common /BLOCK/ x, y, z, j > + > + do i = 1, n > + if (abs(x(i) - i - z) .ge. 0.0001) call abort > + end do > +end subroutine validate > + > +subroutine incr_parallel > + use consts > + > + implicit none > + integer i, j > + real*4 x(n), y(n), z > + common /BLOCK/ x, y, z, j > + > + !$acc parallel loop > + do i = 1, n > + x(i) = x(i) + z > + end do > + !$acc end parallel loop > +end subroutine incr_parallel > + > +subroutine incr_kernels > + use consts > + > + implicit none > + integer i, j > + real*4 x(n), y(n), z > + common /BLOCK/ x, y, z, j > + > + !$acc kernels > + do i = 1, n > + x(i) = x(i) + z > + end do > + !$acc end kernels > +end subroutine incr_kernels > + > +program main > + use consts > + > + implicit none > + integer i, j > + real*4 a(n), b(n), c > + common /BLOCK/ a, b, c, j > + > + !$acc data copyout(a, c) > + > + c = 1.0 > + > + !$acc update device(c) > + > + !$acc parallel loop > + do i = 1, n > + a(i) = i > + end do > + !$acc end parallel loop > + > + call incr_parallel > + call incr_parallel > + call incr_parallel > + !$acc end data > + > + c = 3.0 > + call validate > + > + ! Test pcopy without copyout > + > + c = 2.0 > + call incr_kernels > + c = 5.0 > + call validate > + > + !$acc kernels > + do i = 1, n > + b(i) = i > + end do > + !$acc end kernels > + > + !$acc parallel loop > + do i = 1, n > + a(i) = b(i) + c > + end do > + !$acc end parallel loop > + > + call validate > + > + a(:) = b(:) > + c = 0.0 > + call validate > + > + ! Test copy > + > + c = 1.0 > + !$acc parallel loop > + do i = 1, n > + a(i) = b(i) + c > + end do > + !$acc end parallel loop > + > + call validate > + > + c = 2.0 > + !$acc data copyin(b, c) copyout(a) > + > + !$acc kernels > + do i = 1, n > + a(i) = b(i) + c > + end do > + !$acc end kernels > + > + !$acc end data > + > + call validate > + > + j = 0 > + > + !$acc parallel loop reduction(+:j) > + do i = 1, n > + j = j + 1 > + end do > + !$acc end parallel loop > + > + if (j .ne. n) call abort > +end program main
signature.asc
Description: PGP signature