Jennifer Schmitz <jschm...@nvidia.com> writes:
> @@ -1365,6 +1368,91 @@ simplify_const_binop (tree_code code, tree op, tree 
> other_op,
>    return NULL_TREE;
>  }
>  
> +/* Combine two (vector) constants ARG1 and ARG2 element-wise under operation
> +   CODE using function ELT_CONST_BINOP to produce a new (vector) 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
> +   combining the constants is not allowed in the current operating mode.  */

How about:

/* If ARG1 and ARG2 are constants, and if performing CODE on them would
   be an elementwise vector operation, try to fold the operation to a
   constant vector, using ELT_CONST_BINOP to fold each element.  Return
   the folded value on success, otherwise return null.  */

The reason for suggesting this is that the caller doesn't need to check
whether ARG1 or ARG2 are constant or whether the operation is a vector
operation.  The routine does those checks itself.

I also don't think we need to specify the assumptions on well-typed
vector operations, since those apply generally.

OK for trunk with that change, thanks.

Richard

> +tree
> +vector_const_binop (tree_code code, tree arg1, tree arg2,
> +                 tree (*elt_const_binop) (enum tree_code, tree, tree))
> +{
> +  if (TREE_CODE (arg1) == VECTOR_CST && TREE_CODE (arg2) == VECTOR_CST
> +      && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)),
> +                TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2))))
> +    {
> +      tree type = TREE_TYPE (arg1);
> +      bool step_ok_p;
> +      if (VECTOR_CST_STEPPED_P (arg1)
> +       && VECTOR_CST_STEPPED_P (arg2))
> +      /* We can operate directly on the encoding if:
> +
> +      a3 - a2 == a2 - a1 && b3 - b2 == b2 - b1
> +      implies
> +      (a3 op b3) - (a2 op b2) == (a2 op b2) - (a1 op b1)
> +
> +      Addition and subtraction are the supported operators
> +      for which this is true.  */
> +     step_ok_p = (code == PLUS_EXPR || code == MINUS_EXPR);
> +      else if (VECTOR_CST_STEPPED_P (arg1))
> +      /* We can operate directly on stepped encodings if:
> +
> +      a3 - a2 == a2 - a1
> +      implies:
> +      (a3 op c) - (a2 op c) == (a2 op c) - (a1 op c)
> +
> +      which is true if (x -> x op c) distributes over addition.  */
> +     step_ok_p = distributes_over_addition_p (code, 1);
> +      else
> +      /* Similarly in reverse.  */
> +     step_ok_p = distributes_over_addition_p (code, 2);
> +      tree_vector_builder elts;
> +      if (!elts.new_binary_operation (type, arg1, arg2, 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);
> +       tree elem2 = VECTOR_CST_ELT (arg2, i);
> +
> +       tree elt = elt_const_binop (code, elem1, elem2);
> +
> +      /* It is possible that const_binop cannot handle the given
> +      code and return NULL_TREE */
> +       if (elt == NULL_TREE)
> +         return NULL_TREE;
> +       elts.quick_push (elt);
> +     }
> +
> +      return elts.build ();
> +    }
> +
> +  if (TREE_CODE (arg1) == VECTOR_CST
> +      && TREE_CODE (arg2) == INTEGER_CST)
> +    {
> +      tree type = TREE_TYPE (arg1);
> +      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);
> +
> +       tree elt = elt_const_binop (code, elem1, arg2);
> +
> +       /* It is possible that const_binop cannot handle the given
> +          code and return NULL_TREE.  */
> +       if (elt == NULL_TREE)
> +         return NULL_TREE;
> +       elts.quick_push (elt);
> +     }
> +
> +      return elts.build ();
> +    }
> +  return NULL_TREE;
> +}
>  
>  /* 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
> @@ -1677,83 +1765,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
>        && (simplified = simplify_const_binop (code, arg2, arg1, 1)))
>      return simplified;
>  
> -  if (TREE_CODE (arg1) == VECTOR_CST
> -      && TREE_CODE (arg2) == VECTOR_CST
> -      && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)),
> -                TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2))))
> -    {
> -      tree type = TREE_TYPE (arg1);
> -      bool step_ok_p;
> -      if (VECTOR_CST_STEPPED_P (arg1)
> -       && VECTOR_CST_STEPPED_P (arg2))
> -     /* We can operate directly on the encoding if:
> -
> -           a3 - a2 == a2 - a1 && b3 - b2 == b2 - b1
> -         implies
> -           (a3 op b3) - (a2 op b2) == (a2 op b2) - (a1 op b1)
> -
> -        Addition and subtraction are the supported operators
> -        for which this is true.  */
> -     step_ok_p = (code == PLUS_EXPR || code == MINUS_EXPR);
> -      else if (VECTOR_CST_STEPPED_P (arg1))
> -     /* We can operate directly on stepped encodings if:
> -
> -          a3 - a2 == a2 - a1
> -        implies:
> -          (a3 op c) - (a2 op c) == (a2 op c) - (a1 op c)
> -
> -        which is true if (x -> x op c) distributes over addition.  */
> -     step_ok_p = distributes_over_addition_p (code, 1);
> -      else
> -     /* Similarly in reverse.  */
> -     step_ok_p = distributes_over_addition_p (code, 2);
> -      tree_vector_builder elts;
> -      if (!elts.new_binary_operation (type, arg1, arg2, 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);
> -       tree elem2 = VECTOR_CST_ELT (arg2, i);
> -
> -       tree elt = const_binop (code, elem1, elem2);
> -
> -       /* It is possible that const_binop cannot handle the given
> -          code and return NULL_TREE */
> -       if (elt == NULL_TREE)
> -         return NULL_TREE;
> -       elts.quick_push (elt);
> -     }
> -
> -      return elts.build ();
> -    }
> -
> -  /* Shifts allow a scalar offset for a vector.  */
> -  if (TREE_CODE (arg1) == VECTOR_CST
> -      && TREE_CODE (arg2) == INTEGER_CST)
> -    {
> -      tree type = TREE_TYPE (arg1);
> -      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);
> -
> -       tree elt = const_binop (code, elem1, arg2);
> -
> -       /* It is possible that const_binop cannot handle the given
> -          code and return NULL_TREE.  */
> -       if (elt == NULL_TREE)
> -         return NULL_TREE;
> -       elts.quick_push (elt);
> -     }
> -
> -      return elts.build ();
> -    }
> -  return NULL_TREE;
> +  return vector_const_binop (code, arg1, arg2, const_binop);
>  }
>  
>  /* Overload that adds a TYPE parameter to be able to dispatch

Reply via email to