diff options
| -rw-r--r-- | gcc/c-common.c | 4 | ||||
| -rw-r--r-- | gcc/c-typeck.c | 5 | ||||
| -rw-r--r-- | gcc/convert.c | 6 | ||||
| -rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
| -rw-r--r-- | gcc/cp/typeck.c | 9 | ||||
| -rw-r--r-- | gcc/expr.c | 214 | ||||
| -rw-r--r-- | gcc/fold-const.c | 9 | ||||
| -rw-r--r-- | 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  <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 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);  | 

