From patchwork Tue Sep 10 10:19:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tobias Burnus X-Patchwork-Id: 1983132 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=ZDfL7yVp; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4X307l3KTXz1y1S for ; Tue, 10 Sep 2024 20:20:03 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1FAA9385840C for ; Tue, 10 Sep 2024 10:20:01 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [IPv6:2a00:1450:4864:20::635]) by sourceware.org (Postfix) with ESMTPS id AA61F385841E for ; Tue, 10 Sep 2024 10:19:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AA61F385841E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org AA61F385841E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::635 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725963581; cv=none; b=rYJmFM3EiPeUbMafDYbqftldyZyHOn8wgV+YNgPMQ2Fklwb31aeegqvv+SKQTfYwodhgaUaPKo9t3gc0p6Osvock1M40rvG9sDuFdCWrkQne69RIod4EkvdW25WgArhnrZmIfuwQoEKWDz4VQLxJpDLq3FWZpHAicrtEkUPxLWg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725963581; c=relaxed/simple; bh=4meaNuKfiMUE94IOR9B+eEskfvE6z9LGHD6FhcQFRyU=; h=DKIM-Signature:Message-ID:Date:MIME-Version:To:From:Subject; b=rZh5kosXcI/NKElvigdzvGTHHcdF2uBX1FfVpAsLqwKXPhe6ypcytRRmbs7tICoMOActAEdU9CYAynEnel32kVFXR7ujQIEvQieZ+OscxMxSR3xBOHV+KwIxWJcONZ/xB+uUyQ6xIC1G3jnzg/MEqJPW9tQT884Am9eKAj9scU4= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-ej1-x635.google.com with SMTP id a640c23a62f3a-a8d6ac24a3bso245354466b.1 for ; Tue, 10 Sep 2024 03:19:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1725963575; x=1726568375; darn=gcc.gnu.org; h=subject:from:to:content-language:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=ZEpqm8LeGx3bo47aFc8xW0ouiSHHAa/nvQ28fMNxefA=; b=ZDfL7yVp81tTdTPRfZRLUZv/4KCyYSJKHHX8nC2j2/O33kZdwrhs6HkX0T3v0vo1Fx bv12apwBqfC41V66wDFUtqIIUHUjVbqOlfUoVfbRv7g/+kuEnt5XZ90hIb7aMUh58Bj4 xJfrpGZp6v/SQxKSBlBV45YmKio+FmfE5BmC/uxqwjlxnWVcJ3mr51hKgd3l/PrnUiRb 1cC+RcBDVYfQZu7K06dx/d4SyJoyYcZG0SaN7NHN+jl4totjn9JWLprCc1JPCNd0M58D B4EuLuW/prpblz1eZv4bML8Mtbc7XjZiSH5s9JyxjDfcxIVo0aoEXyUfttXe7/mGiluL M9aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725963575; x=1726568375; h=subject:from:to:content-language:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=ZEpqm8LeGx3bo47aFc8xW0ouiSHHAa/nvQ28fMNxefA=; b=YbC4v8NbSCd3h3RG8sIK1dEK75HzP8b0ot2RMwF6WnvozOO3jdigc2v+vAAQWz5Xdq RRTTotYBd9IFiZl6/PwDsak5jktTHzF3HKJec0tp/cGH5Nb6H7nQdxAux1vxFeWajR+8 639tl87IBU9Po4mtH4EVSSqRkC3A4PYrS7qnBVh91H4niNeksdn0F/EGxfeKay98WHx7 9tAh2L9WSSjWZ/R4KkAo3YgfrLzz71YOnKpUw/fSEwrjEgMEG3+LwJesRI5JPqd3+2e4 wPZ5nguyTG7HDCB37BN0bmTVeY72D69DgG8zmvdaWwNCcn0uBNDcfbp6dJtCWNNURnuT TPCQ== X-Gm-Message-State: AOJu0YzOF5IwcF+utwy8UtnRqWgYNzwoTZU0xZ27Ptg708W8m4TmgBC9 BCzI2HZZkyBhlgJjhTTqItt5Q34Zt/z+Gek/WQzZDJYnO/egrXUb1LXNHOOOGtD5bcqlUxH0suo + X-Google-Smtp-Source: AGHT+IHj9yE76vn1onCbmxF2TVgJaoyKHqQJQ0KkrnlrLAjIMgu0o4E/SSYOVjXFSKH2g11ffkADyA== X-Received: by 2002:a17:907:ea9:b0:a8b:58e3:ac1f with SMTP id a640c23a62f3a-a8ffb20fe17mr23164466b.12.1725963575008; Tue, 10 Sep 2024 03:19:35 -0700 (PDT) Received: from ?IPV6:2001:16b8:3dc5:d00:9e8c:aea3:fd3:a6f4? ([2001:16b8:3dc5:d00:9e8c:aea3:fd3:a6f4]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a8d25d63bebsm459594166b.207.2024.09.10.03.19.34 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 10 Sep 2024 03:19:34 -0700 (PDT) Message-ID: Date: Tue, 10 Sep 2024 12:19:33 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: gcc-patches , Jakub Jelinek From: Tobias Burnus Subject: [Patch][RFC] Fortran/OpenMP: Middle-end support for mapping of DT with allocatable components X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Background: OpenMP states that for 'map(var)', all allocatable components of 'var' will automatically also be mapped ('deep mapping'). Thus, for type(t), allocatable :: var(:) this leads to a pseudo code like: map(var, storage_size(var)) do i = lbound(var), ubound(var) if (allocated(var(i)%comp1) & map(var(i)%comp1, storage_size(var(i)%comp1)) end do and more complicated, e.g. var(1204)%comp1(395)%str might be an allocatable scalar. Or var is an recursive type, e.g. it has 'type(t), allocatable :: self' as component such that var%self%self%self%self ... might exist (and 'self' could also be an array …). * * * Approach: The idea is to handle it inlower_omp_target as follows (semi-pseudocode): /* Obtain number of additional mappings, in the example above, it would be size(var) * 2 for map + attach of 'comp1', assuming all 'var(:)%comp1' are allocated and no other alloc comp. exist. */ tree cnt = lang_hooks.decls.omp_deep_mapping_cnt (...) if (cnt) deep_map_cnt *= cnt; if (cnt) → switch to pointer type + dynamically allocate addrs, kinds, sizes → add 'uintptr_t s[]' as tailing member to addr struct. (Thus, all automatically mapped items are added to the end.) In the big map loop, call additionally: lang_hooks.decls.omp_deep_mapping Additionally, in some cases, the only question that needs to be solved is: Does the decl have an allocatable component or not. In that case, lang_hooks.decls.omp_deep_mapping_p is sufficient. * * * RFC: Does this approach sound sensible? Does the attached patch (middle-end part) look reasonable? One downside of the current approach is that for map(var) when 'var' is present we still attempt to map all allocatable components instead of stopping directly after finding 'var' in the splay table. this can be fixed by passing more attributes to libgomp, but as the items come last in the list, it might be not straight forward. (maybe a starts-here + ends-here flags, where the attach next to starts-here flag could be used to do the lookup?). This might also lead to cases where an allocatable variable is mapped that otherwise would not be mapped. Albeit as 'map(var%comp)' of a later allocated 'comp' is only guaranteed to work with the 'always' modifier, having it automapped for 'map(var)' should at least not affect the values that were mapped. * * * The full patch has been applied to OG14 (= devel/omp/gcc-14) branch. The interesting bit are the hook entry points gfc_omp_deep_mapping_p, gfc_omp_deep_mapping_cnt, and gfc_omp_deep_mapping → https://github.com/gcc-mirror/gcc/blob/devel/omp/gcc-14/gcc/fortran/trans-openmp.cc#L3068-L3209 * * * I have attached the middle-end patch, only, of the patch: https://gcc.gnu.org/g:92c3af3d4f8 Fortran/OpenMP: Support mapping of DT with allocatable components to focus on that part. Tobias PS: In TR13 and also after TR13, a couple of mapping features were added that permit shallow mapping, unmapping of allocatable components etc. I have not tried to analyze whether this affects this patch, but I think it remains largely as is. Fortran/OpenMP: Middle-end support for mapping of DT with allocatable components gcc/ChangeLog: * langhooks-def.h (lhd_omp_deep_mapping_p, lhd_omp_deep_mapping_cnt, lhd_omp_deep_mapping): New. (LANG_HOOKS_OMP_DEEP_MAPPING_P, LANG_HOOKS_OMP_DEEP_MAPPING_CNT, LANG_HOOKS_OMP_DEEP_MAPPING): Define. (LANG_HOOKS_DECLS): Use it. * langhooks.cc (lhd_omp_deep_mapping_p, lhd_omp_deep_mapping_cnt, lhd_omp_deep_mapping): New stubs. * langhooks.h (struct lang_hooks_for_decls): Add new hooks * omp-expand.cc (expand_omp_target): Handle dynamic-size addr/sizes/kinds arrays. * omp-low.cc (build_sender_ref, fixup_child_record_type, scan_sharing_clauses, lower_omp_target): Update to handle new hooks and dynamic-size addr/sizes/kinds arrays. --- gcc/langhooks-def.h | 10 +++ gcc/langhooks.cc | 24 ++++++ gcc/langhooks.h | 15 ++++ gcc/omp-expand.cc | 18 ++++- gcc/omp-low.cc | 224 ++++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 265 insertions(+), 26 deletions(-) diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index f5c67b6823c..756714558e5 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -86,6 +86,10 @@ extern enum omp_clause_defaultmap_kind lhd_omp_predetermined_mapping (tree); extern tree lhd_omp_assignment (tree, tree, tree); extern void lhd_omp_finish_clause (tree, gimple_seq *, bool); extern tree lhd_omp_array_size (tree, gimple_seq *); +extern bool lhd_omp_deep_mapping_p (const gimple *, tree); +extern tree lhd_omp_deep_mapping_cnt (const gimple *, tree, gimple_seq *); +extern void lhd_omp_deep_mapping (const gimple *, tree, unsigned HOST_WIDE_INT, + tree, tree, tree, tree, tree, gimple_seq *); struct gimplify_omp_ctx; extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, tree); @@ -272,6 +276,9 @@ extern tree lhd_unit_size_without_reusable_padding (tree); #define LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR NULL #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_DEEP_MAPPING_P lhd_omp_deep_mapping_p +#define LANG_HOOKS_OMP_DEEP_MAPPING_CNT lhd_omp_deep_mapping_cnt +#define LANG_HOOKS_OMP_DEEP_MAPPING lhd_omp_deep_mapping #define LANG_HOOKS_OMP_ALLOCATABLE_P hook_bool_tree_false #define LANG_HOOKS_OMP_SCALAR_P lhd_omp_scalar_p #define LANG_HOOKS_OMP_SCALAR_TARGET_P hook_bool_tree_false @@ -306,6 +313,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_DEEP_MAPPING_P, \ + LANG_HOOKS_OMP_DEEP_MAPPING_CNT, \ + LANG_HOOKS_OMP_DEEP_MAPPING, \ LANG_HOOKS_OMP_ALLOCATABLE_P, \ LANG_HOOKS_OMP_SCALAR_P, \ LANG_HOOKS_OMP_SCALAR_TARGET_P, \ diff --git a/gcc/langhooks.cc b/gcc/langhooks.cc index 8614f44f187..ac844204288 100644 --- a/gcc/langhooks.cc +++ b/gcc/langhooks.cc @@ -642,6 +642,30 @@ lhd_omp_array_size (tree, gimple_seq *) return NULL_TREE; } +/* Returns true when additional mappings for a decl are needed. */ + +bool +lhd_omp_deep_mapping_p (const gimple *, tree) +{ + return false; +} + +/* Returns number of additional mappings for a decl. */ + +tree +lhd_omp_deep_mapping_cnt (const gimple *, tree, gimple_seq *) +{ + return NULL_TREE; +} + +/* Do the additional mappings. */ + +void +lhd_omp_deep_mapping (const gimple *, tree, unsigned HOST_WIDE_INT, tree, tree, + tree, tree, tree, gimple_seq *) +{ +} + /* Return true if DECL is a scalar variable (for the purpose of implicit firstprivatization & mapping). Only if alloc_ptr_ok are allocatables and pointers accepted. */ diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 5a4dfb6ef62..b4bd0771976 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -313,6 +313,21 @@ struct lang_hooks_for_decls /* Do language specific checking on an implicitly determined clause. */ void (*omp_finish_clause) (tree clause, gimple_seq *pre_p, bool); + /* Additional language-specific mappings for a decl; returns true + if those may occur. */ + bool (*omp_deep_mapping_p) (const gimple *ctx_stmt, tree clause); + + /* Additional language-specific mappings for a decl; returns the + number of additional mappings needed. */ + tree (*omp_deep_mapping_cnt) (const gimple *ctx_stmt, tree clause, + gimple_seq *seq); + + /* Do the actual additional language-specific mappings for a decl. */ + void (*omp_deep_mapping) (const gimple *stmt, tree clause, + unsigned HOST_WIDE_INT tkind, + tree data, tree sizes, tree kinds, + tree offset_data, tree offset, gimple_seq *seq); + /* Return true if DECL is an allocatable variable (for the purpose of implicit mapping). */ bool (*omp_allocatable_p) (tree decl); diff --git a/gcc/omp-expand.cc b/gcc/omp-expand.cc index 24287826444..9ff9553c3ea 100644 --- a/gcc/omp-expand.cc +++ b/gcc/omp-expand.cc @@ -9928,8 +9928,9 @@ expand_omp_target (struct omp_region *region) /* We're ignoring the subcode because we're effectively doing a STRIP_NOPS. */ - if (TREE_CODE (arg) == ADDR_EXPR - && TREE_OPERAND (arg, 0) == sender) + if ((TREE_CODE (arg) == ADDR_EXPR + && TREE_OPERAND (arg, 0) == sender) + || arg == sender) { tgtcopy_stmt = stmt; break; @@ -10428,7 +10429,7 @@ expand_omp_target (struct omp_region *region) t3 = t2; t4 = t2; } - else + else if (TREE_VEC_LENGTH (t) == 3 || is_gimple_omp_oacc (entry_stmt)) { t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1)))); t1 = size_binop (PLUS_EXPR, t1, size_int (1)); @@ -10436,6 +10437,17 @@ expand_omp_target (struct omp_region *region) t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1)); t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2)); } + else + { + t1 = force_gimple_operand_gsi (&gsi, TREE_VEC_ELT (t, 3), true, NULL_TREE, + true, GSI_SAME_STMT); + t2 = force_gimple_operand_gsi (&gsi, TREE_VEC_ELT (t, 0), true, NULL_TREE, + true, GSI_SAME_STMT); + t3 = force_gimple_operand_gsi (&gsi, TREE_VEC_ELT (t, 1), true, NULL_TREE, + true, GSI_SAME_STMT); + t4 = force_gimple_operand_gsi (&gsi, TREE_VEC_ELT (t, 2), true, NULL_TREE, + true, GSI_SAME_STMT); + } gimple *g; bool tagging = false; diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc index 241f79e34a9..da2051b0279 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -767,7 +767,10 @@ static tree build_sender_ref (splay_tree_key key, omp_context *ctx) { tree field = lookup_sfield (key, ctx); - return omp_build_component_ref (ctx->sender_decl, field); + tree tmp = ctx->sender_decl; + if (POINTER_TYPE_P (TREE_TYPE (tmp))) + tmp = build_fold_indirect_ref (tmp); + return omp_build_component_ref (tmp, field); } static tree @@ -1138,7 +1141,9 @@ fixup_child_record_type (omp_context *ctx) type = build_qualified_type (type, TYPE_QUAL_CONST); TREE_TYPE (ctx->receiver_decl) - = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT); + = build_qualified_type (flexible_array_type_p (type) + ? build_pointer_type (type) + : build_reference_type (type), TYPE_QUAL_RESTRICT); } /* Instantiate decls as necessary in CTX to satisfy the data sharing @@ -1149,6 +1154,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) { tree c, decl; bool scan_array_reductions = false; + bool flex_array_ptr = false; for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE @@ -1596,6 +1602,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)) break; } + if (!flex_array_ptr) + flex_array_ptr = lang_hooks.decls.omp_deep_mapping_p (ctx->stmt, c); if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && DECL_P (decl) && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH @@ -2009,6 +2017,18 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)) scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx); } + if (flex_array_ptr) + { + tree field = build_range_type (size_type_node, + build_int_cstu (size_type_node, 0), + NULL_TREE); + field = build_array_type (ptr_type_node, field); + field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, field); + SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node)); + DECL_CONTEXT (field) = ctx->record_type; + DECL_CHAIN (field) = TYPE_FIELDS (ctx->record_type); + TYPE_FIELDS (ctx->record_type) = field; + } } /* Create a new name for omp child function. Returns an identifier. */ @@ -12603,6 +12623,11 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) unsigned int map_cnt = 0; tree in_reduction_clauses = NULL_TREE; + tree deep_map_cnt = NULL_TREE; + tree deep_map_data = NULL_TREE; + tree deep_map_offset_data = NULL_TREE; + tree deep_map_offset = NULL_TREE; + offloaded = is_gimple_omp_offloaded (stmt); switch (gimple_omp_target_kind (stmt)) { @@ -12681,6 +12706,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) push_gimplify_context (); fplist = NULL; + ilist = NULL; + olist = NULL; for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) switch (OMP_CLAUSE_CODE (c)) { @@ -12739,6 +12766,16 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) case OMP_CLAUSE_FROM: oacc_firstprivate: var = OMP_CLAUSE_DECL (c); + { + tree extra = lang_hooks.decls.omp_deep_mapping_cnt (stmt, c, &ilist); + if (extra != NULL_TREE && deep_map_cnt != NULL_TREE) + deep_map_cnt = fold_build2_loc (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, + size_type_node, deep_map_cnt, + extra); + else if (extra != NULL_TREE) + deep_map_cnt = extra; + } + if (!DECL_P (var)) { if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP @@ -12973,18 +13010,31 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) record_vars_into (gimple_bind_vars (tgt_bind), child_fn); } - olist = NULL; - ilist = NULL; if (ctx->record_type) { + if (deep_map_cnt && TREE_CODE (deep_map_cnt) == INTEGER_CST) + /* map_cnt = map_cnt + tree_to_hwi (deep_map_cnt); */ + /* deep_map_cnt = NULL_TREE; */ + gcc_unreachable (); + else if (deep_map_cnt) + { + gcc_assert (flexible_array_type_p (ctx->record_type)); + tree n = create_tmp_var_raw (size_type_node, "nn_map"); + gimple_add_tmp_var (n); + gimplify_assign (n, deep_map_cnt, &ilist); + deep_map_cnt = n; + } ctx->sender_decl - = create_tmp_var (ctx->record_type, ".omp_data_arr"); + = create_tmp_var (deep_map_cnt ? build_pointer_type (ctx->record_type) + : ctx->record_type, ".omp_data_arr"); DECL_NAMELESS (ctx->sender_decl) = 1; TREE_ADDRESSABLE (ctx->sender_decl) = 1; - t = make_tree_vec (3); + t = make_tree_vec (deep_map_cnt ? 4 : 3); TREE_VEC_ELT (t, 0) = ctx->sender_decl; TREE_VEC_ELT (t, 1) - = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt), + = create_tmp_var (deep_map_cnt + ? build_pointer_type (size_type_node) + : build_array_type_nelts (size_type_node, map_cnt), ".omp_data_sizes"); DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1; TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1; @@ -12992,13 +13042,65 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) tree tkind_type = short_unsigned_type_node; int talign_shift = 8; TREE_VEC_ELT (t, 2) - = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt), + = create_tmp_var (deep_map_cnt + ? build_pointer_type (tkind_type) + : build_array_type_nelts (tkind_type, map_cnt), ".omp_data_kinds"); DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1; TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1; TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1; gimple_omp_target_set_data_arg (stmt, t); + if (deep_map_cnt) + { + tree tmp, size; + size = create_tmp_var (size_type_node, NULL); + DECL_NAMELESS (size) = 1; + gimplify_assign (size, + fold_build2_loc (UNKNOWN_LOCATION, PLUS_EXPR, + size_type_node, deep_map_cnt, + build_int_cst (size_type_node, + map_cnt)), &ilist); + TREE_VEC_ELT (t, 3) = size; + + tree call = builtin_decl_explicit (BUILT_IN_MALLOC); + size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR, + size_type_node, deep_map_cnt, + TYPE_SIZE_UNIT (ptr_type_node)); + size = fold_build2_loc (UNKNOWN_LOCATION, PLUS_EXPR, + size_type_node, size, + TYPE_SIZE_UNIT (ctx->record_type)); + tmp = build_call_expr_loc (input_location, call, 1, size); + gimplify_assign (ctx->sender_decl, tmp, &ilist); + + size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR, + size_type_node, TREE_VEC_ELT (t, 3), + TYPE_SIZE_UNIT (size_type_node)); + tmp = build_call_expr_loc (input_location, call, 1, size); + gimplify_assign (TREE_VEC_ELT (t, 1), tmp, &ilist); + + size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR, + size_type_node, TREE_VEC_ELT (t, 3), + TYPE_SIZE_UNIT (tkind_type)); + tmp = build_call_expr_loc (input_location, call, 1, size); + gimplify_assign (TREE_VEC_ELT (t, 2), tmp, &ilist); + tree field = TYPE_FIELDS (TREE_TYPE (TREE_TYPE (ctx->sender_decl))); + for ( ; DECL_CHAIN (field) != NULL_TREE; field = DECL_CHAIN (field)) + ; + gcc_assert (TREE_CODE (TREE_TYPE (field))); + tmp = build_fold_indirect_ref (ctx->sender_decl); + deep_map_data = omp_build_component_ref (tmp, field); + deep_map_offset_data = create_tmp_var_raw (size_type_node, + "map_offset_data"); + deep_map_offset = create_tmp_var_raw (size_type_node, "map_offset"); + gimple_add_tmp_var (deep_map_offset_data); + gimple_add_tmp_var (deep_map_offset); + gimplify_assign (deep_map_offset_data, build_int_cst (size_type_node, + 0), &ilist); + gimplify_assign (deep_map_offset, build_int_cst (size_type_node, + map_cnt), &ilist); + } + vec *vsize; vec *vkind; vec_alloc (vsize, map_cnt); @@ -13025,6 +13127,24 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) || (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))) break; + if (deep_map_cnt) + { + unsigned HOST_WIDE_INT tkind2; + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_MAP: tkind2 = OMP_CLAUSE_MAP_KIND (c); break; + case OMP_CLAUSE_FIRSTPRIVATE: tkind2 = GOMP_MAP_TO; break; + case OMP_CLAUSE_TO: tkind2 = GOMP_MAP_TO; break; + case OMP_CLAUSE_FROM: tkind2 = GOMP_MAP_FROM; break; + default: gcc_unreachable (); + } + lang_hooks.decls.omp_deep_mapping (stmt, c, tkind2, + deep_map_data, + TREE_VEC_ELT (t, 1), + TREE_VEC_ELT (t, 2), + deep_map_offset_data, + deep_map_offset, &ilist); + } if (!DECL_P (ovar)) { if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP @@ -13586,23 +13706,65 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) gcc_assert (map_idx == map_cnt); - DECL_INITIAL (TREE_VEC_ELT (t, 1)) - = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize); - DECL_INITIAL (TREE_VEC_ELT (t, 2)) - = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind); + if (!deep_map_cnt) + { + DECL_INITIAL (TREE_VEC_ELT (t, 1)) + = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize); + DECL_INITIAL (TREE_VEC_ELT (t, 2)) + = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind); + } for (int i = 1; i <= 2; i++) - if (!TREE_STATIC (TREE_VEC_ELT (t, i))) + if (deep_map_cnt || !TREE_STATIC (TREE_VEC_ELT (t, i))) { + tree tmp = TREE_VEC_ELT (t, i); + if (deep_map_cnt) + { + const char *prefix = (i == 1 ? ".omp_data_sizes0" + : ".omp_data_kinds0"); + tree type = (i == 1) ? size_type_node : tkind_type; + type = build_array_type_nelts (type, map_cnt); + tree var = create_tmp_var (type, prefix); + DECL_NAMELESS (var) = 1; + TREE_ADDRESSABLE (var) = 1; + TREE_STATIC (var) = TREE_STATIC (tmp); + DECL_INITIAL (var) = build_constructor (type, i == 1 + ? vsize : vkind); + tmp = var; + TREE_STATIC (TREE_VEC_ELT (t, i)) = 0; + } + gimple_seq initlist = NULL; - force_gimple_operand (build1 (DECL_EXPR, void_type_node, - TREE_VEC_ELT (t, i)), + force_gimple_operand (build1 (DECL_EXPR, void_type_node, tmp), &initlist, true, NULL_TREE); gimple_seq_add_seq (&ilist, initlist); - tree clobber = build_clobber (TREE_TYPE (TREE_VEC_ELT (t, i))); - gimple_seq_add_stmt (&olist, - gimple_build_assign (TREE_VEC_ELT (t, i), - clobber)); + if (deep_map_cnt) + { + tree tmp2; + tree call = builtin_decl_explicit (BUILT_IN_MEMCPY); + tmp2 = TYPE_SIZE_UNIT (TREE_TYPE (tmp)); + call = build_call_expr_loc (input_location, call, 3, + TREE_VEC_ELT (t, i), + build_fold_addr_expr (tmp), tmp2); + gimplify_and_add (call, &ilist); + } + + if (!TREE_STATIC (tmp)) + { + tree clobber = build_clobber (TREE_TYPE (tmp)); + gimple_seq_add_stmt (&olist, + gimple_build_assign (tmp, clobber)); + } + if (deep_map_cnt) + { + tmp = TREE_VEC_ELT (t, i); + tree call = builtin_decl_explicit (BUILT_IN_FREE); + call = build_call_expr_loc (input_location, call, 1, tmp); + gimplify_and_add (call, &olist); + tree clobber = build_clobber (TREE_TYPE (tmp)); + gimple_seq_add_stmt (&olist, + gimple_build_assign (tmp, clobber)); + } } else if (omp_maybe_offloaded_ctx (ctx->outer)) { @@ -13622,7 +13784,18 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) } } - tree clobber = build_clobber (ctx->record_type); + if (deep_map_cnt) + { + tree call = builtin_decl_explicit (BUILT_IN_FREE); + call = build_call_expr_loc (input_location, call, 1, + TREE_VEC_ELT (t, 0)); + gimplify_and_add (call, &olist); + + gimplify_expr (&TREE_VEC_ELT (t, 1), &ilist, NULL, is_gimple_val, + fb_rvalue); + } + + tree clobber = build_clobber (TREE_TYPE (ctx->sender_decl)); gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl, clobber)); } @@ -13635,11 +13808,16 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) if (offloaded && ctx->record_type) { - t = build_fold_addr_expr_loc (loc, ctx->sender_decl); + t = ctx->sender_decl; + if (!deep_map_cnt) + t = build_fold_addr_expr_loc (loc, t); /* fixup_child_record_type might have changed receiver_decl's type. */ t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t); - gimple_seq_add_stmt (&new_body, - gimple_build_assign (ctx->receiver_decl, t)); + if (!AGGREGATE_TYPE_P (TREE_TYPE (ctx->sender_decl))) + gimplify_assign (ctx->receiver_decl, t, &new_body); + else + gimple_seq_add_stmt (&new_body, + gimple_build_assign (ctx->receiver_decl, t)); } gimple_seq_add_seq (&new_body, fplist);