https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126940

--- Comment #3 from Tobias Burnus <burnus at gcc dot gnu.org> ---
First, the reason why the issue only shows up with offloading enabled:

  !$acc data copyin(host_p, host_parr)
 ...
#if !ACC_MEM_SHARED
 ...
    if (acc_is_present(parr, 1)) stop 6
#endif
 ...
  !$acc end data


Namely, 'acc_is_present' is only called if offloading is enabled.

Here,
  real, target, intent(in) :: parr(:), p2

such that 'parr' is not contiguous. And Fortran semantic might require packing
the argument in a function call.

* * *

Second: I have to admit that I do not understand why the contiguous check is
only now active - and not before? Or was it - but some additional check causes
this (like an elem_len != 0 check?)

JERRY, any idea? (I have not read your patch, admittedly.)

* * *

NOTE: OpenACC semantic requires that the argument is contiguous - i.e. for
valid code, there will be a runtime check for being contiguous - but no actual
packing is done.

* * *

Regarding the testcase, we could do:

--- a/libgomp/testsuite/libgomp.oacc-fortran/host_data-5.F90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/host_data-5.F90
@@ -28 +28,2 @@ subroutine foo (p2, parr, host_p, host_parr, cond)
-  real, target, intent(in) :: parr(:), p2
+  real, target, contiguous, intent(in) :: parr(:)
+  real, target, intent(in) :: p2

... or do what we state below.

* * *

On the specification side, OpenACC 2.0 to 2.5 has:

logical function acc_is_present( a )
  type, dimension(:[,:]. . . ) :: a
logical function acc_is_present( a, len )
  type :: a
  integer :: len

OpenMP 2.6 changed this to:

logical function acc_is_present( a )
logical function acc_is_present( a, len )
  type(*), dimension(..) :: a
  integer :: len

* * *

GCC implements it since r5-6458-g41dbbb3789850d as:

+    function acc_is_present_32_h (a, len)
+      use iso_c_binding, only: c_int32_t
+      logical acc_is_present_32_h
+      !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
+      type (*), dimension (*) :: a
+      integer (c_int32_t) len
+    end function
+
+    function acc_is_present_64_h (a, len)
+      use iso_c_binding, only: c_int64_t
+      logical acc_is_present_64_h
+      !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
+      type (*), dimension (*) :: a
+      integer (c_int64_t) len
+    end function
+
+    function acc_is_present_array_h (a)
+      logical acc_is_present_array_h
+      type (*), dimension (..), contiguous :: a
+    end function
+  end interface

...

+  interface acc_is_present
+    procedure :: acc_is_present_32_h
+    procedure :: acc_is_present_64_h
+    procedure :: acc_is_present_array_h
+  end interface


I wonder whether:

(0) There should be an 'intent(in)' which aids optimization, e.g. for packing,
it avoid copy out and it make clear that the array values aren't modified.


(1) The 'contiguous' in 'acc_is_present_array_h' should be removed. If the
passed argument is noncontiguous, both packing and not packing will lead to
bogus code. - This requires in the implementation to change
   acc_is_present_array_h = acc_is_present_l (a, sizeof (a)) == 1
to
   acc_is_present_array_h = acc_is_present_l (loc(a), sizeof (a)) == 1
to avoid the packing in the library.


(2) Whether acc_is_present_{32,64}_h should be changed to
  type (*), dimension (..) [, intent(in)] :: a

(and the specific function renamed - as we need to keep the old one for
backward compatibility.)

THOMAS, what do you think?

Reply via email to