Share code from fold_array_ctor_reference with fold.
authorAlan Lawrence <alan.lawrence@arm.com>
Fri, 30 Oct 2015 19:03:14 +0000 (19:03 +0000)
committerAlan Lawrence <alalaw01@gcc.gnu.org>
Fri, 30 Oct 2015 19:03:14 +0000 (19:03 +0000)
        * gimple-fold.c (fold_array_ctor_reference): Move searching code to:
        * fold-const.c (get_array_ctor_element_at_index): New.
        (fold): Remove binary-search through CONSTRUCTOR, call previous.

        * fold-const.h (get_array_ctor_element_at_index): New.

From-SVN: r229605

gcc/ChangeLog
gcc/fold-const.c
gcc/fold-const.h
gcc/gimple-fold.c

index 1edff5d2a917bbc3bfa4f50954ad87234be1fb7b..ee6a34ff94d288b0316087e0bc91ef2d57a682b5 100644 (file)
@@ -1,3 +1,11 @@
+2015-10-30  Alan Lawrence  <alan.lawrence@arm.com>
+
+       * gimple-fold.c (fold_array_ctor_reference): Move searching code to:
+       * fold-const.c (get_array_ctor_element_at_index): New.
+       (fold): Remove binary-search through CONSTRUCTOR, call previous.
+
+       * fold-const.h (get_array_ctor_element_at_index): New.
+
 2015-10-30  Evgeny Stupachenko  <evstupac@gmail.com>
 
        * Makefile.in (OBJS): Add multiple_target.o.
index 06d0b59eb3fb19baf688dd4d04f28a2c75deafaf..b9168f331ed534afb02f02af7f946179a01b85da 100644 (file)
@@ -11845,6 +11845,73 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
     } /* switch (code) */
 }
 
+/* Gets the element ACCESS_INDEX from CTOR, which must be a CONSTRUCTOR
+   of an array (or vector).  */
+
+tree
+get_array_ctor_element_at_index (tree ctor, offset_int access_index)
+{
+  tree index_type = NULL_TREE;
+  offset_int low_bound = 0;
+
+  if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE)
+  {
+    tree domain_type = TYPE_DOMAIN (TREE_TYPE (ctor));
+    if (domain_type && TYPE_MIN_VALUE (domain_type))
+    {
+      /* Static constructors for variably sized objects makes no sense.  */
+      gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST);
+      index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type));
+      low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
+    }
+  }
+
+  if (index_type)
+    access_index = wi::ext (access_index, TYPE_PRECISION (index_type),
+                           TYPE_SIGN (index_type));
+
+  offset_int index = low_bound - 1;
+  if (index_type)
+    index = wi::ext (index, TYPE_PRECISION (index_type),
+                    TYPE_SIGN (index_type));
+
+  offset_int max_index;
+  unsigned HOST_WIDE_INT cnt;
+  tree cfield, cval;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+  {
+    /* Array constructor might explicitely set index, or specify range
+     * or leave index NULL meaning that it is next index after previous
+     * one.  */
+    if (cfield)
+    {
+      if (TREE_CODE (cfield) == INTEGER_CST)
+       max_index = index = wi::to_offset (cfield);
+      else
+      {
+       gcc_assert (TREE_CODE (cfield) == RANGE_EXPR);
+       index = wi::to_offset (TREE_OPERAND (cfield, 0));
+       max_index = wi::to_offset (TREE_OPERAND (cfield, 1));
+      }
+    }
+    else
+    {
+      index += 1;
+      if (index_type)
+       index = wi::ext (index, TYPE_PRECISION (index_type),
+                        TYPE_SIGN (index_type));
+       max_index = index;
+    }
+
+    /* Do we have match?  */
+    if (wi::cmpu (access_index, index) >= 0
+       && wi::cmpu (access_index, max_index) <= 0)
+      return cval;
+  }
+  return NULL_TREE;
+}
+
 /* Perform constant folding and related simplification of EXPR.
    The related simplifications include x*1 => x, x*0 => 0, etc.,
    and application of the associative law.
@@ -11921,31 +11988,10 @@ fold (tree expr)
            && TREE_CODE (op0) == CONSTRUCTOR
            && ! type_contains_placeholder_p (TREE_TYPE (op0)))
          {
-           vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (op0);
-           unsigned HOST_WIDE_INT end = vec_safe_length (elts);
-           unsigned HOST_WIDE_INT begin = 0;
-
-           /* Find a matching index by means of a binary search.  */
-           while (begin != end)
-             {
-               unsigned HOST_WIDE_INT middle = (begin + end) / 2;
-               tree index = (*elts)[middle].index;
-
-               if (TREE_CODE (index) == INTEGER_CST
-                   && tree_int_cst_lt (index, op1))
-                 begin = middle + 1;
-               else if (TREE_CODE (index) == INTEGER_CST
-                        && tree_int_cst_lt (op1, index))
-                 end = middle;
-               else if (TREE_CODE (index) == RANGE_EXPR
-                        && tree_int_cst_lt (TREE_OPERAND (index, 1), op1))
-                 begin = middle + 1;
-               else if (TREE_CODE (index) == RANGE_EXPR
-                        && tree_int_cst_lt (op1, TREE_OPERAND (index, 0)))
-                 end = middle;
-               else
-                 return (*elts)[middle].value;
-             }
+           tree val = get_array_ctor_element_at_index (op0,
+                                                       wi::to_offset (op1));
+           if (val)
+             return val;
          }
 
        return t;
index 8e49c98b9c5cb6162e342b6dfaf2957000536c41..97d18cf0e22a31f70131c3d29f940e925e4e6f64 100644 (file)
@@ -73,6 +73,7 @@ extern tree fold_build_call_array_loc (location_t, tree, tree, int, tree *);
 #define fold_build_call_array_initializer(T1,T2,N,T4)\
    fold_build_call_array_initializer_loc (UNKNOWN_LOCATION, T1, T2, N, T4)
 extern tree fold_build_call_array_initializer_loc (location_t, tree, tree, int, tree *);
+extern tree get_array_ctor_element_at_index (tree, offset_int);
 extern bool fold_convertible_p (const_tree, const_tree);
 #define fold_convert(T1,T2)\
    fold_convert_loc (UNKNOWN_LOCATION, T1, T2)
index 77c3e75839a9dd5b4e25b899c76da27741ffe5af..c9b9593c23a4273d0e2e47c9782b598ec31c1b0f 100644 (file)
@@ -5301,13 +5301,10 @@ fold_array_ctor_reference (tree type, tree ctor,
                           unsigned HOST_WIDE_INT size,
                           tree from_decl)
 {
-  unsigned HOST_WIDE_INT cnt;
-  tree cfield, cval;
   offset_int low_bound;
   offset_int elt_size;
-  offset_int index, max_index;
   offset_int access_index;
-  tree domain_type = NULL_TREE, index_type = NULL_TREE;
+  tree domain_type = NULL_TREE;
   HOST_WIDE_INT inner_offset;
 
   /* Compute low bound and elt size.  */
@@ -5317,7 +5314,6 @@ fold_array_ctor_reference (tree type, tree ctor,
     {
       /* Static constructors for variably sized objects makes no sense.  */
       gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST);
-      index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type));
       low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
     }
   else
@@ -5339,9 +5335,6 @@ fold_array_ctor_reference (tree type, tree ctor,
   access_index = wi::udiv_trunc (offset_int (offset / BITS_PER_UNIT),
                                 elt_size);
   access_index += low_bound;
-  if (index_type)
-    access_index = wi::ext (access_index, TYPE_PRECISION (index_type),
-                           TYPE_SIGN (index_type));
 
   /* And offset within the access.  */
   inner_offset = offset % (elt_size.to_uhwi () * BITS_PER_UNIT);
@@ -5350,43 +5343,9 @@ fold_array_ctor_reference (tree type, tree ctor,
      care to fold accesses spanning multiple array indexes.  */
   if (inner_offset + size > elt_size.to_uhwi () * BITS_PER_UNIT)
     return NULL_TREE;
+  if (tree val = get_array_ctor_element_at_index (ctor, access_index))
+    return fold_ctor_reference (type, val, inner_offset, size, from_decl);
 
-  index = low_bound - 1;
-  if (index_type)
-    index = wi::ext (index, TYPE_PRECISION (index_type),
-                    TYPE_SIGN (index_type));
-
-  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
-    {
-      /* Array constructor might explicitely set index, or specify range
-        or leave index NULL meaning that it is next index after previous
-        one.  */
-      if (cfield)
-       {
-         if (TREE_CODE (cfield) == INTEGER_CST)
-           max_index = index = wi::to_offset (cfield);
-         else
-           {
-             gcc_assert (TREE_CODE (cfield) == RANGE_EXPR);
-             index = wi::to_offset (TREE_OPERAND (cfield, 0));
-             max_index = wi::to_offset (TREE_OPERAND (cfield, 1));
-           }
-       }
-      else
-       {
-         index += 1;
-         if (index_type)
-           index = wi::ext (index, TYPE_PRECISION (index_type),
-                            TYPE_SIGN (index_type));
-         max_index = index;
-       }
-
-      /* Do we have match?  */
-      if (wi::cmpu (access_index, index) >= 0
-         && wi::cmpu (access_index, max_index) <= 0)
-       return fold_ctor_reference (type, cval, inner_offset, size,
-                                   from_decl);
-    }
   /* When memory is not explicitely mentioned in constructor,
      it is 0 (or out of range).  */
   return build_zero_cst (type);