From 3a021db2999ccd790948dc36c876f39601922884 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Jul 2004 08:57:07 +0000 Subject: [PATCH] c-common.c (vector_types_convertible_p): Use vector types' TYPE_SIZE and TREE_TYPE instead of their mode. 2004-07-21 Paolo Bonzini * 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 * c-typeck.c (build_binary_op): Do not use RDIV_EXPR for integer vectors. From-SVN: r85002 --- gcc/c-common.c | 4 +- gcc/c-typeck.c | 5 ++ gcc/convert.c | 6 +- gcc/cp/ChangeLog | 5 ++ gcc/cp/typeck.c | 9 +- gcc/expr.c | 214 +++++++++++++++++++++++++++++++---------------- gcc/fold-const.c | 9 +- gcc/varasm.c | 4 +- 8 files changed, 171 insertions(+), 85 deletions(-) diff --git a/gcc/c-common.c b/gcc/c-common.c index 093e839b5c8..4d409222615 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 82b0108bee3..6e1b9281b63 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 5441bf173f4..9e89163e1b1 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 ddc31069616..a3d142fcda6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2004-07-21 Paolo Bonzini + + * typeck.c (build_binary_op): Do not use RDIV_EXPR for + integer vectors. + 2004-07-21 Giovanni Bajo PR c++/14497 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 0e23e9a48c6..640f512fe73 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 858a7ff2400..9bd383463c9 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 946a2fb1cc4..e976117d133 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 1e1a8d980dd..7107c5f9a69 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);