Jennifer Schmitz <[email protected]> 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