aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.cc
diff options
context:
space:
mode:
authorJulian Brown <julian@codesourcery.com>2022-10-09 20:26:09 +0000
committerJulian Brown <julian@codesourcery.com>2023-12-15 10:33:52 +0000
commitf5745dc1426bdb1a53ebaf7af758b2250ccbff02 (patch)
treedd1d55ced447489b6c07b17be14616cba68d54ce /gcc/gimplify.cc
parentef9754dfdf18a89de3da23c4f23365f4c2611367 (diff)
downloadgcc-f5745dc1426bdb1a53ebaf7af758b2250ccbff02.zip
gcc-f5745dc1426bdb1a53ebaf7af758b2250ccbff02.tar.gz
gcc-f5745dc1426bdb1a53ebaf7af758b2250ccbff02.tar.bz2
OpenMP/OpenACC: Unordered/non-constant component offset runtime diagnostic
This patch adds support for non-constant component offsets in "map" clauses for OpenMP (and the equivalants for OpenACC), which are not able to be sorted into order at compile time. Normally struct accesses in such clauses are gathered together and sorted into increasing address order after a "GOMP_MAP_STRUCT" node: if we have variable indices, that is no longer possible. This version of the patch scales back the previously-posted version to merely add a diagnostic for incorrect usage of component accesses with variably-indexed arrays of structs: the only permitted variant is where we have multiple indices that are the same, but we could not prove so at compile time. Rather than silently producing the wrong result for cases where the indices are in fact different, we error out (e.g., "map(dtarr(i)%arrptr, dtarr(j)%arrptr(4:8))", for different i/j). For now, multiple *constant* array indices are still supported (see map-arrayofstruct-1.c). That could perhaps be addressed with a follow-up patch, if necessary. This version of the patch renumbers the GOMP_MAP_STRUCT_UNORD kind to avoid clashing with the OpenACC "non-contiguous" dynamic array support (though that is not yet applied to mainline). 2023-08-18 Julian Brown <julian@codesourcery.com> gcc/ * gimplify.cc (extract_base_bit_offset): Add VARIABLE_OFFSET parameter. (omp_get_attachment, omp_group_last, omp_group_base, omp_directive_maps_explicitly): Add GOMP_MAP_STRUCT_UNORD support. (omp_accumulate_sibling_list): Update calls to extract_base_bit_offset. Support GOMP_MAP_STRUCT_UNORD. (omp_build_struct_sibling_lists, gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses, gimplify_omp_target_update): Add GOMP_MAP_STRUCT_UNORD support. * omp-low.cc (lower_omp_target): Add GOMP_MAP_STRUCT_UNORD support. * tree-pretty-print.cc (dump_omp_clause): Likewise. include/ * gomp-constants.h (gomp_map_kind): Add GOMP_MAP_STRUCT_UNORD. libgomp/ * oacc-mem.c (find_group_last, goacc_enter_data_internal, goacc_exit_data_internal, GOACC_enter_exit_data): Add GOMP_MAP_STRUCT_UNORD support. * target.c (gomp_map_vars_internal): Add GOMP_MAP_STRUCT_UNORD support. Detect incorrect use of variable indexing of arrays of structs. (GOMP_target_enter_exit_data, gomp_target_task_fn): Add GOMP_MAP_STRUCT_UNORD support. * testsuite/libgomp.c-c++-common/map-arrayofstruct-1.c: New test. * testsuite/libgomp.c-c++-common/map-arrayofstruct-2.c: New test. * testsuite/libgomp.c-c++-common/map-arrayofstruct-3.c: New test. * testsuite/libgomp.fortran/map-subarray-5.f90: New test.
Diffstat (limited to 'gcc/gimplify.cc')
-rw-r--r--gcc/gimplify.cc106
1 files changed, 88 insertions, 18 deletions
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 9665746..a6bdcea 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -9238,7 +9238,8 @@ build_omp_struct_comp_nodes (enum tree_code code, tree grp_start, tree grp_end,
static tree
extract_base_bit_offset (tree base, poly_int64 *bitposp,
- poly_offset_int *poffsetp)
+ poly_offset_int *poffsetp,
+ bool *variable_offset)
{
tree offset;
poly_int64 bitsize, bitpos;
@@ -9256,10 +9257,13 @@ extract_base_bit_offset (tree base, poly_int64 *bitposp,
if (offset && poly_int_tree_p (offset))
{
poffset = wi::to_poly_offset (offset);
- offset = NULL_TREE;
+ *variable_offset = false;
}
else
- poffset = 0;
+ {
+ poffset = 0;
+ *variable_offset = (offset != NULL_TREE);
+ }
if (maybe_ne (bitpos, 0))
poffset += bits_to_bytes_round_down (bitpos);
@@ -9439,6 +9443,7 @@ omp_get_attachment (omp_mapping_group *grp)
return error_mark_node;
case GOMP_MAP_STRUCT:
+ case GOMP_MAP_STRUCT_UNORD:
case GOMP_MAP_FORCE_DEVICEPTR:
case GOMP_MAP_DEVICE_RESIDENT:
case GOMP_MAP_LINK:
@@ -9544,6 +9549,7 @@ omp_group_last (tree *start_p)
break;
case GOMP_MAP_STRUCT:
+ case GOMP_MAP_STRUCT_UNORD:
{
unsigned HOST_WIDE_INT num_mappings
= tree_to_uhwi (OMP_CLAUSE_SIZE (c));
@@ -9710,6 +9716,7 @@ omp_group_base (omp_mapping_group *grp, unsigned int *chained,
return error_mark_node;
case GOMP_MAP_STRUCT:
+ case GOMP_MAP_STRUCT_UNORD:
{
unsigned HOST_WIDE_INT num_mappings
= tree_to_uhwi (OMP_CLAUSE_SIZE (node));
@@ -10352,7 +10359,8 @@ omp_directive_maps_explicitly (hash_map<tree_operand_hash_no_se,
/* We might be called during omp_build_struct_sibling_lists, when
GOMP_MAP_STRUCT might have been inserted at the start of the group.
Skip over that, and also possibly the node after it. */
- if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT)
+ if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT
+ || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT_UNORD)
{
grp_first = OMP_CLAUSE_CHAIN (grp_first);
if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_FIRSTPRIVATE_POINTER
@@ -11040,7 +11048,9 @@ omp_accumulate_sibling_list (enum omp_region_type region_type,
}
}
- tree base = extract_base_bit_offset (ocd, &cbitpos, &coffset);
+ bool variable_offset;
+ tree base
+ = extract_base_bit_offset (ocd, &cbitpos, &coffset, &variable_offset);
int base_token;
for (base_token = addr_tokens.length () - 1; base_token >= 0; base_token--)
@@ -11074,14 +11084,20 @@ omp_accumulate_sibling_list (enum omp_region_type region_type,
if (!struct_map_to_clause || struct_map_to_clause->get (base) == NULL)
{
+ enum gomp_map_kind str_kind = GOMP_MAP_STRUCT;
+
+ if (struct_map_to_clause == NULL)
+ struct_map_to_clause = new hash_map<tree_operand_hash, tree>;
+
+ if (variable_offset)
+ str_kind = GOMP_MAP_STRUCT_UNORD;
+
tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (l, GOMP_MAP_STRUCT);
+ OMP_CLAUSE_SET_MAP_KIND (l, str_kind);
OMP_CLAUSE_DECL (l) = unshare_expr (base);
OMP_CLAUSE_SIZE (l) = size_int (1);
- if (struct_map_to_clause == NULL)
- struct_map_to_clause = new hash_map<tree_operand_hash, tree>;
struct_map_to_clause->put (base, l);
/* On first iterating through the clause list, we insert the struct node
@@ -11321,6 +11337,11 @@ omp_accumulate_sibling_list (enum omp_region_type region_type,
{
tree *osc = struct_map_to_clause->get (base);
tree *sc = NULL, *scp = NULL;
+ bool unordered = false;
+
+ if (osc && OMP_CLAUSE_MAP_KIND (*osc) == GOMP_MAP_STRUCT_UNORD)
+ unordered = true;
+
unsigned HOST_WIDE_INT i, elems = tree_to_uhwi (OMP_CLAUSE_SIZE (*osc));
sc = &OMP_CLAUSE_CHAIN (*osc);
/* The struct mapping might be immediately followed by a
@@ -11361,12 +11382,20 @@ omp_accumulate_sibling_list (enum omp_region_type region_type,
== REFERENCE_TYPE))
sc_decl = TREE_OPERAND (sc_decl, 0);
- tree base2 = extract_base_bit_offset (sc_decl, &bitpos, &offset);
+ bool variable_offset2;
+ tree base2 = extract_base_bit_offset (sc_decl, &bitpos, &offset,
+ &variable_offset2);
if (!base2 || !operand_equal_p (base2, base, 0))
break;
if (scp)
continue;
- if ((region_type & ORT_ACC) != 0)
+ if (variable_offset2)
+ {
+ OMP_CLAUSE_SET_MAP_KIND (*osc, GOMP_MAP_STRUCT_UNORD);
+ unordered = true;
+ break;
+ }
+ else if ((region_type & ORT_ACC) != 0)
{
/* For OpenACC, allow (ignore) duplicate struct accesses in
the middle of a mapping clause, e.g. "mystruct->foo" in:
@@ -11398,6 +11427,15 @@ omp_accumulate_sibling_list (enum omp_region_type region_type,
}
}
+ /* If this is an unordered struct, just insert the new element at the
+ end of the list. */
+ if (unordered)
+ {
+ for (; i < elems; i++)
+ sc = &OMP_CLAUSE_CHAIN (*sc);
+ scp = NULL;
+ }
+
OMP_CLAUSE_SIZE (*osc)
= size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), size_one_node);
@@ -11789,14 +11827,42 @@ omp_build_struct_sibling_lists (enum tree_code code,
/* This is the first sorted node in the struct sibling list. Use it
to recalculate the correct bias to use.
- (&first_node - attach_decl). */
- tree first_node = OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (attach));
- first_node = build_fold_addr_expr (first_node);
- first_node = fold_convert (ptrdiff_type_node, first_node);
+ (&first_node - attach_decl).
+ For GOMP_MAP_STRUCT_UNORD, we need e.g. the
+ min(min(min(first,second),third),fourth) element, because the
+ elements aren't in any particular order. */
+ tree lowest_addr;
+ if (OMP_CLAUSE_MAP_KIND (struct_node) == GOMP_MAP_STRUCT_UNORD)
+ {
+ tree first_node = OMP_CLAUSE_CHAIN (attach);
+ unsigned HOST_WIDE_INT num_mappings
+ = tree_to_uhwi (OMP_CLAUSE_SIZE (struct_node));
+ lowest_addr = OMP_CLAUSE_DECL (first_node);
+ lowest_addr = build_fold_addr_expr (lowest_addr);
+ lowest_addr = fold_convert (pointer_sized_int_node, lowest_addr);
+ tree next_node = OMP_CLAUSE_CHAIN (first_node);
+ while (num_mappings > 1)
+ {
+ tree tmp = OMP_CLAUSE_DECL (next_node);
+ tmp = build_fold_addr_expr (tmp);
+ tmp = fold_convert (pointer_sized_int_node, tmp);
+ lowest_addr = fold_build2 (MIN_EXPR, pointer_sized_int_node,
+ lowest_addr, tmp);
+ next_node = OMP_CLAUSE_CHAIN (next_node);
+ num_mappings--;
+ }
+ lowest_addr = fold_convert (ptrdiff_type_node, lowest_addr);
+ }
+ else
+ {
+ tree first_node = OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (attach));
+ first_node = build_fold_addr_expr (first_node);
+ lowest_addr = fold_convert (ptrdiff_type_node, first_node);
+ }
tree attach_decl = OMP_CLAUSE_DECL (attach);
attach_decl = fold_convert (ptrdiff_type_node, attach_decl);
OMP_CLAUSE_SIZE (attach)
- = fold_build2 (MINUS_EXPR, ptrdiff_type_node, first_node,
+ = fold_build2 (MINUS_EXPR, ptrdiff_type_node, lowest_addr,
attach_decl);
/* Remove GOMP_MAP_ATTACH node from after struct node. */
@@ -12364,7 +12430,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
GOVD_FIRSTPRIVATE | GOVD_SEEN);
}
- if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
+ if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
&& (addr_tokens[0]->type == STRUCTURE_BASE
|| addr_tokens[0]->type == ARRAY_BASE)
&& addr_tokens[0]->u.structure_base_kind == BASE_DECL)
@@ -13990,7 +14057,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
}
}
}
- if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
+ if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
&& (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
{
remove = true;
@@ -14034,7 +14102,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
in target block and none of the mapping has always modifier,
remove all the struct element mappings, which immediately
follow the GOMP_MAP_STRUCT map clause. */
- if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT)
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
{
HOST_WIDE_INT cnt = tree_to_shwi (OMP_CLAUSE_SIZE (c));
while (cnt--)
@@ -16814,6 +16883,7 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
have_clause = false;
break;
case GOMP_MAP_STRUCT:
+ case GOMP_MAP_STRUCT_UNORD:
have_clause = false;
break;
default: