On Wed, Nov 24, 2021 at 06:08:02PM +0100, Marcel Vollweiler wrote: > + case OMP_CLAUSE_HAS_DEVICE_ADDR: > + t = OMP_CLAUSE_DECL (c); > + if (TREE_CODE (t) == TREE_LIST) > + { > + if (handle_omp_array_sections (c, ort)) > + remove = true; > + else > + { > + t = OMP_CLAUSE_DECL (c); > + while (TREE_CODE (t) == ARRAY_REF) > + t = TREE_OPERAND (t, 0); > + } > + } > + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR) > + bitmap_set_bit (&is_on_device_head, DECL_UID (t));
Why the OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR check? There is no goto into this block nor fallthru into it, and handle_omp_array_sections better shouldn't change OMP_CLAUSE_CODE. > goto check_dup_generic; > > + case OMP_CLAUSE_HAS_DEVICE_ADDR: > + t = OMP_CLAUSE_DECL (c); > + if (TREE_CODE (t) == TREE_LIST) > + if (handle_omp_array_sections (c, ort)) > + remove = true; > + else > + { > + t = OMP_CLAUSE_DECL (c); > + while (TREE_CODE (t) == ARRAY_REF) > + t = TREE_OPERAND (t, 0); > + } > + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR) > + bitmap_set_bit (&is_on_device_head, DECL_UID (t)); Likewise. > + if (VAR_P (t) || TREE_CODE (t) == PARM_DECL) > + cxx_mark_addressable (t); > + goto check_dup_generic_t; > + > case OMP_CLAUSE_USE_DEVICE_ADDR: > field_ok = true; > t = OMP_CLAUSE_DECL (c); > --- a/gcc/fortran/gfortran.h > +++ b/gcc/fortran/gfortran.h > @@ -1391,7 +1391,8 @@ enum > OMP_LIST_USE_DEVICE_PTR, > OMP_LIST_USE_DEVICE_ADDR, > OMP_LIST_NONTEMPORAL, > - OMP_LIST_NUM > + OMP_LIST_HAS_DEVICE_ADDR, > + OMP_LIST_NUM /* must be the last */ Capital M and . at the end. > @@ -2077,6 +2078,12 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const > omp_mask mask, > } > break; > case 'h': > + if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR) > + && gfc_match_omp_variable_list > + ("has_device_addr (", > + &c->lists[OMP_LIST_HAS_DEVICE_ADDR], false, NULL, NULL, > + true) == MATCH_YES) Formatting, true should be IMO below &c->lists. > + continue; > if ((mask & OMP_CLAUSE_HINT) > && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint)) > != MATCH_NO) > @@ -2850,7 +2857,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const > omp_mask mask, > if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR) > && gfc_match_omp_variable_list > ("use_device_addr (", > - &c->lists[OMP_LIST_USE_DEVICE_ADDR], false) == MATCH_YES) > + &c->lists[OMP_LIST_USE_DEVICE_ADDR], false, NULL, NULL, > + true) == MATCH_YES) Likewise. > --- a/gcc/fortran/trans-openmp.c > +++ b/gcc/fortran/trans-openmp.c > @@ -1910,7 +1910,17 @@ gfc_trans_omp_variable_list (enum omp_clause_code code, > tree t = gfc_trans_omp_variable (namelist->sym, declare_simd); > if (t != error_mark_node) > { > - tree node = build_omp_clause (input_location, code); > + tree node; > + /* For HAS_DEVICE_ADDR of an array descriptor, firstprivatize the > + descriptor such that the bounds are available; its data component > + is unmodified; it is handled as device address inside target. */ > + if (code == OMP_CLAUSE_HAS_DEVICE_ADDR > + && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (t)) > + || (POINTER_TYPE_P (TREE_TYPE (t)) > + && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (t)))))) > + node = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); Not sure about the above, > --- a/gcc/gimplify.c > +++ b/gcc/gimplify.c > @@ -10024,6 +10024,15 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq > *pre_p, > flags = GOVD_EXPLICIT; > goto do_add; > > + case OMP_CLAUSE_HAS_DEVICE_ADDR: > + decl = OMP_CLAUSE_DECL (c); > + if (TREE_CODE (decl) == ARRAY_REF) > + { > + flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT; > + while (TREE_CODE (decl) == ARRAY_REF) > + decl = TREE_OPERAND (decl, 0); > + goto do_add_decl; but this looks weird. If decl after stripping the ARRAY_REFs is a var with pointer type, sure, firstprivatizing it is the way to go. But it can be also a variable with ARRAY_TYPE, can't it? Something like: int a[64]; #pragma omp target data map(a) use_device_addr(a) { #pragma omp target has_device_addr(a[3:16]) a[3] = 1; } and in this case firstprivatization of a looks wrong. use_device_addr should replace (but only at omp-low.c time I think) a used in the block with the remapped a (i.e. *device_address_of_a). Or perhaps it could be a non-static data member with array type inside of a C++ method. > + case OMP_CLAUSE_HAS_DEVICE_ADDR: > + decl = OMP_CLAUSE_DECL (c); > + if (TREE_CODE (decl) == ARRAY_REF) > + while (TREE_CODE (decl) == ARRAY_REF) > + decl = TREE_OPERAND (decl, 0); Isn't this equivalent to just the while loop without the if? Jakub