public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Thomas Schwinge <thomas@codesourcery.com>
To: Julian Brown <julian@codesourcery.com>
Cc: <jakub@redhat.com>, <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH 3/4] Factor out duplicate code in gimplify_scan_omp_clauses
Date: Wed, 16 Oct 2019 14:43:00 -0000	[thread overview]
Message-ID: <87o8ygwy4k.fsf@euler.schwinge.homeip.net> (raw)
In-Reply-To: <20191006223237.81842-4-julian@codesourcery.com>

[-- Attachment #1: Type: text/plain, Size: 16196 bytes --]

Hi Julian!

On 2019-10-06T15:32:36-0700, Julian Brown <julian@codesourcery.com> wrote:
> This patch factors out some code in gimplify_scan_omp_clauses into two
> new outlined functions.

Yay for such simplification, and yay for documenting what's going on!

> Previously approved here:
>
>   https://gcc.gnu.org/ml/gcc-patches/2018-12/msg01309.html
>
> FAOD, OK for trunk?

I have not reviewed whether it's a suitable refactoring; I'm not at all
familiar with that code.

I started to "functionally" review it by re-inlining your outlined code,
and checking the differences to the original code.  Additionally to the
'gcc_assert' item I just raised with Jakub, there are a few more things I
don't understand:

> 	gcc/
> 	* gimplify.c (insert_struct_comp_map, check_base_and_compare_lt): New.
> 	(gimplify_scan_omp_clauses): Outline duplicated code into calls to
> 	above two functions.
> ---
>  gcc/gimplify.c | 307 ++++++++++++++++++++++++++++---------------------
>  1 file changed, 174 insertions(+), 133 deletions(-)

> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -8120,6 +8120,160 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
>    return 1;
>  }
>  
> +/* Insert a GOMP_MAP_ALLOC or GOMP_MAP_RELEASE node following a
> +   GOMP_MAP_STRUCT mapping.  C is an always_pointer mapping.  STRUCT_NODE is
> +   the struct node to insert the new mapping after (when the struct node is
> +   initially created).  PREV_NODE is the first of two or three mappings for a
> +   pointer, and is either:
> +     - the node before C, when a pair of mappings is used, e.g. for a C/C++
> +       array section.
> +     - not the node before C.  This is true when we have a reference-to-pointer
> +       type (with a mapping for the reference and for the pointer), or for
> +       Fortran derived-type mappings with a GOMP_MAP_TO_PSET.
> +   If SCP is non-null, the new node is inserted before *SCP.
> +   if SCP is null, the new node is inserted before PREV_NODE.
> +   The return type is:
> +     - PREV_NODE, if SCP is non-null.
> +     - The newly-created ALLOC or RELEASE node, if SCP is null.
> +     - The second newly-created ALLOC or RELEASE node, if we are mapping a
> +       reference to a pointer.  */
> +
> +static tree
> +insert_struct_comp_map (enum tree_code code, tree c, tree struct_node,
> +			tree prev_node, tree *scp)
> +{
> +  enum gomp_map_kind mkind
> +    = ((code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
> +       ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC);

The original code does not handle 'OACC_EXIT_DATA', so that will be a
change separate from this refactoring?

> +
> +  tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
> +  tree cl = scp ? prev_node : c2;
> +  OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
> +  OMP_CLAUSE_DECL (c2) = unshare_expr (OMP_CLAUSE_DECL (c));
> +  OMP_CLAUSE_CHAIN (c2) = scp ? *scp : prev_node;
> +  OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node);
> +  if (struct_node)
> +    OMP_CLAUSE_CHAIN (struct_node) = c2;
> +
> +  /* We might need to create an additional mapping if we have a reference to a
> +     pointer (in C++).  Don't do this if we have something other than a
> +     GOMP_MAP_ALWAYS_POINTER though, i.e. a GOMP_MAP_TO_PSET.  */
> +  if (OMP_CLAUSE_CHAIN (prev_node) != c
> +      && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (prev_node)) == OMP_CLAUSE_MAP
> +      && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (prev_node))
> +	  == GOMP_MAP_ALWAYS_POINTER))

In the original code, and with 'prev_node' being '*prev_list_p', this
condition was just 'if (OMP_CLAUSE_CHAIN (*prev_list_p) != c)', without
the 'GOMP_MAP_ALWAYS_POINTER' handling, so that'd be another change
separate from this refactoring?

> +    {
> +      tree c4 = OMP_CLAUSE_CHAIN (prev_node);
> +      tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
> +      OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
> +      OMP_CLAUSE_DECL (c3) = unshare_expr (OMP_CLAUSE_DECL (c4));
> +      OMP_CLAUSE_SIZE (c3) = TYPE_SIZE_UNIT (ptr_type_node);
> +      OMP_CLAUSE_CHAIN (c3) = prev_node;
> +      if (!scp)
> +	OMP_CLAUSE_CHAIN (c2) = c3;
> +      else
> +	cl = c3;
> +    }
> +
> +  if (scp)
> +    *scp = c2;
> +
> +  return cl;
> +}
> +
> +/* Called initially with ORIG_BASE non-null, sets PREV_BITPOS and PREV_POFFSET
> +   to the offset of the field given in BASE.  Return type is 1 if BASE is equal
> +   to *ORIG_BASE after stripping off ARRAY_REF and INDIRECT_REF nodes and
> +   calling get_inner_reference, else 0.
> +
> +   Called subsequently with ORIG_BASE null, compares the offset of the field
> +   given in BASE to PREV_BITPOS, PREV_POFFSET. Returns -1 if the base object
> +   has changed, 0 if the new value has a higher bit position than that
> +   described by the aforementioned arguments, or 1 if the new value is less
> +   than them.  Used for (insertion) sorting components after a GOMP_MAP_STRUCT
> +   mapping.  */

Hmm, that doesn't seem to be the most intuitive API: the 'orig_base'
handling, specifically.  (See my struggle below.)

> +
> +static int
> +check_base_and_compare_lt (tree base, tree *orig_base, tree decl,
> +			   poly_int64 *prev_bitpos,
> +			   poly_offset_int *prev_poffset)
> +{
> +  tree offset;
> +  poly_int64 bitsize, bitpos;
> +  machine_mode mode;
> +  int unsignedp, reversep, volatilep = 0;
> +  poly_offset_int poffset;
> +
> +  if (orig_base)
> +    {
> +      while (TREE_CODE (base) == ARRAY_REF)
> +	base = TREE_OPERAND (base, 0);
> +
> +      if (TREE_CODE (base) == INDIRECT_REF)
> +	base = TREE_OPERAND (base, 0);
> +    }
> +  else
> +    {
> +      if (TREE_CODE (base) == ARRAY_REF)
> +	{
> +	  while (TREE_CODE (base) == ARRAY_REF)
> +	    base = TREE_OPERAND (base, 0);
> +	  if (TREE_CODE (base) != COMPONENT_REF
> +	      || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
> +	    return -1;
> +	}
> +      else if (TREE_CODE (base) == INDIRECT_REF
> +	       && TREE_CODE (TREE_OPERAND (base, 0)) == COMPONENT_REF
> +	       && (TREE_CODE (TREE_TYPE (TREE_OPERAND (base, 0)))
> +		   == REFERENCE_TYPE))
> +	base = TREE_OPERAND (base, 0);
> +    }
> +
> +  base = get_inner_reference (base, &bitsize, &bitpos, &offset, &mode,
> +			      &unsignedp, &reversep, &volatilep);
> +
> +  if (orig_base)
> +    *orig_base = base;
> +
> +  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);
> +
> +  gcc_assert (offset == NULL_TREE || poly_int_tree_p (offset));
> +
> +  if (offset)
> +    poffset = wi::to_poly_offset (offset);
> +  else
> +    poffset = 0;
> +
> +  if (maybe_ne (bitpos, 0))
> +    poffset += bits_to_bytes_round_down (bitpos);
> +

I find the block of code following below until the end of the function a
bit unwieldy to (a) understand, and (b) relate to the original code:

> +  if (orig_base)
> +    {
> +      gcc_assert (base == decl);
> +
> +      *prev_bitpos = bitpos;
> +      *prev_poffset = poffset;
> +
> +      return *orig_base == base;
> +    }
> +  else
> +    {
> +      if (base != decl)
> +	return -1;
> +
> +      return (maybe_lt (*prev_poffset, poffset)
> +	      || (known_eq (*prev_poffset, poffset)
> +		  && maybe_lt (*prev_bitpos, bitpos)));
> +    }
> +
> +  return 0;
> +}

Can this be done differently, to make it easier to understand?  For
example, would it help if that code was not outlined into
'insert_struct_comp_map', but kept in its original places?  At least on
first sight that seemsa reasonable thing to do, given that it's just two
separate variants/code paths (as guarded by 'if (orig_base)'), where the
first of two calls takes the first branch ('orig_base' supplied), and the
other caller takes the second branch ('orig_base' not supplied).  If you
tell me that's not feasible, then I shall again try to understand that
code in the form you've proposed.


Grüße
 Thomas


> @@ -8660,29 +8814,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
>  			}
>  		    }
>  
> -		  tree offset;
> -		  poly_int64 bitsize, bitpos;
> -		  machine_mode mode;
> -		  int unsignedp, reversep, volatilep = 0;
> -		  tree base = OMP_CLAUSE_DECL (c);
> -		  while (TREE_CODE (base) == ARRAY_REF)
> -		    base = TREE_OPERAND (base, 0);
> -		  if (TREE_CODE (base) == INDIRECT_REF)
> -		    base = TREE_OPERAND (base, 0);
> -		  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))))
> -		      && DECL_P (TREE_OPERAND (base, 0))
> -		      && (TREE_CODE (TREE_TYPE (TREE_OPERAND (base, 0)))
> -			  == REFERENCE_TYPE))
> -		    base = TREE_OPERAND (base, 0);
> -		  gcc_assert (base == decl
> -			      && (offset == NULL_TREE
> -				  || poly_int_tree_p (offset)));
> +		  tree orig_base;
> +		  poly_int64 bitpos1;
> +		  poly_offset_int offset1;
> +
> +		  int base_eq_orig_base
> +		    = check_base_and_compare_lt (OMP_CLAUSE_DECL (c),
> +						 &orig_base, decl, &bitpos1,
> +						 &offset1);
>  
>  		  splay_tree_node n
>  		    = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
> @@ -8693,7 +8832,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
>  		      tree l = build_omp_clause (OMP_CLAUSE_LOCATION (c),
>  						 OMP_CLAUSE_MAP);
>  		      OMP_CLAUSE_SET_MAP_KIND (l, GOMP_MAP_STRUCT);
> -		      if (orig_base != base)
> +		      if (!base_eq_orig_base)
>  			OMP_CLAUSE_DECL (l) = unshare_expr (orig_base);
>  		      else
>  			OMP_CLAUSE_DECL (l) = decl;
> @@ -8703,32 +8842,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
>  		      struct_map_to_clause->put (decl, l);
>  		      if (ptr)
>  			{
> -			  enum gomp_map_kind mkind
> -			    = code == OMP_TARGET_EXIT_DATA
> -			      ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
> -			  tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
> -						      OMP_CLAUSE_MAP);
> -			  OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
> -			  OMP_CLAUSE_DECL (c2)
> -			    = unshare_expr (OMP_CLAUSE_DECL (c));
> -			  OMP_CLAUSE_CHAIN (c2) = *prev_list_p;
> -			  OMP_CLAUSE_SIZE (c2)
> -			    = TYPE_SIZE_UNIT (ptr_type_node);
> -			  OMP_CLAUSE_CHAIN (l) = c2;
> -			  if (OMP_CLAUSE_CHAIN (*prev_list_p) != c)
> -			    {
> -			      tree c4 = OMP_CLAUSE_CHAIN (*prev_list_p);
> -			      tree c3
> -				= build_omp_clause (OMP_CLAUSE_LOCATION (c),
> -						    OMP_CLAUSE_MAP);
> -			      OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
> -			      OMP_CLAUSE_DECL (c3)
> -				= unshare_expr (OMP_CLAUSE_DECL (c4));
> -			      OMP_CLAUSE_SIZE (c3)
> -				= TYPE_SIZE_UNIT (ptr_type_node);
> -			      OMP_CLAUSE_CHAIN (c3) = *prev_list_p;
> -			      OMP_CLAUSE_CHAIN (c2) = c3;
> -			    }
> +			  insert_struct_comp_map (code, c, l, *prev_list_p,
> +						  NULL);
>  			  *prev_list_p = l;
>  			  prev_list_p = NULL;
>  			}
> @@ -8738,7 +8853,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
>  			  *list_p = l;
>  			  list_p = &OMP_CLAUSE_CHAIN (l);
>  			}
> -		      if (orig_base != base && code == OMP_TARGET)
> +		      if (!base_eq_orig_base && code == OMP_TARGET)
>  			{
>  			  tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
>  						      OMP_CLAUSE_MAP);
> @@ -8761,13 +8876,6 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
>  		      tree *sc = NULL, *scp = NULL;
>  		      if (GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) || ptr)
>  			n->value |= GOVD_SEEN;
> -		      poly_offset_int o1, o2;
> -		      if (offset)
> -			o1 = wi::to_poly_offset (offset);
> -		      else
> -			o1 = 0;
> -		      if (maybe_ne (bitpos, 0))
> -			o1 += bits_to_bytes_round_down (bitpos);
>  		      sc = &OMP_CLAUSE_CHAIN (*osc);
>  		      if (*sc != c
>  			  && (OMP_CLAUSE_MAP_KIND (*sc)
> @@ -8785,44 +8893,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
>  			  break;
>  			else
>  			  {
> -			    tree offset2;
> -			    poly_int64 bitsize2, bitpos2;
> -			    base = OMP_CLAUSE_DECL (*sc);
> -			    if (TREE_CODE (base) == ARRAY_REF)
> -			      {
> -				while (TREE_CODE (base) == ARRAY_REF)
> -				  base = TREE_OPERAND (base, 0);
> -				if (TREE_CODE (base) != COMPONENT_REF
> -				    || (TREE_CODE (TREE_TYPE (base))
> -					!= ARRAY_TYPE))
> -				  break;
> -			      }
> -			    else if (TREE_CODE (base) == INDIRECT_REF
> -				     && (TREE_CODE (TREE_OPERAND (base, 0))
> -					 == COMPONENT_REF)
> -				     && (TREE_CODE (TREE_TYPE
> -						     (TREE_OPERAND (base, 0)))
> -					 == REFERENCE_TYPE))
> -			      base = TREE_OPERAND (base, 0);
> -			    base = get_inner_reference (base, &bitsize2,
> -							&bitpos2, &offset2,
> -							&mode, &unsignedp,
> -							&reversep, &volatilep);
> -			    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 != decl)
> +			    tree sc_decl = OMP_CLAUSE_DECL (*sc);
> +			    int same_decl_offset_lt
> +			      = check_base_and_compare_lt (sc_decl, NULL, decl,
> +							   &bitpos1, &offset1);
> +			    if (same_decl_offset_lt == -1)
>  			      break;
>  			    if (scp)
>  			      continue;
> -			    gcc_assert (offset == NULL_TREE
> -					|| poly_int_tree_p (offset));
>  			    tree d1 = OMP_CLAUSE_DECL (*sc);
>  			    tree d2 = OMP_CLAUSE_DECL (c);
>  			    while (TREE_CODE (d1) == ARRAY_REF)
> @@ -8851,14 +8929,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
>  				remove = true;
>  				break;
>  			      }
> -			    if (offset2)
> -			      o2 = wi::to_poly_offset (offset2);
> -			    else
> -			      o2 = 0;
> -			    o2 += bits_to_bytes_round_down (bitpos2);
> -			    if (maybe_lt (o1, o2)
> -				|| (known_eq (o1, o2)
> -				    && maybe_lt (bitpos, bitpos2)))
> +			    if (same_decl_offset_lt)
>  			      {
>  				if (ptr)
>  				  scp = sc;
> @@ -8873,38 +8944,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
>  				      size_one_node);
>  		      if (ptr)
>  			{
> -			  tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
> -						      OMP_CLAUSE_MAP);
> -			  tree cl = NULL_TREE;
> -			  enum gomp_map_kind mkind
> -			    = code == OMP_TARGET_EXIT_DATA
> -			      ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
> -			  OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
> -			  OMP_CLAUSE_DECL (c2)
> -			    = unshare_expr (OMP_CLAUSE_DECL (c));
> -			  OMP_CLAUSE_CHAIN (c2) = scp ? *scp : *prev_list_p;
> -			  OMP_CLAUSE_SIZE (c2)
> -			    = TYPE_SIZE_UNIT (ptr_type_node);
> -			  cl = scp ? *prev_list_p : c2;
> -			  if (OMP_CLAUSE_CHAIN (*prev_list_p) != c)
> -			    {
> -			      tree c4 = OMP_CLAUSE_CHAIN (*prev_list_p);
> -			      tree c3
> -				= build_omp_clause (OMP_CLAUSE_LOCATION (c),
> -						    OMP_CLAUSE_MAP);
> -			      OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
> -			      OMP_CLAUSE_DECL (c3)
> -				= unshare_expr (OMP_CLAUSE_DECL (c4));
> -			      OMP_CLAUSE_SIZE (c3)
> -				= TYPE_SIZE_UNIT (ptr_type_node);
> -			      OMP_CLAUSE_CHAIN (c3) = *prev_list_p;
> -			      if (!scp)
> -				OMP_CLAUSE_CHAIN (c2) = c3;
> -			      else
> -				cl = c3;
> -			    }
> -			  if (scp)
> -			    *scp = c2;
> +			  tree cl = insert_struct_comp_map (code, c, NULL,
> +							    *prev_list_p, scp);
>  			  if (sc == prev_list_p)
>  			    {
>  			      *sc = cl;


Grüße
 Thomas

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 658 bytes --]

  reply	other threads:[~2019-10-16 14:42 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-06 22:32 [PATCH 0/4] OpenACC 2.6 manual deep copy (repost) Julian Brown
2019-10-06 22:33 ` [PATCH 1/4] Add function for pretty-printing OpenACC clause names Julian Brown
2019-10-18 12:44   ` Thomas Schwinge
2022-02-17 12:33     ` Add 'gcc/tree.cc:user_omp_clause_code_name' [PR65095] (was: [PATCH 1/4] Add function for pretty-printing OpenACC clause names) Thomas Schwinge
2022-03-12 10:11       ` Add 'gcc/tree.cc:user_omp_clause_code_name' [PR65095] Thomas Schwinge
2019-10-06 22:33 ` [PATCH 3/4] Factor out duplicate code in gimplify_scan_omp_clauses Julian Brown
2019-10-16 14:43   ` Thomas Schwinge [this message]
2019-11-05 16:42     ` Julian Brown
2019-10-06 22:33 ` [PATCH 4/4] OpenACC 2.6 manual deep copy support (attach/detach) Julian Brown
2019-10-06 22:33 ` [PATCH 2/4] Use gomp_map_val for OpenACC host-to-device address translation Julian Brown
2019-10-16  9:34   ` Thomas Schwinge

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87o8ygwy4k.fsf@euler.schwinge.homeip.net \
    --to=thomas@codesourcery.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=julian@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).