Use tree_vector_builder::new_unary_operation for folding

Richard Biener richard.guenther@gmail.com
Thu Dec 7 11:06:00 GMT 2017


On Wed, Dec 6, 2017 at 4:23 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch makes fold-const.c operate directly on the VECTOR_CST
> encoding when folding an operation that has a single VECTOR_CST input.
>
> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
> Also spot-checked on sparc64-linux-gnu.  OK to install?

Ok.

Richard.

> Thanks,
> Richard
>
> 2017-12-06  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * fold-const.c (fold_negate_expr_1): Use tree_vector_builder and
>         new_unary_operation, operating only on the encoded elements.
>         (const_unop): Likewise.
>         (exact_inverse): Likewise.
>         (distributes_over_addition_p): New function.
>         (const_binop): Use tree_vector_builder and new_unary_operation
>         for combinations of VECTOR_CST and INTEGER_CST.  Operate only
>         on the encoded elements unless the encoding is strided and the
>         operation does not distribute over addition.
>         (fold_convert_const):  Use tree_vector_builder and
>         new_unary_operation.  Operate only on the encoded elements
>         for truncating integer conversions, or for non-stepped encodings.
>
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c    2017-12-06 14:48:52.887162217 +0000
> +++ gcc/fold-const.c    2017-12-06 14:48:56.997993407 +0000
> @@ -566,10 +566,10 @@ fold_negate_expr_1 (location_t loc, tree
>
>      case VECTOR_CST:
>        {
> -       int count = VECTOR_CST_NELTS (t), i;
> -
> -       auto_vec<tree, 32> elts (count);
> -       for (i = 0; i < count; i++)
> +       tree_vector_builder elts;
> +       elts.new_unary_operation (type, t, true);
> +       unsigned int count = elts.encoded_nelts ();
> +       for (unsigned int i = 0; i < count; ++i)
>           {
>             tree elt = fold_negate_expr (loc, VECTOR_CST_ELT (t, i));
>             if (elt == NULL_TREE)
> @@ -577,7 +577,7 @@ fold_negate_expr_1 (location_t loc, tree
>             elts.quick_push (elt);
>           }
>
> -       return build_vector (type, elts);
> +       return elts.build ();
>        }
>
>      case COMPLEX_EXPR:
> @@ -1121,6 +1121,27 @@ int_const_binop (enum tree_code code, co
>    return int_const_binop_1 (code, arg1, arg2, 1);
>  }
>
> +/* Return true if binary operation OP distributes over addition in operand
> +   OPNO, with the other operand being held constant.  OPNO counts from 1.  */
> +
> +static bool
> +distributes_over_addition_p (tree_code op, int opno)
> +{
> +  switch (op)
> +    {
> +    case PLUS_EXPR:
> +    case MINUS_EXPR:
> +    case MULT_EXPR:
> +      return true;
> +
> +    case LSHIFT_EXPR:
> +      return opno == 1;
> +
> +    default:
> +      return false;
> +    }
> +}
> +
>  /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
>     constant.  We assume ARG1 and ARG2 have the same data type, or at least
>     are the same kind of constant and the same machine mode.  Return zero if
> @@ -1442,10 +1463,12 @@ const_binop (enum tree_code code, tree a
>        && TREE_CODE (arg2) == INTEGER_CST)
>      {
>        tree type = TREE_TYPE (arg1);
> -      int count = VECTOR_CST_NELTS (arg1), i;
> -
> -      auto_vec<tree, 32> elts (count);
> -      for (i = 0; i < count; i++)
> +      bool step_ok_p = distributes_over_addition_p (code, 1);
> +      tree_vector_builder elts;
> +      if (!elts.new_unary_operation (type, arg1, step_ok_p))
> +       return NULL_TREE;
> +      unsigned int count = elts.encoded_nelts ();
> +      for (unsigned int i = 0; i < count; ++i)
>         {
>           tree elem1 = VECTOR_CST_ELT (arg1, i);
>
> @@ -1458,7 +1481,7 @@ const_binop (enum tree_code code, tree a
>           elts.quick_push (elt);
>         }
>
> -      return build_vector (type, elts);
> +      return elts.build ();
>      }
>    return NULL_TREE;
>  }
> @@ -1649,10 +1672,12 @@ const_unop (enum tree_code code, tree ty
>        else if (TREE_CODE (arg0) == VECTOR_CST)
>         {
>           tree elem;
> -         unsigned count = VECTOR_CST_NELTS (arg0), i;
>
> -         auto_vec<tree, 32> elements (count);
> -         for (i = 0; i < count; i++)
> +         /* This can cope with stepped encodings because ~x == -1 - x.  */
> +         tree_vector_builder elements;
> +         elements.new_unary_operation (type, arg0, true);
> +         unsigned int i, count = elements.encoded_nelts ();
> +         for (i = 0; i < count; ++i)
>             {
>               elem = VECTOR_CST_ELT (arg0, i);
>               elem = const_unop (BIT_NOT_EXPR, TREE_TYPE (type), elem);
> @@ -1661,7 +1686,7 @@ const_unop (enum tree_code code, tree ty
>               elements.quick_push (elem);
>             }
>           if (i == count)
> -           return build_vector (type, elements);
> +           return elements.build ();
>         }
>        break;
>
> @@ -2135,10 +2160,19 @@ fold_convert_const (enum tree_code code,
>        if (TREE_CODE (arg1) == VECTOR_CST
>           && TYPE_VECTOR_SUBPARTS (type) == VECTOR_CST_NELTS (arg1))
>         {
> -         int len = VECTOR_CST_NELTS (arg1);
>           tree elttype = TREE_TYPE (type);
> -         auto_vec<tree, 32> v (len);
> -         for (int i = 0; i < len; ++i)
> +         tree arg1_elttype = TREE_TYPE (TREE_TYPE (arg1));
> +         /* We can't handle steps directly when extending, since the
> +            values need to wrap at the original precision first.  */
> +         bool step_ok_p
> +           = (INTEGRAL_TYPE_P (elttype)
> +              && INTEGRAL_TYPE_P (arg1_elttype)
> +              && TYPE_PRECISION (elttype) <= TYPE_PRECISION (arg1_elttype));
> +         tree_vector_builder v;
> +         if (!v.new_unary_operation (type, arg1, step_ok_p))
> +           return NULL_TREE;
> +         unsigned int len = v.encoded_nelts ();
> +         for (unsigned int i = 0; i < len; ++i)
>             {
>               tree elt = VECTOR_CST_ELT (arg1, i);
>               tree cvt = fold_convert_const (code, elttype, elt);
> @@ -2146,7 +2180,7 @@ fold_convert_const (enum tree_code code,
>                 return NULL_TREE;
>               v.quick_push (cvt);
>             }
> -         return build_vector (type, v);
> +         return v.build ();
>         }
>      }
>    return NULL_TREE;
> @@ -8832,7 +8866,6 @@ exact_inverse (tree type, tree cst)
>    REAL_VALUE_TYPE r;
>    tree unit_type;
>    machine_mode mode;
> -  unsigned vec_nelts, i;
>
>    switch (TREE_CODE (cst))
>      {
> @@ -8846,12 +8879,14 @@ exact_inverse (tree type, tree cst)
>
>      case VECTOR_CST:
>        {
> -       vec_nelts = VECTOR_CST_NELTS (cst);
>         unit_type = TREE_TYPE (type);
>         mode = TYPE_MODE (unit_type);
>
> -       auto_vec<tree, 32> elts (vec_nelts);
> -       for (i = 0; i < vec_nelts; i++)
> +       tree_vector_builder elts;
> +       if (!elts.new_unary_operation (type, cst, false))
> +         return NULL_TREE;
> +       unsigned int count = elts.encoded_nelts ();
> +       for (unsigned int i = 0; i < count; ++i)
>           {
>             r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
>             if (!exact_real_inverse (mode, &r))
> @@ -8859,7 +8894,7 @@ exact_inverse (tree type, tree cst)
>             elts.quick_push (build_real (unit_type, r));
>           }
>
> -       return build_vector (type, elts);
> +       return elts.build ();
>        }
>
>      default:



More information about the Gcc-patches mailing list