produce a new constant in RES. Return FALSE if we don't know how
to evaluate CODE at compile-time. */
-static bool
+bool
poly_int_binop (poly_wide_int &res, enum tree_code code,
const_tree arg1, const_tree arg2,
signop sign, wi::overflow_type *overflow)
{
gcc_assert (NUM_POLY_INT_COEFFS != 1);
gcc_assert (poly_int_tree_p (arg1) && poly_int_tree_p (arg2));
+
+ if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST)
+ {
+ wide_int warg1 = wi::to_wide (arg1), wi_res;
+ wide_int warg2 = wi::to_wide (arg2, TYPE_PRECISION (TREE_TYPE (arg1)));
+ if (!wide_int_binop (wi_res, code, warg1, warg2, sign, overflow))
+ return NULL_TREE;
+ res = wi_res;
+ return true;
+ }
+
switch (code)
{
case PLUS_EXPR:
signop sign = TYPE_SIGN (type);
wi::overflow_type overflow = wi::OVF_NONE;
- if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST)
- {
- wide_int warg1 = wi::to_wide (arg1), res;
- wide_int warg2 = wi::to_wide (arg2, TYPE_PRECISION (type));
- if (!wide_int_binop (res, code, warg1, warg2, sign, &overflow))
- return NULL_TREE;
- poly_res = res;
- }
- else if (!poly_int_tree_p (arg1)
- || !poly_int_tree_p (arg2)
- || !poly_int_binop (poly_res, code, arg1, arg2, sign, &overflow))
+ if (!poly_int_tree_p (arg1)
+ || !poly_int_tree_p (arg2)
+ || !poly_int_binop (poly_res, code, arg1, arg2, sign, &overflow))
return NULL_TREE;
return force_fit_type (type, poly_res, overflowable,
(((sign == SIGNED || overflowable == -1)
return NULL_TREE;
}
+/* 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. */
+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
&& (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