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;