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 --]
next prev parent 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).