This patch factors out some code in gimplify_scan_omp_clauses into two
new outlined functions. Previously approved here:

  https://gcc.gnu.org/ml/gcc-patches/2018-12/msg01309.html

FAOD, OK for trunk?

Thanks,

Julian

ChangeLog

        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(-)

diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 88d6571976f..5d50713a9f1 100644
--- 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);
+
+  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))
+    {
+      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.  */
+
+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);
+
+  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;
+}
+
 /* Scan the OMP clauses in *LIST_P, installing mappings into a new
    and previous omp contexts.  */
 
@@ -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;
-- 
2.23.0

Reply via email to