]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Implicitly add 'declare target' directives for dynamic initializers in C++
authorKwok Cheung Yeung <kcy@codesourcery.com>
Fri, 18 Dec 2020 16:26:34 +0000 (08:26 -0800)
committerKwok Cheung Yeung <kcy@codesourcery.com>
Fri, 18 Dec 2020 19:13:46 +0000 (11:13 -0800)
This is a backport from mainline (commit
3af02d32cce2ff1ff11d078cf8094305f57ca179).

2020-12-18  Kwok Cheung Yeung  <kcy@codesourcery.com>

gcc/
* langhooks-def.h (lhd_get_decl_init): New.
(lhd_finish_decl_inits): New.
(LANG_HOOKS_GET_DECL_INIT): New.
(LANG_HOOKS_OMP_FINISH_DECL_INITS): New.
(LANG_HOOKS_DECLS): Add LANG_HOOKS_GET_DECL_INIT and
LANG_HOOKS_OMP_FINISH_DECL_INITS.
* langhooks.c (lhd_omp_get_decl_init): New.
(lhd_omp_finish_decl_inits): New.
* langhooks.h (struct lang_hooks_for_decls): Add omp_get_decl_init
and omp_finish_decl_inits.
* omp-offload.c (omp_discover_declare_target_var_r): Use
get_decl_init langhook in place of DECL_INITIAL.  Call
omp_finish_decl_inits langhook at end of function.

gcc/cp/
* cp-lang.c (cxx_get_decl_init): New.
(cxx_omp_finish_decl_inits): New.
(LANG_HOOKS_GET_DECL_INIT): New.
(LANG_HOOKS_OMP_FINISH_DECL_INITS): New.
* cp-tree.h (dynamic_initializers): New.
* decl.c (dynamic_initializers): New.
* decl2.c (c_parse_final_cleanups): Add initializer entries
from vars to dynamic_initializers.

gcc/testsuite/
* g++.dg/gomp/declare-target-3.C: New.

12 files changed:
gcc/ChangeLog.omp
gcc/cp/ChangeLog.omp
gcc/cp/cp-lang.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/langhooks-def.h
gcc/langhooks.c
gcc/langhooks.h
gcc/omp-offload.c
gcc/testsuite/ChangeLog.omp
gcc/testsuite/g++.dg/gomp/declare-target-3.C [new file with mode: 0644]

index 595a89583145df92a69dcb40ecdaff4e1c13753f..9bc07f1425af598fc8255c8eecba477b136144ff 100644 (file)
@@ -1,3 +1,22 @@
+2020-12-18  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+       Backport from mainline
+       2020-12-18  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+       * langhooks-def.h (lhd_get_decl_init): New.
+       (lhd_finish_decl_inits): New.
+       (LANG_HOOKS_GET_DECL_INIT): New.
+       (LANG_HOOKS_OMP_FINISH_DECL_INITS): New.
+       (LANG_HOOKS_DECLS): Add LANG_HOOKS_GET_DECL_INIT and
+       LANG_HOOKS_OMP_FINISH_DECL_INITS.
+       * langhooks.c (lhd_omp_get_decl_init): New.
+       (lhd_omp_finish_decl_inits): New.
+       * langhooks.h (struct lang_hooks_for_decls): Add omp_get_decl_init
+       and omp_finish_decl_inits.
+       * omp-offload.c (omp_discover_declare_target_var_r): Use
+       get_decl_init langhook in place of DECL_INITIAL.  Call
+       omp_finish_decl_inits langhook at end of function.
+
 2020-09-28  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline
index 1aaed1b8beae56724d0ad2559ef0af78ded368dd..3dac62b4edcdc29dd49d5db6f9497fabbbbcf231 100644 (file)
@@ -1,3 +1,17 @@
+2020-12-18  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+       Backport from mainline
+       2020-12-18  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+       * cp-lang.c (cxx_get_decl_init): New.
+       (cxx_omp_finish_decl_inits): New.
+       (LANG_HOOKS_GET_DECL_INIT): New.
+       (LANG_HOOKS_OMP_FINISH_DECL_INITS): New.
+       * cp-tree.h (dynamic_initializers): New.
+       * decl.c (dynamic_initializers): New.
+       * decl2.c (c_parse_final_cleanups): Add initializer entries
+       from vars to dynamic_initializers.
+
 2020-09-17  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline
index 9e980bc6de97906012557094c4c70d62cbff2a10..6a9b26f6145ce779aaaa18f79c2aa50643c63b57 100644 (file)
@@ -34,6 +34,8 @@ static tree cp_eh_personality (void);
 static tree get_template_innermost_arguments_folded (const_tree);
 static tree get_template_argument_pack_elems_folded (const_tree);
 static tree cxx_enum_underlying_base_type (const_tree);
+static tree *cxx_omp_get_decl_init (tree);
+static void cxx_omp_finish_decl_inits (void);
 
 /* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
    consequently, there should be very few hooks below.  */
@@ -86,6 +88,12 @@ static tree cxx_enum_underlying_base_type (const_tree);
 #undef LANG_HOOKS_GET_SUBSTRING_LOCATION
 #define LANG_HOOKS_GET_SUBSTRING_LOCATION c_get_substring_location
 
+#undef LANG_HOOKS_OMP_GET_DECL_INIT
+#define LANG_HOOKS_OMP_GET_DECL_INIT cxx_omp_get_decl_init
+
+#undef LANG_HOOKS_OMP_FINISH_DECL_INITS
+#define LANG_HOOKS_OMP_FINISH_DECL_INITS cxx_omp_finish_decl_inits
+
 /* Each front end provides its own lang hook initializer.  */
 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
@@ -227,6 +235,30 @@ tree cxx_enum_underlying_base_type (const_tree type)
   return underlying_type;
 }
 
+/* The C++ version of the omp_get_decl_init langhook returns the static
+   initializer for a variable declaration if present, otherwise it
+   tries to find and return the dynamic initializer.  If not present,
+   it returns NULL.  */
+
+static tree *
+cxx_omp_get_decl_init (tree decl)
+{
+  if (DECL_INITIAL (decl))
+    return &DECL_INITIAL (decl);
+
+  return hash_map_safe_get (dynamic_initializers, decl);
+}
+
+/* The C++ version of the omp_finish_decl_inits langhook allows GC to
+   reclaim the memory used by the hash-map used to hold dynamic initializer
+   information.  */
+
+static void
+cxx_omp_finish_decl_inits (void)
+{
+  dynamic_initializers = NULL;
+}
+
 #if CHECKING_P
 
 namespace selftest {
index 841981dd9df8d346c753885c86271746c810e696..af7df8687a187f403e71c05eecc91c2c044e9811 100644 (file)
@@ -5497,6 +5497,10 @@ extern GTY(()) tree static_aggregates;
 /* Likewise, for thread local storage.  */
 extern GTY(()) tree tls_aggregates;
 
+/* A hash-map mapping from variable decls to the dynamic initializer for
+   the decl.  This is currently only used by OpenMP.  */
+extern GTY(()) decl_tree_map *dynamic_initializers;
+
 enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 
 /* These are uses as bits in flags passed to various functions to
index cb9e019016082ffcdd6687b9dc070b59ccb5e0c2..3f4bea40d73d298902db145f3b68be059f0a9ce2 100644 (file)
@@ -146,6 +146,10 @@ tree static_aggregates;
 /* Like static_aggregates, but for thread_local variables.  */
 tree tls_aggregates;
 
+/* A hash-map mapping from variable decls to the dynamic initializer for
+   the decl.  This is currently only used by OpenMP.  */
+decl_tree_map *dynamic_initializers;
+
 /* -- end of C++ */
 
 /* A node for the integer constant 2.  */
index 8d3ac31a0c93f3bd3fc849827b9c5ccc41a60f34..5343ea3b068ff39cdbbdd044e2328e5743d87c1d 100644 (file)
@@ -4927,6 +4927,13 @@ c_parse_final_cleanups (void)
 
       if (vars)
        {
+         if (flag_openmp)
+           /* Add initializer information from VARS into
+              DYNAMIC_INITIALIZERS.  */
+           for (t = vars; t; t = TREE_CHAIN (t))
+             hash_map_safe_put<hm_ggc> (dynamic_initializers,
+                                        TREE_VALUE (t), TREE_PURPOSE (t));
+
          /* We need to start a new initialization function each time
             through the loop.  That's because we need to know which
             vtables have been referenced, and TREE_SYMBOL_REFERENCED
index bb5371d38e47ca536c2b2ee470b7e30f81ef8e63..e5ab028edcf04ef143d46ee89c5311c12cc2d35f 100644 (file)
@@ -87,6 +87,8 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
                                               tree);
 extern bool lhd_omp_mappable_type (tree);
 extern bool lhd_omp_scalar_p (tree);
+extern tree *lhd_omp_get_decl_init (tree);
+extern void lhd_omp_finish_decl_inits ();
 
 extern const char *lhd_get_substring_location (const substring_loc &,
                                               location_t *out_loc);
@@ -259,6 +261,8 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
 #define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
 #define LANG_HOOKS_OMP_FINISH_CLAUSE lhd_omp_finish_clause
 #define LANG_HOOKS_OMP_SCALAR_P lhd_omp_scalar_p
+#define LANG_HOOKS_OMP_GET_DECL_INIT lhd_omp_get_decl_init
+#define LANG_HOOKS_OMP_FINISH_DECL_INITS lhd_omp_finish_decl_inits
 
 #define LANG_HOOKS_DECLS { \
   LANG_HOOKS_GLOBAL_BINDINGS_P, \
@@ -287,7 +291,9 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
   LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR, \
   LANG_HOOKS_OMP_CLAUSE_DTOR, \
   LANG_HOOKS_OMP_FINISH_CLAUSE, \
-  LANG_HOOKS_OMP_SCALAR_P \
+  LANG_HOOKS_OMP_SCALAR_P, \
+  LANG_HOOKS_OMP_GET_DECL_INIT, \
+  LANG_HOOKS_OMP_FINISH_DECL_INITS \
 }
 
 /* LTO hooks.  */
index d90d5eccae35936ad7118a52f0ba224ccc6dcfae..3c68224da8334d04b7c9e1d00cdebb4179e66598 100644 (file)
@@ -630,6 +630,22 @@ lhd_omp_scalar_p (tree decl)
   return false;
 }
 
+/* Return static initializer for DECL.  */
+
+tree *
+lhd_omp_get_decl_init (tree decl)
+{
+  return &DECL_INITIAL (decl);
+}
+
+/* Free any extra memory used to hold initializer information for
+   variable declarations.  */
+
+void
+lhd_omp_finish_decl_inits (void)
+{
+}
+
 /* Register language specific type size variables as potentially OpenMP
    firstprivate variables.  */
 
index 6d62460460544638b7a43715b2dbe56a75c48475..52174b5ff56ec802862e8155ef91cf14072d8855 100644 (file)
@@ -299,6 +299,16 @@ struct lang_hooks_for_decls
   /* Return true if DECL is a scalar variable (for the purpose of
      implicit firstprivatization).  */
   bool (*omp_scalar_p) (tree decl);
+
+  /* Return a pointer to the tree representing the initializer
+     expression for the non-local variable DECL.  Return NULL if
+     DECL is not initialized.  */
+  tree *(*omp_get_decl_init) (tree decl);
+
+  /* Free any extra memory used to hold initializer information for
+     variable declarations.  omp_get_decl_init must not be called
+     after calling this.  */
+  void (*omp_finish_decl_inits) (void);
 };
 
 /* Language hooks related to LTO serialization.  */
index edfac72bc7c5d46f633bbff5fd2d9b7e2ccd3860..46e5d8f84a4f06b512c685f160e4cda5a720190f 100644 (file)
@@ -297,7 +297,7 @@ omp_discover_declare_target_var_r (tree *tp, int *walk_subtrees, void *data)
          DECL_ATTRIBUTES (*tp)
            = remove_attribute ("omp declare target link", DECL_ATTRIBUTES (*tp));
        }
-      if (TREE_STATIC (*tp) && DECL_INITIAL (*tp))
+      if (TREE_STATIC (*tp) && lang_hooks.decls.omp_get_decl_init (*tp))
        ((vec<tree> *) data)->safe_push (*tp);
       DECL_ATTRIBUTES (*tp) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (*tp));
       symtab_node *node = symtab_node::get (*tp);
@@ -335,14 +335,15 @@ omp_discover_implicit_declare_target (void)
                 && DECL_STRUCT_FUNCTION (node->decl)->has_omp_target)
          worklist.safe_push (node->decl);
       }
-  FOR_EACH_STATIC_INITIALIZER (vnode)
-    if (omp_declare_target_var_p (vnode->decl))
+  FOR_EACH_VARIABLE (vnode)
+    if (lang_hooks.decls.omp_get_decl_init (vnode->decl)
+       && omp_declare_target_var_p (vnode->decl))
       worklist.safe_push (vnode->decl);
   while (!worklist.is_empty ())
     {
       tree decl = worklist.pop ();
       if (VAR_P (decl))
-       walk_tree_without_duplicates (&DECL_INITIAL (decl),
+       walk_tree_without_duplicates (lang_hooks.decls.omp_get_decl_init (decl),
                                      omp_discover_declare_target_var_r,
                                      &worklist);
       else if (omp_declare_target_fn_p (decl))
@@ -354,6 +355,8 @@ omp_discover_implicit_declare_target (void)
                                      omp_discover_declare_target_fn_r,
                                      &worklist);
     }
+
+  lang_hooks.decls.omp_finish_decl_inits ();
 }
 
 
index 4c4c33a73757b9e65642788ff06296afb90cdb49..bff88afbf0d9c42fec97c547e7bac0dce61203e1 100644 (file)
@@ -1,3 +1,10 @@
+2020-12-18  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+       Backport from mainline
+       2020-12-18  Kwok Cheung Yeung  <kcy@codesourcery.com>
+
+       * g++.dg/gomp/declare-target-3.C: New.
+
 2020-09-28  Tobias Burnus  <tobias@codesourcery.com>
 
        * c-c++-common/gomp/pr94874.c: Update scan-tree-dump.
diff --git a/gcc/testsuite/g++.dg/gomp/declare-target-3.C b/gcc/testsuite/g++.dg/gomp/declare-target-3.C
new file mode 100644 (file)
index 0000000..8e9eafc
--- /dev/null
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+// Test implicit marking of declare target to.
+
+int foo () { return 1; }
+int bar () { return 2; }       // Implicitly marked (due to b)
+int baz () { return 3; }       // Implicitly marked (due to d via c)
+int qux () { return 4; }       // Implicitly marked (due to g via f and e)
+
+int a = foo ();
+int b = bar ();        // Explicitly marked
+int c = baz ();        // Implicitly marked (due to d)
+int *d = &c;   // Explicitly marked
+int e = qux ();        // Implicitly marked (due to g via f)
+int f = e + 1; // Implicitly marked (due to g)
+int *g = &f;   // Explicitly marked
+
+#pragma omp declare target to(b, d, g)
+
+// { dg-final { scan-tree-dump-not "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nfoo \\\(\\\)" "gimple" } }
+// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nbar \\\(\\\)" "gimple" } }
+// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nbaz \\\(\\\)" "gimple" } }
+// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nqux \\\(\\\)" "gimple" } }
+// { dg-final { scan-assembler-not "\\\.offload_var_table:\\n.+\\\.quad\\s+a" } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+b" } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+c" } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+d" } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+e" } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+f" } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+g" } }