This patch updates the way that lower_omp_target uses firstprivate pointers in OpenACC offloaded regions. On host side, when preparing firstprivate data mapping for pointer type objects, not to be confused with GOMP_MAP_FIRSTPRIVATE_POINTER, the compiler passes passes the address of the value being pointed to and not the address of the pointer itself to the runtime. Correspondingly, on the device side, the compiler generates to code to dereference the remapped pointer once to copy the data to a local buffer.
While this behavior looks like it would break things, it will not affect C or C++ data mappings, because those languages transfer pointers via GOMP_MAP_FIRSTPRIVATE_POINTER. In addition, this will not cause problems with array types, because the default remapping rules for OpenACC is to transfer them in via copy. Besides it really doesn't make sense to allow arrays to be transferred in via firstprivate because that would use up a lot of memory on the accelerator. Is this OK for trunk? I bootstrapped and regtested it for x86_64 with nvptx offloading. Thanks, Cesar
>From b8fb83b36d0f96b12af9a1f5596f31b3c6b72ef0 Mon Sep 17 00:00:00 2001 From: Cesar Philippidis <ce...@codesourcery.com> Date: Mon, 6 Aug 2018 09:19:28 -0700 Subject: [PATCH] [OpenACC] Add support for firstprivate Fortran allocatable scalars This patch updates the way that lower_omp_target uses firstprivate pointers in OpenACC offloaded regions. On host side, when preparing pointer type firstprivate data mapping, not to be confused with GOMP_MAP_FIRSTPRIVATE_POINTER, the compiler passes passes the address of the value being pointed to, not the address of the pointer itself. Correspondingly, on the device side, the compiler generates to deference the remapped pointer once and copy the data to a local buffer. While this behavior like it would break things, it will not affect C or C++ data mappings, because those languages transfer pointers via GOMP_MAP_FIRSTPRIVATE_POINTER. In addition, this will not cause problems with array types, because the default remapping rules for OpenACC is to transfer them in via copy. Besides it really doesn't make sense to allow arrays to be transferred in via firstprivate because that would use up a lot of memory on the accelerator. 2018-XX-YY Cesar Philippidis <ce...@codesourcery.com> gcc/ omp-low.c (lower_omp_target): Update OpenACC handling of pointer variables with GOMP_MAP_FIRSTPRIVATE mappings. libgomp/ testsuite/libgomp.oacc-fortran/allocatable-scalar.f90: New test. --- gcc/omp-low.c | 18 ++++++++---- .../libgomp.oacc-fortran/allocatable-scalar.f90 | 33 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 libgomp/testsuite/libgomp.oacc-fortran/allocatable-scalar.f90 diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 843c66f..47603c4 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -7643,15 +7643,21 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE) { gcc_assert (is_gimple_omp_oacc (ctx->stmt)); - if (omp_is_reference (new_var) - && TREE_CODE (TREE_TYPE (new_var)) != POINTER_TYPE) + if (omp_is_reference (new_var)) { /* Create a local object to hold the instance value. */ - tree type = TREE_TYPE (TREE_TYPE (new_var)); + tree type = TREE_TYPE (new_var); + /* Pointer types are mapped onto the device via a + single level of indirection. */ + if (TREE_CODE (type) != POINTER_TYPE) + type = TREE_TYPE (type); const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var)); tree inst = create_tmp_var (type, id); - gimplify_assign (inst, fold_indirect_ref (x), &fplist); + if (TREE_CODE (TREE_TYPE (new_var)) == POINTER_TYPE) + gimplify_assign (inst, fold_indirect_ref (x), &fplist); + else + gimplify_assign (inst, fold_indirect_ref (x), &fplist); x = build_fold_addr_expr (inst); } gimplify_assign (new_var, x, &fplist); @@ -7879,7 +7885,9 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE) { gcc_assert (is_gimple_omp_oacc (ctx->stmt)); - if (!omp_is_reference (var)) + /* Handle Fortran allocatable scalars. */ + if (!omp_is_reference (var) + && TREE_CODE (TREE_TYPE (var)) != POINTER_TYPE) { if (is_gimple_reg (var) && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)) diff --git a/libgomp/testsuite/libgomp.oacc-fortran/allocatable-scalar.f90 b/libgomp/testsuite/libgomp.oacc-fortran/allocatable-scalar.f90 new file mode 100644 index 0000000..be86d14 --- /dev/null +++ b/libgomp/testsuite/libgomp.oacc-fortran/allocatable-scalar.f90 @@ -0,0 +1,33 @@ +! Test non-declared allocatable scalars in OpenACC data clauses. + +! { dg-do run } + +program main + implicit none + integer, parameter :: n = 100 + integer, allocatable :: a, c + integer :: i, b(n) + + allocate (a) + + a = 50 + + !$acc parallel loop + do i = 1, n; + b(i) = a + end do + + do i = 1, n + if (b(i) /= a) call abort + end do + + allocate (c) + + !$acc parallel copyout(c) num_gangs(1) + c = a + !$acc end parallel + + if (c /= a) call abort + + deallocate (a, c) +end program main -- 2.7.4