diff options
author | Julian Brown <julian@codesourcery.com> | 2023-08-14 12:41:56 +0000 |
---|---|---|
committer | Julian Brown <julian@codesourcery.com> | 2023-12-13 20:30:49 +0000 |
commit | 5fdb150cd4bf8f2da335e3f5c3a17aafcbc66dbe (patch) | |
tree | a08dda7f55f405825c9af6e21c5fc5887b8e2614 /libgomp/testsuite | |
parent | e1fde9de3ffa0afc804beca654a7540405de54f7 (diff) | |
download | gcc-5fdb150cd4bf8f2da335e3f5c3a17aafcbc66dbe.zip gcc-5fdb150cd4bf8f2da335e3f5c3a17aafcbc66dbe.tar.gz gcc-5fdb150cd4bf8f2da335e3f5c3a17aafcbc66dbe.tar.bz2 |
OpenMP/OpenACC: Rework clause expansion and nested struct handling
This patch reworks clause expansion in the C, C++ and (to a lesser
extent) Fortran front ends for OpenMP and OpenACC mapping nodes used in
GPU offloading support.
At present a single clause may be turned into several mapping nodes,
or have its mapping type changed, in several places scattered through
the front- and middle-end. The analysis relating to which particular
transformations are needed for some given expression has become quite hard
to follow. Briefly, we manipulate clause types in the following places:
1. During parsing, in c_omp_adjust_map_clauses. Depending on a set of
rules, we may change a FIRSTPRIVATE_POINTER (etc.) mapping into
ATTACH_DETACH, or mark the decl addressable.
2. In semantics.cc or c-typeck.cc, clauses are expanded in
handle_omp_array_sections (called via {c_}finish_omp_clauses, or in
finish_omp_clauses itself. The two cases are for processing array
sections (the former), or non-array sections (the latter).
3. In gimplify.cc, we build sibling lists for struct accesses, which
groups and sorts accesses along with their struct base, creating
new ALLOC/RELEASE nodes for pointers.
4. In gimplify.cc:gimplify_adjust_omp_clauses, mapping nodes may be
adjusted or created.
This patch doesn't completely disrupt this scheme, though clause
types are no longer adjusted in c_omp_adjust_map_clauses (step 1).
Clause expansion in step 2 (for C and C++) now uses a single, unified
mechanism, parts of which are also reused for analysis in step 3.
Rather than the kind-of "ad-hoc" pattern matching on addresses used to
expand clauses used at present, a new method for analysing addresses is
introduced. This does a recursive-descent tree walk on expression nodes,
and emits a vector of tokens describing each "part" of the address.
This tokenized address can then be translated directly into mapping nodes,
with the assurance that no part of the expression has been inadvertently
skipped or misinterpreted. In this way, all the variations of ways
pointers, arrays, references and component accesses might be combined
can be teased apart into easily-understood cases - and we know we've
"parsed" the whole address before we start analysis, so the right code
paths can easily be selected.
For example, a simple access "arr[idx]" might parse as:
base-decl access-indexed-array
or "mystruct->foo[x]" with a pointer "foo" component might parse as:
base-decl access-pointer component-selector access-pointer
A key observation is that support for "array" bases, e.g. accesses
whose root nodes are not structures, but describe scalars or arrays,
and also *one-level deep* structure accesses, have first-class support
in gimplify and beyond. Expressions that use deeper struct accesses
or e.g. multiple indirections were more problematic: some cases worked,
but lots of cases didn't. This patch reimplements the support for those
in gimplify.cc, again using the new "address tokenization" support.
An expression like "mystruct->foo->bar[0:10]" used in a mapping node will
translate the right-hand access directly in the front-end. The base for
the access will be "mystruct->foo". This is handled recursively in
gimplify.cc -- there may be several accesses of "mystruct"'s members
on the same directive, so the sibling-list building machinery can be
used again. (This was already being done for OpenACC, but the new
implementation differs somewhat in details, and is more robust.)
For OpenMP, in the case where the base pointer itself,
i.e. "mystruct->foo" here, is NOT mapped on the same directive, we
create a "fragile" mapping. This turns the "foo" component access
into a zero-length allocation (which is a new feature for the runtime,
so support has been added there too).
A couple of changes have been made to how mapping clauses are turned
into mapping nodes:
The first change is based on the observation that it is probably never
correct to use GOMP_MAP_ALWAYS_POINTER for component accesses (e.g. for
references), because if the containing struct is already mapped on the
target then the host version of the pointer in question will be corrupted
if the struct is copied back from the target. This patch removes all
such uses, across each of C, C++ and Fortran.
The second change is to the way that GOMP_MAP_ATTACH_DETACH nodes
are processed during sibling-list creation. For OpenMP, for pointer
components, we must map the base pointer separately from an array section
that uses the base pointer, so e.g. we must have both "map(mystruct.base)"
and "map(mystruct.base[0:10])" mappings. These create nodes such as:
GOMP_MAP_TOFROM mystruct.base
G_M_TOFROM *mystruct.base [len: 10*elemsize] G_M_ATTACH_DETACH mystruct.base
Instead of using the first of these directly when building the struct
sibling list then skipping the group using GOMP_MAP_ATTACH_DETACH,
leading to:
GOMP_MAP_STRUCT mystruct [len: 1] GOMP_MAP_TOFROM mystruct.base
we now introduce a new "mini-pass", omp_resolve_clause_dependencies, that
drops the GOMP_MAP_TOFROM for the base pointer, marks the second group
as having had a base-pointer mapping, then omp_build_struct_sibling_lists
can create:
GOMP_MAP_STRUCT mystruct [len: 1] GOMP_MAP_ALLOC mystruct.base [len: ptrsize]
This ends up working better in many cases, particularly those involving
references. (The "alloc" space is immediately overwritten by a pointer
attachment, so this is mildly more efficient than a redundant TO mapping
at runtime also.)
There is support in the address tokenizer for "arbitrary" base expressions
which aren't rooted at a decl, but that is not used as present because
such addresses are disallowed at parse time.
In the front-ends, the address tokenization machinery is mostly only
used for clause expansion and not for diagnostics at present. It could
be used for those too, which would allow more of my previous "address
inspector" implementation to be removed.
The new bits in gimplify.cc work with OpenACC also.
This version of the patch addresses several first-pass review comments
from Tobias, and fixes a few previously-missed cases for manually-managed
ragged array mappings (including cases using references). Some arbitrary
differences between handling of clause expansion for C vs. C++ have also
been fixed, and some fragments from later in the patch series have been
moved forward (where they were useful for fixing bugs). Several new
test cases have been added.
2023-11-29 Julian Brown <julian@codesourcery.com>
gcc/c-family/
* c-common.h (c_omp_region_type): Add C_ORT_EXIT_DATA,
C_ORT_OMP_EXIT_DATA and C_ORT_ACC_TARGET.
(omp_addr_token): Add forward declaration.
(c_omp_address_inspector): New class.
* c-omp.cc (c_omp_adjust_map_clauses): Mark decls addressable here, but
do not change any mapping node types.
(c_omp_address_inspector::unconverted_ref_origin,
c_omp_address_inspector::component_access_p,
c_omp_address_inspector::check_clause,
c_omp_address_inspector::get_root_term,
c_omp_address_inspector::map_supported_p,
c_omp_address_inspector::get_origin,
c_omp_address_inspector::maybe_unconvert_ref,
c_omp_address_inspector::maybe_zero_length_array_section,
c_omp_address_inspector::expand_array_base,
c_omp_address_inspector::expand_component_selector,
c_omp_address_inspector::expand_map_clause): New methods.
(omp_expand_access_chain): New function.
gcc/c/
* c-parser.cc (c_parser_oacc_all_clauses): Add TARGET_P parameter. Use
to select region type for c_finish_omp_clauses call.
(c_parser_oacc_loop): Update calls to c_parser_oacc_all_clauses.
(c_parser_oacc_compute): Likewise.
(c_parser_omp_target_data, c_parser_omp_target_enter_data): Support
ATTACH kind.
(c_parser_omp_target_exit_data): Support DETACH kind.
(check_clauses): Handle GOMP_MAP_POINTER and GOMP_MAP_ATTACH here.
* c-typeck.cc (handle_omp_array_sections_1,
handle_omp_array_sections, c_finish_omp_clauses): Use
c_omp_address_inspector class and OMP address tokenizer to analyze and
expand map clause expressions. Fix some diagnostics. Fix "is OpenACC"
condition for C_ORT_ACC_TARGET addition.
gcc/cp/
* parser.cc (cp_parser_oacc_all_clauses): Add TARGET_P parameter. Use
to select region type for finish_omp_clauses call.
(cp_parser_omp_target_data, cp_parser_omp_target_enter_data): Support
GOMP_MAP_ATTACH kind.
(cp_parser_omp_target_exit_data): Support GOMP_MAP_DETACH kind.
(cp_parser_oacc_declare): Update call to cp_parser_oacc_all_clauses.
(cp_parser_oacc_loop): Update calls to cp_parser_oacc_all_clauses.
(cp_parser_oacc_compute): Likewise.
* pt.cc (tsubst_expr): Use C_ORT_ACC_TARGET for call to
tsubst_omp_clauses for OpenACC compute regions.
* semantics.cc (cp_omp_address_inspector): New class, derived from
c_omp_address_inspector.
(handle_omp_array_sections_1, handle_omp_array_sections,
finish_omp_clauses): Use cp_omp_address_inspector class and OMP address
tokenizer to analyze and expand OpenMP map clause expressions. Fix
some diagnostics. Support C_ORT_ACC_TARGET.
(finish_omp_target): Handle GOMP_MAP_POINTER.
gcc/fortran/
* trans-openmp.cc (gfc_trans_omp_array_section): Add OPENMP parameter.
Use GOMP_MAP_ATTACH_DETACH instead of GOMP_MAP_ALWAYS_POINTER for
derived type components.
(gfc_trans_omp_clauses): Update calls to gfc_trans_omp_array_section.
gcc/
* gimplify.cc (build_struct_comp_nodes): Don't process
GOMP_MAP_ATTACH_DETACH "middle" nodes here.
(omp_mapping_group): Add REPROCESS_STRUCT and FRAGILE booleans for
nested struct handling.
(omp_strip_components_and_deref, omp_strip_indirections): Remove
functions.
(omp_get_attachment): Handle GOMP_MAP_DETACH here.
(omp_group_last): Handle GOMP_MAP_*, GOMP_MAP_DETACH,
GOMP_MAP_ATTACH_DETACH groups for "exit data" of reference-to-pointer
component array sections.
(omp_gather_mapping_groups_1): Initialise reprocess_struct and fragile
fields.
(omp_group_base): Handle GOMP_MAP_ATTACH_DETACH after GOMP_MAP_STRUCT.
(omp_index_mapping_groups_1): Skip reprocess_struct groups.
(omp_get_nonfirstprivate_group, omp_directive_maps_explicitly,
omp_resolve_clause_dependencies, omp_first_chained_access_token): New
functions.
(omp_check_mapping_compatibility): Adjust accepted node combinations
for "from" clauses using release instead of alloc.
(omp_accumulate_sibling_list): Add GROUP_MAP, ADDR_TOKENS, FRAGILE_P,
REPROCESSING_STRUCT, ADDED_TAIL parameters. Use OMP address tokenizer
to analyze addresses. Reimplement nested struct handling, and
implement "fragile groups".
(omp_build_struct_sibling_lists): Adjust for changes to
omp_accumulate_sibling_list. Recalculate bias for ATTACH_DETACH nodes
after GOMP_MAP_STRUCT nodes.
(gimplify_scan_omp_clauses): Call omp_resolve_clause_dependencies. Use
OMP address tokenizer.
(gimplify_adjust_omp_clauses_1): Use build_fold_indirect_ref_loc
instead of build_simple_mem_ref_loc.
* omp-general.cc (omp-general.h, tree-pretty-print.h): Include.
(omp_addr_tokenizer): New namespace.
(omp_addr_tokenizer::omp_addr_token): New.
(omp_addr_tokenizer::omp_parse_component_selector,
omp_addr_tokenizer::omp_parse_ref,
omp_addr_tokenizer::omp_parse_pointer,
omp_addr_tokenizer::omp_parse_access_method,
omp_addr_tokenizer::omp_parse_access_methods,
omp_addr_tokenizer::omp_parse_structure_base,
omp_addr_tokenizer::omp_parse_structured_expr,
omp_addr_tokenizer::omp_parse_array_expr,
omp_addr_tokenizer::omp_access_chain_p,
omp_addr_tokenizer::omp_accessed_addr): New functions.
(omp_parse_expr, debug_omp_tokenized_addr): New functions.
* omp-general.h (omp_addr_tokenizer::access_method_kinds,
omp_addr_tokenizer::structure_base_kinds,
omp_addr_tokenizer::token_type,
omp_addr_tokenizer::omp_addr_token,
omp_addr_tokenizer::omp_access_chain_p,
omp_addr_tokenizer::omp_accessed_addr): New.
(omp_addr_token, omp_parse_expr): New.
* omp-low.cc (scan_sharing_clauses): Skip error check for references
to pointers.
* tree.h (OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED): New macro.
gcc/testsuite/
* c-c++-common/gomp/clauses-2.c: Fix error output.
* c-c++-common/gomp/target-implicit-map-2.c: Adjust scan output.
* c-c++-common/gomp/target-50.c: Adjust scan output.
* c-c++-common/gomp/target-enter-data-1.c: Adjust scan output.
* g++.dg/gomp/static-component-1.C: New test.
* gcc.dg/gomp/target-3.c: Adjust scan output.
* gfortran.dg/gomp/map-9.f90: Adjust scan output.
libgomp/
* target.c (gomp_map_pointer): Modify zero-length array section
pointer handling.
(gomp_attach_pointer): Likewise.
(gomp_map_fields_existing): Use gomp_map_0len_lookup.
(gomp_attach_pointer): Allow attaching null pointers (or Fortran
"unassociated" pointers).
(gomp_map_vars_internal): Handle zero-sized struct members. Add
diagnostic for unmapped struct pointer members.
* testsuite/libgomp.c-c++-common/baseptrs-1.c: New test.
* testsuite/libgomp.c-c++-common/baseptrs-2.c: New test.
* testsuite/libgomp.c-c++-common/baseptrs-6.c: New test.
* testsuite/libgomp.c-c++-common/baseptrs-7.c: New test.
* testsuite/libgomp.c-c++-common/ptr-attach-2.c: New test.
* testsuite/libgomp.c-c++-common/target-implicit-map-2.c: Fix missing
"free".
* testsuite/libgomp.c-c++-common/target-implicit-map-5.c: New test.
* testsuite/libgomp.c-c++-common/target-map-zlas-1.c: New test.
* testsuite/libgomp.c++/class-array-1.C: New test.
* testsuite/libgomp.c++/baseptrs-3.C: New test.
* testsuite/libgomp.c++/baseptrs-4.C: New test.
* testsuite/libgomp.c++/baseptrs-5.C: New test.
* testsuite/libgomp.c++/baseptrs-8.C: New test.
* testsuite/libgomp.c++/baseptrs-9.C: New test.
* testsuite/libgomp.c++/ref-mapping-1.C: New test.
* testsuite/libgomp.c++/target-48.C: New test.
* testsuite/libgomp.c++/target-49.C: New test.
* testsuite/libgomp.c++/target-exit-data-reftoptr-1.C: New test.
* testsuite/libgomp.c++/target-lambda-1.C: Update for OpenMP 5.2
semantics.
* testsuite/libgomp.c++/target-this-3.C: Likewise.
* testsuite/libgomp.c++/target-this-4.C: Likewise.
* testsuite/libgomp.fortran/struct-elem-map-1.f90: Add temporary XFAIL.
* testsuite/libgomp.fortran/target-enter-data-6.f90: Likewise.
Diffstat (limited to 'libgomp/testsuite')
23 files changed, 4284 insertions, 9 deletions
diff --git a/libgomp/testsuite/libgomp.c++/baseptrs-3.C b/libgomp/testsuite/libgomp.c++/baseptrs-3.C new file mode 100644 index 0000000..39a48a4 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/baseptrs-3.C @@ -0,0 +1,275 @@ +#include <cstdlib> +#include <cstring> +#include <cassert> + +struct sa0 +{ + int *ptr; +}; + +struct sb0 +{ + int arr[10]; +}; + +struct sc0 +{ + sa0 a; + sb0 b; + sc0 (sa0 &my_a, sb0 &my_b) : a(my_a), b(my_b) {} +}; + +void +foo0 () +{ + sa0 my_a; + sb0 my_b; + + my_a.ptr = (int *) malloc (sizeof (int) * 10); + sc0 my_c(my_a, my_b); + + memset (my_c.a.ptr, 0, sizeof (int) * 10); + + #pragma omp target map (my_c.a.ptr, my_c.a.ptr[:10]) + { + for (int i = 0; i < 10; i++) + my_c.a.ptr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_c.a.ptr[i] == i); + + memset (my_c.b.arr, 0, sizeof (int) * 10); + + #pragma omp target map (my_c.b.arr[:10]) + { + for (int i = 0; i < 10; i++) + my_c.b.arr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_c.b.arr[i] == i); + + free (my_a.ptr); +} + +struct sa +{ + int *ptr; +}; + +struct sb +{ + int arr[10]; +}; + +struct sc +{ + sa &a; + sb &b; + sc (sa &my_a, sb &my_b) : a(my_a), b(my_b) {} +}; + +void +foo () +{ + sa my_a; + sb my_b; + + my_a.ptr = (int *) malloc (sizeof (int) * 10); + sc my_c(my_a, my_b); + + memset (my_c.a.ptr, 0, sizeof (int) * 10); + + #pragma omp target map (my_c.a.ptr, my_c.a.ptr[:10]) + { + for (int i = 0; i < 10; i++) + my_c.a.ptr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_c.a.ptr[i] == i); + + memset (my_c.b.arr, 0, sizeof (int) * 10); + + #pragma omp target map (my_c.b.arr[:10]) + { + for (int i = 0; i < 10; i++) + my_c.b.arr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_c.b.arr[i] == i); + + free (my_a.ptr); +} + +void +bar () +{ + sa my_a; + sb my_b; + + my_a.ptr = (int *) malloc (sizeof (int) * 10); + sc my_c(my_a, my_b); + sc &my_cref = my_c; + + memset (my_cref.a.ptr, 0, sizeof (int) * 10); + + #pragma omp target map (my_cref.a.ptr, my_cref.a.ptr[:10]) + { + for (int i = 0; i < 10; i++) + my_cref.a.ptr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_cref.a.ptr[i] == i); + + memset (my_cref.b.arr, 0, sizeof (int) * 10); + + #pragma omp target map (my_cref.b.arr[:10]) + { + for (int i = 0; i < 10; i++) + my_cref.b.arr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_cref.b.arr[i] == i); + + free (my_a.ptr); +} + +struct scp0 +{ + sa *a; + sb *b; + scp0 (sa *my_a, sb *my_b) : a(my_a), b(my_b) {} +}; + +void +foop0 () +{ + sa *my_a = new sa; + sb *my_b = new sb; + + my_a->ptr = new int[10]; + scp0 *my_c = new scp0(my_a, my_b); + + memset (my_c->a->ptr, 0, sizeof (int) * 10); + + #pragma omp target map (my_c->a, my_c->a[:1], my_c->a->ptr, my_c->a->ptr[:10]) + { + for (int i = 0; i < 10; i++) + my_c->a->ptr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_c->a->ptr[i] == i); + + memset (my_c->b->arr, 0, sizeof (int) * 10); + + #pragma omp target map (my_c->b, my_c->b[:1], my_c->b->arr[:10]) + { + for (int i = 0; i < 10; i++) + my_c->b->arr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_c->b->arr[i] == i); + + delete[] my_a->ptr; + delete my_a; + delete my_b; +} + +struct scp +{ + sa *&a; + sb *&b; + scp (sa *&my_a, sb *&my_b) : a(my_a), b(my_b) {} +}; + +void +foop () +{ + sa *my_a = new sa; + sb *my_b = new sb; + + my_a->ptr = new int[10]; + scp *my_c = new scp(my_a, my_b); + + memset (my_c->a->ptr, 0, sizeof (int) * 10); + + #pragma omp target map (my_c->a, my_c->a[:1], my_c->a->ptr, my_c->a->ptr[:10]) + { + for (int i = 0; i < 10; i++) + my_c->a->ptr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_c->a->ptr[i] == i); + + memset (my_c->b->arr, 0, sizeof (int) * 10); + + #pragma omp target map (my_c->b, my_c->b[:1], my_c->b->arr[:10]) + { + for (int i = 0; i < 10; i++) + my_c->b->arr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_c->b->arr[i] == i); + + delete[] my_a->ptr; + delete my_a; + delete my_b; +} + +void +barp () +{ + sa *my_a = new sa; + sb *my_b = new sb; + + my_a->ptr = new int[10]; + scp *my_c = new scp(my_a, my_b); + scp *&my_cref = my_c; + + memset (my_cref->a->ptr, 0, sizeof (int) * 10); + + #pragma omp target map (my_cref->a, my_cref->a[:1], my_cref->a->ptr, \ + my_cref->a->ptr[:10]) + { + for (int i = 0; i < 10; i++) + my_cref->a->ptr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_cref->a->ptr[i] == i); + + memset (my_cref->b->arr, 0, sizeof (int) * 10); + + #pragma omp target map (my_cref->b, my_cref->b[:1], my_cref->b->arr[:10]) + { + for (int i = 0; i < 10; i++) + my_cref->b->arr[i] = i; + } + + for (int i = 0; i < 10; i++) + assert (my_cref->b->arr[i] == i); + + delete my_a->ptr; + delete my_a; + delete my_b; +} + +int main (int argc, char *argv[]) +{ + foo0 (); + foo (); + bar (); + foop0 (); + foop (); + barp (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/baseptrs-4.C b/libgomp/testsuite/libgomp.c++/baseptrs-4.C new file mode 100644 index 0000000..196029a --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/baseptrs-4.C @@ -0,0 +1,3154 @@ +// { dg-do run } + +#include <cstring> +#include <cassert> + +#define MAP_DECLS + +#define NONREF_DECL_BASE +#define REF_DECL_BASE +#define PTR_DECL_BASE +#define REF2PTR_DECL_BASE + +#define ARRAY_DECL_BASE +// Needs map clause "lvalue"-parsing support. +//#define REF2ARRAY_DECL_BASE +#define PTR_OFFSET_DECL_BASE +// Needs map clause "lvalue"-parsing support. +//#define REF2PTR_OFFSET_DECL_BASE + +#define MAP_SECTIONS + +#define NONREF_DECL_MEMBER_SLICE +#define NONREF_DECL_MEMBER_SLICE_BASEPTR +#define REF_DECL_MEMBER_SLICE +#define REF_DECL_MEMBER_SLICE_BASEPTR +#define PTR_DECL_MEMBER_SLICE +#define PTR_DECL_MEMBER_SLICE_BASEPTR +#define REF2PTR_DECL_MEMBER_SLICE +#define REF2PTR_DECL_MEMBER_SLICE_BASEPTR + +#define ARRAY_DECL_MEMBER_SLICE +#define ARRAY_DECL_MEMBER_SLICE_BASEPTR +// Needs map clause "lvalue"-parsing support. +//#define REF2ARRAY_DECL_MEMBER_SLICE +//#define REF2ARRAY_DECL_MEMBER_SLICE_BASEPTR +#define PTR_OFFSET_DECL_MEMBER_SLICE +#define PTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR +// Needs map clause "lvalue"-parsing support. +//#define REF2PTR_OFFSET_DECL_MEMBER_SLICE +//#define REF2PTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR + +#define PTRARRAY_DECL_MEMBER_SLICE +#define PTRARRAY_DECL_MEMBER_SLICE_BASEPTR +// Needs map clause "lvalue"-parsing support. +//#define REF2PTRARRAY_DECL_MEMBER_SLICE +//#define REF2PTRARRAY_DECL_MEMBER_SLICE_BASEPTR +#define PTRPTR_OFFSET_DECL_MEMBER_SLICE +#define PTRPTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR +// Needs map clause "lvalue"-parsing support. +//#define REF2PTRPTR_OFFSET_DECL_MEMBER_SLICE +//#define REF2PTRPTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR + +#define NONREF_COMPONENT_BASE +#define NONREF_COMPONENT_MEMBER_SLICE +#define NONREF_COMPONENT_MEMBER_SLICE_BASEPTR + +#define REF_COMPONENT_BASE +#define REF_COMPONENT_MEMBER_SLICE +#define REF_COMPONENT_MEMBER_SLICE_BASEPTR + +#define PTR_COMPONENT_BASE +#define PTR_COMPONENT_MEMBER_SLICE +#define PTR_COMPONENT_MEMBER_SLICE_BASEPTR + +#define REF2PTR_COMPONENT_BASE +#define REF2PTR_COMPONENT_MEMBER_SLICE +#define REF2PTR_COMPONENT_MEMBER_SLICE_BASEPTR + +#ifdef MAP_DECLS +void +map_decls (void) +{ + int x = 0; + int &y = x; + int arr[4]; + int (&arrref)[4] = arr; + int *z = &arr[0]; + int *&t = z; + + memset (arr, 0, sizeof arr); + + #pragma omp target map(x) + { + x++; + } + + #pragma omp target map(y) + { + y++; + } + + assert (x == 2); + assert (y == 2); + + /* "A variable that is of type pointer is treated as if it is the base + pointer of a zero-length array section that appeared as a list item in a + map clause." */ + #pragma omp target map(z) + { + z++; + } + + /* "A variable that is of type reference to pointer is treated as if it had + appeared in a map clause as a zero-length array section." + + The pointer here is *not* associated with a target address, so we're not + disallowed from modifying it. */ + #pragma omp target map(t) + { + t++; + } + + assert (z == &arr[2]); + assert (t == &arr[2]); + + #pragma omp target map(arr) + { + arr[2]++; + } + + #pragma omp target map(arrref) + { + arrref[2]++; + } + + assert (arr[2] == 2); + assert (arrref[2] == 2); +} +#endif + +struct S { + int a; + int &b; + int *c; + int *&d; + int e[4]; + int (&f)[4]; + + S(int a1, int &b1, int *c1, int *&d1) : + a(a1), b(b1), c(c1), d(d1), f(e) + { + memset (e, 0, sizeof e); + } +}; + +#ifdef NONREF_DECL_BASE +void +nonref_decl_base (void) +{ + int a = 0, b = 0, c, *d = &c; + S mys(a, b, &c, d); + + #pragma omp target map(mys.a) + { + mys.a++; + } + + #pragma omp target map(mys.b) + { + mys.b++; + } + + assert (mys.a == 1); + assert (mys.b == 1); + + #pragma omp target map(mys.c) + { + mys.c++; + } + + #pragma omp target map(mys.d) + { + mys.d++; + } + + assert (mys.c == &c + 1); + assert (mys.d == &c + 1); + + #pragma omp target map(mys.e) + { + mys.e[0]++; + } + + #pragma omp target map(mys.f) + { + mys.f[0]++; + } + + assert (mys.e[0] == 2); + assert (mys.f[0] == 2); +} +#endif + +#ifdef REF_DECL_BASE +void +ref_decl_base (void) +{ + int a = 0, b = 0, c, *d = &c; + S mys_orig(a, b, &c, d); + S &mys = mys_orig; + + #pragma omp target map(mys.a) + { + mys.a++; + } + + #pragma omp target map(mys.b) + { + mys.b++; + } + + assert (mys.a == 1); + assert (mys.b == 1); + + #pragma omp target map(mys.c) + { + mys.c++; + } + + #pragma omp target map(mys.d) + { + mys.d++; + } + + assert (mys.c == &c + 1); + assert (mys.d == &c + 1); + + #pragma omp target map(mys.e) + { + mys.e[0]++; + } + + #pragma omp target map(mys.f) + { + mys.f[0]++; + } + + assert (mys.e[0] == 2); + assert (mys.f[0] == 2); +} +#endif + +#ifdef PTR_DECL_BASE +void +ptr_decl_base (void) +{ + int a = 0, b = 0, c, *d = &c; + S mys_orig(a, b, &c, d); + S *mys = &mys_orig; + + #pragma omp target map(mys->a) + { + mys->a++; + } + + #pragma omp target map(mys->b) + { + mys->b++; + } + + assert (mys->a == 1); + assert (mys->b == 1); + + #pragma omp target map(mys->c) + { + mys->c++; + } + + #pragma omp target map(mys->d) + { + mys->d++; + } + + assert (mys->c == &c + 1); + assert (mys->d == &c + 1); + + #pragma omp target map(mys->e) + { + mys->e[0]++; + } + + #pragma omp target map(mys->f) + { + mys->f[0]++; + } + + assert (mys->e[0] == 2); + assert (mys->f[0] == 2); +} +#endif + +#ifdef REF2PTR_DECL_BASE +void +ref2ptr_decl_base (void) +{ + int a = 0, b = 0, c, *d = &c; + S mys_orig(a, b, &c, d); + S *mysp = &mys_orig; + S *&mys = mysp; + + #pragma omp target map(mys->a) + { + mys->a++; + } + + #pragma omp target map(mys->b) + { + mys->b++; + } + + assert (mys->a == 1); + assert (mys->b == 1); + + #pragma omp target map(mys->c) + { + mys->c++; + } + + #pragma omp target map(mys->d) + { + mys->d++; + } + + assert (mys->c == &c + 1); + assert (mys->d == &c + 1); + + #pragma omp target map(mys->e) + { + mys->e[0]++; + } + + #pragma omp target map(mys->f) + { + mys->f[0]++; + } + + assert (mys->e[0] == 2); + assert (mys->f[0] == 2); +} +#endif + +#ifdef ARRAY_DECL_BASE +void +array_decl_base (void) +{ + int a = 0, b = 0, c, *d = &c; + S mys[4] = + { + S(a, b, &c, d), + S(a, b, &c, d), + S(a, b, &c, d), + S(a, b, &c, d) + }; + + #pragma omp target map(mys[2].a) + { + mys[2].a++; + } + + #pragma omp target map(mys[2].b) + { + mys[2].b++; + } + + assert (mys[2].a == 1); + assert (mys[2].b == 1); + + #pragma omp target map(mys[2].c) + { + mys[2].c++; + } + + #pragma omp target map(mys[2].d) + { + mys[2].d++; + } + + assert (mys[2].c == &c + 1); + assert (mys[2].d == &c + 1); + + #pragma omp target map(mys[2].e) + { + mys[2].e[0]++; + } + + #pragma omp target map(mys[2].f) + { + mys[2].f[0]++; + } + + assert (mys[2].e[0] == 2); + assert (mys[2].f[0] == 2); +} +#endif + +#ifdef REF2ARRAY_DECL_BASE +void +ref2array_decl_base (void) +{ + int a = 0, b = 0, c, *d = &c; + S mys_orig[4] = + { + S(a, b, &c, d), + S(a, b, &c, d), + S(a, b, &c, d), + S(a, b, &c, d) + }; + S (&mys)[4] = mys_orig; + + #pragma omp target map(mys[2].a) + { + mys[2].a++; + } + + #pragma omp target map(mys[2].b) + { + mys[2].b++; + } + + assert (mys[2].a == 1); + assert (mys[2].b == 1); + + #pragma omp target map(mys[2].c) + { + mys[2].c++; + } + + #pragma omp target map(mys[2].d) + { + mys[2].d++; + } + + assert (mys[2].c == &c + 1); + assert (mys[2].d == &c + 1); + + #pragma omp target map(mys[2].e) + { + mys[2].e[0]++; + } + + #pragma omp target map(mys[2].f) + { + mys[2].f[0]++; + } + + assert (mys[2].e[0] == 2); + assert (mys[2].f[0] == 2); +} +#endif + +#ifdef PTR_OFFSET_DECL_BASE +void +ptr_offset_decl_base (void) +{ + int a = 0, b = 0, c, *d = &c; + S mys_orig[4] = + { + S(a, b, &c, d), + S(a, b, &c, d), + S(a, b, &c, d), + S(a, b, &c, d) + }; + S *mys = &mys_orig[0]; + + #pragma omp target map(mys[2].a) + { + mys[2].a++; + } + + #pragma omp target map(mys[2].b) + { + mys[2].b++; + } + + assert (mys[2].a == 1); + assert (mys[2].b == 1); + + #pragma omp target map(mys[2].c) + { + mys[2].c++; + } + + #pragma omp target map(mys[2].d) + { + mys[2].d++; + } + + assert (mys[2].c == &c + 1); + assert (mys[2].d == &c + 1); + + #pragma omp target map(mys[2].e) + { + mys[2].e[0]++; + } + + #pragma omp target map(mys[2].f) + { + mys[2].f[0]++; + } + + assert (mys[2].e[0] == 2); + assert (mys[2].f[0] == 2); +} +#endif + +#ifdef REF2PTR_OFFSET_DECL_BASE +void +ref2ptr_offset_decl_base (void) +{ + int a = 0, b = 0, c, *d = &c; + S mys_orig[4] = + { + S(a, b, &c, d), + S(a, b, &c, d), + S(a, b, &c, d), + S(a, b, &c, d) + }; + S *mys_ptr = &mys_orig[0]; + S *&mys = mys_ptr; + + #pragma omp target map(mys[2].a) + { + mys[2].a++; + } + + #pragma omp target map(mys[2].b) + { + mys[2].b++; + } + + assert (mys[2].a == 1); + assert (mys[2].b == 1); + + #pragma omp target map(mys[2].c) + { + mys[2].c++; + } + + #pragma omp target map(mys[2].d) + { + mys[2].d++; + } + + assert (mys[2].c == &c + 1); + assert (mys[2].d == &c + 1); + + #pragma omp target map(mys[2].e) + { + mys[2].e[0]++; + } + + #pragma omp target map(mys[2].f) + { + mys[2].f[0]++; + } + + assert (mys[2].e[0] == 2); + assert (mys[2].f[0] == 2); +} +#endif + +#ifdef MAP_SECTIONS +void +map_sections (void) +{ + int arr[10]; + int *ptr; + int (&arrref)[10] = arr; + int *&ptrref = ptr; + + ptr = new int[10]; + memset (ptr, 0, sizeof (int) * 10); + memset (arr, 0, sizeof (int) * 10); + + #pragma omp target map(arr[0:10]) + { + arr[2]++; + } + + #pragma omp target map(ptr[0:10]) + { + ptr[2]++; + } + + #pragma omp target map(arrref[0:10]) + { + arrref[2]++; + } + + #pragma omp target map(ptrref[0:10]) + { + ptrref[2]++; + } + + assert (arr[2] == 2); + assert (ptr[2] == 2); + + delete ptr; +} +#endif + +struct T { + int a[10]; + int (&b)[10]; + int *c; + int *&d; + + T(int (&b1)[10], int *c1, int *&d1) : b(b1), c(c1), d(d1) + { + memset (a, 0, sizeof a); + } +}; + +#ifdef NONREF_DECL_MEMBER_SLICE +void +nonref_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt(c, &c[0], d); + + memset (c, 0, sizeof c); + + #pragma omp target map(myt.a[0:10]) + { + myt.a[2]++; + } + + #pragma omp target map(myt.b[0:10]) + { + myt.b[2]++; + } + + #pragma omp target enter data map(to: myt.c) + + #pragma omp target map(myt.c[0:10]) + { + myt.c[2]++; + } + + #pragma omp target exit data map(release: myt.c) + + #pragma omp target enter data map(to: myt.d) + + #pragma omp target map(myt.d[0:10]) + { + myt.d[2]++; + } + + #pragma omp target exit data map(from: myt.d) + + assert (myt.a[2] == 1); + assert (myt.b[2] == 3); + assert (myt.c[2] == 3); + assert (myt.d[2] == 3); +} +#endif + +#ifdef NONREF_DECL_MEMBER_SLICE_BASEPTR +void +nonref_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt(c, &c[0], d); + + memset (c, 0, sizeof c); + + #pragma omp target map(to:myt.c) map(myt.c[0:10]) + { + myt.c[2]++; + } + + #pragma omp target map(to:myt.d) map(myt.d[0:10]) + { + myt.d[2]++; + } + + assert (myt.c[2] == 2); + assert (myt.d[2] == 2); +} +#endif + +#ifdef REF_DECL_MEMBER_SLICE +void +ref_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T &myt = myt_real; + + memset (c, 0, sizeof c); + + #pragma omp target map(myt.a[0:10]) + { + myt.a[2]++; + } + + #pragma omp target map(myt.b[0:10]) + { + myt.b[2]++; + } + + #pragma omp target enter data map(to: myt.c) + + #pragma omp target map(myt.c[0:10]) + { + myt.c[2]++; + } + + #pragma omp target exit data map(release: myt.c) + + #pragma omp target enter data map(to: myt.d) + + #pragma omp target map(myt.d[0:10]) + { + myt.d[2]++; + } + + #pragma omp target exit data map(release: myt.d) + + assert (myt.a[2] == 1); + assert (myt.b[2] == 3); + assert (myt.c[2] == 3); + assert (myt.d[2] == 3); +} +#endif + +#ifdef REF_DECL_MEMBER_SLICE_BASEPTR +void +ref_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T &myt = myt_real; + + memset (c, 0, sizeof c); + + #pragma omp target map(to:myt.c) map(myt.c[0:10]) + { + myt.c[2]++; + } + + #pragma omp target map(to:myt.d) map(myt.d[0:10]) + { + myt.d[2]++; + } + + assert (myt.c[2] == 2); + assert (myt.d[2] == 2); +} +#endif + +#ifdef PTR_DECL_MEMBER_SLICE +void +ptr_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt = &myt_real; + + memset (c, 0, sizeof c); + + #pragma omp target enter data map(to: myt) + + #pragma omp target map(myt->a[0:10]) + { + myt->a[2]++; + } + + #pragma omp target map(myt->b[0:10]) + { + myt->b[2]++; + } + + #pragma omp target enter data map(to: myt->c) + + #pragma omp target map(myt->c[0:10]) + { + myt->c[2]++; + } + + #pragma omp target exit data map(release: myt->c) + + #pragma omp target enter data map(to: myt->d) + + #pragma omp target map(myt->d[0:10]) + { + myt->d[2]++; + } + + #pragma omp target exit data map(release: myt, myt->d) + + assert (myt->a[2] == 1); + assert (myt->b[2] == 3); + assert (myt->c[2] == 3); + assert (myt->d[2] == 3); +} +#endif + +#ifdef PTR_DECL_MEMBER_SLICE_BASEPTR +void +ptr_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt = &myt_real; + + memset (c, 0, sizeof c); + + // These ones have an implicit firstprivate for 'myt'. + #pragma omp target map(to:myt->c) map(myt->c[0:10]) + { + myt->c[2]++; + } + + #pragma omp target map(to:myt->d) map(myt->d[0:10]) + { + myt->d[2]++; + } + + // These ones have an explicit "TO" mapping for 'myt'. + #pragma omp target map(to:myt) map(to:myt->c) map(myt->c[0:10]) + { + myt->c[2]++; + } + + #pragma omp target map(to:myt) map(to:myt->d) map(myt->d[0:10]) + { + myt->d[2]++; + } + + assert (myt->c[2] == 4); + assert (myt->d[2] == 4); +} +#endif + +#ifdef REF2PTR_DECL_MEMBER_SLICE +void +ref2ptr_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt_ptr = &myt_real; + T *&myt = myt_ptr; + + memset (c, 0, sizeof c); + + #pragma omp target enter data map(to: myt) + + #pragma omp target map(myt->a[0:10]) + { + myt->a[2]++; + } + + #pragma omp target map(myt->b[0:10]) + { + myt->b[2]++; + } + + #pragma omp target enter data map(to: myt->c) + + #pragma omp target map(myt->c[0:10]) + { + myt->c[2]++; + } + + #pragma omp target exit data map(release: myt->c) + + #pragma omp target enter data map(to: myt->d) + + #pragma omp target map(myt->d[0:10]) + { + myt->d[2]++; + } + + #pragma omp target exit data map(from: myt, myt->d) + + assert (myt->a[2] == 1); + assert (myt->b[2] == 3); + assert (myt->c[2] == 3); + assert (myt->d[2] == 3); +} +#endif + +#ifdef REF2PTR_DECL_MEMBER_SLICE_BASEPTR +void +ref2ptr_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt_ptr = &myt_real; + T *&myt = myt_ptr; + + memset (c, 0, sizeof c); + + // These ones have an implicit firstprivate for 'myt'. + #pragma omp target map(to:myt->c) map(myt->c[0:10]) + { + myt->c[2]++; + } + + #pragma omp target map(to:myt->d) map(myt->d[0:10]) + { + myt->d[2]++; + } + + // These ones have an explicit "TO" mapping for 'myt'. + #pragma omp target map(to:myt) map(to:myt->c) map(myt->c[0:10]) + { + myt->c[2]++; + } + + #pragma omp target map(to:myt) map(to:myt->d) map(myt->d[0:10]) + { + myt->d[2]++; + } + + assert (myt->c[2] == 4); + assert (myt->d[2] == 4); +} +#endif + +#ifdef ARRAY_DECL_MEMBER_SLICE +void +array_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt[4] = + { + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d) + }; + + memset (c, 0, sizeof c); + + #pragma omp target map(myt[2].a[0:10]) + { + myt[2].a[2]++; + } + + #pragma omp target map(myt[2].b[0:10]) + { + myt[2].b[2]++; + } + + #pragma omp target enter data map(to: myt[2].c) + + #pragma omp target map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target exit data map(release: myt[2].c) + + #pragma omp target enter data map(to: myt[2].d) + + #pragma omp target map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + #pragma omp target exit data map(release: myt[2].d) + + assert (myt[2].a[2] == 1); + assert (myt[2].b[2] == 3); + assert (myt[2].c[2] == 3); + assert (myt[2].d[2] == 3); +} +#endif + +#ifdef ARRAY_DECL_MEMBER_SLICE_BASEPTR +void +array_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt[4] = + { + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d) + }; + + memset (c, 0, sizeof c); + + #pragma omp target map(to:myt[2].c) map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target map(to:myt[2].d) map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + assert (myt[2].c[2] == 2); + assert (myt[2].d[2] == 2); +} +#endif + +#ifdef REF2ARRAY_DECL_MEMBER_SLICE +void +ref2array_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real[4] = + { + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d) + }; + T (&myt)[4] = myt_real; + + memset (c, 0, sizeof c); + + #pragma omp target map(myt[2].a[0:10]) + { + myt[2].a[2]++; + } + + #pragma omp target map(myt[2].b[0:10]) + { + myt[2].b[2]++; + } + + #pragma omp target enter data map(to: myt[2].c) + + #pragma omp target map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target exit data map(release: myt[2].c) + + #pragma omp target enter data map(to: myt[2].d) + + #pragma omp target map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + #pragma omp target exit data map(release: myt[2].d) + + assert (myt[2].a[2] == 1); + assert (myt[2].b[2] == 3); + assert (myt[2].c[2] == 3); + assert (myt[2].d[2] == 3); +} +#endif + +#ifdef REF2ARRAY_DECL_MEMBER_SLICE_BASEPTR +void +ref2array_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real[4] = + { + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d) + }; + T (&myt)[4] = myt_real; + + memset (c, 0, sizeof c); + + #pragma omp target map(to:myt[2].c) map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target map(to:myt[2].d) map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + assert (myt[2].c[2] == 2); + assert (myt[2].d[2] == 2); +} +#endif + +#ifdef PTR_OFFSET_DECL_MEMBER_SLICE +void +ptr_offset_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real[4] = + { + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d) + }; + T *myt = &myt_real[0]; + + memset (c, 0, sizeof c); + + #pragma omp target map(myt[2].a[0:10]) + { + myt[2].a[2]++; + } + + #pragma omp target map(myt[2].b[0:10]) + { + myt[2].b[2]++; + } + + #pragma omp target enter data map(to: myt[2].c) + + #pragma omp target map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target exit data map(release: myt[2].c) + + #pragma omp target enter data map(to: myt[2].d) + + #pragma omp target map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + #pragma omp target exit data map(release: myt[2].d) + + assert (myt[2].a[2] == 1); + assert (myt[2].b[2] == 3); + assert (myt[2].c[2] == 3); + assert (myt[2].d[2] == 3); +} +#endif + +#ifdef PTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR +void +ptr_offset_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real[4] = + { + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d) + }; + T *myt = &myt_real[0]; + + memset (c, 0, sizeof c); + + /* Implicit 'myt'. */ + #pragma omp target map(to:myt[2].c) map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target map(to:myt[2].d) map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + /* Explicit 'to'-mapped 'myt'. */ + #pragma omp target map(to:myt) map(to:myt[2].c) map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target map(to:myt) map(to:myt[2].d) map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + assert (myt[2].c[2] == 4); + assert (myt[2].d[2] == 4); +} +#endif + +#ifdef REF2PTR_OFFSET_DECL_MEMBER_SLICE +void +ref2ptr_offset_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real[4] = + { + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d) + }; + T *myt_ptr = &myt_real[0]; + T *&myt = myt_ptr; + + memset (c, 0, sizeof c); + + #pragma omp target map(myt[2].a[0:10]) + { + myt[2].a[2]++; + } + + #pragma omp target map(myt[2].b[0:10]) + { + myt[2].b[2]++; + } + + #pragma omp target enter data map(to: myt[2].c) + + #pragma omp target map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target exit data map(release: myt[2].c) + + #pragma omp target enter data map(to: myt[2].d) + + #pragma omp target map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + #pragma omp target exit data map(release: myt[2].d) + + assert (myt[2].a[2] == 1); + assert (myt[2].b[2] == 3); + assert (myt[2].c[2] == 3); + assert (myt[2].d[2] == 3); +} +#endif + +#ifdef REF2PTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR +void +ref2ptr_offset_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real[4] = + { + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d), + T (c, &c[0], d) + }; + T *myt_ptr = &myt_real[0]; + T *&myt = myt_ptr; + + memset (c, 0, sizeof c); + + /* Implicit 'myt'. */ + #pragma omp target map(to:myt[2].c) map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target map(to:myt[2].d) map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + /* Explicit 'to'-mapped 'myt'. */ + #pragma omp target map(to:myt) map(to:myt[2].c) map(myt[2].c[0:10]) + { + myt[2].c[2]++; + } + + #pragma omp target map(to:myt) map(to:myt[2].d) map(myt[2].d[0:10]) + { + myt[2].d[2]++; + } + + assert (myt[2].c[2] == 4); + assert (myt[2].d[2] == 4); +} +#endif + +#ifdef PTRARRAY_DECL_MEMBER_SLICE +void +ptrarray_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt[4] = + { + &myt_real, + &myt_real, + &myt_real, + &myt_real + }; + + memset (c, 0, sizeof c); + + #pragma omp target enter data map(to: myt[2]) + + #pragma omp target map(myt[2]->a[0:10]) + { + myt[2]->a[2]++; + } + + #pragma omp target map(myt[2]->b[0:10]) + { + myt[2]->b[2]++; + } + + #pragma omp target enter data map(to: myt[2]->c) + + #pragma omp target map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target exit data map(from: myt[2]->c) + + #pragma omp target enter data map(to: myt[2]->d) + + #pragma omp target map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + #pragma omp target exit data map(from: myt[2]->d) + + #pragma omp target exit data map(release: myt[2]) + + assert (myt[2]->a[2] == 1); + assert (myt[2]->b[2] == 3); + assert (myt[2]->c[2] == 3); + assert (myt[2]->d[2] == 3); +} +#endif + +#ifdef PTRARRAY_DECL_MEMBER_SLICE_BASEPTR +void +ptrarray_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt[4] = + { + &myt_real, + &myt_real, + &myt_real, + &myt_real + }; + + memset (c, 0, sizeof c); + + // Implicit 'myt' + #pragma omp target map(to: myt[2]->c) map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target map(to: myt[2]->d) map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + // One element of 'myt' + #pragma omp target map(to:myt[2], myt[2]->c) map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target map(to:myt[2], myt[2]->d) map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + // Explicit map of all of 'myt' + #pragma omp target map(to:myt, myt[2]->c) map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target map(to:myt, myt[2]->d) map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + // Explicit map slice of 'myt' + #pragma omp target map(to:myt[1:3], myt[2]->c) map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target map(to:myt[1:3], myt[2]->d) map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + assert (myt[2]->c[2] == 8); + assert (myt[2]->d[2] == 8); +} +#endif + +#ifdef REF2PTRARRAY_DECL_MEMBER_SLICE +void +ref2ptrarray_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt_ptrarr[4] = + { + &myt_real, + &myt_real, + &myt_real, + &myt_real + }; + T *(&myt)[4] = myt_ptrarr; + + memset (c, 0, sizeof c); + + #pragma omp target enter data map(to: myt[2]) + + #pragma omp target map(myt[2]->a[0:10]) + { + myt[2]->a[2]++; + } + + #pragma omp target map(myt[2]->b[0:10]) + { + myt[2]->b[2]++; + } + + #pragma omp target enter data map(to: myt[2]->c) + + #pragma omp target map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target exit data map(release: myt[2]->c) + + #pragma omp target enter data map(to: myt[2]->d) + + #pragma omp target map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + #pragma omp target exit data map(release: myt[2]->d) + + #pragma omp target exit data map(release: myt[2]) + + assert (myt[2]->a[2] == 1); + assert (myt[2]->b[2] == 3); + assert (myt[2]->c[2] == 3); + assert (myt[2]->d[2] == 3); +} +#endif + +#ifdef REF2PTRARRAY_DECL_MEMBER_SLICE_BASEPTR +void +ref2ptrarray_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt_ptrarr[4] = + { + &myt_real, + &myt_real, + &myt_real, + &myt_real + }; + T *(&myt)[4] = myt_ptrarr; + + memset (c, 0, sizeof c); + + #pragma omp target map(to:myt[2], myt[2]->c) map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target map(to:myt[2], myt[2]->d) map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + #pragma omp target map(to:myt, myt[2]->c) map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target map(to:myt, myt[2]->d) map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + assert (myt[2]->c[2] == 4); + assert (myt[2]->d[2] == 4); +} +#endif + +#ifdef PTRPTR_OFFSET_DECL_MEMBER_SLICE +void +ptrptr_offset_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt_ptrarr[4] = + { + &myt_real, + &myt_real, + &myt_real, + &myt_real + }; + T **myt = &myt_ptrarr[0]; + + memset (c, 0, sizeof c); + + #pragma omp target enter data map(to: myt[0:3]) + + /* NOTE: For the implicit firstprivate 'myt' to work, the zeroth element of + myt[] must be mapped above -- otherwise the zero-length array section + lookup fails. */ + #pragma omp target map(myt[2]->a[0:10]) + { + myt[2]->a[2]++; + } + + #pragma omp target map(myt[2]->b[0:10]) + { + myt[2]->b[2]++; + } + + #pragma omp target enter data map(to: myt[2]->c) + + #pragma omp target map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target exit data map(from: myt[2]->c) + + #pragma omp target enter data map(to: myt[2]->d) + + #pragma omp target map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + #pragma omp target exit data map(from: myt[0:3], myt[2]->d) + + assert (myt[2]->a[2] == 1); + assert (myt[2]->b[2] == 3); + assert (myt[2]->c[2] == 3); + assert (myt[2]->d[2] == 3); +} +#endif + +#ifdef PTRPTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR +void +ptrptr_offset_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt_ptrarr[4] = + { + 0, + 0, + 0, + &myt_real + }; + T **myt = &myt_ptrarr[0]; + + memset (c, 0, sizeof c); + + #pragma omp target map(to:myt[3], myt[3]->c) map(myt[3]->c[0:10]) + { + myt[3]->c[2]++; + } + + #pragma omp target map(to:myt[3], myt[3]->d) map(myt[3]->d[0:10]) + { + myt[3]->d[2]++; + } + + #pragma omp target map(to:myt, myt[3], myt[3]->c) map(myt[3]->c[0:10]) + { + myt[3]->c[2]++; + } + + #pragma omp target map(to:myt, myt[3], myt[3]->d) map(myt[3]->d[0:10]) + { + myt[3]->d[2]++; + } + + assert (myt[3]->c[2] == 4); + assert (myt[3]->d[2] == 4); +} +#endif + +#ifdef REF2PTRPTR_OFFSET_DECL_MEMBER_SLICE +void +ref2ptrptr_offset_decl_member_slice (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt_ptrarr[4] = + { + 0, + 0, + &myt_real, + 0 + }; + T **myt_ptrptr = &myt_ptrarr[0]; + T **&myt = myt_ptrptr; + + memset (c, 0, sizeof c); + + #pragma omp target enter data map(to: myt[0:3]) + + #pragma omp target map(myt[2]->a[0:10]) + { + myt[2]->a[2]++; + } + + #pragma omp target map(myt[2]->b[0:10]) + { + myt[2]->b[2]++; + } + + #pragma omp target enter data map(to:myt[2]->c) + + #pragma omp target map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target exit data map(release:myt[2]->c) + + #pragma omp target enter data map(to:myt[2]->d) + + #pragma omp target map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + #pragma omp target exit data map(release: myt[0:3], myt[2]->d) + + assert (myt[2]->a[2] == 1); + assert (myt[2]->b[2] == 3); + assert (myt[2]->c[2] == 3); + assert (myt[2]->d[2] == 3); +} +#endif + +#ifdef REF2PTRPTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR +void +ref2ptrptr_offset_decl_member_slice_baseptr (void) +{ + int c[10]; + int *d = &c[0]; + T myt_real(c, &c[0], d); + T *myt_ptrarr[4] = + { + 0, + 0, + &myt_real, + 0 + }; + T **myt_ptrptr = &myt_ptrarr[0]; + T **&myt = myt_ptrptr; + + memset (c, 0, sizeof c); + + #pragma omp target map(to:myt[2], myt[2]->c) map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target map(to:myt[2], myt[2]->d) map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + #pragma omp target map(to:myt, myt[2], myt[2]->c) map(myt[2]->c[0:10]) + { + myt[2]->c[2]++; + } + + #pragma omp target map(to:myt, myt[2], myt[2]->d) map(myt[2]->d[0:10]) + { + myt[2]->d[2]++; + } + + assert (myt[2]->c[2] == 4); + assert (myt[2]->d[2] == 4); +} +#endif + +struct U +{ + S s1; + T t1; + S &s2; + T &t2; + S *s3; + T *t3; + S *&s4; + T *&t4; + + U(S &sptr1, T &tptr1, S &sptr2, T &tptr2, S *sptr3, T *tptr3, + S *&sptr4, T *&tptr4) + : s1(sptr1), t1(tptr1), s2(sptr2), t2(tptr2), s3(sptr3), t3(tptr3), + s4(sptr4), t4(tptr4) + { + } +}; + +#define INIT_S(N) \ + int a##N = 0, b##N = 0, c##N = 0, d##N = 0; \ + int *d##N##ptr = &d##N; \ + S s##N(a##N, b##N, &c##N, d##N##ptr) + +#define INIT_T(N) \ + int arr##N[10]; \ + int *ptr##N = &arr##N[0]; \ + T t##N(arr##N, &arr##N[0], ptr##N); \ + memset (arr##N, 0, sizeof arr##N) + +#define INIT_ST \ + INIT_S(1); \ + INIT_T(1); \ + INIT_S(2); \ + INIT_T(2); \ + INIT_S(3); \ + INIT_T(3); \ + int a4 = 0, b4 = 0, c4 = 0, d4 = 0; \ + int *d4ptr = &d4; \ + S *s4 = new S(a4, b4, &c4, d4ptr); \ + int arr4[10]; \ + int *ptr4 = &arr4[0]; \ + T *t4 = new T(arr4, &arr4[0], ptr4); \ + memset (arr4, 0, sizeof arr4) + +#ifdef NONREF_COMPONENT_BASE +void +nonref_component_base (void) +{ + INIT_ST; + U myu(s1, t1, s2, t2, &s3, &t3, s4, t4); + + #pragma omp target map(myu.s1.a, myu.s1.b, myu.s1.c, myu.s1.d) + { + myu.s1.a++; + myu.s1.b++; + myu.s1.c++; + myu.s1.d++; + } + + assert (myu.s1.a == 1); + assert (myu.s1.b == 1); + assert (myu.s1.c == &c1 + 1); + assert (myu.s1.d == &d1 + 1); + + #pragma omp target map(myu.s2.a, myu.s2.b, myu.s2.c, myu.s2.d) + { + myu.s2.a++; + myu.s2.b++; + myu.s2.c++; + myu.s2.d++; + } + + assert (myu.s2.a == 1); + assert (myu.s2.b == 1); + assert (myu.s2.c == &c2 + 1); + assert (myu.s2.d == &d2 + 1); + + #pragma omp target map(to:myu.s3) \ + map(myu.s3->a, myu.s3->b, myu.s3->c, myu.s3->d) + { + myu.s3->a++; + myu.s3->b++; + myu.s3->c++; + myu.s3->d++; + } + + assert (myu.s3->a == 1); + assert (myu.s3->b == 1); + assert (myu.s3->c == &c3 + 1); + assert (myu.s3->d == &d3 + 1); + + #pragma omp target map(to:myu.s4) \ + map(myu.s4->a, myu.s4->b, myu.s4->c, myu.s4->d) + { + myu.s4->a++; + myu.s4->b++; + myu.s4->c++; + myu.s4->d++; + } + + assert (myu.s4->a == 1); + assert (myu.s4->b == 1); + assert (myu.s4->c == &c4 + 1); + assert (myu.s4->d == &d4 + 1); + + delete s4; + delete t4; +} +#endif + +#ifdef NONREF_COMPONENT_MEMBER_SLICE +void +nonref_component_member_slice (void) +{ + INIT_ST; + U myu(s1, t1, s2, t2, &s3, &t3, s4, t4); + + #pragma omp target map(myu.t1.a[2:5]) + { + myu.t1.a[2]++; + } + + #pragma omp target map(myu.t1.b[2:5]) + { + myu.t1.b[2]++; + } + + #pragma omp target enter data map(to: myu.t1.c) + + #pragma omp target map(myu.t1.c[2:5]) + { + myu.t1.c[2]++; + } + + #pragma omp target exit data map(release: myu.t1.c) + + #pragma omp target enter data map(to: myu.t1.d) + + #pragma omp target map(myu.t1.d[2:5]) + { + myu.t1.d[2]++; + } + + #pragma omp target exit data map(from: myu.t1.d) + + assert (myu.t1.a[2] == 1); + assert (myu.t1.b[2] == 3); + assert (myu.t1.c[2] == 3); + assert (myu.t1.d[2] == 3); + + #pragma omp target map(myu.t2.a[2:5]) + { + myu.t2.a[2]++; + } + + #pragma omp target map(myu.t2.b[2:5]) + { + myu.t2.b[2]++; + } + + #pragma omp target enter data map(to: myu.t2.c) + + #pragma omp target map(myu.t2.c[2:5]) + { + myu.t2.c[2]++; + } + + #pragma omp target exit data map(release: myu.t2.c) + + #pragma omp target enter data map(to: myu.t2.d) + + #pragma omp target map(myu.t2.d[2:5]) + { + myu.t2.d[2]++; + } + + #pragma omp target exit data map(release: myu.t2.d) + + assert (myu.t2.a[2] == 1); + assert (myu.t2.b[2] == 3); + assert (myu.t2.c[2] == 3); + assert (myu.t2.d[2] == 3); + + #pragma omp target enter data map(to: myu.t3) + + #pragma omp target map(myu.t3->a[2:5]) + { + myu.t3->a[2]++; + } + + #pragma omp target map(myu.t3->b[2:5]) + { + myu.t3->b[2]++; + } + + #pragma omp target enter data map(to: myu.t3->c) + + #pragma omp target map(myu.t3->c[2:5]) + { + myu.t3->c[2]++; + } + + #pragma omp target exit data map(release: myu.t3->c) + + #pragma omp target enter data map(to: myu.t3->d) + + #pragma omp target map(myu.t3->d[2:5]) + { + myu.t3->d[2]++; + } + + #pragma omp target exit data map(release: myu.t3, myu.t3->d) + + assert (myu.t3->a[2] == 1); + assert (myu.t3->b[2] == 3); + assert (myu.t3->c[2] == 3); + assert (myu.t3->d[2] == 3); + + #pragma omp target enter data map(to: myu.t4) + + #pragma omp target map(myu.t4->a[2:5]) + { + myu.t4->a[2]++; + } + + #pragma omp target map(myu.t4->b[2:5]) + { + myu.t4->b[2]++; + } + + #pragma omp target enter data map(to: myu.t4->c) + + #pragma omp target map(myu.t4->c[2:5]) + { + myu.t4->c[2]++; + } + + #pragma omp target exit data map(release: myu.t4->c) + + #pragma omp target enter data map(to: myu.t4->d) + + #pragma omp target map(myu.t4->d[2:5]) + { + myu.t4->d[2]++; + } + + #pragma omp target exit data map(release: myu.t4, myu.t4->d) + + assert (myu.t4->a[2] == 1); + assert (myu.t4->b[2] == 3); + assert (myu.t4->c[2] == 3); + assert (myu.t4->d[2] == 3); + + delete s4; + delete t4; +} +#endif + +#ifdef NONREF_COMPONENT_MEMBER_SLICE_BASEPTR +void +nonref_component_member_slice_baseptr (void) +{ + INIT_ST; + U myu(s1, t1, s2, t2, &s3, &t3, s4, t4); + + #pragma omp target map(to: myu.t1.c) map(myu.t1.c[2:5]) + { + myu.t1.c[2]++; + } + + #pragma omp target map(to: myu.t1.d) map(myu.t1.d[2:5]) + { + myu.t1.d[2]++; + } + + assert (myu.t1.c[2] == 2); + assert (myu.t1.d[2] == 2); + + #pragma omp target map(to: myu.t2.c) map(myu.t2.c[2:5]) + { + myu.t2.c[2]++; + } + + #pragma omp target map(to: myu.t2.d) map(myu.t2.d[2:5]) + { + myu.t2.d[2]++; + } + + assert (myu.t2.c[2] == 2); + assert (myu.t2.d[2] == 2); + + #pragma omp target map(to: myu.t3, myu.t3->c) map(myu.t3->c[2:5]) + { + myu.t3->c[2]++; + } + + #pragma omp target map(to: myu.t3, myu.t3->d) map(myu.t3->d[2:5]) + { + myu.t3->d[2]++; + } + + assert (myu.t3->c[2] == 2); + assert (myu.t3->d[2] == 2); + + #pragma omp target map(to: myu.t4, myu.t4->c) map(myu.t4->c[2:5]) + { + myu.t4->c[2]++; + } + + #pragma omp target map(to: myu.t4, myu.t4->d) map(myu.t4->d[2:5]) + { + myu.t4->d[2]++; + } + + assert (myu.t4->c[2] == 2); + assert (myu.t4->d[2] == 2); + + delete s4; + delete t4; +} +#endif + +#ifdef REF_COMPONENT_BASE +void +ref_component_base (void) +{ + INIT_ST; + U myu_real(s1, t1, s2, t2, &s3, &t3, s4, t4); + U &myu = myu_real; + + #pragma omp target map(myu.s1.a, myu.s1.b, myu.s1.c, myu.s1.d) + { + myu.s1.a++; + myu.s1.b++; + myu.s1.c++; + myu.s1.d++; + } + + assert (myu.s1.a == 1); + assert (myu.s1.b == 1); + assert (myu.s1.c == &c1 + 1); + assert (myu.s1.d == &d1 + 1); + + #pragma omp target map(myu.s2.a, myu.s2.b, myu.s2.c, myu.s2.d) + { + myu.s2.a++; + myu.s2.b++; + myu.s2.c++; + myu.s2.d++; + } + + assert (myu.s2.a == 1); + assert (myu.s2.b == 1); + assert (myu.s2.c == &c2 + 1); + assert (myu.s2.d == &d2 + 1); + + #pragma omp target map(to:myu.s3) \ + map(myu.s3->a, myu.s3->b, myu.s3->c, myu.s3->d) + { + myu.s3->a++; + myu.s3->b++; + myu.s3->c++; + myu.s3->d++; + } + + assert (myu.s3->a == 1); + assert (myu.s3->b == 1); + assert (myu.s3->c == &c3 + 1); + assert (myu.s3->d == &d3 + 1); + + #pragma omp target map(to:myu.s4) \ + map(myu.s4->a, myu.s4->b, myu.s4->c, myu.s4->d) + { + myu.s4->a++; + myu.s4->b++; + myu.s4->c++; + myu.s4->d++; + } + + assert (myu.s4->a == 1); + assert (myu.s4->b == 1); + assert (myu.s4->c == &c4 + 1); + assert (myu.s4->d == &d4 + 1); + + delete s4; + delete t4; +} +#endif + +#ifdef REF_COMPONENT_MEMBER_SLICE +void +ref_component_member_slice (void) +{ + INIT_ST; + U myu_real(s1, t1, s2, t2, &s3, &t3, s4, t4); + U &myu = myu_real; + + #pragma omp target map(myu.t1.a[2:5]) + { + myu.t1.a[2]++; + } + + #pragma omp target map(myu.t1.b[2:5]) + { + myu.t1.b[2]++; + } + + #pragma omp target enter data map(to: myu.t1.c) + + #pragma omp target map(myu.t1.c[2:5]) + { + myu.t1.c[2]++; + } + + #pragma omp target exit data map(release: myu.t1.c) + + #pragma omp target enter data map(to: myu.t1.d) + + #pragma omp target map(myu.t1.d[2:5]) + { + myu.t1.d[2]++; + } + + #pragma omp target exit data map(release: myu.t1.d) + + assert (myu.t1.a[2] == 1); + assert (myu.t1.b[2] == 3); + assert (myu.t1.c[2] == 3); + assert (myu.t1.d[2] == 3); + + #pragma omp target map(myu.t2.a[2:5]) + { + myu.t2.a[2]++; + } + + #pragma omp target map(myu.t2.b[2:5]) + { + myu.t2.b[2]++; + } + + #pragma omp target enter data map(to: myu.t2.c) + + #pragma omp target map(myu.t2.c[2:5]) + { + myu.t2.c[2]++; + } + + #pragma omp target exit data map(release: myu.t2.c) + + #pragma omp target enter data map(to: myu.t2.d) + + #pragma omp target map(myu.t2.d[2:5]) + { + myu.t2.d[2]++; + } + + #pragma omp target exit data map(release: myu.t2.d) + + assert (myu.t2.a[2] == 1); + assert (myu.t2.b[2] == 3); + assert (myu.t2.c[2] == 3); + assert (myu.t2.d[2] == 3); + + #pragma omp target enter data map(to: myu.t3) + + #pragma omp target map(myu.t3->a[2:5]) + { + myu.t3->a[2]++; + } + + #pragma omp target map(myu.t3->b[2:5]) + { + myu.t3->b[2]++; + } + + #pragma omp target enter data map(to: myu.t3->c) + + #pragma omp target map(myu.t3->c[2:5]) + { + myu.t3->c[2]++; + } + + #pragma omp target exit data map(release: myu.t3->c) + + #pragma omp target enter data map(to: myu.t3->d) + + #pragma omp target map(myu.t3->d[2:5]) + { + myu.t3->d[2]++; + } + + #pragma omp target exit data map(release: myu.t3, myu.t3->d) + + assert (myu.t3->a[2] == 1); + assert (myu.t3->b[2] == 3); + assert (myu.t3->c[2] == 3); + assert (myu.t3->d[2] == 3); + + #pragma omp target enter data map(to: myu.t4) + + #pragma omp target map(myu.t4->a[2:5]) + { + myu.t4->a[2]++; + } + + #pragma omp target map(myu.t4->b[2:5]) + { + myu.t4->b[2]++; + } + + #pragma omp target enter data map(to: myu.t4->c) + + #pragma omp target map(myu.t4->c[2:5]) + { + myu.t4->c[2]++; + } + + #pragma omp target exit data map(release: myu.t4->c) + + #pragma omp target enter data map(to: myu.t4->d) + + #pragma omp target map(myu.t4->d[2:5]) + { + myu.t4->d[2]++; + } + + #pragma omp target exit data map(release: myu.t4, myu.t4->d) + + assert (myu.t4->a[2] == 1); + assert (myu.t4->b[2] == 3); + assert (myu.t4->c[2] == 3); + assert (myu.t4->d[2] == 3); + + delete s4; + delete t4; +} +#endif + +#ifdef REF_COMPONENT_MEMBER_SLICE_BASEPTR +void +ref_component_member_slice_baseptr (void) +{ + INIT_ST; + U myu_real(s1, t1, s2, t2, &s3, &t3, s4, t4); + U &myu = myu_real; + + #pragma omp target map(to: myu.t1.c) map(myu.t1.c[2:5]) + { + myu.t1.c[2]++; + } + + #pragma omp target map(to: myu.t1.d) map(myu.t1.d[2:5]) + { + myu.t1.d[2]++; + } + + assert (myu.t1.c[2] == 2); + assert (myu.t1.d[2] == 2); + + #pragma omp target map(to: myu.t2.c) map(myu.t2.c[2:5]) + { + myu.t2.c[2]++; + } + + #pragma omp target map(to: myu.t2.d) map(myu.t2.d[2:5]) + { + myu.t2.d[2]++; + } + + assert (myu.t2.c[2] == 2); + assert (myu.t2.d[2] == 2); + + #pragma omp target map(to: myu.t3, myu.t3->c) map(myu.t3->c[2:5]) + { + myu.t3->c[2]++; + } + + #pragma omp target map(to: myu.t3, myu.t3->d) map(myu.t3->d[2:5]) + { + myu.t3->d[2]++; + } + + assert (myu.t3->c[2] == 2); + assert (myu.t3->d[2] == 2); + + #pragma omp target map(to: myu.t4, myu.t4->c) map(myu.t4->c[2:5]) + { + myu.t4->c[2]++; + } + + #pragma omp target map(to: myu.t4, myu.t4->d) map(myu.t4->d[2:5]) + { + myu.t4->d[2]++; + } + + assert (myu.t4->c[2] == 2); + assert (myu.t4->d[2] == 2); + + delete s4; + delete t4; +} +#endif + +#ifdef PTR_COMPONENT_BASE +void +ptr_component_base (void) +{ + INIT_ST; + U *myu = new U(s1, t1, s2, t2, &s3, &t3, s4, t4); + + #pragma omp target map(myu->s1.a, myu->s1.b, myu->s1.c, myu->s1.d) + { + myu->s1.a++; + myu->s1.b++; + myu->s1.c++; + myu->s1.d++; + } + + assert (myu->s1.a == 1); + assert (myu->s1.b == 1); + assert (myu->s1.c == &c1 + 1); + assert (myu->s1.d == &d1 + 1); + + #pragma omp target map(myu->s2.a, myu->s2.b, myu->s2.c, myu->s2.d) + { + myu->s2.a++; + myu->s2.b++; + myu->s2.c++; + myu->s2.d++; + } + + assert (myu->s2.a == 1); + assert (myu->s2.b == 1); + assert (myu->s2.c == &c2 + 1); + assert (myu->s2.d == &d2 + 1); + + #pragma omp target map(to:myu->s3) \ + map(myu->s3->a, myu->s3->b, myu->s3->c, myu->s3->d) + { + myu->s3->a++; + myu->s3->b++; + myu->s3->c++; + myu->s3->d++; + } + + assert (myu->s3->a == 1); + assert (myu->s3->b == 1); + assert (myu->s3->c == &c3 + 1); + assert (myu->s3->d == &d3 + 1); + + #pragma omp target map(to:myu->s4) \ + map(myu->s4->a, myu->s4->b, myu->s4->c, myu->s4->d) + { + myu->s4->a++; + myu->s4->b++; + myu->s4->c++; + myu->s4->d++; + } + + assert (myu->s4->a == 1); + assert (myu->s4->b == 1); + assert (myu->s4->c == &c4 + 1); + assert (myu->s4->d == &d4 + 1); + + delete s4; + delete t4; + delete myu; +} +#endif + +#ifdef PTR_COMPONENT_MEMBER_SLICE +void +ptr_component_member_slice (void) +{ + INIT_ST; + U *myu = new U(s1, t1, s2, t2, &s3, &t3, s4, t4); + + #pragma omp target map(myu->t1.a[2:5]) + { + myu->t1.a[2]++; + } + + #pragma omp target map(myu->t1.b[2:5]) + { + myu->t1.b[2]++; + } + + #pragma omp target enter data map(to: myu->t1.c) + + #pragma omp target map(myu->t1.c[2:5]) + { + myu->t1.c[2]++; + } + + #pragma omp target exit data map(release: myu->t1.c) + + #pragma omp target enter data map(to: myu->t1.d) + + #pragma omp target map(myu->t1.d[2:5]) + { + myu->t1.d[2]++; + } + + #pragma omp target exit data map(release: myu->t1.d) + + assert (myu->t1.a[2] == 1); + assert (myu->t1.b[2] == 3); + assert (myu->t1.c[2] == 3); + assert (myu->t1.d[2] == 3); + + #pragma omp target map(myu->t2.a[2:5]) + { + myu->t2.a[2]++; + } + + #pragma omp target map(myu->t2.b[2:5]) + { + myu->t2.b[2]++; + } + + #pragma omp target enter data map(to: myu->t2.c) + + #pragma omp target map(myu->t2.c[2:5]) + { + myu->t2.c[2]++; + } + + #pragma omp target exit data map(release: myu->t2.c) + + #pragma omp target enter data map(to: myu->t2.d) + + #pragma omp target map(myu->t2.d[2:5]) + { + myu->t2.d[2]++; + } + + #pragma omp target exit data map(release: myu->t2.d) + + assert (myu->t2.a[2] == 1); + assert (myu->t2.b[2] == 3); + assert (myu->t2.c[2] == 3); + assert (myu->t2.d[2] == 3); + + #pragma omp target enter data map(to: myu->t3) + + #pragma omp target map(myu->t3->a[2:5]) + { + myu->t3->a[2]++; + } + + #pragma omp target map(myu->t3->b[2:5]) + { + myu->t3->b[2]++; + } + + #pragma omp target enter data map(to: myu->t3->c) + + #pragma omp target map(myu->t3->c[2:5]) + { + myu->t3->c[2]++; + } + + #pragma omp target exit data map(release: myu->t3->c) + + #pragma omp target enter data map(to: myu->t3->d) + + #pragma omp target map(myu->t3->d[2:5]) + { + myu->t3->d[2]++; + } + + #pragma omp target exit data map(release: myu->t3, myu->t3->d) + + assert (myu->t3->a[2] == 1); + assert (myu->t3->b[2] == 3); + assert (myu->t3->c[2] == 3); + assert (myu->t3->d[2] == 3); + + #pragma omp target enter data map(to: myu->t4) + + #pragma omp target map(myu->t4->a[2:5]) + { + myu->t4->a[2]++; + } + + #pragma omp target map(myu->t4->b[2:5]) + { + myu->t4->b[2]++; + } + + #pragma omp target enter data map(to: myu->t4->c) + + #pragma omp target map(myu->t4->c[2:5]) + { + myu->t4->c[2]++; + } + + #pragma omp target exit data map(release: myu->t4->c) + + #pragma omp target enter data map(to: myu->t4->d) + + #pragma omp target map(myu->t4->d[2:5]) + { + myu->t4->d[2]++; + } + + #pragma omp target exit data map(release: myu->t4, myu->t4->d) + + assert (myu->t4->a[2] == 1); + assert (myu->t4->b[2] == 3); + assert (myu->t4->c[2] == 3); + assert (myu->t4->d[2] == 3); + + delete s4; + delete t4; + delete myu; +} +#endif + +#ifdef PTR_COMPONENT_MEMBER_SLICE_BASEPTR +void +ptr_component_member_slice_baseptr (void) +{ + INIT_ST; + U *myu = new U(s1, t1, s2, t2, &s3, &t3, s4, t4); + + /* Implicit firstprivate 'myu'. */ + #pragma omp target map(to: myu->t1.c) map(myu->t1.c[2:5]) + { + myu->t1.c[2]++; + } + + #pragma omp target map(to: myu->t1.d) map(myu->t1.d[2:5]) + { + myu->t1.d[2]++; + } + + assert (myu->t1.c[2] == 2); + assert (myu->t1.d[2] == 2); + + /* Explicitly-mapped 'myu'. */ + #pragma omp target map(to: myu, myu->t1.c) map(myu->t1.c[2:5]) + { + myu->t1.c[2]++; + } + + #pragma omp target map(to: myu, myu->t1.d) map(myu->t1.d[2:5]) + { + myu->t1.d[2]++; + } + + assert (myu->t1.c[2] == 4); + assert (myu->t1.d[2] == 4); + + /* Implicit firstprivate 'myu'. */ + #pragma omp target map(to: myu->t2.c) map(myu->t2.c[2:5]) + { + myu->t2.c[2]++; + } + + #pragma omp target map(to: myu->t2.d) map(myu->t2.d[2:5]) + { + myu->t2.d[2]++; + } + + assert (myu->t2.c[2] == 2); + assert (myu->t2.d[2] == 2); + + /* Explicitly-mapped 'myu'. */ + #pragma omp target map(to: myu, myu->t2.c) map(myu->t2.c[2:5]) + { + myu->t2.c[2]++; + } + + #pragma omp target map(to: myu, myu->t2.d) map(myu->t2.d[2:5]) + { + myu->t2.d[2]++; + } + + assert (myu->t2.c[2] == 4); + assert (myu->t2.d[2] == 4); + + /* Implicit firstprivate 'myu'. */ + #pragma omp target map(to: myu->t3, myu->t3->c) map(myu->t3->c[2:5]) + { + myu->t3->c[2]++; + } + + #pragma omp target map(to: myu->t3, myu->t3->d) map(myu->t3->d[2:5]) + { + myu->t3->d[2]++; + } + + assert (myu->t3->c[2] == 2); + assert (myu->t3->d[2] == 2); + + /* Explicitly-mapped 'myu'. */ + #pragma omp target map(to: myu, myu->t3, myu->t3->c) map(myu->t3->c[2:5]) + { + myu->t3->c[2]++; + } + + #pragma omp target map(to: myu, myu->t3, myu->t3->d) map(myu->t3->d[2:5]) + { + myu->t3->d[2]++; + } + + assert (myu->t3->c[2] == 4); + assert (myu->t3->d[2] == 4); + + /* Implicit firstprivate 'myu'. */ + #pragma omp target map(to: myu->t4, myu->t4->c) map(myu->t4->c[2:5]) + { + myu->t4->c[2]++; + } + + #pragma omp target map(to: myu->t4, myu->t4->d) map(myu->t4->d[2:5]) + { + myu->t4->d[2]++; + } + + assert (myu->t4->c[2] == 2); + assert (myu->t4->d[2] == 2); + + /* Explicitly-mapped 'myu'. */ + #pragma omp target map(to: myu, myu->t4, myu->t4->c) map(myu->t4->c[2:5]) + { + myu->t4->c[2]++; + } + + #pragma omp target map(to: myu, myu->t4, myu->t4->d) map(myu->t4->d[2:5]) + { + myu->t4->d[2]++; + } + + assert (myu->t4->c[2] == 4); + assert (myu->t4->d[2] == 4); + + delete s4; + delete t4; + delete myu; +} +#endif + +#ifdef REF2PTR_COMPONENT_BASE +void +ref2ptr_component_base (void) +{ + INIT_ST; + U *myu_ptr = new U(s1, t1, s2, t2, &s3, &t3, s4, t4); + U *&myu = myu_ptr; + + #pragma omp target map(myu->s1.a, myu->s1.b, myu->s1.c, myu->s1.d) + { + myu->s1.a++; + myu->s1.b++; + myu->s1.c++; + myu->s1.d++; + } + + assert (myu->s1.a == 1); + assert (myu->s1.b == 1); + assert (myu->s1.c == &c1 + 1); + assert (myu->s1.d == &d1 + 1); + + #pragma omp target map(myu->s2.a, myu->s2.b, myu->s2.c, myu->s2.d) + { + myu->s2.a++; + myu->s2.b++; + myu->s2.c++; + myu->s2.d++; + } + + assert (myu->s2.a == 1); + assert (myu->s2.b == 1); + assert (myu->s2.c == &c2 + 1); + assert (myu->s2.d == &d2 + 1); + + #pragma omp target map(to:myu->s3) \ + map(myu->s3->a, myu->s3->b, myu->s3->c, myu->s3->d) + { + myu->s3->a++; + myu->s3->b++; + myu->s3->c++; + myu->s3->d++; + } + + assert (myu->s3->a == 1); + assert (myu->s3->b == 1); + assert (myu->s3->c == &c3 + 1); + assert (myu->s3->d == &d3 + 1); + + #pragma omp target map(to:myu->s4) \ + map(myu->s4->a, myu->s4->b, myu->s4->c, myu->s4->d) + { + myu->s4->a++; + myu->s4->b++; + myu->s4->c++; + myu->s4->d++; + } + + assert (myu->s4->a == 1); + assert (myu->s4->b == 1); + assert (myu->s4->c == &c4 + 1); + assert (myu->s4->d == &d4 + 1); + + delete s4; + delete t4; + delete myu_ptr; +} +#endif + +#ifdef REF2PTR_COMPONENT_MEMBER_SLICE +void +ref2ptr_component_member_slice (void) +{ + INIT_ST; + U *myu_ptr = new U(s1, t1, s2, t2, &s3, &t3, s4, t4); + U *&myu = myu_ptr; + + #pragma omp target map(myu->t1.a[2:5]) + { + myu->t1.a[2]++; + } + + #pragma omp target map(myu->t1.b[2:5]) + { + myu->t1.b[2]++; + } + + #pragma omp target enter data map(to: myu->t1.c) + + #pragma omp target map(myu->t1.c[2:5]) + { + myu->t1.c[2]++; + } + + #pragma omp target exit data map(release: myu->t1.c) + + #pragma omp target enter data map(to: myu->t1.d) + + #pragma omp target map(myu->t1.d[2:5]) + { + myu->t1.d[2]++; + } + + #pragma omp target exit data map(release: myu->t1.d) + + assert (myu->t1.a[2] == 1); + assert (myu->t1.b[2] == 3); + assert (myu->t1.c[2] == 3); + assert (myu->t1.d[2] == 3); + + #pragma omp target map(myu->t2.a[2:5]) + { + myu->t2.a[2]++; + } + + #pragma omp target map(myu->t2.b[2:5]) + { + myu->t2.b[2]++; + } + + #pragma omp target enter data map(to: myu->t2.c) + + #pragma omp target map(myu->t2.c[2:5]) + { + myu->t2.c[2]++; + } + + #pragma omp target exit data map(release: myu->t2.c) + + #pragma omp target enter data map(to: myu->t2.d) + + #pragma omp target map(myu->t2.d[2:5]) + { + myu->t2.d[2]++; + } + + #pragma omp target exit data map(release: myu->t2.d) + + assert (myu->t2.a[2] == 1); + assert (myu->t2.b[2] == 3); + assert (myu->t2.c[2] == 3); + assert (myu->t2.d[2] == 3); + + #pragma omp target enter data map(to: myu->t3) + + #pragma omp target map(myu->t3->a[2:5]) + { + myu->t3->a[2]++; + } + + #pragma omp target map(myu->t3->b[2:5]) + { + myu->t3->b[2]++; + } + + #pragma omp target enter data map(to: myu->t3->c) + + #pragma omp target map(myu->t3->c[2:5]) + { + myu->t3->c[2]++; + } + + #pragma omp target exit data map(release: myu->t3->c) + + #pragma omp target enter data map(to: myu->t3->d) + + #pragma omp target map(myu->t3->d[2:5]) + { + myu->t3->d[2]++; + } + + #pragma omp target exit data map(release: myu->t3, myu->t3->d) + + assert (myu->t3->a[2] == 1); + assert (myu->t3->b[2] == 3); + assert (myu->t3->c[2] == 3); + assert (myu->t3->d[2] == 3); + + #pragma omp target enter data map(to: myu->t4) + + #pragma omp target map(myu->t4->a[2:5]) + { + myu->t4->a[2]++; + } + + #pragma omp target map(myu->t4->b[2:5]) + { + myu->t4->b[2]++; + } + + #pragma omp target enter data map(to: myu->t4->c) + + #pragma omp target map(myu->t4->c[2:5]) + { + myu->t4->c[2]++; + } + + #pragma omp target exit data map(release: myu->t4->c) + + #pragma omp target enter data map(to: myu->t4->d) + + #pragma omp target map(myu->t4->d[2:5]) + { + myu->t4->d[2]++; + } + + #pragma omp target exit data map(release: myu->t4, myu->t4->d) + + assert (myu->t4->a[2] == 1); + assert (myu->t4->b[2] == 3); + assert (myu->t4->c[2] == 3); + assert (myu->t4->d[2] == 3); + + delete s4; + delete t4; + delete myu_ptr; +} +#endif + +#ifdef REF2PTR_COMPONENT_MEMBER_SLICE_BASEPTR +void +ref2ptr_component_member_slice_baseptr (void) +{ + INIT_ST; + U *myu_ptr = new U(s1, t1, s2, t2, &s3, &t3, s4, t4); + U *&myu = myu_ptr; + + /* Implicit firstprivate 'myu'. */ + #pragma omp target map(to: myu->t1.c) map(myu->t1.c[2:5]) + { + myu->t1.c[2]++; + } + + #pragma omp target map(to: myu->t1.d) map(myu->t1.d[2:5]) + { + myu->t1.d[2]++; + } + + assert (myu->t1.c[2] == 2); + assert (myu->t1.d[2] == 2); + + /* Explicitly-mapped 'myu'. */ + #pragma omp target map(to: myu, myu->t1.c) map(myu->t1.c[2:5]) + { + myu->t1.c[2]++; + } + + #pragma omp target map(to: myu, myu->t1.d) map(myu->t1.d[2:5]) + { + myu->t1.d[2]++; + } + + assert (myu->t1.c[2] == 4); + assert (myu->t1.d[2] == 4); + + /* Implicit firstprivate 'myu'. */ + #pragma omp target map(to: myu->t2.c) map(myu->t2.c[2:5]) + { + myu->t2.c[2]++; + } + + #pragma omp target map(to: myu->t2.d) map(myu->t2.d[2:5]) + { + myu->t2.d[2]++; + } + + assert (myu->t2.c[2] == 2); + assert (myu->t2.d[2] == 2); + + /* Explicitly-mapped 'myu'. */ + #pragma omp target map(to: myu, myu->t2.c) map(myu->t2.c[2:5]) + { + myu->t2.c[2]++; + } + + #pragma omp target map(to: myu, myu->t2.d) map(myu->t2.d[2:5]) + { + myu->t2.d[2]++; + } + + assert (myu->t2.c[2] == 4); + assert (myu->t2.d[2] == 4); + + /* Implicit firstprivate 'myu'. */ + #pragma omp target map(to: myu->t3, myu->t3->c) map(myu->t3->c[2:5]) + { + myu->t3->c[2]++; + } + + #pragma omp target map(to: myu->t3, myu->t3->d) map(myu->t3->d[2:5]) + { + myu->t3->d[2]++; + } + + assert (myu->t3->c[2] == 2); + assert (myu->t3->d[2] == 2); + + /* Explicitly-mapped 'myu'. */ + #pragma omp target map(to: myu, myu->t3, myu->t3->c) map(myu->t3->c[2:5]) + { + myu->t3->c[2]++; + } + + #pragma omp target map(to: myu, myu->t3, myu->t3->d) map(myu->t3->d[2:5]) + { + myu->t3->d[2]++; + } + + assert (myu->t3->c[2] == 4); + assert (myu->t3->d[2] == 4); + + /* Implicit firstprivate 'myu'. */ + #pragma omp target map(to: myu->t4, myu->t4->c) map(myu->t4->c[2:5]) + { + myu->t4->c[2]++; + } + + #pragma omp target map(to: myu->t4, myu->t4->d) map(myu->t4->d[2:5]) + { + myu->t4->d[2]++; + } + + assert (myu->t4->c[2] == 2); + assert (myu->t4->d[2] == 2); + + /* Explicitly-mapped 'myu'. */ + #pragma omp target map(to: myu, myu->t4, myu->t4->c) map(myu->t4->c[2:5]) + { + myu->t4->c[2]++; + } + + #pragma omp target map(to: myu, myu->t4, myu->t4->d) map(myu->t4->d[2:5]) + { + myu->t4->d[2]++; + } + + assert (myu->t4->c[2] == 4); + assert (myu->t4->d[2] == 4); + + delete s4; + delete t4; + delete myu_ptr; +} +#endif + +int main (int argc, char *argv[]) +{ +#ifdef MAP_DECLS + map_decls (); +#endif + +#ifdef NONREF_DECL_BASE + nonref_decl_base (); +#endif +#ifdef REF_DECL_BASE + ref_decl_base (); +#endif +#ifdef PTR_DECL_BASE + ptr_decl_base (); +#endif +#ifdef REF2PTR_DECL_BASE + ref2ptr_decl_base (); +#endif + +#ifdef ARRAY_DECL_BASE + array_decl_base (); +#endif +#ifdef REF2ARRAY_DECL_BASE + ref2array_decl_base (); +#endif +#ifdef PTR_OFFSET_DECL_BASE + ptr_offset_decl_base (); +#endif +#ifdef REF2PTR_OFFSET_DECL_BASE + ref2ptr_offset_decl_base (); +#endif + +#ifdef MAP_SECTIONS + map_sections (); +#endif + +#ifdef NONREF_DECL_MEMBER_SLICE + nonref_decl_member_slice (); +#endif +#ifdef NONREF_DECL_MEMBER_SLICE_BASEPTR + nonref_decl_member_slice_baseptr (); +#endif +#ifdef REF_DECL_MEMBER_SLICE + ref_decl_member_slice (); +#endif +#ifdef REF_DECL_MEMBER_SLICE_BASEPTR + ref_decl_member_slice_baseptr (); +#endif +#ifdef PTR_DECL_MEMBER_SLICE + ptr_decl_member_slice (); +#endif +#ifdef PTR_DECL_MEMBER_SLICE_BASEPTR + ptr_decl_member_slice_baseptr (); +#endif +#ifdef REF2PTR_DECL_MEMBER_SLICE + ref2ptr_decl_member_slice (); +#endif +#ifdef REF2PTR_DECL_MEMBER_SLICE_BASEPTR + ref2ptr_decl_member_slice_baseptr (); +#endif + +#ifdef ARRAY_DECL_MEMBER_SLICE + array_decl_member_slice (); +#endif +#ifdef ARRAY_DECL_MEMBER_SLICE_BASEPTR + array_decl_member_slice_baseptr (); +#endif +#ifdef REF2ARRAY_DECL_MEMBER_SLICE + ref2array_decl_member_slice (); +#endif +#ifdef REF2ARRAY_DECL_MEMBER_SLICE_BASEPTR + ref2array_decl_member_slice_baseptr (); +#endif +#ifdef PTR_OFFSET_DECL_MEMBER_SLICE + ptr_offset_decl_member_slice (); +#endif +#ifdef PTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR + ptr_offset_decl_member_slice_baseptr (); +#endif +#ifdef REF2PTR_OFFSET_DECL_MEMBER_SLICE + ref2ptr_offset_decl_member_slice (); +#endif +#ifdef REF2PTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR + ref2ptr_offset_decl_member_slice_baseptr (); +#endif + +#ifdef PTRARRAY_DECL_MEMBER_SLICE + ptrarray_decl_member_slice (); +#endif +#ifdef PTRARRAY_DECL_MEMBER_SLICE_BASEPTR + ptrarray_decl_member_slice_baseptr (); +#endif +#ifdef REF2PTRARRAY_DECL_MEMBER_SLICE + ref2ptrarray_decl_member_slice (); +#endif +#ifdef REF2PTRARRAY_DECL_MEMBER_SLICE_BASEPTR + ref2ptrarray_decl_member_slice_baseptr (); +#endif +#ifdef PTRPTR_OFFSET_DECL_MEMBER_SLICE + ptrptr_offset_decl_member_slice (); +#endif +#ifdef PTRPTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR + ptrptr_offset_decl_member_slice_baseptr (); +#endif +#ifdef REF2PTRPTR_OFFSET_DECL_MEMBER_SLICE + ref2ptrptr_offset_decl_member_slice (); +#endif +#ifdef REF2PTRPTR_OFFSET_DECL_MEMBER_SLICE_BASEPTR + ref2ptrptr_offset_decl_member_slice_baseptr (); +#endif + +#ifdef NONREF_COMPONENT_BASE + nonref_component_base (); +#endif +#ifdef NONREF_COMPONENT_MEMBER_SLICE + nonref_component_member_slice (); +#endif +#ifdef NONREF_COMPONENT_MEMBER_SLICE_BASEPTR + nonref_component_member_slice_baseptr (); +#endif + +#ifdef REF_COMPONENT_BASE + ref_component_base (); +#endif +#ifdef REF_COMPONENT_MEMBER_SLICE + ref_component_member_slice (); +#endif +#ifdef REF_COMPONENT_MEMBER_SLICE_BASEPTR + ref_component_member_slice_baseptr (); +#endif + +#ifdef PTR_COMPONENT_BASE + ptr_component_base (); +#endif +#ifdef PTR_COMPONENT_MEMBER_SLICE + ptr_component_member_slice (); +#endif +#ifdef PTR_COMPONENT_MEMBER_SLICE_BASEPTR + ptr_component_member_slice_baseptr (); +#endif + +#ifdef REF2PTR_COMPONENT_BASE + ref2ptr_component_base (); +#endif +#ifdef REF2PTR_COMPONENT_MEMBER_SLICE + ref2ptr_component_member_slice (); +#endif +#ifdef REF2PTR_COMPONENT_MEMBER_SLICE_BASEPTR + ref2ptr_component_member_slice_baseptr (); +#endif + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/baseptrs-5.C b/libgomp/testsuite/libgomp.c++/baseptrs-5.C new file mode 100644 index 0000000..16bdfff --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/baseptrs-5.C @@ -0,0 +1,62 @@ +// { dg-do run } + +#include <cstring> +#include <cassert> + +struct sa +{ + int *ptr; + int *ptr2; +}; + +struct sb +{ + int arr[10]; +}; + +struct scp +{ + sa *&a; + sb *&b; + scp (sa *&my_a, sb *&my_b) : a(my_a), b(my_b) {} +}; + +int +main () +{ + sa *my_a = new sa; + sb *my_b = new sb; + + my_a->ptr = new int[10]; + my_a->ptr2 = new int[10]; + scp *my_c = new scp(my_a, my_b); + + memset (my_c->a->ptr, 0, sizeof (int) * 10); + memset (my_c->a->ptr2, 0, sizeof (int) * 10); + + #pragma omp target map (my_c->a, \ + my_c->a->ptr, my_c->a->ptr[:10], \ + my_c->a->ptr2, my_c->a->ptr2[:10]) + { + for (int i = 0; i < 10; i++) + { + my_c->a->ptr[i] = i; + my_c->a->ptr2[i] = i * 2; + } + } + + for (int i = 0; i < 10; i++) + { + assert (my_c->a->ptr[i] == i); + assert (my_c->a->ptr2[i] == i * 2); + } + + delete[] my_a->ptr; + delete[] my_a->ptr2; + delete my_a; + delete my_b; + delete my_c; + + return 0; +} + diff --git a/libgomp/testsuite/libgomp.c++/baseptrs-8.C b/libgomp/testsuite/libgomp.c++/baseptrs-8.C new file mode 100644 index 0000000..f999181 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/baseptrs-8.C @@ -0,0 +1,70 @@ +/* { dg-do run } */ + +#include <stdlib.h> +#include <assert.h> + +#define N 1024 +#define M 64 + +int main (void) +{ + int *a_orig[N]; + int *(&a)[N] = a_orig; + + for (int i = 0; i < N; i++) + a[i] = (int *) calloc (M, sizeof (int)); + + /* 'target enter data'/'target exit data' with array of pointers. */ +#pragma omp target enter data map(alloc: a[0:N]) + + for (int i = 0; i < N; i++) + { +#pragma omp target enter data map(to: a[i][0:M]) + } + +#pragma omp target map(alloc: a) + { + for (int i = 0; i < N; i++) + for (int j = 0; j < M; j++) + a[i][j] = i + j; + } + +for (int i = 0; i < N; i++) + { +#pragma omp target exit data map(release: a[i]) map(from: a[i][0:M]) + } + +#pragma omp target exit data map(release: a, a[0:N]) + + /* 'target data' with array of pointers. */ +#pragma omp target data map(alloc: a[0:N]) + { +#pragma omp target data map(tofrom: a[5][0:M]) + { +#pragma omp target map(alloc: a) + { + for (int i = 0; i < M; i++) + a[5][i]++; + } + } + } + + /* 'target' with array of pointers. */ +#pragma omp target data map(alloc: a[0:N]) + { +#pragma omp target map(tofrom: a[7][0:M]) + { + for (int i = 0; i < M; i++) + a[7][i] += 2; + } + } + + for (int i = 0; i < N; i++) + for (int j = 0; j < M; j++) + assert (a[i][j] == i + j + (i == 5) + 2 * (i == 7)); + + for (int i = 0; i < N; i++) + free (a[i]); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/baseptrs-9.C b/libgomp/testsuite/libgomp.c++/baseptrs-9.C new file mode 100644 index 0000000..95e7eeb --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/baseptrs-9.C @@ -0,0 +1,57 @@ +/* { dg-do run } */ + +#include <stdlib.h> +#include <assert.h> + +int main (void) +{ + int **a_orig,i,j,n; + int **&a = a_orig; + + j = 3; + n = 12; + + a = (int **) calloc (32, sizeof (int *)); + for (int x = 0; x < 32; x++) + a[x] = (int *) calloc (32, sizeof (int)); + + for (int i = 2; i < 32; i++) + { + #pragma omp target enter data map(a, a[2:30]) + #pragma omp target enter data map(a[i][j:n]) + #pragma omp target map(alloc: a) + { + for (int x = j; x < j + n; x++) + a[i][x]++; + } + #pragma omp target exit data map(a[i][j:n]) + + #pragma omp target data map(a, a[i][j:n]) + { + #pragma omp target map(alloc: a) + { + for (int x = j; x < j + n; x++) + a[i][x]++; + } + } + #pragma omp target exit data map(a, a[2:30]) + + #pragma omp target data map(a, a[2:30]) + { + #pragma omp target map(a[i][j:n]) + { + for (int x = j; x < j + n; x++) + a[i][x]++; + } + } + } + + for (int i = 0; i < 32; i++) + for (int j = 0; j < 32; j++) + if (i >= 2 && j >= 3 && j < 15) + assert (a[i][j] == 3); + else + assert (a[i][j] == 0); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/class-array-1.C b/libgomp/testsuite/libgomp.c++/class-array-1.C new file mode 100644 index 0000000..d8d3f7f --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/class-array-1.C @@ -0,0 +1,59 @@ +/* { dg-do run } */ + +#include <cassert> + +#define N 1024 + +class M { + int array[N]; + +public: + M () + { + for (int i = 0; i < N; i++) + array[i] = 0; + } + + void incr_with_this (int c) + { +#pragma omp target map(this->array[:N]) + for (int i = 0; i < N; i++) + array[i] += c; + } + + void incr_without_this (int c) + { +#pragma omp target map(array[:N]) + for (int i = 0; i < N; i++) + array[i] += c; + } + + void incr_implicit (int c) + { +#pragma omp target + for (int i = 0; i < N; i++) + array[i] += c; + } + + void check (int c) + { + for (int i = 0; i < N; i++) + assert (array[i] == c); + } +}; + +int +main (int argc, char *argv[]) +{ + M m; + + m.check (0); + m.incr_with_this (3); + m.check (3); + m.incr_without_this (5); + m.check (8); + m.incr_implicit (2); + m.check (10); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/ref-mapping-1.C b/libgomp/testsuite/libgomp.c++/ref-mapping-1.C new file mode 100644 index 0000000..9aa232f --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/ref-mapping-1.C @@ -0,0 +1,80 @@ +/* { dg-do run } */ + +#include <cassert> + +void test_ref () +{ + int c_orig = 5; + int &c = c_orig; + +#pragma omp target map(tofrom: c) + { + c++; + } + + assert (c == 6); +} + +void test_ref_to_ptr () +{ + int val = 5; + int *ptr_orig = &val; + int *&ptr_ref = ptr_orig; + +#pragma omp target map(tofrom: ptr_ref[0]) + { + (*ptr_ref)++; + } + + assert (val == 6); +} + +void test_ref_to_array () +{ + int arr[1]; + int (&arr_ref)[1] = arr; + + arr_ref[0] = 5; + +#pragma omp target map(tofrom: arr_ref[0:1]) + { + arr_ref[0]++; + } + + assert (arr_ref[0] == 6); + +#pragma omp target map(tofrom: arr_ref[0]) + { + arr_ref[0]++; + } + + assert (arr_ref[0] == 7); +} + +void test_ref_to_ptr_array () +{ + int *arr[1]; + int *(&arr_ref)[1] = arr; + int val = 5; + + arr_ref[0] = &val; + +#pragma omp target data map(alloc: arr_ref, arr_ref[0]) + { +#pragma omp target map(tofrom: arr_ref[0][0:1]) + { + arr_ref[0][0]++; + } + } + + assert (arr_ref[0][0] == 6); +} + +int main () +{ + test_ref (); + test_ref_to_ptr (); + test_ref_to_array (); + test_ref_to_ptr_array (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/target-48.C b/libgomp/testsuite/libgomp.c++/target-48.C new file mode 100644 index 0000000..db171d2 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/target-48.C @@ -0,0 +1,32 @@ +#include <cstring> +#include <cassert> + +struct s { + int (&a)[10]; + s(int (&a0)[10]) : a(a0) {} +}; + +int +main (int argc, char *argv[]) +{ + int la[10]; + s v(la); + + memset (la, 0, sizeof la); + + #pragma omp target enter data map(to: v) + + /* This mapping must use GOMP_MAP_ATTACH_DETACH not GOMP_MAP_ALWAYS_POINTER, + else the host reference v.a will be corrupted on copy-out. */ + + #pragma omp target map(v.a[0:10]) + { + v.a[5]++; + } + + #pragma omp target exit data map(from: v) + + assert (v.a[5] == 1); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/target-49.C b/libgomp/testsuite/libgomp.c++/target-49.C new file mode 100644 index 0000000..b0746b4 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/target-49.C @@ -0,0 +1,37 @@ +#include <cstring> +#include <cassert> + +struct s { + int (&a)[10]; + s(int (&a0)[10]) : a(a0) {} +}; + +int +main (int argc, char *argv[]) +{ + int la[10]; + s v_real(la); + s *v = &v_real; + + memset (la, 0, sizeof la); + + #pragma omp target enter data map(to: v) + + /* Copying the whole v[0] here DOES NOT WORK yet because the reference 'a' is + not copied "as if" it was mapped explicitly as a member. FIXME. */ + #pragma omp target enter data map(to: v[0]) + + #pragma omp target + { + v->a[5]++; + } + + #pragma omp target exit data map(release: v[0]) + #pragma omp target exit data map(from: v) + + assert (v->a[5] == 1); + + return 0; +} + +// { dg-xfail-run-if "TODO" { offload_device_nonshared_as } } diff --git a/libgomp/testsuite/libgomp.c++/target-exit-data-reftoptr-1.C b/libgomp/testsuite/libgomp.c++/target-exit-data-reftoptr-1.C new file mode 100644 index 0000000..1a66fcb --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/target-exit-data-reftoptr-1.C @@ -0,0 +1,34 @@ +#include <cstring> +#include <cassert> + +struct S { + int *&ptr; + S(int *&ptr_) : ptr(ptr_) { } +}; + +int main() +{ + int *orig = new int[100]; + + memset (orig, 0, sizeof (int) * 100); + + S svar(orig); + +#pragma omp target enter data map(to: svar.ptr, svar.ptr[10:80]) + +#pragma omp target + { + for (int i = 10; i < 90; i++) + svar.ptr[i]++; + } + +#pragma omp target exit data map(release: svar.ptr) map(from: svar.ptr[10:80]) + + for (int i = 0; i < 100; i++) + assert (i >= 10 && i < 90 && svar.ptr[i] == 1 + || svar.ptr[i] == 0); + + delete orig; + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/target-lambda-1.C b/libgomp/testsuite/libgomp.c++/target-lambda-1.C index c5acbb8..fa882d0 100644 --- a/libgomp/testsuite/libgomp.c++/target-lambda-1.C +++ b/libgomp/testsuite/libgomp.c++/target-lambda-1.C @@ -2,6 +2,7 @@ #include <cstdlib> #include <cstring> +#include <cstdint> template <typename L> void @@ -22,9 +23,11 @@ struct S auto fn = [=](void) -> bool { bool mapped; + uintptr_t hostptr = (uintptr_t) ptr; + uintptr_t hostiptr = (uintptr_t) iptr; #pragma omp target map(from:mapped) { - mapped = (ptr != NULL && iptr != NULL); + mapped = (ptr != (int*) hostptr && iptr != (int*) hostiptr); if (mapped) { for (int i = 0; i < len; i++) diff --git a/libgomp/testsuite/libgomp.c++/target-this-3.C b/libgomp/testsuite/libgomp.c++/target-this-3.C index 6049ba8..9865824 100644 --- a/libgomp/testsuite/libgomp.c++/target-this-3.C +++ b/libgomp/testsuite/libgomp.c++/target-this-3.C @@ -2,6 +2,7 @@ #include <stdio.h> #include <string.h> +#include <stdint.h> extern "C" void abort (); struct S @@ -15,12 +16,13 @@ struct S bool set_ptr (int n) { bool mapped; + uintptr_t hostptr = (uintptr_t) ptr; #pragma omp target map(from:mapped) { - if (ptr != NULL) + if (ptr != (int *) hostptr) for (int i = 0; i < ptr_len; i++) ptr[i] = n; - mapped = (ptr != NULL); + mapped = (ptr != (int *) hostptr); } return mapped; } @@ -28,12 +30,13 @@ struct S bool set_refptr (int n) { bool mapped; + uintptr_t hostrefptr = (uintptr_t) refptr; #pragma omp target map(from:mapped) { - if (refptr != NULL) + if (refptr != (int *) hostrefptr) for (int i = 0; i < refptr_len; i++) refptr[i] = n; - mapped = (refptr != NULL); + mapped = (refptr != (int *) hostrefptr); } return mapped; } diff --git a/libgomp/testsuite/libgomp.c++/target-this-4.C b/libgomp/testsuite/libgomp.c++/target-this-4.C index f0237c9..b2a593d 100644 --- a/libgomp/testsuite/libgomp.c++/target-this-4.C +++ b/libgomp/testsuite/libgomp.c++/target-this-4.C @@ -4,6 +4,7 @@ #include <cstdlib> #include <cstring> +#include <cstdint> struct T { @@ -18,12 +19,13 @@ struct T auto fn = [=](void) -> bool { bool mapped; + uintptr_t hostptr = (uintptr_t) ptr; #pragma omp target map(from:mapped) { - if (ptr) + if (ptr != (int *) hostptr) for (int i = 0; i < ptr_len; i++) ptr[i] = n; - mapped = (ptr != NULL); + mapped = (ptr != (int *) hostptr); } return mapped; }; @@ -35,12 +37,13 @@ struct T auto fn = [=](void) -> bool { bool mapped; + uintptr_t hostrefptr = (uintptr_t) refptr; #pragma omp target map(from:mapped) { - if (refptr) + if (refptr != (int *) hostrefptr) for (int i = 0; i < refptr_len; i++) refptr[i] = n; - mapped = (refptr != NULL); + mapped = (refptr != (int *) hostrefptr); } return mapped; }; diff --git a/libgomp/testsuite/libgomp.c-c++-common/baseptrs-1.c b/libgomp/testsuite/libgomp.c-c++-common/baseptrs-1.c new file mode 100644 index 0000000..0736156 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/baseptrs-1.c @@ -0,0 +1,50 @@ +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <stdio.h> + +#define N 32 + +typedef struct { + int x2[10][N]; +} x1type; + +typedef struct { + x1type x1[10]; +} p2type; + +typedef struct { + p2type *p2; +} p1type; + +typedef struct { + p1type *p1; +} x0type; + +typedef struct { + x0type x0[10]; +} p0type; + +int main(int argc, char *argv[]) +{ + p0type *p0; + int k1 = 0, k2 = 0, k3 = 0, n = N; + + p0 = (p0type *) malloc (sizeof *p0); + p0->x0[0].p1 = (p1type *) malloc (sizeof *p0->x0[0].p1); + p0->x0[0].p1->p2 = (p2type *) malloc (sizeof *p0->x0[0].p1->p2); + memset (p0->x0[0].p1->p2, 0, sizeof *p0->x0[0].p1->p2); + +#pragma omp target map(tofrom: p0->x0[k1].p1->p2[k2].x1[k3].x2[4][0:n]) \ + map(to: p0->x0[k1].p1, p0->x0[k1].p1->p2) \ + map(to: p0->x0[k1].p1[0]) + { + for (int i = 0; i < n; i++) + p0->x0[k1].p1->p2[k2].x1[k3].x2[4][i] = i; + } + + for (int i = 0; i < n; i++) + assert (i == p0->x0[k1].p1->p2[k2].x1[k3].x2[4][i]); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/baseptrs-2.c b/libgomp/testsuite/libgomp.c-c++-common/baseptrs-2.c new file mode 100644 index 0000000..e335d7d --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/baseptrs-2.c @@ -0,0 +1,70 @@ +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#define N 32 + +typedef struct { + int arr[N]; + int *ptr; +} sc; + +typedef struct { + sc *c; +} sb; + +typedef struct { + sb *b; + sc *c; +} sa; + +int main (int argc, char *argv[]) +{ + sa *p; + + p = (sa *) malloc (sizeof *p); + p->b = (sb *) malloc (sizeof *p->b); + p->b->c = (sc *) malloc (sizeof *p->b->c); + p->c = (sc *) malloc (sizeof *p->c); + p->b->c->ptr = (int *) malloc (N * sizeof (int)); + p->c->ptr = (int *) malloc (N * sizeof (int)); + + for (int i = 0; i < N; i++) + { + p->b->c->ptr[i] = 0; + p->c->ptr[i] = 0; + p->b->c->arr[i] = 0; + p->c->arr[i] = 0; + } + +#pragma omp target map(to: p->b, p->b[0], p->c, p->c[0], p->b->c, p->b->c[0]) \ + map(to: p->b->c->ptr, p->c->ptr) \ + map(tofrom: p->b->c->ptr[:N], p->c->ptr[:N]) + { + for (int i = 0; i < N; i++) + { + p->b->c->ptr[i] = i; + p->c->ptr[i] = i * 2; + } + } + +#pragma omp target map(to: p->b, p->b[0], p->b->c, p->c) \ + map(tofrom: p->c[0], p->b->c[0]) + { + for (int i = 0; i < N; i++) + { + p->b->c->arr[i] = i * 3; + p->c->arr[i] = i * 4; + } + } + + for (int i = 0; i < N; i++) + { + assert (p->b->c->ptr[i] == i); + assert (p->c->ptr[i] == i * 2); + assert (p->b->c->arr[i] == i * 3); + assert (p->c->arr[i] == i * 4); + } + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/baseptrs-6.c b/libgomp/testsuite/libgomp.c-c++-common/baseptrs-6.c new file mode 100644 index 0000000..4b6e237 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/baseptrs-6.c @@ -0,0 +1,69 @@ +/* { dg-do run } */ + +#include <stdlib.h> +#include <assert.h> + +#define N 1024 +#define M 64 + +int main (void) +{ + int *a[N]; + + for (int i = 0; i < N; i++) + a[i] = (int *) calloc (M, sizeof (int)); + + /* 'target enter data'/'target exit data' with array of pointers. */ +#pragma omp target enter data map(alloc: a[0:N]) + + for (int i = 0; i < N; i++) + { +#pragma omp target enter data map(to: a[i][0:M]) + } + +#pragma omp target map(alloc: a) + { + for (int i = 0; i < N; i++) + for (int j = 0; j < M; j++) + a[i][j] = i + j; + } + +for (int i = 0; i < N; i++) + { +#pragma omp target exit data map(release: a[i]) map(from: a[i][0:M]) + } + +#pragma omp target exit data map(release: a, a[0:N]) + + /* 'target data' with array of pointers. */ +#pragma omp target data map(alloc: a[0:N]) + { +#pragma omp target data map(tofrom: a[5][0:M]) + { +#pragma omp target map(alloc: a) + { + for (int i = 0; i < M; i++) + a[5][i]++; + } + } + } + + /* 'target' with array of pointers. */ +#pragma omp target data map(alloc: a[0:N]) + { +#pragma omp target map(tofrom: a[7][0:M]) + { + for (int i = 0; i < M; i++) + a[7][i] += 2; + } + } + + for (int i = 0; i < N; i++) + for (int j = 0; j < M; j++) + assert (a[i][j] == i + j + (i == 5) + 2 * (i == 7)); + + for (int i = 0; i < N; i++) + free (a[i]); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/baseptrs-7.c b/libgomp/testsuite/libgomp.c-c++-common/baseptrs-7.c new file mode 100644 index 0000000..9c6710e --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/baseptrs-7.c @@ -0,0 +1,56 @@ +/* { dg-do run } */ + +#include <stdlib.h> +#include <assert.h> + +int main (void) +{ + int **a,i,j,n; + + j = 3; + n = 12; + + a = (int **) calloc (32, sizeof (int *)); + for (int x = 0; x < 32; x++) + a[x] = (int *) calloc (32, sizeof (int)); + + for (int i = 2; i < 32; i++) + { + #pragma omp target enter data map(a, a[2:30]) + #pragma omp target enter data map(a[i][j:n]) + #pragma omp target map(alloc: a) + { + for (int x = j; x < j + n; x++) + a[i][x]++; + } + #pragma omp target exit data map(a[i][j:n]) + + #pragma omp target data map(a, a[i][j:n]) + { + #pragma omp target map(alloc: a) + { + for (int x = j; x < j + n; x++) + a[i][x]++; + } + } + #pragma omp target exit data map(a, a[2:30]) + + #pragma omp target data map(a, a[0:32]) + { + #pragma omp target map(a[i][j:n]) + { + for (int x = j; x < j + n; x++) + a[i][x]++; + } + } + } + + for (int i = 0; i < 32; i++) + for (int j = 0; j < 32; j++) + if (i >= 2 && j >= 3 && j < 15) + assert (a[i][j] == 3); + else + assert (a[i][j] == 0); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/ptr-attach-2.c b/libgomp/testsuite/libgomp.c-c++-common/ptr-attach-2.c new file mode 100644 index 0000000..889a4a2 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/ptr-attach-2.c @@ -0,0 +1,60 @@ +#include <stdlib.h> + +struct blk { int x, y; }; +struct L +{ + #define N 10 + struct { + int num_blocks[N]; + struct blk * blocks[N]; + } m; +}; + +void foo (struct L *l) +{ + for (int i = 0; i < N; i++) + { + l->m.blocks[i] = (struct blk *) malloc (sizeof (struct blk) * N); + l->m.num_blocks[i] = N; + } + + #pragma omp target enter data map(to:l[:1]) + for (int i = 0; i < N; i++) + { + #pragma omp target enter data map(to:l->m.blocks[i][:l->m.num_blocks[i]]) + } + + #pragma omp target + { + for (int i = 0; i < N; i++) + for (int j = 0; j < N; j++) + { + l->m.blocks[i][j].x = i + j; + l->m.blocks[i][j].y = i * j; + } + } + + for (int i = 0; i < N; i++) + { + #pragma omp target exit data map(from:l->m.blocks[i][:l->m.num_blocks[i]]) + } + #pragma omp target exit data map(from:l[:1]) + + + for (int i = 0; i < N; i++) + for (int j = 0; j < N; j++) + { + if (l->m.blocks[i][j].x != i + j) + abort (); + if (l->m.blocks[i][j].y != i * j) + abort (); + } + +} + +int main (void) +{ + struct L l; + foo (&l); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-2.c b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-2.c index 974a978..4c49cd0 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-2.c +++ b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-2.c @@ -42,5 +42,7 @@ main (void) #pragma omp target exit data map(from:a.ptr, a.ptr[:N]) + free (a.ptr); + return 0; } diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-5.c b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-5.c new file mode 100644 index 0000000..81a7752 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-5.c @@ -0,0 +1,50 @@ +#include <stdlib.h> + +#define N 10 + +struct S +{ + int a, b; + int *ptr; + int c, d; +}; + +int +main (void) +{ + struct S a; + a.ptr = (int *) malloc (sizeof (int) * N); + + for (int i = 0; i < N; i++) + a.ptr[i] = 0; + + #pragma omp target enter data map(to: a.ptr) + #pragma omp target enter data map(to: a.ptr[:N]) + + #pragma omp target + for (int i = 0; i < N; i++) + a.ptr[i] += 1; + + #pragma omp target update from(a.ptr[:N]) + + for (int i = 0; i < N; i++) + if (a.ptr[i] != 1) + abort (); + + #pragma omp target map(a.ptr[:N]) + for (int i = 0; i < N; i++) + a.ptr[i] += 1; + + #pragma omp target update from(a.ptr[:N]) + + for (int i = 0; i < N; i++) + if (a.ptr[i] != 2) + abort (); + + #pragma omp target exit data map(release: a.ptr[:N]) + #pragma omp target exit data map(release: a.ptr) + + free (a.ptr); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-map-zlas-1.c b/libgomp/testsuite/libgomp.c-c++-common/target-map-zlas-1.c new file mode 100644 index 0000000..1ec0c9a --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/target-map-zlas-1.c @@ -0,0 +1,36 @@ +#include <stdlib.h> + +#define N 10 + +struct S +{ + int a, b; + int *ptr; + int c, d; +}; + +int +main (void) +{ + struct S a; + a.ptr = (int *) malloc (sizeof (int) * N); + + for (int i = 0; i < N; i++) + a.ptr[i] = 0; + + #pragma omp target enter data map(to: a.ptr[:N]) + + #pragma omp target map(a, a.ptr[:0]) + for (int i = 0; i < N; i++) + a.ptr[i] += 1; + + #pragma omp target exit data map(from: a.ptr[:N]) + + for (int i = 0; i < N; i++) + if (a.ptr[i] != 1) + abort (); + + free (a.ptr); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.fortran/struct-elem-map-1.f90 b/libgomp/testsuite/libgomp.fortran/struct-elem-map-1.f90 index 58550c7..7f3d817 100644 --- a/libgomp/testsuite/libgomp.fortran/struct-elem-map-1.f90 +++ b/libgomp/testsuite/libgomp.fortran/struct-elem-map-1.f90 @@ -409,3 +409,6 @@ contains end subroutine eight end program main + +! Fixed by the "Fortran pointers and member mappings" patch +! { dg-xfail-run-if TODO { offload_device_nonshared_as } } diff --git a/libgomp/testsuite/libgomp.fortran/target-enter-data-6.f90 b/libgomp/testsuite/libgomp.fortran/target-enter-data-6.f90 index 80d30ed..b55d0b2 100644 --- a/libgomp/testsuite/libgomp.fortran/target-enter-data-6.f90 +++ b/libgomp/testsuite/libgomp.fortran/target-enter-data-6.f90 @@ -3,6 +3,16 @@ ! - arrays with array descriptors ! For those, the array descriptor / string length must be mapped with 'to:' +! This test fails without the following additional patches: +! +! "OpenMP: Pointers and member mappings": +! https://gcc.gnu.org/pipermail/gcc-patches/2023-August/627898.html +! +! "OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc": +! https://gcc.gnu.org/pipermail/gcc-patches/2023-August/627900.html +! +! { dg-xfail-run-if TODO { offload_device_nonshared_as } } + program main implicit none |