Commit 059c18ab by Richard Sandiford Committed by Richard Sandiford

Use tree_vector_builder::new_unary_operation for folding

This patch makes fold-const.c operate directly on the VECTOR_CST
encoding when folding an operation that has a single VECTOR_CST input.

2017-12-07  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.

From-SVN: r255476
parent 5ebaa477
2017-12-07 Richard Sandiford <richard.sandiford@linaro.org> 2017-12-07 Richard Sandiford <richard.sandiford@linaro.org>
* 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.
2017-12-07 Richard Sandiford <richard.sandiford@linaro.org>
* config/sparc/sparc.c: Include tree-vector-builder.h. * config/sparc/sparc.c: Include tree-vector-builder.h.
(sparc_fold_builtin): Use tree_vector_builder instead of build_vector. (sparc_fold_builtin): Use tree_vector_builder instead of build_vector.
* expmed.c: Include tree-vector-builder.h. * expmed.c: Include tree-vector-builder.h.
...@@ -566,10 +566,10 @@ fold_negate_expr_1 (location_t loc, tree t) ...@@ -566,10 +566,10 @@ fold_negate_expr_1 (location_t loc, tree t)
case VECTOR_CST: case VECTOR_CST:
{ {
int count = VECTOR_CST_NELTS (t), i; tree_vector_builder elts;
elts.new_unary_operation (type, t, true);
auto_vec<tree, 32> elts (count); unsigned int count = elts.encoded_nelts ();
for (i = 0; i < count; i++) for (unsigned int i = 0; i < count; ++i)
{ {
tree elt = fold_negate_expr (loc, VECTOR_CST_ELT (t, i)); tree elt = fold_negate_expr (loc, VECTOR_CST_ELT (t, i));
if (elt == NULL_TREE) if (elt == NULL_TREE)
...@@ -577,7 +577,7 @@ fold_negate_expr_1 (location_t loc, tree t) ...@@ -577,7 +577,7 @@ fold_negate_expr_1 (location_t loc, tree t)
elts.quick_push (elt); elts.quick_push (elt);
} }
return build_vector (type, elts); return elts.build ();
} }
case COMPLEX_EXPR: case COMPLEX_EXPR:
...@@ -1121,6 +1121,27 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2) ...@@ -1121,6 +1121,27 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
return int_const_binop_1 (code, arg1, arg2, 1); 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 /* 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 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 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 arg1, tree arg2) ...@@ -1442,10 +1463,12 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
&& TREE_CODE (arg2) == INTEGER_CST) && TREE_CODE (arg2) == INTEGER_CST)
{ {
tree type = TREE_TYPE (arg1); tree type = TREE_TYPE (arg1);
int count = VECTOR_CST_NELTS (arg1), i; bool step_ok_p = distributes_over_addition_p (code, 1);
tree_vector_builder elts;
auto_vec<tree, 32> elts (count); if (!elts.new_unary_operation (type, arg1, step_ok_p))
for (i = 0; i < count; i++) 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 elem1 = VECTOR_CST_ELT (arg1, i);
...@@ -1458,7 +1481,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2) ...@@ -1458,7 +1481,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
elts.quick_push (elt); elts.quick_push (elt);
} }
return build_vector (type, elts); return elts.build ();
} }
return NULL_TREE; return NULL_TREE;
} }
...@@ -1649,10 +1672,12 @@ const_unop (enum tree_code code, tree type, tree arg0) ...@@ -1649,10 +1672,12 @@ const_unop (enum tree_code code, tree type, tree arg0)
else if (TREE_CODE (arg0) == VECTOR_CST) else if (TREE_CODE (arg0) == VECTOR_CST)
{ {
tree elem; tree elem;
unsigned count = VECTOR_CST_NELTS (arg0), i;
auto_vec<tree, 32> elements (count); /* This can cope with stepped encodings because ~x == -1 - x. */
for (i = 0; i < count; i++) 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 = VECTOR_CST_ELT (arg0, i);
elem = const_unop (BIT_NOT_EXPR, TREE_TYPE (type), elem); elem = const_unop (BIT_NOT_EXPR, TREE_TYPE (type), elem);
...@@ -1661,7 +1686,7 @@ const_unop (enum tree_code code, tree type, tree arg0) ...@@ -1661,7 +1686,7 @@ const_unop (enum tree_code code, tree type, tree arg0)
elements.quick_push (elem); elements.quick_push (elem);
} }
if (i == count) if (i == count)
return build_vector (type, elements); return elements.build ();
} }
break; break;
...@@ -2135,10 +2160,19 @@ fold_convert_const (enum tree_code code, tree type, tree arg1) ...@@ -2135,10 +2160,19 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
if (TREE_CODE (arg1) == VECTOR_CST if (TREE_CODE (arg1) == VECTOR_CST
&& TYPE_VECTOR_SUBPARTS (type) == VECTOR_CST_NELTS (arg1)) && TYPE_VECTOR_SUBPARTS (type) == VECTOR_CST_NELTS (arg1))
{ {
int len = VECTOR_CST_NELTS (arg1);
tree elttype = TREE_TYPE (type); tree elttype = TREE_TYPE (type);
auto_vec<tree, 32> v (len); tree arg1_elttype = TREE_TYPE (TREE_TYPE (arg1));
for (int i = 0; i < len; ++i) /* 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 elt = VECTOR_CST_ELT (arg1, i);
tree cvt = fold_convert_const (code, elttype, elt); tree cvt = fold_convert_const (code, elttype, elt);
...@@ -2146,7 +2180,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1) ...@@ -2146,7 +2180,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
return NULL_TREE; return NULL_TREE;
v.quick_push (cvt); v.quick_push (cvt);
} }
return build_vector (type, v); return v.build ();
} }
} }
return NULL_TREE; return NULL_TREE;
...@@ -8832,7 +8866,6 @@ exact_inverse (tree type, tree cst) ...@@ -8832,7 +8866,6 @@ exact_inverse (tree type, tree cst)
REAL_VALUE_TYPE r; REAL_VALUE_TYPE r;
tree unit_type; tree unit_type;
machine_mode mode; machine_mode mode;
unsigned vec_nelts, i;
switch (TREE_CODE (cst)) switch (TREE_CODE (cst))
{ {
...@@ -8846,12 +8879,14 @@ exact_inverse (tree type, tree cst) ...@@ -8846,12 +8879,14 @@ exact_inverse (tree type, tree cst)
case VECTOR_CST: case VECTOR_CST:
{ {
vec_nelts = VECTOR_CST_NELTS (cst);
unit_type = TREE_TYPE (type); unit_type = TREE_TYPE (type);
mode = TYPE_MODE (unit_type); mode = TYPE_MODE (unit_type);
auto_vec<tree, 32> elts (vec_nelts); tree_vector_builder elts;
for (i = 0; i < vec_nelts; i++) 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)); r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
if (!exact_real_inverse (mode, &r)) if (!exact_real_inverse (mode, &r))
...@@ -8859,7 +8894,7 @@ exact_inverse (tree type, tree cst) ...@@ -8859,7 +8894,7 @@ exact_inverse (tree type, tree cst)
elts.quick_push (build_real (unit_type, r)); elts.quick_push (build_real (unit_type, r));
} }
return build_vector (type, elts); return elts.build ();
} }
default: default:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment