On 5/14/21 11:26 PM, Julian Brown wrote:
> This patch reworks indirect struct handling in gimplify.c (i.e. for struct
> components mapped with "mystruct->a[0:n]", "mystruct->b", etc.), for
> both OpenACC and OpenMP.  The key observation leading to these changes
> was that component mappings of references-to-structures is already
> implemented and working, and indirect struct component handling via a
> pointer can work quite similarly.  That lets us remove some earlier,
> special-case handling for mapping indirect struct component accesses
> for OpenACC, which required the pointed-to struct to be manually mapped
> before the indirect component mapping.
> 
> With this patch, you can map struct components directly (e.g. an array
> slice "mystruct->a[0:n]") just like you can map a non-indirect struct
> component slice ("mystruct.a[0:n]"). Both references-to-pointers (with
> the former syntax) and references to structs (with the latter syntax)
> work now.
> 
> For Fortran class pointers, we no longer re-use GOMP_MAP_TO_PSET for the
> class metadata (the structure that points to the class data and vptr)
> -- it is instead treated as any other struct.
> 
> For C++, the struct handling also works for class members ("this->foo"),
> without having to explicitly map "this[:1]" first.
> 
> For OpenACC, we permit chained indirect component references
> ("mystruct->a->b[0:n]"), though only the last part of such mappings will
> trigger an attach/detach operation.  To properly use such a construct
> on the target, you must still manually map "mystruct->a[:1]" first --
> but there's no need to map "mystruct[:1]" explicitly before that.
> 
> This patch incorporates parts of Chung-Lin's patch "Recommit "Enable
> gimplify GOMP_MAP_STRUCT handling of (COMPONENT_REF (INDIRECT_REF
> ...)) map clauses"." from the og10 branch.
> 
> OK for trunk?
> 
> Thanks,
> 
> Julian
> 
> 2021-05-14  Julian Brown  <jul...@codesourcery.com>
>           Chung-Lin Tang  <clt...@codesourcery.com>
> 
> gcc/fortran/
>       * trans-openmp.c (gfc_trans_omp_clauses): Don't create GOMP_MAP_TO_PSET
>       mappings for class metadata, nor GOMP_MAP_POINTER mappings for
>       POINTER_TYPE_P decls.
> 
> gcc/
>       * gimplify.c (tree-hash-traits.h): Include.
>       (extract_base_bit_offset): Add BASE_IND parameter.  Handle
>       pointer-typed indirect references alongside reference-typed ones.
>       (strip_components_and_deref, aggregate_base_p): New functions.
>       (build_struct_group): Update struct_map_to_clause type.  Add pointer
>       type indirect ref handling, including chained references.  Handle
>       pointers and references to structs in OpenACC regions as well as
>       OpenMP ones.
>       (gimplify_scan_omp_clauses): Remove struct_deref_set handling.  Rework
>       pointer-type indirect structure access handling to work more like
>       the reference-typed handling.
>       * omp-low.c (scan_sharing_clauses): Handle pointer-type indirect struct
>       references, and references to pointers to structs also.
> 
> gcc/testsuite/
>       * g++.dg/goacc/member-array-acc.C: New test (XFAILed for now).
>       * g++.dg/gomp/member-array-omp.C: New test (XFAILed for now).
> 
> libgomp/
>       * testsuite/libgomp.oacc-c-c++-common/deep-copy-15.c: New test.
>       * testsuite/libgomp.oacc-c-c++-common/deep-copy-16.c: New test.
>       * testsuite/libgomp.oacc-c++/deep-copy-17.C: New test.
> ---
>  gcc/fortran/trans-openmp.c                    |  20 +-
>  gcc/gimplify.c                                | 285 ++++++++++--------
>  gcc/omp-low.c                                 |  16 +-
>  gcc/testsuite/g++.dg/goacc/member-array-acc.C |  14 +
>  gcc/testsuite/g++.dg/gomp/member-array-omp.C  |  14 +
>  .../testsuite/libgomp.oacc-c++/deep-copy-17.C | 101 +++++++
>  .../libgomp.oacc-c-c++-common/deep-copy-15.c  |  71 +++++
>  .../libgomp.oacc-c-c++-common/deep-copy-16.c  | 231 ++++++++++++++
>  8 files changed, 612 insertions(+), 140 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/goacc/member-array-acc.C
>  create mode 100644 gcc/testsuite/g++.dg/gomp/member-array-omp.C
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c++/deep-copy-17.C
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/deep-copy-15.c
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/deep-copy-16.c
> 
> diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
> index 5666cd68c7e..ff614ffe744 100644
> --- a/gcc/fortran/trans-openmp.c
> +++ b/gcc/fortran/trans-openmp.c
> @@ -2721,30 +2721,16 @@ gfc_trans_omp_clauses (stmtblock_t *block, 
> gfc_omp_clauses *clauses,
>                 tree present = gfc_omp_check_optional_argument (decl, true);
>                 if (openacc && n->sym->ts.type == BT_CLASS)
>                   {
> -                   tree type = TREE_TYPE (decl);
>                     if (n->sym->attr.optional)
>                       sorry ("optional class parameter");
> -                   if (POINTER_TYPE_P (type))
> -                     {
> -                       node4 = build_omp_clause (input_location,
> -                                                 OMP_CLAUSE_MAP);
> -                       OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
> -                       OMP_CLAUSE_DECL (node4) = decl;
> -                       OMP_CLAUSE_SIZE (node4) = size_int (0);
> -                       decl = build_fold_indirect_ref (decl);
> -                     }
>                     tree ptr = gfc_class_data_get (decl);
>                     ptr = build_fold_indirect_ref (ptr);
>                     OMP_CLAUSE_DECL (node) = ptr;
>                     OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl);
>                     node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
> -                   OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
> -                   OMP_CLAUSE_DECL (node2) = decl;
> -                   OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
> -                   node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
> -                   OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH_DETACH);
> -                   OMP_CLAUSE_DECL (node3) = gfc_class_data_get (decl);
> -                   OMP_CLAUSE_SIZE (node3) = size_int (0);
> +                   OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH);
> +                   OMP_CLAUSE_DECL (node2) = gfc_class_data_get (decl);
> +                   OMP_CLAUSE_SIZE (node2) = size_int (0);
>                     goto finalize_map_clause;
>                   }
>                 else if (POINTER_TYPE_P (TREE_TYPE (decl))
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index 69ab637367c..c0f068a725d 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "langhooks.h"
>  #include "tree-cfg.h"
>  #include "tree-ssa.h"
> +#include "tree-hash-traits.h"
>  #include "omp-general.h"
>  #include "omp-low.h"
>  #include "gimple-low.h"
> @@ -8351,8 +8352,8 @@ build_struct_comp_nodes (enum tree_code code, tree 
> grp_start, tree grp_end,
>     has array type, else return NULL.  */
>  
>  static tree
> -extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
> -                      poly_offset_int *poffsetp)
> +extract_base_bit_offset (tree base, tree *base_ind, tree *base_ref,
> +                      poly_int64 *bitposp, poly_offset_int *poffsetp)
>  {
>    tree offset;
>    poly_int64 bitsize, bitpos;
> @@ -8360,6 +8361,9 @@ extract_base_bit_offset (tree base, tree *base_ref, 
> poly_int64 *bitposp,
>    int unsignedp, reversep, volatilep = 0;
>    poly_offset_int poffset;
>  
> +  if (base_ind)
> +    *base_ind = NULL_TREE;
> +
>    if (base_ref)
>      *base_ref = NULL_TREE;
>  
> @@ -8380,14 +8384,27 @@ extract_base_bit_offset (tree base, tree *base_ref, 
> poly_int64 *bitposp,
>    base = get_inner_reference (base, &bitsize, &bitpos, &offset, &mode,
>                             &unsignedp, &reversep, &volatilep);
>  
> -  tree orig_base = base;
> -
> +  if ((TREE_CODE (base) == INDIRECT_REF
> +       || (TREE_CODE (base) == MEM_REF
> +        && integer_zerop (TREE_OPERAND (base, 1))))
> +      && TREE_CODE (TREE_TYPE (TREE_OPERAND (base, 0))) == POINTER_TYPE)
> +    {
> +      if (base_ind)
> +     *base_ind = base;
> +      base = TREE_OPERAND (base, 0);
> +    }
>    if ((TREE_CODE (base) == INDIRECT_REF
>         || (TREE_CODE (base) == MEM_REF
>          && integer_zerop (TREE_OPERAND (base, 1))))
>        && DECL_P (TREE_OPERAND (base, 0))
>        && TREE_CODE (TREE_TYPE (TREE_OPERAND (base, 0))) == REFERENCE_TYPE)
> -    base = TREE_OPERAND (base, 0);
> +    {
> +      if (base_ref)
> +     *base_ref = base;
> +      base = TREE_OPERAND (base, 0);
> +    }
> +
> +  STRIP_NOPS (base);
>  
>    gcc_assert (offset == NULL_TREE || poly_int_tree_p (offset));
>  
> @@ -8402,10 +8419,6 @@ extract_base_bit_offset (tree base, tree *base_ref, 
> poly_int64 *bitposp,
>    *bitposp = bitpos;
>    *poffsetp = poffset;
>  
> -  /* Set *BASE_REF if BASE was a dereferenced reference variable.  */
> -  if (base_ref && orig_base != base)
> -    *base_ref = orig_base;
> -
>    return base;
>  }
>  
> @@ -8422,6 +8435,48 @@ is_or_contains_p (tree expr, tree base_ptr)
>    return expr == base_ptr;
>  }
>  
> +/* Remove COMPONENT_REFS and indirections from EXPR.  */
> +
> +static tree
> +strip_components_and_deref (tree expr)
> +{
> +  while (TREE_CODE (expr) == COMPONENT_REF
> +      || TREE_CODE (expr) == INDIRECT_REF
> +      || (TREE_CODE (expr) == MEM_REF
> +          && integer_zerop (TREE_OPERAND (expr, 1))))
> +    expr = TREE_OPERAND (expr, 0);
> +
> +  return expr;
> +}
> +
> +/* Return TRUE if EXPR is something we will use as the base of an aggregate
> +   access, either:
> +
> +  - a DECL_P.
> +  - a struct component with no indirection ("a.b.c").
> +  - a struct component with indirection ("a->b->c").
> +*/
> +
> +static bool
> +aggregate_base_p (tree expr)
> +{
> +  while (TREE_CODE (expr) == COMPONENT_REF
> +      && (DECL_P (TREE_OPERAND (expr, 0))
> +          || (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF)))
> +    expr = TREE_OPERAND (expr, 0);
> +
> +  if (DECL_P (expr))
> +    return true;
> +
> +  if (TREE_CODE (expr) == COMPONENT_REF
> +      && (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF
> +       || (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF
> +           && integer_zerop (TREE_OPERAND (TREE_OPERAND (expr, 0), 1)))))
> +    return true;
> +
> +  return false;
> +}
> +
>  /* Implement OpenMP 5.x map ordering rules for target directives. There are
>     several rules, and with some level of ambiguity, hopefully we can at least
>     collect the complexity here in one place.  */
> @@ -8715,19 +8770,26 @@ static tree
>  build_struct_group (struct gimplify_omp_ctx *ctx,
>                   enum omp_region_type region_type, enum tree_code code,
>                   tree decl, unsigned int *flags, tree c,
> -                 hash_map<tree, tree> *&struct_map_to_clause,
> +                 hash_map<tree_operand_hash, tree> *&struct_map_to_clause,
>                   tree *&prev_list_p, tree *&list_p, bool *cont)
>  {
>    poly_offset_int coffset;
>    poly_int64 cbitpos;
> -  tree base_ref;
> +  tree base_ind, base_ref;
> +  tree *list_in_p = list_p, *prev_list_in_p = prev_list_p;
>  

Is this a kind of debug code?
This fails to compile:

../../gcc-trunk/gcc/gimplify.c: In function ‘tree_node* 
build_struct_group(gimplify_omp_ctx*, omp_region_type, tree_code, tree, 
unsigned int*, tree, hash_map<tree_operand_hash, tree_node*>*&, tree_node**&, 
tree_node**&, bool*)’:
../../gcc-trunk/gcc/gimplify.c:8779:9: error: unused variable ‘list_in_p’ 
[-Werror=unused-variable]
 8779 |   tree *list_in_p = list_p, *prev_list_in_p = prev_list_p;
      |         ^~~~~~~~~
../../gcc-trunk/gcc/gimplify.c:8779:30: error: unused variable ‘prev_list_in_p’ 
[-Werror=unused-variable]
 8779 |   tree *list_in_p = list_p, *prev_list_in_p = prev_list_p;
      |                              ^~~~~~~~~~~~~~


You need to boot-strap and do your regression testing before sending
a patch to this list.


Thanks
Bernd.

Reply via email to