aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorChung-Lin Tang <cltang@codesourcery.com>2021-12-08 23:58:55 +0800
committerChung-Lin Tang <cltang@codesourcery.com>2021-12-09 00:01:10 +0800
commit6c0399378e77d02962e5d49f7b72d6fa8ebe5e07 (patch)
tree1b5644f24197dedde1aa8dbf1d8b983d14ab5b19 /gcc/gimplify.c
parent6b49d50a27428e9de0ae2913651a6379744f3067 (diff)
downloadgcc-6c0399378e77d02962e5d49f7b72d6fa8ebe5e07.zip
gcc-6c0399378e77d02962e5d49f7b72d6fa8ebe5e07.tar.gz
gcc-6c0399378e77d02962e5d49f7b72d6fa8ebe5e07.tar.bz2
OpenMP 5.0: Remove array section base-pointer mapping semantics and other front-end adjustments
This patch implements three pieces of functionality: (1) Adjust array section mapping to have standards conforming behavior, mapping array sections should *NOT* also map the base-pointer: struct S { int *ptr; ... }; struct S s; Instead of generating this during gimplify: map(to:*_1 [len: 400]) map(attach:s.ptr [bias: 0]) Now, adjust to: (i.e. do not map the base-pointer together. The attach operation is still generated, and if s.ptr is already mapped prior, attachment will happen) The correct way of achieving the base-pointer-also-mapped behavior would be to use: (A small Fortran front-end patch to trans-openmp.c:gfc_trans_omp_array_section is also included, which removes generation of a GOMP_MAP_ALWAYS_POINTER for array types, which appears incorrect and causes a regression in libgomp.fortranlibgomp.fortran/struct-elem-map-1.f90) (2) Related to the first item above, are fixes in libgomp/target.c to not overwrite attached pointers when handling device<->host copies, mainly for the "always" case. (3) The third is a set of changes to the C/C++ front-ends to extend the allowed component access syntax in map clauses. These changes are enabled for both OpenACC and OpenMP. gcc/c/ChangeLog: * c-parser.c (struct omp_dim): New struct type for use inside c_parser_omp_variable_list. (c_parser_omp_variable_list): Allow multiple levels of array and component accesses in array section base-pointer expression. (c_parser_omp_clause_to): Set 'allow_deref' to true in call to c_parser_omp_var_list_parens. (c_parser_omp_clause_from): Likewise. * c-typeck.c (handle_omp_array_sections_1): Extend allowed range of base-pointer expressions involving INDIRECT/MEM/ARRAY_REF and POINTER_PLUS_EXPR. (c_finish_omp_clauses): Extend allowed ranged of expressions involving INDIRECT/MEM/ARRAY_REF and POINTER_PLUS_EXPR. gcc/cp/ChangeLog: * parser.c (struct omp_dim): New struct type for use inside cp_parser_omp_var_list_no_open. (cp_parser_omp_var_list_no_open): Allow multiple levels of array and component accesses in array section base-pointer expression. (cp_parser_omp_all_clauses): Set 'allow_deref' to true in call to cp_parser_omp_var_list for to/from clauses. * semantics.c (handle_omp_array_sections_1): Extend allowed range of base-pointer expressions involving INDIRECT/MEM/ARRAY_REF and POINTER_PLUS_EXPR. (handle_omp_array_sections): Adjust pointer map generation of references. (finish_omp_clauses): Extend allowed ranged of expressions involving INDIRECT/MEM/ARRAY_REF and POINTER_PLUS_EXPR. gcc/fortran/ChangeLog: * trans-openmp.c (gfc_trans_omp_array_section): Do not generate GOMP_MAP_ALWAYS_POINTER map for main array maps of ARRAY_TYPE type. gcc/ChangeLog: * gimplify.c (extract_base_bit_offset): Add 'tree *offsetp' parameter, accomodate case where 'offset' return of get_inner_reference is non-NULL. (is_or_contains_p): Further robustify conditions. (omp_target_reorder_clauses): In alloc/to/from sorting phase, also move following GOMP_MAP_ALWAYS_POINTER maps along. Add new sorting phase where we make sure pointers with an attach/detach map are ordered correctly. (gimplify_scan_omp_clauses): Add modifications to avoid creating GOMP_MAP_STRUCT and associated alloc map for attach/detach maps. gcc/testsuite/ChangeLog: * c-c++-common/goacc/deep-copy-arrayofstruct.c: Adjust testcase. * c-c++-common/gomp/target-enter-data-1.c: New testcase. * c-c++-common/gomp/target-implicit-map-2.c: New testcase. libgomp/ChangeLog: * target.c (gomp_map_vars_existing): Make sure attached pointer is not overwritten during cross-host/device copying. (gomp_update): Likewise. (gomp_exit_data): Likewise. * testsuite/libgomp.c++/target-11.C: Adjust testcase. * testsuite/libgomp.c++/target-12.C: Likewise. * testsuite/libgomp.c++/target-15.C: Likewise. * testsuite/libgomp.c++/target-16.C: Likewise. * testsuite/libgomp.c++/target-17.C: Likewise. * testsuite/libgomp.c++/target-21.C: Likewise. * testsuite/libgomp.c++/target-23.C: Likewise. * testsuite/libgomp.c/target-23.c: Likewise. * testsuite/libgomp.c/target-29.c: Likewise. * testsuite/libgomp.c-c++-common/target-implicit-map-2.c: New testcase.
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c220
1 files changed, 187 insertions, 33 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 0a55bf7..b118c72 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -8660,7 +8660,7 @@ insert_struct_comp_map (enum tree_code code, tree c, tree struct_node,
static tree
extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
- poly_offset_int *poffsetp)
+ poly_offset_int *poffsetp, tree *offsetp)
{
tree offset;
poly_int64 bitsize, bitpos;
@@ -8707,10 +8707,11 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (base, 0))) == REFERENCE_TYPE)
base = TREE_OPERAND (base, 0);
- gcc_assert (offset == NULL_TREE || poly_int_tree_p (offset));
-
- if (offset)
- poffset = wi::to_poly_offset (offset);
+ if (offset && poly_int_tree_p (offset))
+ {
+ poffset = wi::to_poly_offset (offset);
+ offset = NULL_TREE;
+ }
else
poffset = 0;
@@ -8719,6 +8720,7 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
*bitposp = bitpos;
*poffsetp = poffset;
+ *offsetp = offset;
/* Set *BASE_REF if BASE was a dereferenced reference variable. */
if (base_ref && orig_base != base)
@@ -8732,12 +8734,22 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
static bool
is_or_contains_p (tree expr, tree base_ptr)
{
- while (expr != base_ptr)
- if (TREE_CODE (base_ptr) == COMPONENT_REF)
- base_ptr = TREE_OPERAND (base_ptr, 0);
- else
- break;
- return expr == 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
@@ -8817,21 +8829,107 @@ omp_target_reorder_clauses (tree *list_p)
tree base_ptr = TREE_OPERAND (decl, 0);
STRIP_TYPE_NOPS (base_ptr);
for (unsigned int j = i + 1; j < atf.length (); j++)
- {
- tree *cp2 = atf[j];
- tree 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;
- atf[j] = NULL;
+ 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_ALWAYS_POINTER)
+ {
+ tree c2 = *cp2;
+ *cp2 = OMP_CLAUSE_CHAIN (c2);
+ OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = c2;
+ }
+
+ atf[j] = NULL;
}
- }
+ }
}
}
+
+ /* For attach_detach map clauses, if there is another map that maps the
+ attached/detached pointer, make sure that map is ordered before the
+ attach_detach. */
+ atf.truncate (0);
+ 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 clauses, and
+ always_pointer/attach_detach clauses. */
+ 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
+ || k == GOMP_MAP_ATTACH_DETACH
+ || k == GOMP_MAP_ALWAYS_POINTER)
+ atf.safe_push (cp);
+ }
+
+ for (unsigned int i = 0; i < atf.length (); i++)
+ if (atf[i])
+ {
+ tree *cp = atf[i];
+ tree ptr = OMP_CLAUSE_DECL (*cp);
+ STRIP_TYPE_NOPS (ptr);
+ if (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ATTACH_DETACH)
+ for (unsigned int j = i + 1; j < atf.length (); j++)
+ {
+ tree *cp2 = atf[j];
+ tree decl2 = OMP_CLAUSE_DECL (*cp2);
+ if (OMP_CLAUSE_MAP_KIND (*cp2) != GOMP_MAP_ATTACH_DETACH
+ && OMP_CLAUSE_MAP_KIND (*cp2) != GOMP_MAP_ALWAYS_POINTER
+ && is_or_contains_p (decl2, ptr))
+ {
+ /* Move *cp2 to before *cp. */
+ tree c = *cp2;
+ *cp2 = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = *cp;
+ *cp = c;
+ atf[j] = NULL;
+
+ /* If decl2 is of the form '*decl2_opnd0', and followed by an
+ ALWAYS_POINTER or ATTACH_DETACH of 'decl2_opnd0', move the
+ pointer operation along with *cp2. This can happen for C++
+ reference sequences. */
+ if (j + 1 < atf.length ()
+ && (TREE_CODE (decl2) == INDIRECT_REF
+ || TREE_CODE (decl2) == MEM_REF))
+ {
+ tree *cp3 = atf[j + 1];
+ tree decl3 = OMP_CLAUSE_DECL (*cp3);
+ tree decl2_opnd0 = TREE_OPERAND (decl2, 0);
+ if ((OMP_CLAUSE_MAP_KIND (*cp3) == GOMP_MAP_ALWAYS_POINTER
+ || OMP_CLAUSE_MAP_KIND (*cp3) == GOMP_MAP_ATTACH_DETACH)
+ && operand_equal_p (decl3, decl2_opnd0))
+ {
+ /* Also move *cp3 to before *cp. */
+ c = *cp3;
+ *cp2 = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = *cp;
+ *cp = c;
+ atf[j + 1] = NULL;
+ j += 1;
+ }
+ }
+ }
+ }
+ }
}
/* DECL is supposed to have lastprivate semantics in the outer contexts
@@ -8923,6 +9021,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
struct gimplify_omp_ctx *ctx, *outer_ctx;
tree c;
hash_map<tree_operand_hash, tree> *struct_map_to_clause = NULL;
+ hash_map<tree_operand_hash, tree *> *struct_seen_clause = NULL;
hash_set<tree> *struct_deref_set = NULL;
tree *prev_list_p = NULL, *orig_list_p = list_p;
int handled_depend_iterators = -1;
@@ -9398,6 +9497,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
}
bool indir_p = false;
bool component_ref_p = false;
+ tree indir_base = NULL_TREE;
tree orig_decl = decl;
tree decl_ref = NULL_TREE;
if ((region_type & (ORT_ACC | ORT_TARGET | ORT_TARGET_DATA)) != 0
@@ -9416,6 +9516,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
== POINTER_TYPE))
{
indir_p = true;
+ indir_base = decl;
decl = TREE_OPERAND (decl, 0);
STRIP_NOPS (decl);
}
@@ -9462,7 +9563,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
!= GOMP_MAP_POINTER)
|| OMP_CLAUSE_DECL (next_clause) != decl)
&& (!struct_deref_set
- || !struct_deref_set->contains (decl)))
+ || !struct_deref_set->contains (decl))
+ && (!struct_map_to_clause
+ || !struct_map_to_clause->get (indir_base)))
{
if (!struct_deref_set)
struct_deref_set = new hash_set<tree> ();
@@ -9506,7 +9609,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if ((DECL_P (decl)
|| (component_ref_p
&& (INDIRECT_REF_P (decl)
- || TREE_CODE (decl) == MEM_REF)))
+ || TREE_CODE (decl) == MEM_REF
+ || TREE_CODE (decl) == ARRAY_REF)))
&& 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
@@ -9541,7 +9645,15 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
remove = true;
break;
}
- if (OMP_CLAUSE_CHAIN (*prev_list_p) != c)
+
+ /* The below prev_list_p based error recovery code is
+ currently no longer valid for OpenMP. */
+ if (code != OMP_TARGET
+ && code != OMP_TARGET_DATA
+ && code != OMP_TARGET_UPDATE
+ && code != OMP_TARGET_ENTER_DATA
+ && code != OMP_TARGET_EXIT_DATA
+ && OMP_CLAUSE_CHAIN (*prev_list_p) != c)
{
tree ch = OMP_CLAUSE_CHAIN (*prev_list_p);
if (ch == NULL_TREE || OMP_CLAUSE_CHAIN (ch) != c)
@@ -9554,13 +9666,15 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
poly_offset_int offset1;
poly_int64 bitpos1;
+ tree tree_offset1;
tree base_ref;
tree base
= extract_base_bit_offset (OMP_CLAUSE_DECL (c), &base_ref,
- &bitpos1, &offset1);
+ &bitpos1, &offset1,
+ &tree_offset1);
- gcc_assert (base == decl);
+ bool do_map_struct = (base == decl && !tree_offset1);
splay_tree_node n
= (DECL_P (decl)
@@ -9592,6 +9706,32 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
OMP_CLAUSE_SET_MAP_KIND (c, k);
has_attachments = true;
}
+
+ /* We currently don't handle non-constant offset accesses wrt to
+ GOMP_MAP_STRUCT elements. */
+ if (!do_map_struct)
+ goto skip_map_struct;
+
+ /* Nor for attach_detach for OpenMP. */
+ if ((code == OMP_TARGET
+ || code == OMP_TARGET_DATA
+ || code == OMP_TARGET_UPDATE
+ || code == OMP_TARGET_ENTER_DATA
+ || code == OMP_TARGET_EXIT_DATA)
+ && attach_detach)
+ {
+ if (DECL_P (decl))
+ {
+ if (struct_seen_clause == NULL)
+ struct_seen_clause
+ = new hash_map<tree_operand_hash, tree *>;
+ if (!struct_seen_clause->get (decl))
+ struct_seen_clause->put (decl, list_p);
+ }
+
+ goto skip_map_struct;
+ }
+
if ((DECL_P (decl)
&& (n == NULL || (n->value & GOVD_MAP) == 0))
|| (!DECL_P (decl)
@@ -9631,9 +9771,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
struct_map_to_clause->put (decl, l);
if (ptr || attach_detach)
{
- insert_struct_comp_map (code, c, l, *prev_list_p,
+ tree **sc = (struct_seen_clause
+ ? struct_seen_clause->get (decl)
+ : NULL);
+ tree *insert_node_pos = sc ? *sc : prev_list_p;
+
+ insert_struct_comp_map (code, c, l, *insert_node_pos,
NULL);
- *prev_list_p = l;
+ *insert_node_pos = l;
prev_list_p = NULL;
}
else
@@ -9719,9 +9864,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
tree sc_decl = OMP_CLAUSE_DECL (*sc);
poly_offset_int offsetn;
poly_int64 bitposn;
+ tree tree_offsetn;
tree base
= extract_base_bit_offset (sc_decl, NULL,
- &bitposn, &offsetn);
+ &bitposn, &offsetn,
+ &tree_offsetn);
if (base != decl)
break;
if (scp)
@@ -9809,16 +9956,21 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
continue;
}
}
+ skip_map_struct:
+ ;
}
else if ((code == OACC_ENTER_DATA
|| code == OACC_EXIT_DATA
|| code == OACC_DATA
|| code == OACC_PARALLEL
|| code == OACC_KERNELS
- || code == OACC_SERIAL)
+ || code == OACC_SERIAL
+ || code == OMP_TARGET_ENTER_DATA
+ || code == OMP_TARGET_EXIT_DATA)
&& OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
{
- gomp_map_kind k = (code == OACC_EXIT_DATA
+ gomp_map_kind k = ((code == OACC_EXIT_DATA
+ || code == OMP_TARGET_EXIT_DATA)
? GOMP_MAP_DETACH : GOMP_MAP_ATTACH);
OMP_CLAUSE_SET_MAP_KIND (c, k);
}
@@ -10650,6 +10802,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
ctx->clauses = *orig_list_p;
gimplify_omp_ctxp = ctx;
+ if (struct_seen_clause)
+ delete struct_seen_clause;
if (struct_map_to_clause)
delete struct_map_to_clause;
if (struct_deref_set)