From patchwork Wed Dec 18 06:03:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Brown X-Patchwork-Id: 1211985 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-516177-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="esSrVec0"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47d4Hp1JRTz9sS6 for ; Wed, 18 Dec 2019 17:05:41 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; q=dns; s= default; b=oIf3dEdNj9WDI1Jk5cDffsiUYPoKt/TyzxthAqRXJN0IqttykC/Lh go2kte2OVrm5dCMTzsCoceDfBm6fce9zPATM1TO+9+0wedM77rYJ8IcCna7i+U/v x98QYRNXvaXUNBO97RHoez06d3ykrjKtMzjCNk9I+8LHE9aIuANp6U= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s=default; bh=DYsfvPA3xNJHBaDtyp3HeT9cudY=; b=esSrVec0nGUJ3cWI540k3VRFq2k9 8VoIqnqsowEsUGvZBVQWxp+lcuD12pTEjbOmwPO2excxbTTHQwlU8dZtc+bVOHns njdUt0/ndRwAcshiSKZmPiw6uuxiuY3U9Ax8cXXbU/j9ZL9o+8pKfOoLLcJFxxiZ u0ZV/25WZuzsDUA= Received: (qmail 106208 invoked by alias); 18 Dec 2019 06:04:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 106145 invoked by uid 89); 18 Dec 2019 06:04:24 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.1 spammy=beware, 8496 X-HELO: esa4.mentor.iphmx.com Received: from esa4.mentor.iphmx.com (HELO esa4.mentor.iphmx.com) (68.232.137.252) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 18 Dec 2019 06:04:20 +0000 IronPort-SDR: /HKbA0CRhb4Mv1oviJjIaKa7TFBLhopBIPLnSs55uyWOQTmTZaHU02R4IVJKryvnoGFoqtohSq OoDGgtZ27g94FNVFPqM3Afp0e/ke9fao+sBivnhV6GO8zlmgRlehczi3x04GOqrWTojwCgj443 4mC2KOSdq5XDLBpIocs2GcPexE+/E7uJo7dhMiiC4CStDYG6pknACIHNcdulqAMO+o1P+06CMq m05BjQbLBtGQw7EExydKcZyqBHVBK+OhF5/AH5tv8lcPcpgSpOs7ZDHC3Rw1bECyhv7uDSxhzk T9Q= Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa4.mentor.iphmx.com with ESMTP; 17 Dec 2019 22:04:14 -0800 IronPort-SDR: MCkBFM2c4lDhRoEHgtIV8cwQE57nPxGJMpjtdEgaoRvKEEWhkBtXlNWZ5A81NmDM94+DFxxc6W QYBWkGLEtFaXTilY5fMVIgTMbjQViyVoTpb+/UB2kXk5IcgSPQ+PKb1Xv043BkBGfcWfWrNbe+ WHEkDWqDMQzYRAH0I43zAlVXfBqNcgELtCZjWsovNFhksTGwbVJEMC6PtjcLHrvrPYF+JJjr99 995qga4wj7FPrTFMsYqGHNifx0T6aI1VzLSochTpaGoVChNZ5i8mXiXDaz2OxEQMwIqvHy8qH3 X34= From: Julian Brown To: CC: Thomas Schwinge , Jakub Jelinek , Tobias Burnus , , Subject: [PATCH 08/13] OpenACC 2.6 deep copy: middle-end parts Date: Tue, 17 Dec 2019 22:03:48 -0800 Message-ID: <62e541dadce16450ba0da2bad66caf9bf443cd6e.1576648001.git.julian@codesourcery.com> In-Reply-To: References: MIME-Version: 1.0 X-IsSubscribed: yes This patch has been broken out of the "OpenACC 2.6 manual deep copy support" patch, last posted here: https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02376.html This part contains the middle-end support for OpenACC 2.6 attach and detach operations, either as standalone clauses or as "attach/detach" actions triggered by other (data movement) clauses, as detailed in the specification. Tested alongside other patches in this series with offloading to NVPTX. OK? Thanks, Julian ChangeLog gcc/ * gimplify.c (gimplify_omp_var_data): Add GOVD_MAP_HAS_ATTACHMENTS. (insert_struct_comp_map): Support derived-type member mappings for arrays with descriptors which use GOMP_MAP_TO_PSET. Support GOMP_MAP_ATTACH_DETACH. (gimplify_scan_omp_clauses): Tidy up OACC_ENTER_DATA/OACC_EXIT_DATA mappings. Handle attach/detach clauses and component references. (gimplify_adjust_omp_clauses_1): Skip adjustments for explicit attach/detach clauses. (gimplify_omp_target_update): Handle finalize for detach. * omp-low.c (lower_omp_target): Support GOMP_MAP_ATTACH, GOMP_MAP_DETACH, GOMP_MAP_FORCE_DETACH. * tree-pretty-print.c (dump_omp_clause): Likewise, plus GOMP_MAP_ATTACH_DETACH. include/ * gomp-constants.h (gomp_map_kind): Add GOMP_MAP_ATTACH_DETACH. --- gcc/gimplify.c | 232 ++++++++++++++++++++++++++++++++++----- gcc/omp-low.c | 3 + gcc/tree-pretty-print.c | 18 +++ include/gomp-constants.h | 6 +- 4 files changed, 229 insertions(+), 30 deletions(-) diff --git a/gcc/gimplify.c b/gcc/gimplify.c index e3088dcbe05..e3d5bc83c4f 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -123,6 +123,10 @@ enum gimplify_omp_var_data /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */ GOVD_REDUCTION_INSCAN = 0x2000000, + /* Flag for GOVD_MAP: (struct) vars that have pointer attachments for + fields. */ + GOVD_MAP_HAS_ATTACHMENTS = 8388608, + GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR | GOVD_LOCAL) @@ -8209,20 +8213,33 @@ insert_struct_comp_map (enum tree_code code, tree c, tree struct_node, tree prev_node, tree *scp) { enum gomp_map_kind mkind - = code == OMP_TARGET_EXIT_DATA ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC; + = (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA) + ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC; tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); tree cl = scp ? prev_node : c2; OMP_CLAUSE_SET_MAP_KIND (c2, mkind); OMP_CLAUSE_DECL (c2) = unshare_expr (OMP_CLAUSE_DECL (c)); OMP_CLAUSE_CHAIN (c2) = scp ? *scp : prev_node; - OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node); + if (OMP_CLAUSE_CHAIN (prev_node) != c + && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (prev_node)) == OMP_CLAUSE_MAP + && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (prev_node)) + == GOMP_MAP_TO_PSET)) + OMP_CLAUSE_SIZE (c2) = OMP_CLAUSE_SIZE (OMP_CLAUSE_CHAIN (prev_node)); + else + OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node); if (struct_node) OMP_CLAUSE_CHAIN (struct_node) = c2; /* We might need to create an additional mapping if we have a reference to a - pointer (in C++). */ - if (OMP_CLAUSE_CHAIN (prev_node) != c) + pointer (in C++). Don't do this if we have something other than a + GOMP_MAP_ALWAYS_POINTER though, i.e. a GOMP_MAP_TO_PSET. */ + if (OMP_CLAUSE_CHAIN (prev_node) != c + && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (prev_node)) == OMP_CLAUSE_MAP + && ((OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (prev_node)) + == GOMP_MAP_ALWAYS_POINTER) + || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (prev_node)) + == GOMP_MAP_ATTACH_DETACH))) { tree c4 = OMP_CLAUSE_CHAIN (prev_node); tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); @@ -8329,6 +8346,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, struct gimplify_omp_ctx *ctx, *outer_ctx; tree c; hash_map *struct_map_to_clause = NULL; + hash_set *struct_deref_set = NULL; tree *prev_list_p = NULL, *orig_list_p = list_p; int handled_depend_iterators = -1; int nowait = -1; @@ -8731,8 +8749,6 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_TARGET_DATA: case OMP_TARGET_ENTER_DATA: case OMP_TARGET_EXIT_DATA: - case OACC_ENTER_DATA: - case OACC_EXIT_DATA: case OACC_HOST_DATA: if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER || (OMP_CLAUSE_MAP_KIND (c) @@ -8741,6 +8757,15 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, mapped, but not the pointer to it. */ remove = true; break; + case OACC_ENTER_DATA: + case OACC_EXIT_DATA: + if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER + || (OMP_CLAUSE_MAP_KIND (c) + == GOMP_MAP_FIRSTPRIVATE_REFERENCE)) + remove = true; + break; default: break; } @@ -8814,7 +8839,35 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, pd = &TREE_OPERAND (decl, 0); decl = TREE_OPERAND (decl, 0); } - if (TREE_CODE (decl) == COMPONENT_REF) + bool indir_p = false; + tree orig_decl = decl; + tree decl_ref = NULL_TREE; + if ((region_type & ORT_ACC) != 0 + && TREE_CODE (*pd) == COMPONENT_REF + && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH + && code != OACC_UPDATE) + { + while (TREE_CODE (decl) == COMPONENT_REF) + { + decl = TREE_OPERAND (decl, 0); + if ((TREE_CODE (decl) == MEM_REF + && integer_zerop (TREE_OPERAND (decl, 1))) + || INDIRECT_REF_P (decl)) + { + indir_p = true; + decl = TREE_OPERAND (decl, 0); + } + if (TREE_CODE (decl) == INDIRECT_REF + && DECL_P (TREE_OPERAND (decl, 0)) + && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0))) + == REFERENCE_TYPE)) + { + decl_ref = decl; + decl = TREE_OPERAND (decl, 0); + } + } + } + else if (TREE_CODE (decl) == COMPONENT_REF) { while (TREE_CODE (decl) == COMPONENT_REF) decl = TREE_OPERAND (decl, 0); @@ -8824,13 +8877,76 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, == REFERENCE_TYPE)) decl = TREE_OPERAND (decl, 0); } + if (decl != orig_decl && DECL_P (decl) && indir_p) + { + gomp_map_kind k = (code == OACC_EXIT_DATA) ? GOMP_MAP_DETACH + : GOMP_MAP_ATTACH; + /* We have a dereference of a struct member. Make this an + attach/detach operation, and ensure the base pointer is + mapped as a FIRSTPRIVATE_POINTER. */ + OMP_CLAUSE_SET_MAP_KIND (c, k); + flags = GOVD_MAP | GOVD_SEEN | GOVD_EXPLICIT; + tree next_clause = OMP_CLAUSE_CHAIN (c); + if (k == GOMP_MAP_ATTACH + && code != OACC_ENTER_DATA + && (!next_clause + || (OMP_CLAUSE_CODE (next_clause) != OMP_CLAUSE_MAP) + || (OMP_CLAUSE_MAP_KIND (next_clause) + != GOMP_MAP_POINTER) + || OMP_CLAUSE_DECL (next_clause) != decl) + && (!struct_deref_set + || !struct_deref_set->contains (decl))) + { + if (!struct_deref_set) + struct_deref_set = new hash_set (); + /* As well as the attach, we also need a + FIRSTPRIVATE_POINTER clause to properly map the + pointer to the struct base. */ + tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), + OMP_CLAUSE_MAP); + OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALLOC); + OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c2) + = 1; + tree charptr_zero + = build_int_cst (build_pointer_type (char_type_node), + 0); + OMP_CLAUSE_DECL (c2) + = build2 (MEM_REF, char_type_node, + decl_ref ? decl_ref : decl, charptr_zero); + OMP_CLAUSE_SIZE (c2) = size_zero_node; + tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), + OMP_CLAUSE_MAP); + OMP_CLAUSE_SET_MAP_KIND (c3, + GOMP_MAP_FIRSTPRIVATE_POINTER); + OMP_CLAUSE_DECL (c3) = decl; + OMP_CLAUSE_SIZE (c3) = size_zero_node; + tree mapgrp = *prev_list_p; + *prev_list_p = c2; + OMP_CLAUSE_CHAIN (c3) = mapgrp; + OMP_CLAUSE_CHAIN (c2) = c3; + + struct_deref_set->add (decl); + } + goto do_add_decl; + } + /* An "attach/detach" operation on an update directive should + behave as a GOMP_MAP_ALWAYS_POINTER. Beware that + unlike attach or detach map kinds, GOMP_MAP_ALWAYS_POINTER + depends on the previous mapping. */ + if (code == OACC_UPDATE + && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH) + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER); if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue, fb_lvalue) == GS_ERROR) { remove = true; break; } - if (DECL_P (decl)) + if (DECL_P (decl) + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH + && code != OACC_UPDATE) { if (error_operand_p (decl)) { @@ -8851,7 +8967,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, break; } - if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER) + if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH) { /* Error recovery. */ if (prev_list_p == NULL) @@ -8884,20 +9001,47 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, = splay_tree_lookup (ctx->variables, (splay_tree_key)decl); bool ptr = (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER); + bool attach_detach = (OMP_CLAUSE_MAP_KIND (c) + == GOMP_MAP_ATTACH_DETACH); + bool attach = OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH; + bool has_attachments = false; + /* For OpenACC, pointers in structs should trigger an + attach action. */ + if (attach_detach && (region_type & ORT_ACC) != 0) + { + /* Turn a GOMP_MAP_ATTACH_DETACH clause into a + GOMP_MAP_ATTACH or GOMP_MAP_DETACH clause after we + have detected a case that needs a GOMP_MAP_STRUCT + mapping added. */ + gomp_map_kind k + = (code == OACC_EXIT_DATA) ? GOMP_MAP_DETACH + : GOMP_MAP_ATTACH; + OMP_CLAUSE_SET_MAP_KIND (c, k); + has_attachments = true; + } if (n == NULL || (n->value & GOVD_MAP) == 0) { tree l = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (l, GOMP_MAP_STRUCT); + gomp_map_kind k = attach ? GOMP_MAP_FORCE_PRESENT + : GOMP_MAP_STRUCT; + + OMP_CLAUSE_SET_MAP_KIND (l, k); if (base_ref) OMP_CLAUSE_DECL (l) = unshare_expr (base_ref); else OMP_CLAUSE_DECL (l) = decl; - OMP_CLAUSE_SIZE (l) = size_int (1); + OMP_CLAUSE_SIZE (l) + = (!attach + ? size_int (1) + : DECL_P (OMP_CLAUSE_DECL (l)) + ? DECL_SIZE_UNIT (OMP_CLAUSE_DECL (l)) + : TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (l)))); if (struct_map_to_clause == NULL) struct_map_to_clause = new hash_map; struct_map_to_clause->put (decl, l); - if (ptr) + if (ptr || attach_detach) { insert_struct_comp_map (code, c, l, *prev_list_p, NULL); @@ -8923,23 +9067,31 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, OMP_CLAUSE_CHAIN (l) = c2; } flags = GOVD_MAP | GOVD_EXPLICIT; - if (GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) || ptr) + if (GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) + || ptr + || attach_detach) flags |= GOVD_SEEN; + if (has_attachments) + flags |= GOVD_MAP_HAS_ATTACHMENTS; goto do_add_decl; } - else + else if (struct_map_to_clause) { tree *osc = struct_map_to_clause->get (decl); tree *sc = NULL, *scp = NULL; - if (GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) || ptr) + if (GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) + || ptr + || attach_detach) n->value |= GOVD_SEEN; sc = &OMP_CLAUSE_CHAIN (*osc); if (*sc != c && (OMP_CLAUSE_MAP_KIND (*sc) - == GOMP_MAP_FIRSTPRIVATE_REFERENCE)) + == GOMP_MAP_FIRSTPRIVATE_REFERENCE)) sc = &OMP_CLAUSE_CHAIN (*sc); + /* Here "prev_list_p" is the end of the inserted + alloc/release nodes after the struct node, OSC. */ for (; *sc != c; sc = &OMP_CLAUSE_CHAIN (*sc)) - if (ptr && sc == prev_list_p) + if ((ptr || attach_detach) && sc == prev_list_p) break; else if (TREE_CODE (OMP_CLAUSE_DECL (*sc)) != COMPONENT_REF @@ -8992,7 +9144,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, || (known_eq (offset1, offsetn) && maybe_lt (bitpos1, bitposn))) { - if (ptr) + if (ptr || attach_detach) scp = sc; else break; @@ -9000,10 +9152,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } if (remove) break; - OMP_CLAUSE_SIZE (*osc) - = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), - size_one_node); - if (ptr) + if (!attach) + OMP_CLAUSE_SIZE (*osc) + = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), + size_one_node); + if (ptr || attach_detach) { tree cl = insert_struct_comp_map (code, c, NULL, *prev_list_p, scp); @@ -9033,11 +9186,18 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } if (!remove && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_POINTER + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET && OMP_CLAUSE_CHAIN (c) && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c)) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c)) - == GOMP_MAP_ALWAYS_POINTER)) + && ((OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c)) + == GOMP_MAP_ALWAYS_POINTER) + || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c)) + == GOMP_MAP_ATTACH_DETACH) + || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c)) + == GOMP_MAP_TO_PSET))) prev_list_p = list_p; + break; } flags = GOVD_MAP | GOVD_EXPLICIT; @@ -9561,6 +9721,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, gimplify_omp_ctxp = ctx; if (struct_map_to_clause) delete struct_map_to_clause; + if (struct_deref_set) + delete struct_deref_set; } /* Return true if DECL is a candidate for shared to firstprivate @@ -9708,6 +9870,8 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) return 0; if ((flags & GOVD_SEEN) == 0) return 0; + if ((flags & GOVD_MAP_HAS_ATTACHMENTS) != 0) + return 0; if (flags & GOVD_DEBUG_PRIVATE) { gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_SHARED); @@ -12762,8 +12926,9 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p) && omp_find_clause (OMP_STANDALONE_CLAUSES (expr), OMP_CLAUSE_FINALIZE)) { - /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote that "finalize" - semantics apply to all mappings of this OpenACC directive. */ + /* Use GOMP_MAP_DELETE, GOMP_MAP_FORCE_DETACH, and + GOMP_MAP_FORCE_FROM to denote that "finalize" semantics apply + to all mappings of this OpenACC directive. */ bool finalize_marked = false; for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP) @@ -12777,10 +12942,19 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p) OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE); finalize_marked = true; break; + case GOMP_MAP_DETACH: + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_DETACH); + finalize_marked = true; + break; + case GOMP_MAP_STRUCT: + case GOMP_MAP_FORCE_PRESENT: + /* Skip over an initial struct or force_present mapping. */ + break; default: - /* Check consistency: libgomp relies on the very first data - mapping clause being marked, so make sure we did that before - any other mapping clauses. */ + /* Check consistency: libgomp relies on the very first + non-struct, non-force-present data mapping clause being + marked, so make sure we did that before any other mapping + clauses. */ gcc_assert (finalize_marked); break; } diff --git a/gcc/omp-low.c b/gcc/omp-low.c index d422c205836..3eb7815449a 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -11439,6 +11439,9 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) case GOMP_MAP_FORCE_DEVICEPTR: case GOMP_MAP_DEVICE_RESIDENT: case GOMP_MAP_LINK: + case GOMP_MAP_ATTACH: + case GOMP_MAP_DETACH: + case GOMP_MAP_FORCE_DETACH: gcc_assert (is_gimple_omp_oacc (stmt)); break; default: diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 1cf7a912133..379858d0f1f 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -849,6 +849,18 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) case GOMP_MAP_LINK: pp_string (pp, "link"); break; + case GOMP_MAP_ATTACH: + pp_string (pp, "attach"); + break; + case GOMP_MAP_DETACH: + pp_string (pp, "detach"); + break; + case GOMP_MAP_FORCE_DETACH: + pp_string (pp, "force_detach"); + break; + case GOMP_MAP_ATTACH_DETACH: + pp_string (pp, "attach_detach"); + break; default: gcc_unreachable (); } @@ -870,6 +882,12 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) case GOMP_MAP_TO_PSET: pp_string (pp, " [pointer set, len: "); break; + case GOMP_MAP_ATTACH: + case GOMP_MAP_DETACH: + case GOMP_MAP_FORCE_DETACH: + case GOMP_MAP_ATTACH_DETACH: + pp_string (pp, " [bias: "); + break; default: pp_string (pp, " [len: "); break; diff --git a/include/gomp-constants.h b/include/gomp-constants.h index e8bd52e81bd..f40d6069582 100644 --- a/include/gomp-constants.h +++ b/include/gomp-constants.h @@ -142,7 +142,11 @@ enum gomp_map_kind /* Do not map, but pointer assign a pointer instead. */ GOMP_MAP_FIRSTPRIVATE_POINTER = (GOMP_MAP_LAST | 1), /* Do not map, but pointer assign a reference instead. */ - GOMP_MAP_FIRSTPRIVATE_REFERENCE = (GOMP_MAP_LAST | 2) + GOMP_MAP_FIRSTPRIVATE_REFERENCE = (GOMP_MAP_LAST | 2), + /* An attach or detach operation. Rewritten to the appropriate type during + gimplification, depending on directive (i.e. "enter data" or + parallel/kernels region vs. "exit data"). */ + GOMP_MAP_ATTACH_DETACH = (GOMP_MAP_LAST | 3) }; #define GOMP_MAP_COPY_TO_P(X) \