This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR18191


Hi,

This fixes a wrong-code regression that affects all targets.  Bootstrapped
and tested on {i686,x86_64,ia64,ppc}-unknown-linux-gnu.  This fixes two
mudflap problems on i686, apparently:

libmudflap.cth/pass39-frag.c (-static -DSTATIC) (rerun 4) execution test
libmudflap.cth/pass39-frag.c (rerun 13) execution test

Thanks to Andrew Pinski for writing the nice code to expand RANGE_EXPR
CONSTRUCTORs.

It also fixes a potential wrong code but in categorize_ctor_elements_1.
We can only handle RANGE_EXPRs with a range that we can represent on the
host.

I also found two other bugs in the process of fixing this one, but I've
already applied patches for those.

Is this one OK?

Gr.
Steven

2004-12-18  Steven Bosscher  <stevenb@suse.de>
	    Andrew Pinski  <pinskia@physics.uc.edu>

	* expr.c (categorize_ctor_elements_1): Abort when the range of
	a RANGE_EXPR is larger than the maximum value of HOST_WIDE_INT.
	Count the total number of elements in the constructor.
	elements in the constructor.
	(categorize_ctor_elements): Return it in a new argument.
	* tree.h (categorize_ctor_elements): Adjust prototype.
	* gimplify.c (gimplify_init_ctor_eval): Gimplify RANGE_EXPR.
	(gimplify_init_constructor): Block clear the object if the
	constructor has fewer elements than the object type.  Only try
	to add assignments to individual elements when we have to.
	
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.760
diff -c -3 -p -r1.760 expr.c
*** expr.c	12 Dec 2004 21:12:43 -0000	1.760
--- expr.c	17 Dec 2004 18:13:56 -0000
*************** store_expr (tree exp, rtx target, int ca
*** 4220,4238 ****
    return NULL_RTX;
  }
  
! /* Examine CTOR.  Discover how many scalar fields are set to nonzero
!    values and place it in *P_NZ_ELTS.  Discover how many scalar fields
!    are set to non-constant values and place it in  *P_NC_ELTS.  */
  
  static void
  categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
! 			    HOST_WIDE_INT *p_nc_elts)
  {
!   HOST_WIDE_INT nz_elts, nc_elts;
    tree list;
  
    nz_elts = 0;
    nc_elts = 0;
  
    for (list = CONSTRUCTOR_ELTS (ctor); list; list = TREE_CHAIN (list))
      {
--- 4220,4244 ----
    return NULL_RTX;
  }
  
! /* Examine CTOR to discover:
!    * how many scalar fields are set to nonzero values,
!      and place it in *P_NZ_ELTS;
!    * how many scalar fields are set to non-constant values,
!      and place it in  *P_NC_ELTS; and
!    * how many scalar fields in total are in CTOR,
!      and place it in *P_ELT_COUNT.  */
  
  static void
  categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
! 			    HOST_WIDE_INT *p_nc_elts,
! 			    HOST_WIDE_INT *p_elt_count)
  {
!   HOST_WIDE_INT nz_elts, nc_elts, elt_count;
    tree list;
  
    nz_elts = 0;
    nc_elts = 0;
+   elt_count = 0;
  
    for (list = CONSTRUCTOR_ELTS (ctor); list; list = TREE_CHAIN (list))
      {
*************** categorize_ctor_elements_1 (tree ctor, H
*** 4246,4264 ****
  	  tree lo_index = TREE_OPERAND (purpose, 0);
  	  tree hi_index = TREE_OPERAND (purpose, 1);
  
  	  if (host_integerp (lo_index, 1) && host_integerp (hi_index, 1))
  	    mult = (tree_low_cst (hi_index, 1)
  		    - tree_low_cst (lo_index, 1) + 1);
  	}
  
        switch (TREE_CODE (value))
  	{
  	case CONSTRUCTOR:
  	  {
! 	    HOST_WIDE_INT nz = 0, nc = 0;
! 	    categorize_ctor_elements_1 (value, &nz, &nc);
  	    nz_elts += mult * nz;
  	    nc_elts += mult * nc;
  	  }
  	  break;
  
--- 4252,4275 ----
  	  tree lo_index = TREE_OPERAND (purpose, 0);
  	  tree hi_index = TREE_OPERAND (purpose, 1);
  
+ 	  /* We can silently generate wrong code when the indices of the
+ 	     range are not representable on the host machine.  */
  	  if (host_integerp (lo_index, 1) && host_integerp (hi_index, 1))
  	    mult = (tree_low_cst (hi_index, 1)
  		    - tree_low_cst (lo_index, 1) + 1);
+ 	  else
+ 	    abort ();
  	}
  
        switch (TREE_CODE (value))
  	{
  	case CONSTRUCTOR:
  	  {
! 	    HOST_WIDE_INT nz = 0, nc = 0, count = 0;
! 	    categorize_ctor_elements_1 (value, &nz, &nc, &count);
  	    nz_elts += mult * nz;
  	    nc_elts += mult * nc;
+ 	    elt_count += mult * count;
  	  }
  	  break;
  
*************** categorize_ctor_elements_1 (tree ctor, H
*** 4266,4275 ****
--- 4277,4288 ----
  	case REAL_CST:
  	  if (!initializer_zerop (value))
  	    nz_elts += mult;
+ 	  elt_count += mult;
  	  break;
  
  	case STRING_CST:
  	  nz_elts += mult * TREE_STRING_LENGTH (value);
+ 	  elt_count += mult * TREE_STRING_LENGTH (value);
  	  break;
  
  	case COMPLEX_CST:
*************** categorize_ctor_elements_1 (tree ctor, H
*** 4277,4295 ****
  	    nz_elts += mult;
  	  if (!initializer_zerop (TREE_IMAGPART (value)))
  	    nz_elts += mult;
  	  break;
  
  	case VECTOR_CST:
  	  {
  	    tree v;
  	    for (v = TREE_VECTOR_CST_ELTS (value); v; v = TREE_CHAIN (v))
! 	      if (!initializer_zerop (TREE_VALUE (v)))
! 	        nz_elts += mult;
  	  }
  	  break;
  
  	default:
  	  nz_elts += mult;
  	  if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
  	    nc_elts += mult;
  	  break;
--- 4290,4313 ----
  	    nz_elts += mult;
  	  if (!initializer_zerop (TREE_IMAGPART (value)))
  	    nz_elts += mult;
+ 	  elt_count += mult;
  	  break;
  
  	case VECTOR_CST:
  	  {
  	    tree v;
  	    for (v = TREE_VECTOR_CST_ELTS (value); v; v = TREE_CHAIN (v))
! 	      {
! 		if (!initializer_zerop (TREE_VALUE (v)))
! 		  nz_elts += mult;
! 		elt_count += mult;
! 	      }
  	  }
  	  break;
  
  	default:
  	  nz_elts += mult;
+ 	  elt_count += mult;
  	  if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
  	    nc_elts += mult;
  	  break;
*************** categorize_ctor_elements_1 (tree ctor, H
*** 4298,4312 ****
  
    *p_nz_elts += nz_elts;
    *p_nc_elts += nc_elts;
  }
  
  void
  categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
! 			  HOST_WIDE_INT *p_nc_elts)
  {
    *p_nz_elts = 0;
    *p_nc_elts = 0;
!   categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts);
  }
  
  /* Count the number of scalars in TYPE.  Return -1 on overflow or
--- 4316,4333 ----
  
    *p_nz_elts += nz_elts;
    *p_nc_elts += nc_elts;
+   *p_elt_count += elt_count;
  }
  
  void
  categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
! 			  HOST_WIDE_INT *p_nc_elts,
! 			  HOST_WIDE_INT *p_elt_count)
  {
    *p_nz_elts = 0;
    *p_nc_elts = 0;
!   *p_elt_count = 0;
!   categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts, p_elt_count);
  }
  
  /* Count the number of scalars in TYPE.  Return -1 on overflow or
*************** mostly_zeros_p (tree exp)
*** 4395,4403 ****
    if (TREE_CODE (exp) == CONSTRUCTOR)
  
      {
!       HOST_WIDE_INT nz_elts, nc_elts, elts;
  
!       categorize_ctor_elements (exp, &nz_elts, &nc_elts);
        elts = count_type_elements (TREE_TYPE (exp));
  
        return nz_elts < elts / 4;
--- 4416,4424 ----
    if (TREE_CODE (exp) == CONSTRUCTOR)
  
      {
!       HOST_WIDE_INT nz_elts, nc_elts, count, elts;
  
!       categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count);
        elts = count_type_elements (TREE_TYPE (exp));
  
        return nz_elts < elts / 4;
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.92
diff -c -3 -p -r2.92 gimplify.c
*** gimplify.c	8 Dec 2004 08:47:47 -0000	2.92
--- gimplify.c	17 Dec 2004 18:13:58 -0000
*************** gimplify_init_ctor_eval (tree object, tr
*** 2395,2408 ****
        if (cleared && initializer_zerop (value))
  	continue;
  
        if (array_elt_type)
  	{
- 	  /* ??? Here's to hoping the front end fills in all of the indicies,
- 	     so we don't have to figure out what's missing ourselves.  */
- 	  gcc_assert (purpose);
- 	  /* ??? Need to handle this.  */
- 	  gcc_assert (TREE_CODE (purpose) != RANGE_EXPR);
- 
  	  cref = build (ARRAY_REF, array_elt_type, unshare_expr (object),
  			purpose, NULL_TREE, NULL_TREE);
  	}
--- 2395,2485 ----
        if (cleared && initializer_zerop (value))
  	continue;
  
+       /* ??? Here's to hoping the front end fills in all of the indices,
+ 	 so we don't have to figure out what's missing ourselves.  */
+       gcc_assert (purpose);
+ 
+       if (TREE_CODE (purpose) == RANGE_EXPR)
+         {
+ 	  tree lower, upper;
+ 
+ 	  gcc_assert (array_elt_type);
+ 
+ 	  lower = TREE_OPERAND (purpose, 0);
+ 	  upper = TREE_OPERAND (purpose, 1);
+ 
+ 	  /* If the lower bound is equal to upper, just treat it as upper
+ 	     was the purpose.  */
+ 	  if (simple_cst_equal (lower, upper))
+ 	    purpose = upper;
+ 	  else
+ 	    {
+ 	      tree var;
+ 	      tree type = TREE_TYPE (upper);
+ 	      tree loop_body = NULL_TREE;
+ 
+ 	      /* Create a loop for the RANGE_EXPR:
+ 
+ 		    var = lower;
+ 		    do
+ 		      {
+ 			object[var] = value;
+ 			if (var >= upper)
+ 			  break;
+ 			var = var + 1;
+ 		      }
+ 		    while (true);
+ 
+ 		 We increment var _after_ the loop exit check because
+ 		 we might otherwise fail if upper == TYPE_MAX_VALUE (type).
+ 
+ 		 Note that we never have to deal with SAVE_EXPRs here,
+ 		 because gimplify_init_ctor_preeval() has already taken
+ 		 care of them for us.  */
+  
+ 	      /* Create and initialize the index variable.  */
+ 	      var = create_tmp_var (type, NULL);
+ 	      gimplify_and_add (build2 (MODIFY_EXPR, type, var, lower), pre_p);
+ 
+ 	      /* Build the reference since we might have to call ourself
+ 	         recusive if the value is a constructor.  */
+ 	      cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
+ 			     var, NULL_TREE, NULL_TREE);
+ 
+ 	      /* If we are a constructor, just call gimplify_init_ctor_eval
+ 	         to do the store. */
+ 	      if (TREE_CODE (value) == CONSTRUCTOR)
+ 		gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
+ 					 &loop_body, cleared);
+ 	      else
+ 	        append_to_statement_list (build2 (MODIFY_EXPR, TREE_TYPE (cref),
+ 						  cref, value),
+ 					  &loop_body);
+ 
+ 	      /* We exit the loop when the index variable is greater than 
+ 		 or equal to the upper index of the RANGE_EXPR.  */
+ 	      append_to_statement_list (build1 (EXIT_EXPR, void_type_node,
+ 						build2 (GE_EXPR, boolean_type_node,
+ 							var, upper)),
+ 					&loop_body);
+ 
+ 	      /* Increment the index variable.  */
+ 	      append_to_statement_list (build2 (MODIFY_EXPR, type, var,
+ 						build2 (PLUS_EXPR, type,
+ 							var,
+ 							fold_convert (type,
+ 								      integer_one_node))),
+ 					&loop_body);
+ 
+ 	      /* Build the loop expression and add it.  */
+ 	      gimplify_and_add (build1 (LOOP_EXPR, void_type_node, loop_body),
+ 			        pre_p);
+ 	      continue;
+ 	    }
+ 	}
+ 
        if (array_elt_type)
  	{
  	  cref = build (ARRAY_REF, array_elt_type, unshare_expr (object),
  			purpose, NULL_TREE, NULL_TREE);
  	}
*************** gimplify_init_constructor (tree *expr_p,
*** 2458,2465 ****
      case ARRAY_TYPE:
        {
  	struct gimplify_init_ctor_preeval_data preeval_data;
! 	HOST_WIDE_INT num_elements, num_nonzero_elements;
! 	HOST_WIDE_INT num_nonconstant_elements;
  	bool cleared;
  
  	/* Aggregate types must lower constructors to initialization of
--- 2535,2542 ----
      case ARRAY_TYPE:
        {
  	struct gimplify_init_ctor_preeval_data preeval_data;
! 	HOST_WIDE_INT num_type_elements, num_ctor_elements;
! 	HOST_WIDE_INT num_nonzero_elements, num_nonconstant_elements;
  	bool cleared;
  
  	/* Aggregate types must lower constructors to initialization of
*************** gimplify_init_constructor (tree *expr_p,
*** 2469,2475 ****
  	  break;
  
  	categorize_ctor_elements (ctor, &num_nonzero_elements,
! 				  &num_nonconstant_elements);
  
  	/* If a const aggregate variable is being initialized, then it
  	   should never be a lose to promote the variable to be static.  */
--- 2546,2553 ----
  	  break;
  
  	categorize_ctor_elements (ctor, &num_nonzero_elements,
! 				  &num_nonconstant_elements,
! 				  &num_ctor_elements);
  
  	/* If a const aggregate variable is being initialized, then it
  	   should never be a lose to promote the variable to be static.  */
*************** gimplify_init_constructor (tree *expr_p,
*** 2552,2563 ****
  	   parts in, then generate code for the non-constant parts.  */
  	/* TODO.  There's code in cp/typeck.c to do this.  */
  
! 	num_elements = count_type_elements (TREE_TYPE (ctor));
  
  	/* If there are "lots" of zeros, then block clear the object first.  */
  	cleared = false;
! 	if (num_elements - num_nonzero_elements > CLEAR_RATIO
! 	    && num_nonzero_elements < num_elements/4)
  	  cleared = true;
  
  	/* ??? This bit ought not be needed.  For any element not present
--- 2630,2641 ----
  	   parts in, then generate code for the non-constant parts.  */
  	/* TODO.  There's code in cp/typeck.c to do this.  */
  
! 	num_type_elements = count_type_elements (TREE_TYPE (ctor));
  
  	/* If there are "lots" of zeros, then block clear the object first.  */
  	cleared = false;
! 	if (num_type_elements - num_nonzero_elements > CLEAR_RATIO
! 	    && num_nonzero_elements < num_type_elements/4)
  	  cleared = true;
  
  	/* ??? This bit ought not be needed.  For any element not present
*************** gimplify_init_constructor (tree *expr_p,
*** 2565,2583 ****
  	   we'd need to *find* the elements that are not present, and that
  	   requires trickery to avoid quadratic compile-time behavior in
  	   large cases or excessive memory use in small cases.  */
! 	else
! 	  {
! 	    HOST_WIDE_INT len = list_length (elt_list);
! 	    if (TREE_CODE (type) == ARRAY_TYPE)
! 	      {
! 		tree nelts = array_type_nelts (type);
! 		if (!host_integerp (nelts, 1)
! 		    || tree_low_cst (nelts, 1) + 1 != len)
! 		  cleared = true;
! 	      }
! 	    else if (len != fields_length (type))
! 	      cleared = true;
! 	  }
  
  	if (cleared)
  	  {
--- 2643,2650 ----
  	   we'd need to *find* the elements that are not present, and that
  	   requires trickery to avoid quadratic compile-time behavior in
  	   large cases or excessive memory use in small cases.  */
! 	else if (num_ctor_elements < num_type_elements)
! 	  cleared = true;
  
  	if (cleared)
  	  {
*************** gimplify_init_constructor (tree *expr_p,
*** 2590,2603 ****
  	    append_to_statement_list (*expr_p, pre_p);
  	  }
  
! 	preeval_data.lhs_base_decl = get_base_address (object);
! 	if (!DECL_P (preeval_data.lhs_base_decl))
! 	  preeval_data.lhs_base_decl = NULL;
! 	preeval_data.lhs_alias_set = get_alias_set (object);
! 
! 	gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
! 				    pre_p, post_p, &preeval_data);
! 	gimplify_init_ctor_eval (object, elt_list, pre_p, cleared);
  
  	*expr_p = NULL_TREE;
        }
--- 2657,2676 ----
  	    append_to_statement_list (*expr_p, pre_p);
  	  }
  
! 	/* If we have not block cleared the object, or if there are nonzero
! 	   elements in the constructor, add assignments to the individual
! 	   scalar fields of the object.  */
! 	if (!cleared || num_nonzero_elements > 0)
! 	  {
! 	    preeval_data.lhs_base_decl = get_base_address (object);
! 	    if (!DECL_P (preeval_data.lhs_base_decl))
! 	      preeval_data.lhs_base_decl = NULL;
! 	    preeval_data.lhs_alias_set = get_alias_set (object);
! 
! 	    gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
! 					pre_p, post_p, &preeval_data);
! 	    gimplify_init_ctor_eval (object, elt_list, pre_p, cleared);
! 	  }
  
  	*expr_p = NULL_TREE;
        }
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.666
diff -c -3 -p -r1.666 tree.h
*** tree.h	9 Dec 2004 10:54:38 -0000	1.666
--- tree.h	17 Dec 2004 18:13:59 -0000
*************** extern int fields_length (tree);
*** 3226,3232 ****
  
  extern bool initializer_zerop (tree);
  
! extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *);
  extern HOST_WIDE_INT count_type_elements (tree);
  
  /* add_var_to_bind_expr (bind_expr, var) binds var to bind_expr.  */
--- 3226,3233 ----
  
  extern bool initializer_zerop (tree);
  
! extern void categorize_ctor_elements (tree, HOST_WIDE_INT *,
! 				      HOST_WIDE_INT *, HOST_WIDE_INT *);
  extern HOST_WIDE_INT count_type_elements (tree);
  
  /* add_var_to_bind_expr (bind_expr, var) binds var to bind_expr.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]