Seehttps://gcc.gnu.org/PR127273 for some background.
This fixes an ICE with OpenMP 'link' variable where the offload
compile changes such static variables to be variable of pointer
type of the host variable.
This failed as no varpool_node was available when needed and,
as for some reason, the same decl appeared multiple times
in the FOR_EACH_VARIABLE loop. - For some reasons, and possibly
related to VALUE_EXPR, IPA also decided that it could remove that
node - even though it was used. (It worked at -O0)
Question to more LTO/IPA savor developers: Does this patch look
right? It surely fixes the issue... And other comments before I
commit it?
* * *
Other issues related to 'link', but of different nature:
* PR 127214 and PR 127213 (still to be investigated; one
issue is quite different, the other relates to having
static 'link' variable at function scope; I am not quite
sure it is properly handled, but at least some usage is
working as libgomp.fortran/declare-target-link.f90 tests it.)
[There might be other issues as well.]
* * *
Background about the 'link' feature:
int var[1024];
#pragma omp declare target link(var)
'link' has two purposes: The older one is to permit only partially
mapping data on the device to save memory. Such as only
mapping 'var[200:10]', i.e. element index 200 and 9 following
elements (i.e. length = 10).
This works by having not 'int var[1024]' on the device side but
'int *var$linkptr' – and replacing (VALUE_EXPR) all access by
to 'var' by '*var%linkptr'.
The newer purpose (I ran into): with 'requires self_maps',
the device side is supposed to access the host pointer such
it uses 'link' internally and libgomp initializes the device
side to point to the host variable.
Cheers,
Tobias
lto.cc: OpenMP's offload_handle_link_vars - fix for global variables [PR127273]
This is about variables that appear in OpenMP's 'link' clause of
the 'declare target' directive. On the host, they are normal
static variables - while on the device, they are pointer variables
that point to the actual data, i.e. the access 'var' on the host
becomes '* var$linkptr' on the device side, using a VALUE_EXPR
to achieve this. The offload_handle_link_vars handles this
('#if ACCEL_COMPILER').
For global variables, additional issues occurred:
* The function would be called multiple times for the same variable
each time calling 'build_decl' again.
Solution: If there is already a VALUE_EXPR, skip.
* Some code, in particular ipa_reference_var_uid assumes that also
decl->decl_with_vis.symtab_node is not NULL.
Solution: Call varpool_node::finalize_decl to create it.
* For some reasons some IPA analysis assumes that it is not needed
and, hence, the node can be removed, which fails (see previous item).
Solution: Use force_output.
As global static variables have to be output via the offload_vars,
the host and device side need to exist to make sure the n-th variable
in the host table is the same as the n-th variable on the device side,
i.e. forcing the output makes sense.
PR middle-end/127273
gcc/lto/ChangeLog:
* lto.cc (offload_handle_link_vars): Create node and force_output;
avoid creating the same '...$linkptr' var multiple times.
libgomp/ChangeLog:
* testsuite/libgomp.c/usm_env_handling-1-self.c: Remove 'dg-ice'.
gcc/lto/lto.cc | 4 ++++
libgomp/testsuite/libgomp.c/usm_env_handling-1-self.c | 8 ++------
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/gcc/lto/lto.cc b/gcc/lto/lto.cc
index 76837c27be8..d22827bbcc0 100644
--- a/gcc/lto/lto.cc
+++ b/gcc/lto/lto.cc
@@ -481,29 +481,33 @@ lto_wpa_write_files (void)
static void
offload_handle_link_vars (void)
{
#ifdef ACCEL_COMPILER
varpool_node *var;
FOR_EACH_VARIABLE (var)
if (lookup_attribute ("omp declare target link",
DECL_ATTRIBUTES (var->decl)))
{
+ if (DECL_HAS_VALUE_EXPR_P (var->decl))
+ continue;
tree type = build_pointer_type (TREE_TYPE (var->decl));
tree link_ptr_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
clone_function_name (var->decl,
"linkptr"), type);
TREE_USED (link_ptr_var) = 1;
TREE_STATIC (link_ptr_var) = 1;
TREE_PUBLIC (link_ptr_var) = TREE_PUBLIC (var->decl);
DECL_ARTIFICIAL (link_ptr_var) = 1;
SET_DECL_ASSEMBLER_NAME (link_ptr_var, DECL_NAME (link_ptr_var));
SET_DECL_VALUE_EXPR (var->decl, build_simple_mem_ref (link_ptr_var));
DECL_HAS_VALUE_EXPR_P (var->decl) = 1;
+ varpool_node::finalize_decl (link_ptr_var);
+ varpool_node::get (link_ptr_var)->force_output = var->force_output;
}
#endif
}
/* Perform whole program analysis (WPA) on the callgraph and write out the
optimization plan. */
static void
do_whole_program_analysis (void)
diff --git a/libgomp/testsuite/libgomp.c/usm_env_handling-1-self.c b/libgomp/testsuite/libgomp.c/usm_env_handling-1-self.c
index 37a7b915b18..79cbd9ff031 100644
--- a/libgomp/testsuite/libgomp.c/usm_env_handling-1-self.c
+++ b/libgomp/testsuite/libgomp.c/usm_env_handling-1-self.c
@@ -1,13 +1,9 @@
/* { dg-do run } */
/* Check that a global static variable is consistently updated on the device. */
-// ICE for A$linkptr in nvptx lto1 with ipa_reference_var_uid
-// when compiling with -fopenmp -O1 or higher
-// {Segmentation [Ff]ault}{ offload_target_nvptx } }
-// { dg-ice "PR target/127273" { offload_target_nvptx } }
-// { dg-excess-errors "'mkoffload' failure etc." { xfail { offload_target_nvptx } } } */
-
+// PR middle-end/127273 for an ICE fix
+// PR middle-end/122205 for converting enter to link for self_maps
#define USE_SELF_MAPS 1
#include "usm_env_handling-1.c"