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