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]

Re: [PATCH] PR18191


On Sunday 19 December 2004 21:22, Richard Henderson wrote:
> On Sun, Dec 19, 2004 at 02:03:29PM +0100, Steven Bosscher wrote:
> > +  /* 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);
>
> By using LOOP_EXPR+EXIT_EXPR, you're gimplifying this bit twice.
>
> > +    append_to_statement_list (build2 (MODIFY_EXPR, TREE_TYPE (cref),
> > +				      cref, value),
> > +			      &loop_body);
>
> Gimplification of this one statement would eventually call back to
> gimplify_init_ctor_eval, though I'm not sure how that works out since
> we've already pre-eval'ed it once.
>
> I suggest not using LOOP_EXPR and just emitting the two labels and
> the two gotos yourself.

I'm testing this updated one now; same ChangeLog.

Gr.
Steven

Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.761
diff -u -3 -p -r1.761 expr.c
--- expr.c	18 Dec 2004 14:38:31 -0000	1.761
+++ expr.c	19 Dec 2004 23:59:10 -0000
@@ -4220,19 +4220,25 @@ store_expr (tree exp, rtx target, int ca
   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.  */
+/* 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_nc_elts,
+			    HOST_WIDE_INT *p_elt_count)
 {
-  HOST_WIDE_INT nz_elts, nc_elts;
+  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))
     {
@@ -4255,10 +4261,11 @@ categorize_ctor_elements_1 (tree ctor, H
 	{
 	case CONSTRUCTOR:
 	  {
-	    HOST_WIDE_INT nz = 0, nc = 0;
-	    categorize_ctor_elements_1 (value, &nz, &nc);
+	    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;
 
@@ -4266,10 +4273,12 @@ categorize_ctor_elements_1 (tree ctor, H
 	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:
@@ -4277,19 +4286,24 @@ categorize_ctor_elements_1 (tree ctor, H
 	    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;
+	      {
+		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;
@@ -4298,15 +4312,18 @@ categorize_ctor_elements_1 (tree ctor, H
 
   *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_nc_elts,
+			  HOST_WIDE_INT *p_elt_count)
 {
   *p_nz_elts = 0;
   *p_nc_elts = 0;
-  categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts);
+  *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
@@ -4395,9 +4412,9 @@ mostly_zeros_p (tree exp)
   if (TREE_CODE (exp) == CONSTRUCTOR)
 
     {
-      HOST_WIDE_INT nz_elts, nc_elts, elts;
+      HOST_WIDE_INT nz_elts, nc_elts, count, elts;
 
-      categorize_ctor_elements (exp, &nz_elts, &nc_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.93
diff -u -3 -p -r2.93 gimplify.c
--- gimplify.c	19 Dec 2004 04:42:13 -0000	2.93
+++ gimplify.c	19 Dec 2004 23:59:12 -0000
@@ -2367,6 +2367,88 @@ gimplify_init_ctor_preeval (tree *expr_p
   *expr_p = get_formal_tmp_var (*expr_p, pre_p);
 }
 
+/* A subroutine of gimplify_init_ctor_eval.  Create a loop for
+   a RANGE_EXPR in a CONSTRUCTOR for an array.
+
+      var = lower;
+    loop_entry:
+      object[var] = value;
+      if (var == upper)
+	goto loop_exit;
+      var = var + 1;
+      goto loop_entry;
+    loop_exit:
+
+   We increment var _after_ the loop exit check because we might otherwise
+   fail if upper == TYPE_MAX_VALUE (type for upper).
+
+   Note that we never have to deal with SAVE_EXPRs here, because this has
+   already been taken care of for us, in gimplify_init_ctor_preeval().  */
+
+static void gimplify_init_ctor_eval (tree, tree, tree *, bool);
+
+static void
+gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
+			       tree value, tree array_elt_type,
+			       tree *pre_p, bool cleared)
+{
+  tree loop_entry_label, loop_exit_label;
+  tree var, var_type, cref;
+
+  loop_entry_label = create_artificial_label ();
+  loop_exit_label = create_artificial_label ();
+
+  /* Create and initialize the index variable.  */
+  var_type = TREE_TYPE (upper);
+  var = create_tmp_var (var_type, NULL);
+  append_to_statement_list (build2 (MODIFY_EXPR, var_type, var, lower), pre_p);
+
+  /* Add the loop entry label.  */
+  append_to_statement_list (loop_entry_label, pre_p);
+
+  /* Build the reference.  */
+  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.  Otherwise just assign value to the reference.  */
+  if (TREE_CODE (value) == CONSTRUCTOR)
+    /* NB we might have to call ourself recursively through
+       gimplify_init_ctor_eval if the value is a constructor.  */
+    gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
+			     pre_p, cleared);
+  else
+    append_to_statement_list (build2 (MODIFY_EXPR, TREE_TYPE (cref),
+				      cref, value),
+			      pre_p);
+
+  /* We exit the loop when the index var is equal to the upper bound.  */
+  append_to_statement_list (build3 (COND_EXPR, void_type_node,
+				    build2 (EQ_EXPR, boolean_type_node,
+					    var, upper),
+				    build1 (GOTO_EXPR,
+					    void_type_node,
+					    loop_exit_label),
+				    NULL_TREE),
+			    pre_p);
+
+  /* Otherwise, increment the index var...  */
+  append_to_statement_list (build2 (MODIFY_EXPR, var_type, var,
+				    build2 (PLUS_EXPR, var_type, var,
+					    fold_convert (var_type,
+							  integer_one_node))),
+			    pre_p);
+
+  /* ...and jump back to the loop entry.  */
+  append_to_statement_list (build1 (GOTO_EXPR,
+				    void_type_node,
+				    loop_entry_label),
+			    pre_p);
+
+  /* Add the loop exit label.  */
+  append_to_statement_list (loop_exit_label, pre_p);
+}
+
 /* A subroutine of gimplify_init_constructor.  Generate individual
    MODIFY_EXPRs for a CONSTRUCTOR.  OBJECT is the LHS against which the
    assignments should happen.  LIST is the CONSTRUCTOR_ELTS of the
@@ -2395,14 +2477,31 @@ gimplify_init_ctor_eval (tree object, tr
       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 we have a RANGE_EXPR, we have to build a loop to assign the
+	 whole range.  */
+      if (TREE_CODE (purpose) == RANGE_EXPR)
+	{
+	  tree lower = TREE_OPERAND (purpose, 0);
+	  tree upper = TREE_OPERAND (purpose, 1);
+
+	  /* If the lower bound is equal to upper, just treat it as if
+	     upper was the index.  */
+	  if (simple_cst_equal (lower, upper))
+	    purpose = upper;
+	  else
+	    {
+	      gimplify_init_ctor_eval_range (object, lower, upper, value,
+					     array_elt_type, pre_p, cleared);
+	      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);
 	}
@@ -2458,8 +2557,8 @@ gimplify_init_constructor (tree *expr_p,
     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;
+	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
@@ -2469,7 +2568,8 @@ gimplify_init_constructor (tree *expr_p,
 	  break;
 
 	categorize_ctor_elements (ctor, &num_nonzero_elements,
-				  &num_nonconstant_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.  */
@@ -2552,12 +2652,12 @@ gimplify_init_constructor (tree *expr_p,
 	   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));
+	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_elements - num_nonzero_elements > CLEAR_RATIO
-	    && num_nonzero_elements < num_elements/4)
+	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
@@ -2565,19 +2665,8 @@ gimplify_init_constructor (tree *expr_p,
 	   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;
-	  }
+	else if (num_ctor_elements < num_type_elements)
+	  cleared = true;
 
 	if (cleared)
 	  {
@@ -2590,14 +2679,20 @@ gimplify_init_constructor (tree *expr_p,
 	    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);
+	/* 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.667
diff -u -3 -p -r1.667 tree.h
--- tree.h	19 Dec 2004 04:42:14 -0000	1.667
+++ tree.h	19 Dec 2004 23:59:14 -0000
@@ -3226,7 +3226,8 @@ extern int fields_length (tree);
 
 extern bool initializer_zerop (tree);
 
-extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *);
+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: testsuite/gcc.dg/20041219-1.c
===================================================================
RCS file: testsuite/gcc.dg/20041219-1.c
diff -N testsuite/gcc.dg/20041219-1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/20041219-1.c	19 Dec 2004 23:59:23 -0000
@@ -0,0 +1,47 @@
+/* PR18191 Struct member is not getting default-initialized.
+   Origin: Grigory Zagorodnev  <grigory.zagorodnev@intel.com>  */
+
+/* { dg-do run } */
+
+extern int printf (__const char *__restrict __format, ...);
+
+typedef struct S {
+  const char* s;
+  int         i;
+} S;
+
+void
+foo (void)
+{
+  S dummy[2];
+  unsigned i;
+
+  /* Put some garbage on the stack.  */
+  for (i = 0; i < sizeof(dummy); i++)
+    ((char *)&dummy)[i] = -1;
+}
+
+int
+bar (void)
+{
+  /* Allocate object on the stack.  */
+  S obj[2] = { {"m0"}, {"m1"} };
+
+  /* Assume fields those not explicitly initialized
+     are default initialized to 0 [8.5.1/7 and 8.5/5].  */
+  if (obj[0].i == 0)
+    return 0;
+  else
+    {
+      printf("Failed: obj[0].i == '%d', expecting '0'\n", obj[0].i);
+      return 1;
+    }
+}
+
+int
+main (void)
+{
+  foo();
+  return bar();
+}
+


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