aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2004-07-21 08:57:07 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2004-07-21 08:57:07 +0000
commit3a021db2999ccd790948dc36c876f39601922884 (patch)
tree04000c5f2ebc9c61790505ccc698906864ba8de9
parent4b997cc8bb5bc3c83b9bf3e7866e0f4627f4b708 (diff)
downloadgcc-3a021db2999ccd790948dc36c876f39601922884.zip
gcc-3a021db2999ccd790948dc36c876f39601922884.tar.gz
gcc-3a021db2999ccd790948dc36c876f39601922884.tar.bz2
c-common.c (vector_types_convertible_p): Use vector types' TYPE_SIZE and TREE_TYPE instead of their mode.
2004-07-21 Paolo Bonzini <bonzini@gnu.org> * c-common.c (vector_types_convertible_p): Use vector types' TYPE_SIZE and TREE_TYPE instead of their mode. * convert.c (convert_to_integer): Likewise. (convert_to_vector): Likewise. * fold-const.c (fold_convert): Likewise. * varasm.c (output_constant): Likewise. * expr.c (store_constructor): Split ARRAY_TYPE and VECTOR_TYPE. Allow a VECTOR_TYPE initializer to be made of several vectors. For ARRAY_TYPEs and VECTOR_TYPES, simplify a bit the handling of cleared and need_to_clear, and use fold_convert. * c-typeck.c (build_binary_op): Do not use RDIV_EXPR for integer vectors. cp/ChangeLog: 2004-07-21 Paolo Bonzini <bonzini@gnu.org> * c-typeck.c (build_binary_op): Do not use RDIV_EXPR for integer vectors. From-SVN: r85002
-rw-r--r--gcc/c-common.c4
-rw-r--r--gcc/c-typeck.c5
-rw-r--r--gcc/convert.c6
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/typeck.c9
-rw-r--r--gcc/expr.c214
-rw-r--r--gcc/fold-const.c9
-rw-r--r--gcc/varasm.c4
8 files changed, 171 insertions, 85 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 093e839..4d40922 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -965,7 +965,9 @@ vector_types_convertible_p (tree t1, tree t2)
{
return targetm.vector_opaque_p (t1)
|| targetm.vector_opaque_p (t2)
- || TYPE_MODE (t1) == TYPE_MODE (t2);
+ || (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+ && INTEGRAL_TYPE_P (TREE_TYPE (t1))
+ == INTEGRAL_TYPE_P (TREE_TYPE (t2)));
}
/* Convert EXPR to TYPE, warning about conversion problems with constants.
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 82b0108..6e1b928 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -6908,6 +6908,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
{
+ if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
+ code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+ if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
+ code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
diff --git a/gcc/convert.c b/gcc/convert.c
index 5441bf1..9e89163 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -677,8 +677,7 @@ convert_to_integer (tree type, tree expr)
TREE_TYPE (TREE_TYPE (expr)), expr)));
case VECTOR_TYPE:
- if (GET_MODE_SIZE (TYPE_MODE (type))
- != GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr))))
+ if (!tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (expr))))
{
error ("can't convert between vector values of different size");
return error_mark_node;
@@ -755,8 +754,7 @@ convert_to_vector (tree type, tree expr)
{
case INTEGER_TYPE:
case VECTOR_TYPE:
- if (GET_MODE_SIZE (TYPE_MODE (type))
- != GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr))))
+ if (!tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (expr))))
{
error ("can't convert between vector values of different size");
return error_mark_node;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ddc3106..a3d142f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2004-07-21 Paolo Bonzini <bonzini@gnu.org>
+
+ * typeck.c (build_binary_op): Do not use RDIV_EXPR for
+ integer vectors.
+
2004-07-21 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/14497
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0e23e9a..640f512 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2869,15 +2869,20 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
{
if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
warning ("division by zero in `%E / 0'", op0);
else if (TREE_CODE (op1) == REAL_CST && real_zerop (op1))
warning ("division by zero in `%E / 0.'", op0);
+ if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
+ code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+ if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
+ code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
diff --git a/gcc/expr.c b/gcc/expr.c
index 858a7ff..9bd3834 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4268,8 +4268,7 @@ count_type_elements (tree type)
return 2;
case VECTOR_TYPE:
- /* ??? This is broke. We should encode the vector width in the tree. */
- return GET_MODE_NUNITS (TYPE_MODE (type));
+ return TYPE_VECTOR_SUBPARTS (type);
case INTEGER_TYPE:
case REAL_TYPE:
@@ -4554,8 +4553,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
get_alias_set (TREE_TYPE (field)));
}
}
- else if (TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == VECTOR_TYPE)
+
+ else if (TREE_CODE (type) == ARRAY_TYPE)
{
tree elt;
int i;
@@ -4565,39 +4564,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
int const_bounds_p;
HOST_WIDE_INT minelt = 0;
HOST_WIDE_INT maxelt = 0;
- int icode = 0;
- rtx *vector = NULL;
- int elt_size = 0;
- unsigned n_elts = 0;
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- domain = TYPE_DOMAIN (type);
- else
- /* Vectors do not have domains; look up the domain of
- the array embedded in the debug representation type.
- FIXME Would probably be more efficient to treat vectors
- separately from arrays. */
- {
- domain = TYPE_DEBUG_REPRESENTATION_TYPE (type);
- domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain)));
- if (REG_P (target) && VECTOR_MODE_P (GET_MODE (target)))
- {
- enum machine_mode mode = GET_MODE (target);
-
- icode = (int) vec_init_optab->handlers[mode].insn_code;
- if (icode != CODE_FOR_nothing)
- {
- unsigned int i;
-
- elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
- n_elts = (GET_MODE_SIZE (mode) / elt_size);
- vector = alloca (n_elts);
- for (i = 0; i < n_elts; i++)
- vector [i] = CONST0_RTX (GET_MODE_INNER (mode));
- }
- }
- }
+ domain = TYPE_DOMAIN (type);
const_bounds_p = (TYPE_MIN_VALUE (domain)
&& TYPE_MAX_VALUE (domain)
&& host_integerp (TYPE_MIN_VALUE (domain), 0)
@@ -4613,7 +4581,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
/* If the constructor has fewer elements than the array,
clear the whole array first. Similarly if this is
static constructor of a non-BLKmode object. */
- if (cleared || (REG_P (target) && TREE_STATIC (exp)))
+ if (cleared)
+ need_to_clear = 0;
+ else if (REG_P (target) && TREE_STATIC (exp))
need_to_clear = 1;
else
{
@@ -4660,18 +4630,16 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
need_to_clear = 1;
}
- if (need_to_clear && size > 0 && !vector)
+ if (need_to_clear && size > 0)
{
- if (! cleared)
- {
- if (REG_P (target))
- emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
- else
- clear_storage (target, GEN_INT (size));
- }
+ if (REG_P (target))
+ emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
+ else
+ clear_storage (target, GEN_INT (size));
cleared = 1;
}
- else if (REG_P (target))
+
+ if (!cleared && REG_P (target))
/* Inform later passes that the old value is dead. */
emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
@@ -4710,9 +4678,6 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
HOST_WIDE_INT lo, hi, count;
tree position;
- if (vector)
- abort ();
-
/* If the range is constant and "small", unroll the loop. */
if (const_bounds_p
&& host_integerp (lo_index, 0)
@@ -4807,16 +4772,13 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
{
tree position;
- if (vector)
- abort ();
-
if (index == 0)
index = ssize_int (1);
if (minelt)
- index = convert (ssizetype,
- fold (build (MINUS_EXPR, index,
- TYPE_MIN_VALUE (domain))));
+ index = fold_convert (ssizetype,
+ fold (build (MINUS_EXPR, index,
+ TYPE_MIN_VALUE (domain))));
position = size_binop (MULT_EXPR, index,
convert (ssizetype,
@@ -4827,16 +4789,6 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
xtarget = adjust_address (xtarget, mode, 0);
store_expr (value, xtarget, 0);
}
- else if (vector)
- {
- int pos;
-
- if (index != 0)
- pos = tree_low_cst (index, 0) - minelt;
- else
- pos = i;
- vector[pos] = expand_expr (value, NULL_RTX, VOIDmode, 0);
- }
else
{
if (index != 0)
@@ -4856,12 +4808,128 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
type, cleared, get_alias_set (elttype));
}
}
- if (vector)
+ }
+
+ else if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ tree elt;
+ int i;
+ int need_to_clear;
+ int icode = 0;
+ tree elttype = TREE_TYPE (type);
+ int elt_size = tree_low_cst (TYPE_SIZE (elttype), 1);
+ enum machine_mode eltmode = TYPE_MODE (elttype);
+ HOST_WIDE_INT bitsize;
+ HOST_WIDE_INT bitpos;
+ rtx *vector = NULL;
+ unsigned n_elts;
+
+ if (eltmode == BLKmode)
+ abort ();
+
+ n_elts = TYPE_VECTOR_SUBPARTS (type);
+ if (REG_P (target) && VECTOR_MODE_P (GET_MODE (target)))
{
- emit_insn (GEN_FCN (icode) (target,
- gen_rtx_PARALLEL (GET_MODE (target),
- gen_rtvec_v (n_elts, vector))));
+ enum machine_mode mode = GET_MODE (target);
+
+ icode = (int) vec_init_optab->handlers[mode].insn_code;
+ if (icode != CODE_FOR_nothing)
+ {
+ unsigned int i;
+
+ vector = alloca (n_elts);
+ for (i = 0; i < n_elts; i++)
+ vector [i] = CONST0_RTX (GET_MODE_INNER (mode));
+ }
}
+
+ /* If the constructor has fewer elements than the vector,
+ clear the whole array first. Similarly if this is
+ static constructor of a non-BLKmode object. */
+ if (cleared)
+ need_to_clear = 0;
+ else if (REG_P (target) && TREE_STATIC (exp))
+ need_to_clear = 1;
+ else
+ {
+ unsigned HOST_WIDE_INT count = 0, zero_count = 0;
+
+ for (elt = CONSTRUCTOR_ELTS (exp);
+ elt != NULL_TREE;
+ elt = TREE_CHAIN (elt))
+ {
+ int n_elts_here =
+ tree_low_cst (
+ int_const_binop (TRUNC_DIV_EXPR,
+ TYPE_SIZE (TREE_TYPE (TREE_VALUE (elt))),
+ TYPE_SIZE (elttype), 0), 1);
+
+ count += n_elts_here;
+ if (mostly_zeros_p (TREE_VALUE (elt)))
+ zero_count += n_elts_here;
+ }
+
+ /* Clear the entire vector first if there are any missing elements,
+ or if the incidence of zero elements is >= 75%. */
+ need_to_clear = (count < n_elts || 4 * zero_count >= 3 * count);
+ }
+
+ if (need_to_clear && size > 0 && !vector)
+ {
+ if (REG_P (target))
+ emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
+ else
+ clear_storage (target, GEN_INT (size));
+ cleared = 1;
+ }
+
+ if (!cleared && REG_P (target))
+ /* Inform later passes that the old value is dead. */
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
+
+ /* Store each element of the constructor into the corresponding
+ element of TARGET, determined by counting the elements. */
+ for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
+ elt;
+ elt = TREE_CHAIN (elt), i += bitsize / elt_size)
+ {
+ tree value = TREE_VALUE (elt);
+ tree index = TREE_PURPOSE (elt);
+ HOST_WIDE_INT eltpos;
+
+ bitsize = tree_low_cst (TYPE_SIZE (TREE_TYPE (value)), 1);
+ if (cleared && initializer_zerop (value))
+ continue;
+
+ if (index != 0)
+ eltpos = tree_low_cst (index, 1);
+ else
+ eltpos = i;
+
+ if (vector)
+ {
+ /* Vector CONSTRUCTORs should only be built from smaller
+ vectors in the case of BLKmode vectors. */
+ if (TREE_CODE (TREE_TYPE (value)) == VECTOR_TYPE)
+ abort ();
+ vector[eltpos] = expand_expr (value, NULL_RTX, VOIDmode, 0);
+ }
+ else
+ {
+ enum machine_mode value_mode =
+ TREE_CODE (TREE_TYPE (value)) == VECTOR_TYPE
+ ? TYPE_MODE (TREE_TYPE (value))
+ : eltmode;
+ bitpos = eltpos * elt_size;
+ store_constructor_field (target, bitsize, bitpos, value_mode, value,
+ type, cleared, get_alias_set (elttype));
+ }
+ }
+
+ if (vector)
+ emit_insn (GEN_FCN (icode) (target,
+ gen_rtx_PARALLEL (GET_MODE (target),
+ gen_rtvec_v (n_elts, vector))));
}
/* Set constructor assignments. */
@@ -6430,7 +6498,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return temp;
case VECTOR_CST:
- return const_vector_from_tree (exp);
+ if (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_INT
+ || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_FLOAT)
+ return const_vector_from_tree (exp);
+ else
+ return expand_expr (build1 (CONSTRUCTOR, TREE_TYPE (exp),
+ TREE_VECTOR_CST_ELTS (exp)),
+ ignore ? const0_rtx : target, tmode, modifier);
case CONST_DECL:
return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 946a2fb..e976117 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1931,8 +1931,7 @@ fold_convert (tree type, tree arg)
return fold_convert (type, tem);
}
if (TREE_CODE (orig) == VECTOR_TYPE
- && GET_MODE_SIZE (TYPE_MODE (type))
- == GET_MODE_SIZE (TYPE_MODE (orig)))
+ && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
return fold (build1 (NOP_EXPR, type, arg));
}
else if (TREE_CODE (type) == REAL_TYPE)
@@ -1991,12 +1990,10 @@ fold_convert (tree type, tree arg)
else if (TREE_CODE (type) == VECTOR_TYPE)
{
if ((INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig))
- && GET_MODE_SIZE (TYPE_MODE (type))
- == GET_MODE_SIZE (TYPE_MODE (orig)))
+ && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
return fold (build1 (NOP_EXPR, type, arg));
if (TREE_CODE (orig) == VECTOR_TYPE
- && GET_MODE_SIZE (TYPE_MODE (type))
- == GET_MODE_SIZE (TYPE_MODE (orig)))
+ && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
return fold (build1 (NOP_EXPR, type, arg));
}
else if (VOID_TYPE_P (type))
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 1e1a8d9..7107c5f 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -3615,10 +3615,10 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
unsigned int nalign;
enum machine_mode inner;
- inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp)));
+ inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
- elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));
+ elt_size = GET_MODE_SIZE (inner);
link = TREE_VECTOR_CST_ELTS (exp);
output_constant (TREE_VALUE (link), elt_size, align);