Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization
Hi Harald and Thomas, Thank you for your contributions to understanding the interpretation by different vendors of the F2018 requirements for finalization. While it does appear to be rather chaotic, the differences are down to a small number of "features" of each compiler. Before describing my interpretation of the behaviour of the offerings from other vendors, I should remark briefly about where I am with gfortran. I now have a patch that handles derived types correctly according to F2018 7.5.6.2 and 7.5.6.3, modulo the ambiguous requirement for the handling of parent components that I will come to when discussing ifort. I have a patch ready to fix this, should Intel's interpretation be correct. I have not moved on to class finalization yet because there are memory leaks connected with finalization of function results that I have yet to pin down. Also, finalization of function results within array and structure constructors is yet to come. Once I have it all working, I will break up the patch into a number of stages to make it more digestible for review. However, just in case I fall under the proverbial bus, I have attached the patch for reference. Turning to the results from the other vendors: Cray: Seemingly, the only difference in interpretation concerns the finalization of structure constructors. 7.5.6.3 paragraphs 5 and 6 only mention function results. Having scoured the standard for guidance, I have only found Note 7.57: "name(...) ...snip... is interpreted as a structure constructor only if it cannot be interpreted as a generic function reference." From this, I take it that a structure constructor is distinct from a function reference and, since not mentioned in 7.5.6.3, the result should not be finalized. nagfor 7.1: The NAG offering seems to be a bit inconsistent in the finalization of function results. It is missing in assignment 4 and suffers a surfeit in assignment 5. The two extras in assignment 5 seem to be mangled. As far as I can tell, these are problems of implementation rather than interpretation. ifort: In all the versions tested, assignment 1 generates, contrary to the standard, a finalization of an unallocated allocated 'var'. The other difference from gfortran with the patch applied is in the finalization of the parent component in the finalization of arrays of extended types. ifort makes use of the scalar finalizer, whereas all the other compilers use the array finalizer. In fairness to the folk at Intel, I think that there is an ambiguity in 7.5.6.2 - "(2) All finalizable components that appear in the type definition are finalized in a processor-dependent order. If the entity being finalized is an array, each finalizable component of each element of that entity is finalized separately. (3) If the entity is of extended type and the parent type is finalizable, the parent component is finalized." The separate mention of the parent component in (3) rather than in (2) saying, "..each finalizable component, including the parent component,..." implies that it is in some way different. I think that an interpretation request is in order. I will be unavailable to do any gfortran work for two weeks now but will complete this work then. Best regards and thanks again. Paul On Thu, 17 Feb 2022 at 21:23, Thomas Koenig wrote: > Hi Paul, > > > I have gone back to the start and have gone through finalizable derived > > type assignments with the F2018 in hand. I have had a dreadful time with > > direct by reference function calls and still am struggling with > assignment > > number 6 in the attached. I would be very grateful if you would run this > > testcase for the other brands. > > This is the output of nagfor 7.1, no idea how correct this is. > > Best regards > > Thomas > > At start of program: final_count =0 > *** > > 1st assignment: No finalization because MyType unallocated. > After 1st assignment(var not allocated): final_count =0(0) > *** > > 2nd assignment: MyType(=simple(1,MyType) finalized before assignment > finalize simple - Mytype2%ind =1 > After 2nd assignment(var allocated): final_count =1(1) > *** > > 3rd assignment: MyTypeArray(%ind = [41 42]) finalized before assignment > > finalize simple(:) - MyTypeArray%ind= 42 43 > After 3rd assignment(array var allocated): final_count =1(1) > *** > > Deallocation generates final call with self = simple (21, ThyType) > 4th assignment: MyTypeArray finalized before assignment > Mtype finalized before assignment with self = simple (11, MyType) > Function result finalized after assignment with self = simple (99, > MyType) > > finalize simple - ThyType%ind = 21 > finalize simple - MyType%ind = 11 > After 4th
[PATCH 0/8] OpenMP 5.0: C++ "declare mapper" support (plus struct rework, etc.)
Hi, This patch contains rebased/slightly bug-fixed versions of the patches previously posted in the series: https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585439.html plus a new implementation of "declare mapper" support for C++. This can't be committed now, but posting now so others (mostly Jakub?) have a chance to look at it and comment on the general approach, etc.. Further commentary on individual patches. Thanks, Julian Julian Brown (8): OpenMP 5.0: Clause ordering for OpenMP 5.0 (topological sorting by base pointer) Remove omp_target_reorder_clauses OpenMP/OpenACC struct sibling list gimplification extension and rework OpenMP: Add inspector class to unify mapped address analysis OpenMP: lvalue parsing for map clauses (C++) OpenMP: lvalue parsing for map clauses (C) Use OMP_ARRAY_SECTION instead of TREE_LIST in C++ FE OpenMP 5.0 "declare mapper" support for C++ gcc/c-family/c-common.h | 45 + gcc/c-family/c-omp.cc | 227 ++ gcc/c/c-parser.cc | 150 +- gcc/c/c-tree.h|1 + gcc/c/c-typeck.cc | 251 +- gcc/cp/cp-gimplify.cc |6 + gcc/cp/cp-objcp-common.h |2 + gcc/cp/cp-tree.h | 10 + gcc/cp/decl.cc| 18 +- gcc/cp/error.cc |9 + gcc/cp/mangle.cc |5 +- gcc/cp/name-lookup.cc |3 +- gcc/cp/parser.cc | 520 ++- gcc/cp/parser.h |3 + gcc/cp/pt.cc | 144 +- gcc/cp/semantics.cc | 863 +++-- gcc/fortran/parse.cc |3 + gcc/fortran/trans-openmp.cc | 20 +- gcc/gimplify.cc | 2822 - gcc/langhooks-def.h |3 + gcc/langhooks.cc |9 + gcc/langhooks.h |4 + gcc/omp-general.h | 52 + gcc/omp-low.cc| 23 +- gcc/testsuite/c-c++-common/gomp/map-1.c |3 +- gcc/testsuite/c-c++-common/gomp/map-6.c | 12 +- gcc/testsuite/g++.dg/goacc/member-array-acc.C | 13 + gcc/testsuite/g++.dg/gomp/declare-mapper-1.C | 58 + gcc/testsuite/g++.dg/gomp/declare-mapper-2.C | 30 + gcc/testsuite/g++.dg/gomp/declare-mapper-3.C | 27 + gcc/testsuite/g++.dg/gomp/declare-mapper-4.C | 74 + gcc/testsuite/g++.dg/gomp/ind-base-3.C| 38 + gcc/testsuite/g++.dg/gomp/map-assignment-1.C | 12 + gcc/testsuite/g++.dg/gomp/map-inc-1.C | 10 + gcc/testsuite/g++.dg/gomp/map-lvalue-ref-1.C | 19 + gcc/testsuite/g++.dg/gomp/map-ptrmem-1.C | 36 + gcc/testsuite/g++.dg/gomp/map-ptrmem-2.C | 39 + .../g++.dg/gomp/map-static-cast-lvalue-1.C| 17 + gcc/testsuite/g++.dg/gomp/map-ternary-1.C | 20 + gcc/testsuite/g++.dg/gomp/member-array-2.C| 86 + gcc/testsuite/g++.dg/gomp/member-array-omp.C | 13 + gcc/testsuite/g++.dg/gomp/pr67522.C |2 +- gcc/testsuite/g++.dg/gomp/target-3.C |4 +- gcc/testsuite/g++.dg/gomp/target-lambda-1.C |6 +- gcc/testsuite/g++.dg/gomp/target-this-2.C |2 +- gcc/testsuite/g++.dg/gomp/target-this-3.C |4 +- gcc/testsuite/g++.dg/gomp/target-this-4.C |4 +- .../g++.dg/gomp/unmappable-component-1.C | 21 + gcc/tree-core.h |4 + gcc/tree-pretty-print.cc | 56 + gcc/tree.cc |2 + gcc/tree.def | 10 + gcc/tree.h| 21 + include/gomp-constants.h |8 +- libgomp/testsuite/libgomp.c++/baseptrs-3.C| 275 ++ libgomp/testsuite/libgomp.c++/class-array-1.C | 59 + .../testsuite/libgomp.c++/declare-mapper-1.C | 87 + .../testsuite/libgomp.c++/declare-mapper-2.C | 55 + .../testsuite/libgomp.c++/declare-mapper-3.C | 63 + .../testsuite/libgomp.c++/declare-mapper-4.C | 63 + .../testsuite/libgomp.c++/declare-mapper-5.C | 52 + .../testsuite/libgomp.c++/declare-mapper-6.C | 37 + .../testsuite/libgomp.c++/declare-mapper-7.C | 48 + .../testsuite/libgomp.c++/declare-mapper-8.C | 61 + libgomp/testsuite/libgomp.c++/ind-base-1.C| 162 + libgomp/testsuite/libgomp.c++/ind-base-2.C| 49 + libgomp/testsuite/libgomp.c++/map-comma-1.C | 15 + .../testsuite/libgomp.c++/map-rvalue-ref-1.C | 22 + .../testsuite/libgomp.c++/member-array-1.C| 89 + libgomp/testsuite/libgomp.c++/struct-ref-1.C | 97 + .../libgomp.c-c++-common/baseptrs-1.c | 50 + .../libgomp.c-c++-common/baseptrs-2.c | 70 + .../libgo
[PATCH 1/8] OpenMP 5.0: Clause ordering for OpenMP 5.0 (topological sorting by base pointer)
This patch reimplements the omp_target_reorder_clauses function in anticipation of supporting "deeper" struct mappings (that is, with several structure dereference operators, or similar). The idea is that in place of the (possibly quadratic) algorithm in omp_target_reorder_clauses that greedily moves clauses containing addresses that are subexpressions of other addresses before those other addresses, we employ a topological sort algorithm to calculate a proper order for map clauses. This should run in linear time, and hopefully handles degenerate cases where multiple "levels" of indirect accesses are present on a given directive. The new method also takes care to keep clause groups together, addressing the concerns raised in: https://gcc.gnu.org/pipermail/gcc-patches/2021-May/570501.html To figure out if some given clause depends on a base pointer in another clause, we strip off the outer layers of the address expression, and check (via a tree_operand_hash hash table we have built) if the result is a "base pointer" as defined in OpenMP 5.0 (1.2.6 Data Terminology). There are some subtleties involved, however: - We must treat MEM_REF with zero offset the same as INDIRECT_REF. This should probably be fixed in the front ends instead so we always use a canonical form (probably INDIRECT_REF). The following patch shows one instance of the problem, but there may be others: https://gcc.gnu.org/pipermail/gcc-patches/2021-May/571382.html - Mapping a whole struct implies mapping each of that struct's elements, which may be base pointers. Because those base pointers aren't necessarily explicitly referenced in the directive in question, we treat the whole-struct mapping as a dependency instead. This version of the patch has been moved to the front of the patch queue, thus isn't dependent on any of the following struct-rework patches. Tested with offloading to NVPTX and bootstrapped. OK (for stage 1)? Thanks, Julian 2022-02-18 Julian Brown gcc/ * gimplify.c (is_or_contains_p, omp_target_reorder_clauses): Delete functions. (omp_tsort_mark): Add enum. (omp_mapping_group): Add struct. (debug_mapping_group, omp_get_base_pointer, omp_get_attachment, omp_group_last, omp_gather_mapping_groups, omp_group_base, omp_index_mapping_groups, omp_containing_struct, omp_tsort_mapping_groups_1, omp_tsort_mapping_groups, omp_segregate_mapping_groups, omp_reorder_mapping_groups): New functions. (gimplify_scan_omp_clauses): Call above functions instead of omp_target_reorder_clauses, unless we've seen an error. * omp-low.c (scan_sharing_clauses): Avoid strict test if we haven't sorted mapping groups. gcc/testsuite/ * g++.dg/gomp/target-lambda-1.C: Adjust expected output. * g++.dg/gomp/target-this-3.C: Likewise. * g++.dg/gomp/target-this-4.C: Likewise. --- gcc/gimplify.cc | 785 +++- gcc/omp-low.cc | 7 +- gcc/testsuite/g++.dg/gomp/target-lambda-1.C | 7 +- gcc/testsuite/g++.dg/gomp/target-this-3.C | 4 +- gcc/testsuite/g++.dg/gomp/target-this-4.C | 4 +- 5 files changed, 793 insertions(+), 14 deletions(-) diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 875b115d02d..968cbd263f5 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -8738,6 +8738,7 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp, return base; } +#if 0 /* Returns true if EXPR is or contains (as a sub-component) BASE_PTR. */ static bool @@ -8761,6 +8762,7 @@ is_or_contains_p (tree expr, tree base_ptr) return operand_equal_p (expr, base_ptr); } + /* Implement OpenMP 5.x map ordering rules for target directives. There are several rules, and with some level of ambiguity, hopefully we can at least collect the complexity here in one place. */ @@ -8940,6 +8942,761 @@ omp_target_reorder_clauses (tree *list_p) } } } +#endif + + +enum omp_tsort_mark { + UNVISITED, + TEMPORARY, + PERMANENT +}; + +struct omp_mapping_group { + tree *grp_start; + tree grp_end; + omp_tsort_mark mark; + struct omp_mapping_group *sibling; + struct omp_mapping_group *next; +}; + +__attribute__((used)) static void +debug_mapping_group (omp_mapping_group *grp) +{ + tree tmp = OMP_CLAUSE_CHAIN (grp->grp_end); + OMP_CLAUSE_CHAIN (grp->grp_end) = NULL; + debug_generic_expr (*grp->grp_start); + OMP_CLAUSE_CHAIN (grp->grp_end) = tmp; +} + +/* Return the OpenMP "base pointer" of an expression EXPR, or NULL if there + isn't one. This needs improvement. */ + +static tree +omp_get_base_pointer (tree expr) +{ + while (TREE_CODE (expr) == ARRAY_REF) +expr = TREE_OPERAND (expr, 0); + + while (TREE_CODE (expr) == COMPONENT_REF +&& (DECL_P (TREE_OPERAND (expr, 0)) +|| (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF) +|| TREE_CODE (
[PATCH 2/8] Remove omp_target_reorder_clauses
This patch has been split out from the previous one to avoid a confusingly-interleaved diff. The two patches should probably be committed squashed together. 2021-10-01 Julian Brown gcc/ * gimplify.c (is_or_contains_p, omp_target_reorder_clauses): Delete. --- gcc/gimplify.cc | 207 1 file changed, 207 deletions(-) diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 968cbd263f5..b667012a118 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -8738,213 +8738,6 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp, return base; } -#if 0 -/* Returns true if EXPR is or contains (as a sub-component) BASE_PTR. */ - -static bool -is_or_contains_p (tree expr, tree base_ptr) -{ - if ((TREE_CODE (expr) == INDIRECT_REF && TREE_CODE (base_ptr) == MEM_REF) - || (TREE_CODE (expr) == MEM_REF && TREE_CODE (base_ptr) == INDIRECT_REF)) -return operand_equal_p (TREE_OPERAND (expr, 0), - TREE_OPERAND (base_ptr, 0)); - while (!operand_equal_p (expr, base_ptr)) -{ - if (TREE_CODE (base_ptr) == COMPOUND_EXPR) - base_ptr = TREE_OPERAND (base_ptr, 1); - if (TREE_CODE (base_ptr) == COMPONENT_REF - || TREE_CODE (base_ptr) == POINTER_PLUS_EXPR - || TREE_CODE (base_ptr) == SAVE_EXPR) - base_ptr = TREE_OPERAND (base_ptr, 0); - else - break; -} - return operand_equal_p (expr, base_ptr); -} - - -/* Implement OpenMP 5.x map ordering rules for target directives. There are - several rules, and with some level of ambiguity, hopefully we can at least - collect the complexity here in one place. */ - -static void -omp_target_reorder_clauses (tree *list_p) -{ - /* Collect refs to alloc/release/delete maps. */ - auto_vec ard; - tree *cp = list_p; - while (*cp != NULL_TREE) -if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ALLOC - || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_RELEASE - || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_DELETE)) - { - /* Unlink cp and push to ard. */ - tree c = *cp; - tree nc = OMP_CLAUSE_CHAIN (c); - *cp = nc; - ard.safe_push (c); - - /* Any associated pointer type maps should also move along. */ - while (*cp != NULL_TREE - && OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_FIRSTPRIVATE_REFERENCE - || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_FIRSTPRIVATE_POINTER - || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ATTACH_DETACH - || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_POINTER - || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ALWAYS_POINTER - || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_TO_PSET)) - { - c = *cp; - nc = OMP_CLAUSE_CHAIN (c); - *cp = nc; - ard.safe_push (c); - } - } -else - cp = &OMP_CLAUSE_CHAIN (*cp); - - /* Link alloc/release/delete maps to the end of list. */ - for (unsigned int i = 0; i < ard.length (); i++) -{ - *cp = ard[i]; - cp = &OMP_CLAUSE_CHAIN (ard[i]); -} - *cp = NULL_TREE; - - /* OpenMP 5.0 requires that pointer variables are mapped before - its use as a base-pointer. */ - auto_vec atf; - for (tree *cp = list_p; *cp; cp = &OMP_CLAUSE_CHAIN (*cp)) -if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP) - { - /* Collect alloc, to, from, to/from clause tree pointers. */ - gomp_map_kind k = OMP_CLAUSE_MAP_KIND (*cp); - if (k == GOMP_MAP_ALLOC - || k == GOMP_MAP_TO - || k == GOMP_MAP_FROM - || k == GOMP_MAP_TOFROM - || k == GOMP_MAP_ALWAYS_TO - || k == GOMP_MAP_ALWAYS_FROM - || k == GOMP_MAP_ALWAYS_TOFROM) - atf.safe_push (cp); - } - - for (unsigned int i = 0; i < atf.length (); i++) -if (atf[i]) - { - tree *cp = atf[i]; - tree decl = OMP_CLAUSE_DECL (*cp); - if (TREE_CODE (decl) == INDIRECT_REF || TREE_CODE (decl) == MEM_REF) - { - tree base_ptr = TREE_OPERAND (decl, 0); - STRIP_TYPE_NOPS (base_ptr); - for (unsigned int j = i + 1; j < atf.length (); j++) - if (atf[j]) - { - tree *cp2 = atf[j]; - tree decl2 = OMP_CLAUSE_DECL (*cp2); - - decl2 = OMP_CLAUSE_DECL (*cp2); - if (is_or_contains_p (decl2, base_ptr)) - { - /* Move *cp2 to before *cp. */ - tree c = *cp2; - *cp2 = OMP_CLAUSE_CHAIN (c); - OMP_CLAUSE_CHAIN (c) = *cp; - *cp = c; - - if (*cp2 != NULL_TREE - && OMP_CLAUSE_CODE (*cp2) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_KIND (*cp2) == GOMP_MAP_
[PATCH 3/8] OpenMP/OpenACC struct sibling list gimplification extension and rework
This patch is a combination of several previously-posted patches, rebased and squashed together, and with a couple of additional bugfixes: "Rewrite GOMP_MAP_ATTACH_DETACH mappings unconditionally" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585440.html "OpenMP/OpenACC: Move array_ref/indirect_ref handling code out of extract_base_bit_offset" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585441.html "OpenACC/OpenMP: Refactor struct lowering in gimplify.c" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585442.html "OpenACC: Rework indirect struct handling in gimplify.c" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585443.html "Remove base_ind/base_ref handling from extract_base_bit_offset" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585445.html "OpenMP/OpenACC: Hoist struct sibling list handling in gimplification" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585448.html "OpenMP: Allow array ref components for C & C++" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585449.html "OpenMP: Fix non-zero attach/detach bias for struct dereferences" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585451.html "OpenMP: Handle reference-typed struct members" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585453.html "OpenACC: Make deep-copy-arrayofstruct.c a libgomp/runtime test" https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585452.html This resulting patch thus contains all the struct gimplification changes (and associated fixes) previously posted: the hope was that this would reduce the amount of churn to be reviewed, although maybe this patch does too much at once. The changes as a whole are all relating to increasing the variety of supported expressions in OpenMP and OpenACC map clauses, though. 2022-02-18 Julian Brown gcc/c-family/ * c-common.h (c_omp_decompose_attachable_address): Add prototype. * c-omp.cc (c_omp_decompose_attachable_address): New function. gcc/c/ * c-typeck.cc (handle_omp_array_sections): Handle attach/detach for struct dereferences with non-zero bias. (c_finish_omp_clauses): Allow ARRAY_REF components. gcc/cp/ * semantics.cc (handle_omp_array_section): Handle attach/detach for struct dereferences with non-zero bias. (finish_omp_clauses): Allow ARRAY_REF components. Handle reference-typed members. gcc/fortran/ * trans-openmp.cc (gfc_trans_omp_clauses): Don't create GOMP_MAP_TO_PSET mappings for class metadata, nor GOMP_MAP_POINTER mappings for POINTER_TYPE_P decls. gcc/ * gimplify.c (gimplify_omp_var_data): Remove GOVD_MAP_HAS_ATTACHMENTS. (insert_struct_comp_map): Refactor function into... (build_struct_comp_nodes): This new function. Remove list handling and improve self-documentation. (extract_base_bit_offset): Remove BASE_REF, OFFSETP parameters. Move code to strip outer parts of address out of function, but strip no-op conversions. (omp_mapping_group): Add DELETED field for use during reindexing. (strip_components_and_deref, strip_indirections): New functions. (omp_group_last, omp_group_base): Add GOMP_MAP_STRUCT handling. (omp_gather_mapping_groups): Initialise DELETED field for new groups. (omp_index_mapping_groups): Notice DELETED groups when (re)indexing. (insert_node_after, move_node_after, move_nodes_after, move_concat_nodes_after): New helper functions. (accumulate_sibling_list): New function to build up GOMP_MAP_STRUCT node groups for sibling lists. Outlined from gimplify_scan_omp_clauses. (omp_build_struct_sibling_lists): New function. (gimplify_scan_omp_clauses): Remove struct_map_to_clause, struct_seen_clause, struct_deref_set. Call omp_build_struct_sibling_lists as pre-pass instead of handling sibling lists in the function's main processing loop. (gimplify_adjust_omp_clauses_1): Remove GOVD_MAP_HAS_ATTACHMENTS handling, unused now. * omp-low.cc (scan_sharing_clauses): Handle pointer-type indirect struct references, and references to pointers to structs also. gcc/testsuite/ * g++.dg/goacc/member-array-acc.C: New test. * g++.dg/gomp/member-array-omp.C: New test. * g++.dg/gomp/target-3.C: Update expected output. * g++.dg/gomp/target-lambda-1.C: Likewise. * g++.dg/gomp/target-this-2.C: Likewise. * c-c++-common/goacc/deep-copy-arrayofstruct.c: Move test from here. libgomp/ * testsuite/libgomp.c-c++-common/baseptrs-1.c: Add test. * testsuite/libgomp.c-c++-common/baseptrs-2.c: Add test. * testsuite/libgomp.c++/baseptrs-3.C: Add test. * testsuite/libgomp.oacc-c-c++-common/deep-copy-15.c: New test. * testsuite/libgomp.oacc-c-c++-common/deep-copy-16.c: New test. * testsuite/libgom
[PATCH 4/8] OpenMP: Add inspector class to unify mapped address analysis
Several places in the C and C++ front-ends dig through OpenMP addresses from "map" clauses (etc.) in order to determine whether they are component accesses that need "attach" operations, check duplicate mapping clauses, and so on. When we're extending support for more kinds of lvalues in map clauses, it seems helpful to bring these all into one place in order to keep all the analyses in sync, and to make it easier to reason about which kinds of expressions are supported. This patch introduces an "address inspector" class for that purpose, and adjusts the C and C++ front-ends to use it. 2021-11-15 Julian Brown gcc/c-family/ * c-common.h (c_omp_address_inspector): New class. * c-omp.c (c_omp_address_inspector::init, c_omp_address_inspector::analyze_components, c_omp_address_inspector::map_supported_p, c_omp_address_inspector::mappable_type): New methods. gcc/c/ * c-typeck.c (handle_omp_array_sections_1, c_finish_omp_clauses): Use c_omp_address_inspector class. gcc/cp/ * semantics.c (cp_omp_address_inspector): New class, derived from c_omp_address_inspector. (handle_omp_array_sections_1): Use cp_omp_address_inspector class to analyze OpenMP map clause expressions. Support POINTER_PLUS_EXPR. (finish_omp_clauses): Likewise. Support some additional kinds of lvalues in map clauses. gcc/testsuite/ * g++.dg/gomp/unmappable-component-1.C: New test. Make map_supported_p strip nops lvalue thing, generic part --- gcc/c-family/c-common.h | 44 +++ gcc/c-family/c-omp.cc | 150 +++ gcc/c/c-typeck.cc | 199 +++--- gcc/cp/semantics.cc | 253 ++ .../g++.dg/gomp/unmappable-component-1.C | 21 ++ libgomp/testsuite/libgomp.c++/class-array-1.C | 59 6 files changed, 400 insertions(+), 326 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/unmappable-component-1.C create mode 100644 libgomp/testsuite/libgomp.c++/class-array-1.C diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index d00838a57f0..af8dc6c4e4f 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1254,6 +1254,50 @@ extern const char *c_omp_map_clause_name (tree, bool); extern void c_omp_adjust_map_clauses (tree, bool); extern tree c_omp_decompose_attachable_address (tree t, tree *virtbase); +class c_omp_address_inspector +{ + tree clause; + tree orig; + tree deref_toplevel; + tree outer_virtual_base; + tree root_term; + bool component_access; + bool indirections; + int map_supported; + +protected: + virtual bool reference_ref_p (tree) { return false; } + virtual bool processing_template_decl_p () { return false; } + virtual bool mappable_type (tree t); + virtual void emit_unmappable_type_notes (tree) { } + +public: + c_omp_address_inspector (tree c, tree t) +: clause (c), orig (t), deref_toplevel (NULL_TREE), + outer_virtual_base (NULL_TREE), root_term (NULL_TREE), + component_access (false), indirections (false), map_supported (-1) + { } + + ~c_omp_address_inspector () {} + + virtual void init (); + + tree analyze_components (bool); + + tree get_deref_toplevel () { return deref_toplevel; } + tree get_outer_virtual_base () { return outer_virtual_base; } + tree get_root_term () { gcc_assert (root_term); return root_term; } + bool component_access_p () { return component_access; } + + bool indir_component_ref_p () +{ + gcc_assert (!component_access || root_term != NULL_TREE); + return component_access && indirections; +} + + bool map_supported_p (); +}; + enum c_omp_directive_kind { C_OMP_DIR_STANDALONE, C_OMP_DIR_CONSTRUCT, diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index 0e76eb4392e..e3270f781b0 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -3113,6 +3113,156 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target) } } +/* This could just be done in the constructor, but we need to call the + subclass's version of reference_ref_p, etc. */ + +void +c_omp_address_inspector::init () +{ + tree t = orig; + + gcc_assert (TREE_CODE (t) != ARRAY_REF); + + /* We may have a reference-typed component access at the outermost level + that has had convert_from_reference called on it. Look through that + access. */ + if (reference_ref_p (t) + && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF) +{ + t = TREE_OPERAND (t, 0); + deref_toplevel = t; +} + else +deref_toplevel = t; + + /* Strip off expression nodes that may enclose a COMPONENT_REF. Look through + references, but not indirections through pointers. */ + while (1) +{ + if (TREE_CODE (t) == COMPOUND_EXPR) + { + t = TREE_OPERAND (t, 1); + STRIP_NOPS (t); + } + else if (TREE_CODE (t) == POINTER_PLUS_EXPR +
[PATCH 5/8] OpenMP: lvalue parsing for map clauses (C++)
This patch changes parsing for OpenMP map clauses in C++ to use the generic expression parser, hence adds support for parsing general lvalues (as required by OpenMP 5.0+). So far only a few new types of expression are actually supported throughout compilation (including everything in the testsuite of course, and newly-added tests), and we attempt to reject unsupported expressions in order to avoid surprises for the user. This version of the patch relaxes the check for supported map expressions to include LVALUE_EXPR, which makes pointer-to-member mappings stop "accidentally" failing the check. However such mappings don't actually work yet, so they have been explicitly disallowed elsewhere. Supporting pointer-to-member mappings can probably be done most easily by mapping the whole of the containing struct, and mapping the offsets as firstprivate or similar. That's a little fiddly to get working though, and isn't unambiguously the right thing to do, so that might need more thought. 2022-02-18 Julian Brown gcc/c-family/ * c-omp.cc (c_omp_decompose_attachable_address): Handle more types of expressions. gcc/cp/ * error.cc (dump_expr): Handle OMP_ARRAY_SECTION. * parser.cc (cp_parser_new): Initialize parser->omp_array_section_p. (cp_parser_postfix_open_square_expression): Support OMP_ARRAY_SECTION parsing. (cp_parser_omp_var_list_no_open): Remove ALLOW_DEREF parameter, add MAP_LVALUE in its place. Supported generalised lvalue parsing for map clauses. (cp_parser_omp_var_list): Remove ALLOW_DEREF parameter, add MAP_LVALUE. Pass to cp_parser_omp_var_list_no_open. (cp_parser_oacc_data_clause, cp_parser_omp_all_clauses): Update calls to cp_parser_omp_var_list. * parser.h (cp_parser): Add omp_array_section_p field. * semantics.cc (handle_omp_array_sections_1): Handle more types of map expression. (handle_omp_array_section): Handle non-DECL_P attachment points. (finish_omp_clauses): Check for supported types of expression. gcc/ * gimplify.cc (accumulate_sibling_list): Handle reference-typed component accesses. Fix support for non-DECL_P struct bases. (omp_ptrmem_p): New function. (omp_build_struct_sibling_lists): Support length-two group for synthesized inner struct mapping. Explicitly disallow pointers to members. * tree-pretty-print.c (dump_generic_node): Support OMP_ARRAY_SECTION. * tree.def (OMP_ARRAY_SECTION): New tree code. gcc/testsuite/ * c-c++-common/gomp/map-6.c: Update expected output. * g++.dg/gomp/pr67522.C: Likewise. * g++.dg/gomp/ind-base-3.C: New test. * g++.dg/gomp/map-assignment-1.C: New test. * g++.dg/gomp/map-inc-1.C: New test. * g++.dg/gomp/map-lvalue-ref-1.C: New test. * g++.dg/gomp/map-ptrmem-1.C: New test. * g++.dg/gomp/map-ptrmem-2.C: New test. * g++.dg/gomp/map-static-cast-lvalue-1.C: New test. * g++.dg/gomp/map-ternary-1.C: New test. * g++.dg/gomp/member-array-2.C: New test. libgomp/ * testsuite/libgomp.c++/ind-base-1.C: New test. * testsuite/libgomp.c++/ind-base-2.C: New test. * testsuite/libgomp.c++/map-comma-1.C: New test. * testsuite/libgomp.c++/map-rvalue-ref-1.C: New test. * testsuite/libgomp.c++/member-array-1.C: New test. * testsuite/libgomp.c++/struct-ref-1.C: New test. --- gcc/c-family/c-omp.cc | 25 ++- gcc/cp/error.cc | 9 + gcc/cp/parser.cc | 141 +-- gcc/cp/parser.h | 3 + gcc/cp/semantics.cc | 55 +- gcc/gimplify.cc | 71 +++- gcc/testsuite/c-c++-common/gomp/map-6.c | 4 +- gcc/testsuite/g++.dg/gomp/ind-base-3.C| 38 gcc/testsuite/g++.dg/gomp/map-assignment-1.C | 12 ++ gcc/testsuite/g++.dg/gomp/map-inc-1.C | 10 ++ gcc/testsuite/g++.dg/gomp/map-lvalue-ref-1.C | 19 ++ gcc/testsuite/g++.dg/gomp/map-ptrmem-1.C | 36 gcc/testsuite/g++.dg/gomp/map-ptrmem-2.C | 39 + .../g++.dg/gomp/map-static-cast-lvalue-1.C| 17 ++ gcc/testsuite/g++.dg/gomp/map-ternary-1.C | 20 +++ gcc/testsuite/g++.dg/gomp/member-array-2.C| 86 ++ gcc/testsuite/g++.dg/gomp/pr67522.C | 2 +- gcc/tree-pretty-print.cc | 14 ++ gcc/tree.def | 3 + libgomp/testsuite/libgomp.c++/ind-base-1.C| 162 ++ libgomp/testsuite/libgomp.c++/ind-base-2.C| 49 ++ libgomp/testsuite/libgomp.c++/map-comma-1.C | 15 ++ .../testsuite/libgomp.c++/map-rvalue-ref-1.C | 22 +++ .../testsuite/libgomp.c++/member-array-1.C| 89 ++ libgomp/testsuite/libgomp.c++/struct-ref-1.C | 97 +++ 25 files
[PATCH 7/8] Use OMP_ARRAY_SECTION instead of TREE_LIST in C++ FE
This patch changes the representation of OMP array sections in the C++ front end to use the new OMP_ARRAY_SECTION tree code instead of a TREE_LIST. This is important for "declare mapper" support, because the array section representation may stick around longer (in "declare mapper" definitions), and special-case handling TREE_LIST becomes necessary in more places, which starts to become unwieldy. 2022-02-18 Julian Brown gcc/c-family/ * c-omp.cc (c_omp_split_clauses): Support OMP_ARRAY_SECTION. gcc/cp/ * parser.cc (cp_parser_omp_var_list_no_open): Use OMP_ARRAY_SECTION code instead of TREE_LIST to represent OpenMP array sections. * pt.cc (tsubst_copy, tsubst_omp_clause_decl, tsubst_copy_and_build): Add OMP_ARRAY_SECTION support. * semantics.cc (handle_omp_array_sections_1, handle_omp_array_sections, cp_oacc_check_attachments, finish_omp_clauses): Use OMP_ARRAY_SECTION instead of TREE_LIST where appropriate. * gimplify.cc (gimplify_expr): Ensure OMP_ARRAY_SECTION has been processed out before gimplification. --- gcc/c-family/c-omp.cc | 14 +++ gcc/cp/parser.cc | 15 gcc/cp/pt.cc | 52 gcc/cp/semantics.cc | 56 ++- gcc/gimplify.cc | 3 +++ 5 files changed, 109 insertions(+), 31 deletions(-) diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index ad34f817029..3f5f9637213 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -2662,6 +2662,9 @@ c_omp_split_clauses (location_t loc, enum tree_code code, } else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST) { + /* TODO: This can go away once we transition all uses of +TREE_LIST for representing OMP array sections to +OMP_ARRAY_SECTION. */ tree t; for (t = OMP_CLAUSE_DECL (c); TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t)) @@ -2670,6 +2673,17 @@ c_omp_split_clauses (location_t loc, enum tree_code code, bitmap_clear_bit (&allocate_head, DECL_UID (t)); break; } + else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION) + { + tree t; + for (t = OMP_CLAUSE_DECL (c); + TREE_CODE (t) == OMP_ARRAY_SECTION; + t = TREE_OPERAND (t, 0)) + ; + if (DECL_P (t)) + bitmap_clear_bit (&allocate_head, DECL_UID (t)); + break; + } /* FALLTHRU */ case OMP_CLAUSE_PRIVATE: case OMP_CLAUSE_FIRSTPRIVATE: diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index efb65543e11..8d5ae9c44d0 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -36639,11 +36639,14 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, decl = TREE_OPERAND (decl, 0); for (int i = dims.length () - 1; i >= 0; i--) - decl = tree_cons (dims[i].low_bound, dims[i].length, decl); + decl = build3_loc (input_location, OMP_ARRAY_SECTION, + TREE_TYPE (decl), decl, dims[i].low_bound, + dims[i].length); } else if (TREE_CODE (decl) == INDIRECT_REF) { bool ref_p = REFERENCE_REF_P (decl); + tree type = TREE_TYPE (decl); /* Turn *foo into the representation previously used for foo[0]. */ @@ -36653,7 +36656,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, /* ...but don't add the [0:1] representation for references (because they have special handling elsewhere). */ if (!ref_p) - decl = tree_cons (integer_zero_node, integer_one_node, decl); + decl = build3_loc (input_location, OMP_ARRAY_SECTION, type, + decl, integer_zero_node, integer_one_node); } else if (TREE_CODE (decl) == ARRAY_REF) { @@ -36662,7 +3,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, decl = TREE_OPERAND (decl, 0); STRIP_NOPS (decl); - decl = tree_cons (idx, integer_one_node, decl); + decl = build3_loc (input_location, OMP_ARRAY_SECTION, +TREE_TYPE (decl), decl, idx, integer_one_node); } else if (TREE_CODE (decl) == NON_LVALUE_EXPR || CONVERT_EXPR_P (decl)) @@ -36837,7 +36842,9 @@ cp_parser_omp_var_list_no_open (cp_parser
[PATCH 6/8] OpenMP: lvalue parsing for map clauses (C)
This patch adds support for parsing general lvalues for OpenMP "map" clauses to the C front-end, similar to the previous patch for C++. This version of the patch fixes several omissions regarding non-DECL_P root terms in map clauses (i.e. "*foo" in "(*foo)->ptr->arr[:N]") -- similar to the cp/semantics.c changes in the previous patch -- and adds a couple of new tests. 2021-11-24 Julian Brown gcc/c/ * c-parser.c (c_parser_postfix_expression_after_primary): Add support for OpenMP array section parsing. (c_parser_omp_variable_list): Change ALLOW_DEREF parameter to MAP_LVALUE. Support parsing of general lvalues in "map" clauses. (c_parser_omp_var_list_parens): Change ALLOW_DEREF parameter to MAP_LVALUE. Update call to c_parser_omp_variable_list. (c_parser_oacc_data_clause, c_parser_omp_clause_to, c_parser_omp_clause_from): Update calls to c_parser_omp_var_list_parens. * c-tree.h (c_omp_array_section_p): Add extern declaration. * c-typeck.c (c_omp_array_section_p): Add flag. (mark_exp_read): Support OMP_ARRAY_SECTION. (handle_omp_array_sections_1): Handle more kinds of expressions. (handle_omp_array_sections): Handle non-DECL_P attachment points. (c_finish_omp_clauses): Check for supported expression types. Support non-DECL_P root term for map clauses. gcc/testsuite/ * c-c++-common/gomp/map-1.c: Adjust expected output. * c-c++-common/gomp/map-6.c: Likewise. libgomp/ * testsuite/libgomp.c-c++-common/ind-base-4.c: New test. * testsuite/libgomp.c-c++-common/unary-ptr-1.c: New test. --- gcc/c/c-parser.cc | 150 +++--- gcc/c/c-tree.h| 1 + gcc/c/c-typeck.cc | 45 +- gcc/testsuite/c-c++-common/gomp/map-1.c | 3 +- gcc/testsuite/c-c++-common/gomp/map-6.c | 2 + .../libgomp.c-c++-common/ind-base-4.c | 50 ++ .../libgomp.c-c++-common/unary-ptr-1.c| 16 ++ 7 files changed, 243 insertions(+), 24 deletions(-) create mode 100644 libgomp/testsuite/libgomp.c-c++-common/ind-base-4.c create mode 100644 libgomp/testsuite/libgomp.c-c++-common/unary-ptr-1.c diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index e9086c58524..cc590e56e75 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -10486,7 +10486,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, struct c_expr expr) { struct c_expr orig_expr; - tree ident, idx; + tree ident, idx, len; location_t sizeof_arg_loc[3], comp_loc; tree sizeof_arg[3]; unsigned int literal_zero_mask; @@ -10505,15 +10505,44 @@ c_parser_postfix_expression_after_primary (c_parser *parser, case CPP_OPEN_SQUARE: /* Array reference. */ c_parser_consume_token (parser); - idx = c_parser_expression (parser).value; - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, -"expected %<]%>"); - start = expr.get_start (); - finish = parser->tokens_buf[0].location; - expr.value = build_array_ref (op_loc, expr.value, idx); - set_c_expr_source_range (&expr, start, finish); - expr.original_code = ERROR_MARK; - expr.original_type = NULL; + idx = len = NULL_TREE; + if (!c_omp_array_section_p + || c_parser_next_token_is_not (parser, CPP_COLON)) + idx = c_parser_expression (parser).value; + + if (c_omp_array_section_p + && c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE)) + len = c_parser_expression (parser).value; + + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, +"expected %<]%>"); + +/* NOTE: We are reusing using the type of the whole array as the + type of the array section here, which isn't necessarily + entirely correct. Might need revisiting. */ + start = expr.get_start (); + finish = parser->tokens_buf[0].location; + expr.value = build3_loc (op_loc, OMP_ARRAY_SECTION, + TREE_TYPE (expr.value), expr.value, + idx, len); + set_c_expr_source_range (&expr, start, finish); + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + } + else + { + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, +"expected %<]%>"); + start = expr.get_start (); + finish = parser->tokens_buf[0].location; + expr.value = build_array_ref (op_loc, expr.value, i
[PATCH 8/8] OpenMP 5.0 "declare mapper" support for C++
This patch implements OpenMP 5.0 "declare mapper" support for C++ -- except for arrays of structs with mappers, which are TBD. I've taken cues from the existing "declare reduction" support where appropriate, though obviously the details of implementation differ somewhat (in particular, "declare mappers" must survive longer, until gimplification time). Both named and unnamed (default) mappers are supported, and both explicitly-mapped structures and implicitly-mapped struct-typed variables used within an offload region are supported. For the latter, we need a way to communicate to the middle end which mapper (visible, in-scope) is the right one to use -- for that, we scan the target body in the front end for uses of structure (etc.) types, and create artificial "mapper binding" clauses to associate types with visible mappers. (It doesn't matter too much if we create these mapper bindings a bit over-eagerly, since they will only be used if needed later during gimplification.) Another difficulty concerns the order in which an OpenMP offload region body's clauses are processed relative to its body: in order to add clauses for instantiated mappers, we need to have processed the body already in order to find which variables have been used, but at present the region's clauses are processed strictly before the body. So, this patch adds a second clause-processing step after gimplification of the body in order to add clauses resulting from instantiated mappers. (C and Fortran FE support are TBD.) Tested (alongside previous patches) with offloading to NVPTX, and bootstrapped. Any comments on this general approach? Thoughts on handling arrays of custom-mapped structs? OK (for stage 1)? Thanks, Julian 2022-02-18 Julian Brown gcc/cp/ * cp-gimplify.cc (cxx_omp_finish_mapper_clauses): New function. * cp-objcp-common.h (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES): Add new langhook. * cp-tree.h (lang_decl_fn): Add omp_declare_mapper_p field. (DECL_OMP_DECLARE_MAPPER_P): New function. (omp_mapper_id, cp_check_omp_declare_mapper, omp_instantiate_mappers, cxx_omp_finish_mapper_clauses): Add prototypes. * decl.cc (duplicate_decls): Support DECL_OMP_DECLARE_MAPPER_P functions. (finish_function): Likewise. * mangle.cc (decl_mangling_context): Likewise. * name-lookup.cc (set_decl_context_in_fn): Likewise. * parser.cc (cp_parser_class_specifier_1): Likewise. (cp_parser_omp_declare_mapper, cp_parser_omp_declare_mapper_maplist): New functions. (cp_parser_late_parsing_for_member): Support DECL_OMP_DECLARE_MAPPER_P functions. (cp_parser_omp_clause_map): Add KIND parameter. Support "mapper" modifier. (cp_parser_omp_all_clauses): Add KIND argument to cp_parser_omp_clause_map call. (cp_parser_omp_target): Call omp_instantiate_mappers before finish_omp_clauses. (cp_parser_omp_declare): Add "declare mapper" support. * pt.cc (instantiate_class_template_1, tsubst_function_decl): Support DECL_OMP_DECLARE_MAPPER_P functions. (tsubst_omp_clauses): Call omp_instantiate_mappers before finish_omp_clauses, for target regions. (tsubst_expr): Support DECL_OMP_DECLARE_MAPPER_P functions. (tsubst_omp_udm): New function. (instantiate_body): Support DECL_OMP_DECLARE_MAPPER_P functions. * semantics.cc (gimplify.h): Include. (expand_or_defer_fn_1): Support DECL_OMP_DECLARE_MAPPER_P functions. (omp_mapper_id, omp_mapper_lookup, omp_extract_mapper_directive, cp_check_omp_declare_mapper): New functions. (remap_mapper_decl_info): New struct. (remap_mapper_decl_1, omp_instantiate_mapper, omp_instantiate_mappers): New functions. (finish_omp_clauses): Delete GOMP_MAP_PUSH_MAPPER_NAME and GOMP_MAP_POP_MAPPER_NAME artificial clauses. (mapper_list): New struct. (find_nested_mappers): New function. (omp_target_walk_data): Add MAPPERS field. (finish_omp_target_clauses_r): Scan for uses of struct/union/class type variables. (finish_omp_target_clauses): Create artificial mapper binding clauses for used structs/unions/classes in offload region. gcc/fortran/ * parse.cc (tree.h, fold-const.h, tree-hash-traits.h): Add includes (for additions to omp-general.h). gcc/ * gimplify.cc (gimplify_omp_ctx): Add IMPLICIT_MAPPERS field. (new_omp_context): Initialise IMPLICIT_MAPPERS hash map. (delete_omp_context): Delete IMPLICIT_MAPPERS hash map. (instantiate_mapper_info, remap_mapper_decl_info): New structs. (remap_mapper_decl_1, omp_instantiate_mapper, handled_struct_p, omp_instantiate_implicit_mappers, new_omp_context_for_scan): New functions. (gimplify_scan_omp_clauses): Add optional USE_MAPPERS parameter. Instantia
[PATCH] Add a restriction on allocate clause (OpenMP 5.0)
An allocate clause in target region must specify an allocator unless the compilation unit has requires construct with dynamic_allocators clause. Current implementation of the allocate clause did not check for this restriction. This patch fills that gap. gcc/ChangeLog: * omp-low.cc (omp_maybe_offloaded_ctx): New prototype. (scan_sharing_clauses): Check a restriction on allocate clause. gcc/testsuite/ChangeLog: * c-c++-common/gomp/allocate-2.c: Add tests. * c-c++-common/gomp/allocate-8.c: New test. * gfortran.dg/gomp/allocate-3.f90: Add tests. * gcc.dg/gomp/pr104517.c: Update. --- gcc/omp-low.cc| 10 ++ gcc/testsuite/c-c++-common/gomp/allocate-2.c | 15 +++ gcc/testsuite/c-c++-common/gomp/allocate-8.c | 18 ++ gcc/testsuite/gcc.dg/gomp/pr104517.c | 18 ++ gcc/testsuite/gfortran.dg/gomp/allocate-3.f90 | 14 ++ 5 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/allocate-8.c diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc index 77176efe715..658cb3de7d6 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -195,6 +195,7 @@ static vec task_cpyfns; static void scan_omp (gimple_seq *, omp_context *); static tree scan_omp_1_op (tree *, int *, void *); +static bool omp_maybe_offloaded_ctx (omp_context *ctx); #define WALK_SUBSTMTS \ case GIMPLE_BIND: \ @@ -1169,6 +1170,15 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) || OMP_CLAUSE_ALLOCATE_ALIGN (c) != NULL_TREE)) { + /* The allocate clauses that appear on a target construct or on + constructs in a target region must specify an allocator expression + unless a requires directive with the dynamic_allocators clause + is present in the same compilation unit. */ + if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE + && ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0) + && omp_maybe_offloaded_ctx (ctx)) + error_at (OMP_CLAUSE_LOCATION (c), "% clause must" + " specify an allocator here"); if (ctx->allocate_map == NULL) ctx->allocate_map = new hash_map; tree val = integer_zero_node; diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-2.c b/gcc/testsuite/c-c++-common/gomp/allocate-2.c index cc77efc8ffe..6bb4a8af2e7 100644 --- a/gcc/testsuite/c-c++-common/gomp/allocate-2.c +++ b/gcc/testsuite/c-c++-common/gomp/allocate-2.c @@ -43,3 +43,18 @@ foo (int x, int z) #pragma omp parallel private (x) allocate (0 : x)/* { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" } */ bar (x, &x, 0); } + +void +foo1 () +{ + int a = 10; +#pragma omp target + { +#pragma omp parallel private (a) allocate(a) // { dg-error "'allocate' clause must specify an allocator here" } +a = 20; + } +#pragma omp target private(a) allocate(a) // { dg-error "'allocate' clause must specify an allocator here" } + { +a = 30; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-8.c b/gcc/testsuite/c-c++-common/gomp/allocate-8.c new file mode 100644 index 000..bacefafc6fc --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/allocate-8.c @@ -0,0 +1,18 @@ +#pragma omp requires dynamic_allocators +void +foo () +{ + int a = 10; +#pragma omp parallel private (a) allocate(a) + a = 20; +#pragma omp target + { +#pragma omp parallel private (a) allocate(a) +a = 30; + } +#pragma omp target private(a) allocate(a) + { +a = 40; + } +} + diff --git a/gcc/testsuite/gcc.dg/gomp/pr104517.c b/gcc/testsuite/gcc.dg/gomp/pr104517.c index efb3175beb3..7e3bd1a1d1e 100644 --- a/gcc/testsuite/gcc.dg/gomp/pr104517.c +++ b/gcc/testsuite/gcc.dg/gomp/pr104517.c @@ -2,11 +2,13 @@ /* { dg-do compile } */ /* { dg-options "-O1 -fcompare-debug -fopenmp -fno-tree-ter -save-temps" } */ -enum { - omp_default_mem_alloc, - omp_large_cap_mem_alloc, - omp_const_mem_alloc, - omp_high_bw_mem_alloc +typedef enum omp_allocator_handle_t +{ + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, } omp_allocator_handle_t; int t, bar_nte, bar_tl, bar_i3, bar_dd; @@ -23,7 +25,7 @@ bar (int *idp, int s, int nth, int g, int nta, int fi, int pp, int *q, int p = 0, i2 = 0, i1 = 0, m = 0, d = 0; #pragma omp target parallel for \ - device(p) firstprivate (f) allocate (f) in_reduction(+:r2) + device(p) firstprivate (f) allocate (omp_default_mem_alloc:f) in_reduction(+:r2) for (int i = 0; i < 4; i++) ll++; @@ -31,8 +33,8 @@ bar (int *idp, int s, int nth, int g, int nta, int fi, int pp, int *q, device(d) map (m) \ if