Hi Julian,
first round of comments - I think I need a second pass as the patch is
long and complex. The depth of review also was decreasing, hence, I
assume I will spot things in later parts of the compiler.
In any case, I think the patch is a huge leap forward and very useful!
Contrary to previous iterations of the patch series, it looks as if
{1,2}/5 could be sensibly applied before {3,4,5}/5. However, those are
smaller or tiny, it should be way quicker to review them!
* * *
CROSS REFS
This patch is part of the patch set
"[PATCH v7 0/5] OpenMP/OpenACC: map clause and OMP gimplify rework"
https://gcc.gnu.org/pipermail/gcc-patches/2023-August/627895.html
This patch set in turn is required for the follow-up patch set
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/629363.html
'[PATCH 0/8] OpenMP: lvalue parsing and "declare mapper" support'
and it looks as if it would be very useful for some other WIP patches
like map+iterator.
* * *
The patch 1/5 is just an indentation patch to make the following patch
smaller - and it has been approved multiple times.
This patch can be found at
https://gcc.gnu.org/pipermail/gcc-patches/2023-August/627897.html
in case someone wants to read the full patch or Julian's patch-intro
comments.
* * *
I do note that all 5 patches of this patch set apply cleanly with some
fuzzy line matching, but:
WARNING: at least for this patch (2/5), code gets wrongly applied
in (c-)parser.cc - see below.
On 19.08.23 00:47, Julian Brown wrote:
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:
[...]
[As the patch is very large, I copied the interesting bits out of the patch
and comment on them - I hope that preserves enough context to be useful.]
tree c_omp_address_inspector::get_address ()
This class member function is unused. It returns 'orig' and that member variable
is used a couple of times in the member functions - but not this function.
I think it can be removed. (I also find the name slightly misleading.)
* * *
+c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
+{
+ switch (OMP_CLAUSE_MAP_KIND (clause))
+ {
+ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_IF_PRESENT:
+ case GOMP_MAP_TO:
+ case GOMP_MAP_FROM:
+ case GOMP_MAP_TOFROM:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_RELEASE:
+ case GOMP_MAP_DELETE:
+ case GOMP_MAP_FORCE_TO:
+ case GOMP_MAP_FORCE_FROM:
+ case GOMP_MAP_FORCE_TOFROM:
+ case GOMP_MAP_FORCE_PRESENT:
Shouldn't this also include:
GOMP_MAP_ALWAYS_PRESENT_TO:
GOMP_MAP_ALWAYS_PRESENT_FROM:
GOMP_MAP_ALWAYS_PRESENT_TOFROM:
GOMP_MAP_PRESENT_ALLOC:
GOMP_MAP_PRESENT_TO:
?
* * *
+omp_expand_access_chain (tree c, tree expr, vec<omp_addr_token *> &addr_tokens,
+ unsigned *idx)
+{
+ using namespace omp_addr_tokenizer;
+ location_t loc = OMP_CLAUSE_LOCATION (c);
+ unsigned i = *idx;
+ tree c2 = NULL_TREE;
+ gomp_map_kind kind
+ = (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
+ || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM)))
+ ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH;
GOMP_MAP_ALWAYS_PRESENT_FROM missing?
And I personally find it more readable to have
if (...
...
...)
kind = GOMP_MAP_DETACH;
else
kind = GOMP_MAP_ATTACH;
as in the assignment above, the lhs is in this case really far from the rhs.
* * *
I do see in omp_expand_access_chain, which is shared by C and C++, that the
following
accesses are handled:
ACCESS_POINTER,
ACCESS_POINTER_OFFSET,
ACCESS_INDEXED_ARRAY,
But not:
ACCESS_REF_TO_POINTER,
ACCESS_REF_TO_POINTER_OFFSET,
ACCESS_INDEXED_REF_TO_ARRAY
Do those need to be handled as well?
SIDENOTE: As Fortran allocatable components, reference-type variables in a C++
class ('class', 'struct')
are automatically be copied when doing 'map(var)' - contrary to pointer members
that need to be explicitly
be mapped (either at mapping side or via a mapper). (And contrary to Fortran
allocatables, reference-type members
are always "there" - not like with allocatables can change from unallocated to
allocated - with all compilations
of polymorphism, array sizes, string lengths, ...).
* * *
+tree
+c_omp_address_inspector::expand_array_base (tree c,
...
+ bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
+ bool implicit_p = (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_IMPLICIT (c));
...
+ if (!openmp
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
How about using 'map_p' (twice), given that it is already
defined?
...
+ if (target)
+ {
+ c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ if (target
+ && !ref_to_ptr
Remove 'target &&' from the second condition.
* * *
+++ b/gcc/c/c-parser.cc
@@ -17659,7 +17659,8 @@ c_parser_omp_clause_detach (c_parser *parser, tree list)
static tree
c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
- const char *where, bool finish_p = true)
+ const char *where, bool finish_p = true,
+ bool target = false)
Here but also in gcc/c-family/c-omp.cc - I wonder whether this should be
target_p for
consistency with most other boolean variables. The code is not really
consistent,
but given that there is 'finish_p' here and map_p etc. in the other file, it
seems
to make sense to use 'target_p.
* * *
If I try the example at
https://discourse.llvm.org/t/how-do-i-map-an-array-of-pointers-using-array-notation/53640/3
it fails to compile with:
foo.c:11:34: error: ‘#pragma omp target enter data’ with map-type other than
‘to’, ‘tofrom’ or ‘alloc’ on ‘map’ clause
11 | #pragma omp target enter data map(to: a[i][0:1])
The problem is that fuzzy 'patch' mis-apply the patch for c-parser.cc's
@@ -22106,6 +22111,7 @@ c_parser_omp_target_enter_data (location_t loc,
c_parser *parser,
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
case GOMP_MAP_ATTACH_DETACH:
+ case GOMP_MAP_ATTACH:
break;
default:
map_seen |= 1;
@@ -22215,6 +22221,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser
*parser,
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
case GOMP_MAP_ATTACH_DETACH:
+ case GOMP_MAP_DETACH:
break;
default:
map_seen |= 1;
Namely after applying it, the result is:
@@ -23329,0 +23335 @@ c_parser_omp_target_data (location_t loc, c_parser
*parser, bool *if_p)
+ case GOMP_MAP_ATTACH:
@@ -23494,0 +23501 @@ c_parser_omp_target_enter_data (location_t loc, c_parser
*parser,
+ case GOMP_MAP_DETACH:
That is, the new code is added
to c_parser_omp_target_data and c_parser_omp_target_enter_data
instead of
to c_parser_omp_target_enter_data and c_parser_omp_target_exit_data.
* * *
Likewise issue for C++'s cp/parser.cc.
* * *
The first question is whether such code is also needed for 'target' and 'target
data'
besides 'target enter/exit data'. It looks as if omp_expand_access_chain should
also
apply here.
* * *
And trying the following snippet:
void f(){
int **a,i,j,n;
#pragma omp target enter data map(a[i][j:n])
#pragma omp target exit data map(a[i][j:n])
#pragma omp target data map(a[i][j:n])
{
#pragma omp target map(a[i][j:n])
;
}
}
Results - when putting the enums to enter/exit data
instead of to target data / target enter data:
g++ fails, unless I messed up, with:
fiof.c:4:36: error: ‘#pragma omp target exit data’ with map-type other than
‘from’, ‘tofrom’, ‘release’ or ‘delete’ on ‘map’ clause
4 | #pragma omp target exit data map(a[i][j:n])
| ^
fiof.c:5:31: error: ‘#pragma omp target data’ with map-type other than ‘to’,
‘from’, ‘tofrom’ or ‘alloc’ on ‘map’ clause
5 | #pragma omp target data map(a[i][j:n])
And gcc fails with:
fiof.c:3:36: error: ‘a’ appears more than once in map clauses
3 | #pragma omp target enter data map(a[i][j:n])
| ^
fiof.c:4:35: error: ‘a’ appears more than once in map clauses
4 | #pragma omp target exit data map(a[i][j:n])
| ^
fiof.c:5:30: error: ‘a’ appears more than once in map clauses
5 | #pragma omp target data map(a[i][j:n])
| ^
fiof.c:7:25: error: ‘a’ appears more than once in map clauses
7 | #pragma omp target map(a[i][j:n])
(Plus all '... data' ones: '... must contain at least one ...')
Can you fix this - and add an example in the spirit of the LLVM example above,
except that it should test all four 'target' variants.
Thanks,
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