I've pushed this patch to openacc-gcc-7-branch which teaches the
gimplifier how to create 0-length arrays mappings for certain pointer
and reference typed variables. This is necessary to satisfy the implicit
expectation in OpenACC where the user considers pointer variables used
like arrays as having array types.

In OpenACC, pointers variables officially classified as scalar values,
which requires the content of the scalar to be mapped verbatim onto the
accelerator (i.e., the host pointer doesn't get remapped to a device
address on the accelerator). However, as mentioned above, a lot of users
think that pointers used like arrays are arrays, and therefore expect
things such as

  int *p = ...

  #pragma acc enter data copyin (p[0:100])

  #pragma acc parallel loop
  for (i = ...)
  {
    ... p[i] ...
  }

to work as if 'p' were an array. Note that this patch does not do
anything special with dynamic arrays. E.g.

  int *p = (int *) malloc ...

  #pragma acc parallel loop
  for (i = ...)
  {
    ... p[i] ...
  }

In this case, by virtue of being a 0-length array mapping, p will be
transferred to the accelerator with the host value of &p[0]. I've seen
another compiler which goes through the trouble of mapping the dynamic
array to the accelerator automatically, but that's beyond the scope of
this patch.

Cesar
2017-10-11  Cesar Philippidis  <ce...@codesourcery.com>

	gcc/
	* gimplify.c (oacc_default_clause): Create implicit 0-length
	array data clauses for pointers and reference types.

	libgomp/
	* testsuite/libgomp.oacc-c-c++-common/fp-dyn-arrays.c: New test.


diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2c10c6433a7..7a9cc241792 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6994,7 +6994,12 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags)
     case ORT_ACC_PARALLEL:
       rkind = "parallel";
 
-      if (is_private)
+      if (TREE_CODE (type) == REFERENCE_TYPE
+	  && TREE_CODE (TREE_TYPE (type)) == POINTER_TYPE)
+	flags |= GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
+      else if (!lang_GNU_Fortran () && TREE_CODE (type) == POINTER_TYPE)
+	flags |= GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
+      else if (is_private)
 	flags |= GOVD_FIRSTPRIVATE;
       else if (on_device || declared)
 	flags |= GOVD_MAP;
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/fp-dyn-arrays.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/fp-dyn-arrays.c
new file mode 100644
index 00000000000..c57261f2d12
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/fp-dyn-arrays.c
@@ -0,0 +1,42 @@
+/* Expect dynamic arrays to be mapped on the accelerator via
+   GOMP_MAP_0LEN_ARRAY.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+int
+main ()
+{
+  const int n = 1000;
+  int *a, *b, *c, *d, i;
+
+  d = (int *) 12345;
+  a = (int *) malloc (sizeof (int) * n);
+  b = (int *) malloc (sizeof (int) * n);
+  c = (int *) malloc (sizeof (int) * n);
+
+  for (i = 0; i < n; i++)
+    {
+      a[i] = -1;
+      b[i] = i+1;
+      c[i] = 2*(i+1);
+    }
+
+#pragma acc enter data create(a[0:n]) copyin(b[:n], c[:n])
+#pragma acc parallel loop
+  for (i = 0; i < n; ++i)
+    {
+      a[i] = b[i] + c[i] + *((int *)&d);
+    }
+#pragma acc exit data copyout(a[0:n]) delete(b[0:n], c[0:n])
+
+  for (i = 0; i < n; i++)
+    assert (a[i] == 3*(i+1) + 12345);
+
+  free (a);
+  free (b);
+  free (c);
+
+  return 0;
+}

Reply via email to