Hi everybody,
Here is a patch 2/3: Add tables generation.
This patch is just a slightly modified patch sent a couple of weeks ago. When
compiling with '-fopenmp' compiler generates a special symbol, containing
addresses and sizes of globals/omp_fn-functions, and places it into a special
section. Later, at linking, these sections are merged together and we get a
single table with all addresses/sizes for entire binary. Also, in this patch we
start to pass '__OPENMP_TARGET__' symbol to GOMP_target calls.
Thanks,
Michael
---
gcc/omp-low.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
gcc/omp-low.h | 1 +
gcc/toplev.c | 3 +
3 files changed, 115 insertions(+), 8 deletions(-)
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index e0f7d1d..f860204 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h"
#include "cfgloop.h"
#include "target.h"
+#include "common/common-target.h"
#include "omp-low.h"
#include "gimple-low.h"
#include "tree-cfgcleanup.h"
@@ -8371,19 +8372,22 @@ expand_omp_target (struct omp_region *region)
}
gimple g;
- /* FIXME: This will be address of
- extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
- symbol, as soon as the linker plugin is able to create it for us. */
- tree openmp_target = build_zero_cst (ptr_type_node);
+ tree openmp_target
+ = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier ("__OPENMP_TARGET__"), ptr_type_node);
+ TREE_PUBLIC (openmp_target) = 1;
+ DECL_EXTERNAL (openmp_target) = 1;
if (kind == GF_OMP_TARGET_KIND_REGION)
{
tree fnaddr = build_fold_addr_expr (child_fn);
- g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
- device, fnaddr, openmp_target, t1, t2, t3, t4);
+ g = gimple_build_call (builtin_decl_explicit (start_ix), 7, device,
+ fnaddr, build_fold_addr_expr (openmp_target),
+ t1, t2, t3, t4);
}
else
- g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
- device, openmp_target, t1, t2, t3, t4);
+ g = gimple_build_call (builtin_decl_explicit (start_ix), 6, device,
+ build_fold_addr_expr (openmp_target),
+ t1, t2, t3, t4);
gimple_set_location (g, gimple_location (entry_stmt));
gsi_insert_before (&gsi, g, GSI_SAME_STMT);
if (kind != GF_OMP_TARGET_KIND_REGION)
@@ -12379,4 +12383,103 @@ make_pass_omp_simd_clone (gcc::context *ctxt)
return new pass_omp_simd_clone (ctxt);
}
+/* Helper function for omp_finish_file routine.
+ Takes decls from V_DECLS and adds their addresses and sizes to
+ constructor-vector V_CTOR. It will be later used as DECL_INIT for decl
+ representing a global symbol for OpenMP descriptor.
+ If IS_FUNCTION is true, we use 1 for size. */
+static void
+add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
+ vec<constructor_elt, va_gc> *v_ctor,
+ bool is_function)
+{
+ unsigned int len = 0, i;
+ tree size, it;
+ len = vec_safe_length (v_decls);
+ for (i = 0; i < len; i++)
+ {
+ /* Decls are placed in reversed order in fat-objects, so we need to
+ revert them back if we compile target. */
+ if (!flag_openmp_target)
+ it = (*v_decls)[i];
+ else
+ it = (*v_decls)[len - i - 1];
+ size = is_function ? integer_one_node : DECL_SIZE (it);
+ CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
+ CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
+ fold_convert (const_ptr_type_node,
+ size));
+ }
+}
+
+/* Create new symbol containing (address, size) pairs for omp-marked
+ functions and global variables. */
+void
+omp_finish_file (void)
+{
+ struct cgraph_node *node;
+ struct varpool_node *vnode;
+ const char *section_name = ".offload_func_table_section";
+ tree new_decl, new_decl_type;
+ vec<constructor_elt, va_gc> *v;
+ vec<tree, va_gc> *v_func, *v_var;
+ tree ctor;
+ int num = 0;
+
+ if (!targetm_common.have_named_sections)
+ return;
+
+ vec_alloc (v_func, 0);
+ vec_alloc (v_var, 0);
+
+ /* Collect all omp-target functions. */
+ FOR_EACH_DEFINED_FUNCTION (node)
+ {
+ /* TODO: This check could fail on functions, created by omp
+ parallel/task pragmas. It's better to name outlined for offloading
+ functions in some different way and to check here the function name.
+ It could be something like "*_omp_tgtfn" in contrast with "*_omp_fn"
+ for functions from omp parallel/task pragmas. */
+ if (!lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (node->decl))
+ || !DECL_ARTIFICIAL (node->decl))
+ continue;
+ vec_safe_push (v_func, node->decl);
+ num ++;
+ }
+ /* Collect all omp-target global variables. */
+ FOR_EACH_DEFINED_VARIABLE (vnode)
+ {
+ if (!lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (vnode->decl))
+ || TREE_CODE (vnode->decl) != VAR_DECL
+ || DECL_SIZE (vnode->decl) == 0)
+ continue;
+
+ vec_safe_push (v_var, vnode->decl);
+ num ++;
+ }
+
+ if (num == 0)
+ return;
+
+ vec_alloc (v, num * 2);
+
+ add_decls_addresses_to_decl_constructor (v_func, v, true);
+ add_decls_addresses_to_decl_constructor (v_var, v, false);
+
+ new_decl_type = build_array_type_nelts (pointer_sized_int_node, num * 2);
+ ctor = build_constructor (new_decl_type, v);
+ TREE_CONSTANT (ctor) = 1;
+ TREE_STATIC (ctor) = 1;
+ new_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier (".omp_table"), new_decl_type);
+ TREE_STATIC (new_decl) = 1;
+ DECL_INITIAL (new_decl) = ctor;
+ DECL_SECTION_NAME (new_decl) = build_string (strlen (section_name),
+ section_name);
+
+ varpool_assemble_decl (varpool_node_for_decl (new_decl));
+}
+
#include "gt-omp-low.h"
diff --git a/gcc/omp-low.h b/gcc/omp-low.h
index 6b5a2ff..813189d 100644
--- a/gcc/omp-low.h
+++ b/gcc/omp-low.h
@@ -27,5 +27,6 @@ extern void omp_expand_local (basic_block);
extern void free_omp_regions (void);
extern tree omp_reduction_init (tree, tree);
extern bool make_gimple_omp_edges (basic_block, struct omp_region **);
+extern void omp_finish_file (void);
#endif /* GCC_OMP_LOW_H */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 5fedcea..af010ff 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -78,6 +78,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-color.h"
#include "context.h"
#include "pass_manager.h"
+#include "omp-low.h"
#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
#include "dbxout.h"
@@ -576,6 +577,8 @@ compile_file (void)
if (flag_sanitize & SANITIZE_THREAD)
tsan_finish_file ();
+ omp_finish_file ();
+
output_shared_constant_pool ();
output_object_blocks ();
finish_tm_clone_pairs ();
--
1.7.1