Skip to content

Commit

Permalink
OpenMP: Handle same-directive mapped vars with pointer predefined fir…
Browse files Browse the repository at this point in the history
…stprivate [PR110639]

This patch fixes the issue:

   int a[100];
   p = &a[0];

   #pragma omp target map(a)
     p[0] = p[99] = 3;

where 'p' is predetermined firstprivate, i.e. it is firstprivatized
but its address gets updated to the device address of 'a' as there is
associated storage for the value of 'p', i.e. its pointee.

[This is a C/C++-only feature that cannot be replicated by using a single clause.
('target data map(a) use_device_ptr(p)' + 'target is_device_ptr(p)' would do
so in two steps. - or 'p2 = omp_get_mapped_ptr(p, devnum)' + 'target is_device_ptr(p2)'.)]

Before this only worked when that storage was mapped before and not on the same
directive.

The gimplify_scan_omp_clauses change was done when I saw some runtime fails; I think
those were due to a bug in libgomp (now fixed) and not due to having two pointer
privatisations in a now different order. Still, they at least prevent mapping
'this' multiple times when 'this' is not 'this' but __closure->this which is at least
a missed optimization.  And also for libgomp.c++/pr108286.C which has a normal
'this' and map(tofrom:*this [len: 16]).

Build and tested without offloading and with nvptx offloading.
Comments, remarks, suggestions?

* * *

(I wonder whether our current approach of removing explicit MAP if its
DECL is unsued is the right one if there is any GOVD_MAP_0LEN_ARRAY around
- or even any OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION.)

(See new libgomp.c-c++-common/target-implicit-map-6.c; BTW, I tried:
before '(void) a;' but that only worked with C and not with C++.)

* * *

The other issue in the PR (still to be done) is for code like:

   int a[100];
   p = &a[0];

   #pragma omp target map(a[20:20])  // Map only a[20] to a[40], but p points to &a[0]
     p[20] = p[30] = 3;

where 'p' points to the base address of 'a' but p[0] == a[0] it not actually
mapped. As we currently do not keep track of base pointer, this won't work.
I have not (yet) explored how to best implement this.

* * *

OpenMP Spec:

The first feature is not new, but I have not checked the wording in 4.5 or 5.0;
it might be that older versions only required it to work for storage mapped before
the current taget directive. But at least TR12 is very explicit in permitting it
and the (nonpublic) issue which lead to the 5.1 change also uses this. (See PR.)
(The second feature is definitely new in OpenMP 5.1.)

TR12 states in "14.8 target Construct" [379:8-10]:

"[C/C++] If a list item in a map clause has a base pointer that is predetermined firstprivate
(see Section 6.1.1) and on entry to the target region the list item is mapped, the firstprivate
pointer is updated via corresponding base pointer initialization."

(For OpenMP 5.1, read its Section 2.21.7.2.)

Tobias
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

OpenMP: Handle same-directive mapped vars with pointer predefined firstprivate [PR110639]

Predefined 'firstprivate' for pointer variables firstprivatizes the pointer
but if it is associated with a mapped target, its address is updated to the
corresponding target. (If not, the host value remains.)

This commit extends this handling to also update the pointer address for
storaged mapped on the same directive.

The 'gimplify_scan_omp_clauses' change avoids adding an additional
  map(alloc:this) (+ptr assignment)
when there is already a
  map(tofrom:*this) (+ptr assignment)
This shows up for libgomp.c++/pr108286.C and also when 'this' is
actually '__closure->this' (-> g++.dg/gomp/target-{this-{2,4},lambda-1}.C).

	PR middle-end/110639

gcc/ChangeLog:

	* gimplify.cc (struct gimplify_adjust_omp_clauses_data): Add
	append_list.
	(gimplify_adjust_omp_clauses_1, gimplify_adjust_omp_clauses): Add
	GOVD_MAP_0LEN_ARRAY clauses at the end.
	(gimplify_scan_omp_clauses): Mark also '*var' as found not only
	'var'.

libgomp/ChangeLog:

	* target.c (gomp_map_vars_internal): Handle also variables
	mapped in the same directive for GOVD_MAP_0LEN_ARRAY.
	* testsuite/libgomp.c++/pr108286.C: Add gimple tree-scan test.
	* testsuite/libgomp.c-c++-common/target-implicit-map-6.c: New test.

gcc/testsuite/ChangeLog:

        * g++.dg/gomp/target-this-2.C: Remove 'this' pointer mapping alreay
	mapped via __closure->this.
        * g++.dg/gomp/target-this-4.C: Likewise.
        * g++.dg/gomp/target-lambda-1.C: Likewise. Move 'iptr' pointer
	mapping to the end in scan-tree-dump.

 gcc/gimplify.cc                                    |  45 ++++-
 gcc/testsuite/g++.dg/gomp/target-lambda-1.C        |   4 +-
 gcc/testsuite/g++.dg/gomp/target-this-2.C          |   4 +-
 gcc/testsuite/g++.dg/gomp/target-this-4.C          |   6 +-
 libgomp/target.c                                   |  11 +-
 libgomp/testsuite/libgomp.c++/pr108286.C           |   4 +
 .../libgomp.c-c++-common/target-implicit-map-6.c   | 212 +++++++++++++++++++++
 7 files changed, 276 insertions(+), 10 deletions(-)
  • Loading branch information
tob2 authored and ouuleilei-bot committed Dec 13, 2023
1 parent c2d62cd commit 2e3c468
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 10 deletions.
45 changes: 40 additions & 5 deletions gcc/gimplify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11266,6 +11266,23 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
else if (!DECL_P (decl))
{
tree d = decl, *pd;
pd = &OMP_CLAUSE_DECL (c);
if (TREE_CODE (decl) == INDIRECT_REF)
{
tree d2 = TREE_OPERAND (decl, 0);
STRIP_NOPS (d2);
if (DECL_P (d2))
{
if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue,
fb_lvalue) == GS_ERROR)
{
remove = true;
break;
}
decl = d2;
goto handle_map_decl;
}
}
if (TREE_CODE (d) == ARRAY_REF)
{
while (TREE_CODE (d) == ARRAY_REF)
Expand All @@ -11274,7 +11291,6 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
&& TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
decl = d;
}
pd = &OMP_CLAUSE_DECL (c);
if (d == decl
&& TREE_CODE (decl) == INDIRECT_REF
&& TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
Expand Down Expand Up @@ -11469,6 +11485,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,

break;
}
handle_map_decl:
flags = GOVD_MAP | GOVD_EXPLICIT;
if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
|| OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
Expand Down Expand Up @@ -11501,7 +11518,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
}

goto do_add;
goto do_add_decl;

case OMP_CLAUSE_AFFINITY:
gimplify_omp_affinity (list_p, pre_p);
Expand Down Expand Up @@ -12261,6 +12278,7 @@ omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
struct gimplify_adjust_omp_clauses_data
{
tree *list_p;
tree append_list;
gimple_seq *pre_p;
};

Expand Down Expand Up @@ -12381,6 +12399,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);

bool len0_append_list_used = false;
tree chain = *list_p;
clause = build_omp_clause (input_location, code);
OMP_CLAUSE_DECL (clause) = decl;
Expand All @@ -12397,6 +12416,11 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clause) = 1;
else if (code == OMP_CLAUSE_MAP && (flags & GOVD_MAP_0LEN_ARRAY) != 0)
{
/* For GOVD_MAP_0LEN_ARRAY, add the clauses to append_list such
that those come after any data mapping. */
len0_append_list_used = true;
struct gimplify_adjust_omp_clauses_data *adjdata
= (struct gimplify_adjust_omp_clauses_data *) data;
tree nc = build_omp_clause (input_location, OMP_CLAUSE_MAP);
OMP_CLAUSE_DECL (nc) = decl;
if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
Expand All @@ -12411,8 +12435,9 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_ALLOC);
OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (clause) = 1;
OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
OMP_CLAUSE_CHAIN (nc) = chain;
OMP_CLAUSE_CHAIN (nc) = adjdata->append_list;
OMP_CLAUSE_CHAIN (clause) = nc;
adjdata->append_list = clause;
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
gimplify_omp_ctxp = ctx->outer_context;
gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0),
Expand Down Expand Up @@ -12520,7 +12545,8 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
(ctx->region_type & ORT_ACC) != 0);
gimplify_omp_ctxp = ctx;
}
*list_p = clause;
if (!len0_append_list_used)
*list_p = clause;
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
gimplify_omp_ctxp = ctx->outer_context;
/* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
Expand All @@ -12529,7 +12555,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
lang_hooks.decls.omp_finish_clause (clause, pre_p,
(ctx->region_type & ORT_ACC) != 0);
if (gimplify_omp_ctxp)
if (gimplify_omp_ctxp && !len0_append_list_used)
for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
&& DECL_P (OMP_CLAUSE_SIZE (clause)))
Expand Down Expand Up @@ -13120,6 +13146,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,

/* Add in any implicit data sharing. */
struct gimplify_adjust_omp_clauses_data data;
data.append_list = NULL;
if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
{
/* OpenMP. Implicit clauses are added at the start of the clause list,
Expand Down Expand Up @@ -13147,6 +13174,14 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
"iterator");
break;
}
if (data.append_list != NULL_TREE && *data.list_p != NULL_TREE)
{
for (c = *data.list_p; c && OMP_CLAUSE_CHAIN (c); c = OMP_CLAUSE_CHAIN (c))
;
OMP_CLAUSE_CHAIN (c) = data.append_list;
}
else if (data.append_list != NULL_TREE)
*data.list_p = data.append_list;

gimplify_omp_ctxp = ctx->outer_context;
delete_omp_context (ctx);
Expand Down
4 changes: 3 additions & 1 deletion gcc/testsuite/g++.dg/gomp/target-lambda-1.C
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ int main (void)
return 0;
}

/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(b\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:iptr \[pointer assign, bias: 0\]\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(attach_zero_length_array_section:__closure->__iptr \[bias: 0\]\) map\(attach_zero_length_array_section:_[0-9]+->ptr \[bias: 0\]\)} "gimple" } } */
/* Note that 'this' = '__closure->__this' such that no pointer-assign for 'this' should appear. */

/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(b\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(attach_zero_length_array_section:__closure->__iptr \[bias: 0\]\) map\(attach_zero_length_array_section:_[0-9]+->ptr \[bias: 0\]\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:iptr \[pointer assign, bias: 0\]\)[\r\n]} "gimple" } } */

/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(end\) firstprivate\(begin\) map\(to:loop \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(attach_zero_length_array_section:loop\.__data1 \[bias: 0\]\)} "gimple" } } */

Expand Down
4 changes: 3 additions & 1 deletion gcc/testsuite/g++.dg/gomp/target-this-2.C
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ int main (void)
return 0;
}

/* { dg-final { scan-tree-dump {map\(alloc:MEM\[\(char \*\)_[0-9]+\] \[len: [0-9]+\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) firstprivate\(m\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:v \[len: [0-9]+\]\)} "gimple" } } */
/* Note that 'this' = '__closure->__this' such that no pointer-assign for 'this' should appear. */

/* { dg-final { scan-tree-dump {firstprivate\(n\) firstprivate\(m\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:v \[len: [0-9]+\]\)[\r\n]} "gimple" } } */
6 changes: 4 additions & 2 deletions gcc/testsuite/g++.dg/gomp/target-this-4.C
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ int main (void)
return 0;
}

/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(n\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:mapped \[len: 1\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(attach_zero_length_array_section:_[0-9]+->ptr \[bias: 0\]\)} "gimple" } } */
/* Note that 'this' = '__closure->__this' such that no pointer-assign for 'this' should appear. */

/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(n\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(alloc:\*_[0-9]+ \[pointer assign, zero-length array section, bias: 0\]\) map\(attach:_[0-9]+->refptr \[bias: 0\]\)} "gimple" } } */
/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(n\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:mapped \[len: 1\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(attach_zero_length_array_section:_[0-9]+->ptr \[bias: 0\]\)[\r\n]} "gimple" } } */

/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* firstprivate\(n\) map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(alloc:\*_[0-9]+ \[pointer assign, zero-length array section, bias: 0\]\) map\(attach:_[0-9]+->refptr \[bias: 0\]\)[\r\n]} "gimple" } } */
11 changes: 10 additions & 1 deletion libgomp/target.c
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,8 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
splay_tree_key n;
if ((kind & typemask) == GOMP_MAP_ZERO_LEN_ARRAY_SECTION)
{
n = gomp_map_0len_lookup (mem_map, &cur_node);
/* Defer lookup when mapped item found. */
n = not_found_cnt ? NULL : gomp_map_0len_lookup (mem_map, &cur_node);
if (!n)
{
tgt->list[i].key = NULL;
Expand Down Expand Up @@ -1407,7 +1408,15 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
}
continue;
case GOMP_MAP_FIRSTPRIVATE_INT:
continue;
case GOMP_MAP_ZERO_LEN_ARRAY_SECTION:
cur_node.host_start = (uintptr_t) hostaddrs[i];
cur_node.host_end = cur_node.host_start + sizes[i];
n = gomp_map_0len_lookup (mem_map, &cur_node);
if (n)
gomp_map_vars_existing (devicep, aq, n, &cur_node,
&tgt->list[i], kind & typemask, false,
implicit, NULL, refcount_set);
continue;
case GOMP_MAP_USE_DEVICE_PTR_IF_PRESENT:
/* The OpenACC 'host_data' construct only allows 'use_device'
Expand Down
4 changes: 4 additions & 0 deletions libgomp/testsuite/libgomp.c++/pr108286.C
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// PR c++/108286
// { dg-do run }
// { dg-additional-options "-fdump-tree-gimple" }

struct S {
int
Expand Down Expand Up @@ -27,3 +28,6 @@ main ()
if (s.foo () != 42)
__builtin_abort ();
}

/* Ensure that 'this' is mapped but only once and not additionally via 'this[:0]'. */
/* { dg-final { scan-tree-dump "#pragma omp target num_teams\\(-2\\) thread_limit\\(0\\) map\\(tofrom:\\*this \\\[len: \[0-9\]+\\\]\\) map\\(firstprivate:this \\\[pointer assign, bias: 0\\\]\\) nowait map\\(tofrom:res \\\[len: \[0-9\]+\\\]\\) map\\(tofrom:\\*_\[0-9\]+ \\\[len: _\[0-9\]+\\\]\\) map\\(attach:this->ptr \\\[bias: 0\\\]\\)\[\r\n\]" "gimple" } } */
Loading

0 comments on commit 2e3c468

Please sign in to comment.