This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
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();
+}
+