From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25576 invoked by alias); 14 Feb 2014 15:02:00 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 25566 invoked by uid 89); 14 Feb 2014 15:02:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 14 Feb 2014 15:01:57 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1WEKH2-000014-Si from Bernd_Schmidt@mentor.com ; Fri, 14 Feb 2014 07:01:52 -0800 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Fri, 14 Feb 2014 07:01:52 -0800 Received: from [127.0.0.1] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.2.247.3; Fri, 14 Feb 2014 15:01:50 +0000 Message-ID: <52FE2FDA.5010106@codesourcery.com> Date: Fri, 14 Feb 2014 15:02:00 -0000 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 MIME-Version: 1.0 To: Ilya Verbin , Thomas Schwinge CC: "Michael V. Zolotukhin" , Jakub Jelinek , Richard Biener , Kirill Yukhin , Andrey Turetskiy , Ilya Tocar , gcc , Nathan Sidwell Subject: Re: Fwd: [RFC][gomp4] Offloading patches (2/3): Add tables generation References: <20131217113957.GA39975@msticlxl57.ims.intel.com> <52E7927B.8030509@codesourcery.com> <52E9137C.4020706@codesourcery.com> In-Reply-To: Content-Type: multipart/mixed; boundary="------------070605070908080802000201" X-SW-Source: 2014-02/txt/msg00920.txt.bz2 --------------070605070908080802000201 Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1003 On 02/14/2014 03:49 PM, Ilya Verbin wrote: > Hi Bernd and Thomas, > > Are you planning to support offloading from DSO in PTX/CUDA > environment? If yes, how are you going to solve the problem of the > collision of function names from different DSOs? What I'm currently trying to do is to use get_file_function_name, which should provide a unique string that can be used to look up an offloaded function. That was suggested by Nathan Sidwell, I'd forgotten that such a function existed. I haven't actually given thought to whether that'll be unique across multiple DSOs, but as long as we also pass a value to the libgomp registration function that is unique per DSO, that shouldn't really matter - we should be able to reliably look up a function given these two keys. I'm attaching a work-in-progress patch, which is based on patch #2 of Michael Zolotukhin's series. Does this look like something you could also work with? I should have something a little more complete next week. Bernd --------------070605070908080802000201 Content-Type: text/x-patch; name="omp-unique.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="omp-unique.diff" Content-length: 10812 Index: gomp-4_0-branch/gcc/cgraphunit.c =================================================================== --- gomp-4_0-branch.orig/gcc/cgraphunit.c +++ gomp-4_0-branch/gcc/cgraphunit.c @@ -206,6 +206,7 @@ along with GCC; see the file COPYING3. #include "pass_manager.h" #include "tree-nested.h" #include "gimplify.h" +#include "omp-low.h" #include "lto-section-names.h" /* Queue of cgraph nodes scheduled to be added into cgraph. This is a @@ -2019,6 +2020,8 @@ ipa_passes (void) execute_ipa_summary_passes ((struct ipa_opt_pass_d *) passes->all_regular_ipa_passes); + + omp_finish_file (); } /* Some targets need to handle LTO assembler output specially. */ Index: gomp-4_0-branch/gcc/lto-streamer-out.c =================================================================== --- gomp-4_0-branch.orig/gcc/lto-streamer-out.c +++ gomp-4_0-branch/gcc/lto-streamer-out.c @@ -498,6 +498,7 @@ DFS_write_tree_body (struct output_block special handling in LTO, it must be handled by streamer hooks. */ DFS_follow_tree_edge (DECL_ATTRIBUTES (expr)); + DFS_follow_tree_edge (DECL_UNIQUE_ID (expr)); /* Do not follow DECL_ABSTRACT_ORIGIN. We cannot handle debug information for early inlining so drop it on the floor instead of ICEing in Index: gomp-4_0-branch/gcc/omp-low.c =================================================================== --- gomp-4_0-branch.orig/gcc/omp-low.c +++ gomp-4_0-branch/gcc/omp-low.c @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. #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" @@ -191,7 +192,6 @@ struct omp_for_data struct omp_for_data_loop *loops; }; - static splay_tree all_contexts; static int taskreg_nesting_level; static int target_nesting_level; @@ -1889,6 +1889,7 @@ create_omp_child_function (omp_context * DECL_EXTERNAL (decl) = 0; DECL_CONTEXT (decl) = NULL_TREE; DECL_INITIAL (decl) = make_node (BLOCK); + bool target_p = false; if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (current_function_decl))) @@ -12379,4 +12380,158 @@ make_pass_omp_simd_clone (gcc::context * return new pass_omp_simd_clone (ctxt); } +struct ctor_elt_data +{ + vec *v; + char *buffer; + HOST_WIDE_INT offset; + tree string_decl; +}; + +static void +make_constructor_elts (tree decl, struct ctor_elt_data *d) +{ + const char *str = IDENTIFIER_POINTER (DECL_UNIQUE_ID (decl)); + size_t len = strlen (str) + 1; + memcpy (d->buffer + d->offset, str, len); + tree str_addr = build_fold_addr_expr (d->string_decl); + tree off = build_int_cst (size_type_node, d->offset); + d->offset += len; + + CONSTRUCTOR_APPEND_ELT (d->v, NULL_TREE, build_fold_addr_expr (decl)); + CONSTRUCTOR_APPEND_ELT (d->v, NULL_TREE, + fold_build_pointer_plus (str_addr, off)); +} + +static void +make_unique_name (tree decl) +{ + tree name = DECL_NAME (decl); + char *p = (char *)alloca (strlen (IDENTIFIER_POINTER (name)) + 3); + p[0] = 'O'; + p[1] = '_'; + strcpy (p + 2, IDENTIFIER_POINTER (name)); + tree id = get_file_function_name (p); + DECL_UNIQUE_ID (decl) = id; +} + +static size_t +build_unique_names (size_t *plen) +{ + int n = 0; + size_t len = 0; + /* Collect all omp-target functions. */ + struct cgraph_node *node; + FOR_EACH_DEFINED_FUNCTION (node) + { + if (!lookup_attribute ("omp declare target", + DECL_ATTRIBUTES (node->decl)) + || !DECL_ARTIFICIAL (node->decl)) + continue; + n++; + if (!in_lto_p) + make_unique_name (node->decl); + else + len += strlen (IDENTIFIER_POINTER (DECL_UNIQUE_ID (node->decl))) + 1; + } + /* Collect all omp-target global variables. */ + struct varpool_node *vnode; + 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; + + n++; + if (!in_lto_p) + make_unique_name (vnode->decl); + else + len += strlen (IDENTIFIER_POINTER (DECL_UNIQUE_ID (vnode->decl))) + 1; + } + *plen = len; + return n; +} + +/* Create new symbol containing (address, size) pairs for omp-marked + functions and global variables. */ +void +omp_finish_file () +{ + const char *section_name = ".offload_func_table_section"; + tree new_decl, new_decl_type; + vec *v; + tree ctor; + + size_t len; + int num = build_unique_names (&len); + + if (num == 0 || !in_lto_p || !targetm_common.have_named_sections) + return; + + vec_alloc (v, num); + + struct ctor_elt_data data; + tree array_type = build_array_type_nelts (char_type_node, len); + data.offset = 0; + data.buffer = (char *) xmalloc (len); + data.string_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, + get_file_function_name ("O"), + array_type); + DECL_ARTIFICIAL (data.string_decl) = 1; + TREE_STATIC (data.string_decl) = 1; + data.v = v; + + /* Collect all omp-target functions. */ + struct cgraph_node *node; + FOR_EACH_DEFINED_FUNCTION (node) + { + if (!lookup_attribute ("omp declare target", + DECL_ATTRIBUTES (node->decl)) + || !DECL_ARTIFICIAL (node->decl)) + continue; + make_constructor_elts (node->decl, &data); + } + /* Collect all omp-target global variables. */ + struct varpool_node *vnode; + 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; + + make_constructor_elts (vnode->decl, &data); + } + + if (data.offset == 0) + { + free (data.buffer); + return; + } + + tree cst = build_string (data.offset, data.buffer); + TREE_TYPE (cst) = build_array_type (char_type_node, + build_index_type (size_int (data.offset))); + DECL_INITIAL (data.string_decl) = cst; + free (data.buffer); + + varpool_assemble_decl (varpool_node_for_decl (data.string_decl)); + + 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" Index: gomp-4_0-branch/gcc/omp-low.h =================================================================== --- gomp-4_0-branch.orig/gcc/omp-low.h +++ gomp-4_0-branch/gcc/omp-low.h @@ -27,5 +27,6 @@ extern void omp_expand_local (basic_bloc 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 */ Index: gomp-4_0-branch/gcc/toplev.c =================================================================== --- gomp-4_0-branch.orig/gcc/toplev.c +++ gomp-4_0-branch/gcc/toplev.c @@ -78,6 +78,7 @@ along with GCC; see the file COPYING3. #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 (); Index: gomp-4_0-branch/gcc/tree.c =================================================================== --- gomp-4_0-branch.orig/gcc/tree.c +++ gomp-4_0-branch/gcc/tree.c @@ -9078,7 +9078,8 @@ clean_symbol_name (char *p) I - for constructors D - for destructors N - for C++ anonymous namespaces - F - for DWARF unwind frame information. */ + F - for DWARF unwind frame information + O - for OpenMP/OpenACC target functions. */ tree get_file_function_name (const char *type) Index: gomp-4_0-branch/gcc/tree-core.h =================================================================== --- gomp-4_0-branch.orig/gcc/tree-core.h +++ gomp-4_0-branch/gcc/tree-core.h @@ -1366,6 +1366,10 @@ struct GTY(()) tree_decl_common { tree attributes; tree abstract_origin; + /* An IDENTIFIER_NODE used in omp-lower when offloading to + accelerator targets. */ + tree unique_id; + /* Points to a structure whose details depend on the language in use. */ struct lang_decl *lang_specific; }; Index: gomp-4_0-branch/gcc/tree.h =================================================================== --- gomp-4_0-branch.orig/gcc/tree.h +++ gomp-4_0-branch/gcc/tree.h @@ -2003,6 +2003,11 @@ extern void protected_set_expr_location #define DECL_ATTRIBUTES(NODE) \ (DECL_COMMON_CHECK (NODE)->decl_common.attributes) +/* In a DECL, an optional IDENTIFIER_NODE that holds a unique name for this + decl that is used when offloading to accelerator targets. */ +#define DECL_UNIQUE_ID(NODE) \ + (DECL_COMMON_CHECK (NODE)->decl_common.unique_id) + /* For a FUNCTION_DECL, holds the tree of BINDINGs. For a TRANSLATION_UNIT_DECL, holds the namespace's BLOCK. For a VAR_DECL, holds the initial value. Index: gomp-4_0-branch/gcc/tree-streamer-in.c =================================================================== --- gomp-4_0-branch.orig/gcc/tree-streamer-in.c +++ gomp-4_0-branch/gcc/tree-streamer-in.c @@ -658,6 +658,7 @@ lto_input_ts_decl_common_tree_pointers ( DECL_SIZE (expr) = stream_read_tree (ib, data_in); DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in); DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in); + DECL_UNIQUE_ID (expr) = stream_read_tree (ib, data_in); /* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information for early inlining so drop it on the floor instead of ICEing in Index: gomp-4_0-branch/gcc/tree-streamer-out.c =================================================================== --- gomp-4_0-branch.orig/gcc/tree-streamer-out.c +++ gomp-4_0-branch/gcc/tree-streamer-out.c @@ -593,6 +593,7 @@ write_ts_decl_common_tree_pointers (stru special handling in LTO, it must be handled by streamer hooks. */ stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p); + stream_write_tree (ob, DECL_UNIQUE_ID (expr), ref_p); /* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information for early inlining so drop it on the floor instead of ICEing in --------------070605070908080802000201--