Hi Thomas,

Quick version: The attached patch seems to work, kind of,  but fails at run time with: libgomp: Trying to map into device [0x407218..0x40721c) object when [0x407210..0x40721c) is already mapped This marks the common-block decl but not the common-block vars as 'device resident' (alias "omp declare target").

The attached with '#if 0'  set to '1' does not work as it gives an ICE in lto1. – If one only marks the common-block variables, it fails as the ME check complains "variable 'block' has been referenced in offloaded code but hasn't been marked to be included in the offloaded code" –

I think the first version is fine, but it seems as if the ME needs to use pcreate and not create for those. I think that's also the reason for the odd is-program check mentioned at the very bottom.

Tobias

PS: Hmm, I really wonder why it seemed to have passed before. Looking at the code, it cannot have passed — more below. That goes wrong since r272453 for PR85221 (well, it can't before). I don't quickly see whether it also affects OpenMP or other clauses.

I think for a proper fix it would be very useful to know some more details about the intention of 'declare device_resident' (existing only on the device, existing on both host and device etc.). Cf. previous email.

In terms of this issue, if one does:  "integer :: a, b, c; common /name/ a,b,c; !$acc declare device_resident(a)", should this make all of the common-block variables as device resident or not? Internally, one gets for declare-5.f90 the following, i.e. /another/ is the common name and g, h and i are common-name variables:

  static integer(kind=4) g [value-expr: another.g];
  static integer(kind=4) h[3] [value-expr: another.h];
  static integer(kind=4) i[3] [value-expr: another.i];

For the test case, the issue is that 'gfc_get_symbol_decl' only called after it's tree representation (sym->backend_decl) has already been created; this happens for common blocks. – The attached patch fixes this, marking the common block decl and all its variables as declare device_resident.

One could think of handling other attributes (which ones?). For EQUIVALENCE in commons, the attributes are collected using accumulate_equivalence_attributes – and for normal variables, it is handled in trans-decl.c's add_attributes_to_decl

 * * *

Additionally, and unrelated to the test case, the following code looks very suspicious (from finish_oacc_declare in fortran/trans-decl.c):

  module_oacc_clauses = NULL;
  gfc_traverse_ns (ns, find_module_oacc_declare_clauses);
  if (module_oacc_clauses && sym->attr.flavor == FL_PROGRAM)

First, it very much looks like memory leak – one creates a linked list,
but always dumps it w/o using or freeing it if one is currently not
processing the main program. Additionally, it assumes that the main program
has a full view of module-declared 'declare device_resident' variables, but
it is trivial to construct programs where the main program does not see this
property. Most trivial example is:
  subroutine foo()
    use module_w_device_decl
  end subroutine
independent whether that function exists as such or as module procedure or
(at some place) is a procedure contained in another procedure. A general
assumption is also that the whole program is compiled with -fopenacc
and that the main program is written in Fortran and not, e.g., in C or C++.

Index: gcc/fortran/trans-common.c
===================================================================
--- gcc/fortran/trans-common.c	(revision 278936)
+++ gcc/fortran/trans-common.c	(working copy)
@@ -706,6 +706,15 @@
 	}
     }
 
+  bool is_device_resident = false;
+  for (s = head; s; s = next_s = s->next)
+     is_device_resident |= s->sym->attr.oacc_declare_device_resident;
+
+  if (is_device_resident)
+    DECL_ATTRIBUTES (decl)
+      = tree_cons (get_identifier ("omp declare target"),
+		   NULL_TREE, DECL_ATTRIBUTES (decl));
+
   /* Build component reference for each variable.  */
   for (s = head; s; s = next_s)
     {
@@ -750,6 +759,12 @@
 	  GFC_DECL_ASSIGN_ADDR (var_decl) = GFC_DECL_ASSIGN_ADDR (s->field);
 	}
 
+#if 0
+      if (is_device_resident)
+	DECL_ATTRIBUTES (var_decl)
+	  = tree_cons (get_identifier ("omp declare target"),
+		       NULL_TREE, DECL_ATTRIBUTES (var_decl));
+#endif
       s->sym->backend_decl = var_decl;
 
       next_s = s->next;

Reply via email to