On Thu, Oct 29, 2015 at 8:18 PM, Alan Lawrence <alan.lawre...@arm.com> wrote:
> This is in response to https://gcc.gnu.org/ml/gcc/2015-10/msg00097.html, where
> Richi points out that CONSTRUCTOR elements are not necessarily ordered.
>
> I wasn't sure of a good naming convention for the new 
> get_ctor_element_at_index,
> other suggestions welcome.

get_array_ctor_element_at_index

(ok it also handles vectors).

Ok with that change.

Richard.

> gcc/ChangeLog:
>
>         * gimple-fold.c (fold_array_ctor_reference): Move searching code to:
>         * fold-const.c (get_ctor_element_at_index): New.
>         (fold): Remove binary-search through CONSTRUCTOR, call previous.
>
>         * fold-const.h (get_ctor_element_at_index): New.
> ---
>  gcc/fold-const.c  | 93 
> ++++++++++++++++++++++++++++++++++++++++---------------
>  gcc/fold-const.h  |  1 +
>  gcc/gimple-fold.c | 47 ++--------------------------
>  3 files changed, 72 insertions(+), 69 deletions(-)
>
> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
> index de45a2c..5d27b91 100644
> --- a/gcc/fold-const.c
> +++ b/gcc/fold-const.c
> @@ -12018,6 +12018,72 @@ 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.  */
> +
> +tree
> +get_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.
> @@ -12094,31 +12160,8 @@ 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;
> -             }
> +           if (tree val = get_ctor_element_at_index (op0, wi::to_offset 
> (op1)))
> +             return val;
>           }
>
>         return t;
> diff --git a/gcc/fold-const.h b/gcc/fold-const.h
> index ee74dc8..1fa6ee0 100644
> --- a/gcc/fold-const.h
> +++ b/gcc/fold-const.h
> @@ -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_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)
> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
> index 85ff018..823d952 100644
> --- a/gcc/gimple-fold.c
> +++ b/gcc/gimple-fold.c
> @@ -5308,13 +5308,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.  */
> @@ -5324,7 +5321,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
> @@ -5346,9 +5342,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);
> @@ -5357,43 +5350,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_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);
> --
> 1.9.1
>

Reply via email to