Message ID | 874lp3anio.fsf_-_@linaro.org |
---|---|
State | Accepted |
Commit | 059c18abcb9c88bb5a85eb3ce468ffa7252da230 |
Headers | show |
Series | Use tree_vector_builder::new_unary_operation for folding | expand |
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:
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: