[OpenACC] Add support for firstprivate Fortran allocatable scalars

Message ID 1f88e441-d3da-5b59-4278-058ff1368a73@codesourcery.com
State New
Headers show
Series
  • [OpenACC] Add support for firstprivate Fortran allocatable scalars
Related show

Commit Message

Cesar Philippidis Aug. 7, 2018, 9:55 p.m.
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

Patch

From b8fb83b36d0f96b12af9a1f5596f31b3c6b72ef0 Mon Sep 17 00:00:00 2001
From: Cesar Philippidis <cesar@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  <cesar@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