From 20169a6424f72bb0852b222ccd726793317904d1 Mon Sep 17 00:00:00 2001 From: hainque Date: Tue, 18 Jul 2006 13:07:28 +0000 Subject: [PATCH] * tree.h (categorize_ctor_elements): Adjust prototype and add descriptive comment, both in accordance with the interface change described below. * varasm.c (constructor_static_from_elts_p): New function. Whether a constructor node is a valid static constant initializer if all its elements are. (initializer_constant_valid_p) : Use it. * output.h: Declare it. * expr.c (categorize_ctor_elements_1): Return whether the constructor is a valid constant initializer instead of computing the number of non-constant elements. Use constructor_static_from_elts_p for this purpose. Replace the head comment with an indication that this is a helper for categorize_ctor_elements. (categorize_ctor_elements): Same interface change as for the _1 helper. Former head comment from this helper moved here, adjusted to account for the interface changes. (mostly_zeros_p): Adjust call to categorize_ctor_elements. (all_zeros_p): Likewise. * gimplify.c (gimplify_init_constructor): Decide whether we can make static versions of the constructor from the categorize_ctor_elements return value instead of the formerly computed number of non-constant elements. * gnat.dg/outer_agg_bitfield_constructor.adb: New test. * gnat.dg/nested_agg_bitfield_constructor.adb: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@115553 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 25 ++++++++ gcc/expr.c | 72 +++++++++++++--------- gcc/gimplify.c | 17 ++--- gcc/output.h | 7 +++ gcc/testsuite/ChangeLog | 5 ++ .../gnat.dg/nested_agg_bitfield_constructor.adb | 34 ++++++++++ .../gnat.dg/outer_agg_bitfield_constructor.adb | 44 +++++++++++++ gcc/tree.h | 16 ++++- gcc/varasm.c | 19 ++++-- 9 files changed, 197 insertions(+), 42 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb create mode 100644 gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5cc02be7c4c..558765d4b53 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2006-07-18 Olivier Hainque + + * tree.h (categorize_ctor_elements): Adjust prototype and add + descriptive comment, both in accordance with the interface change + described below. + * varasm.c (constructor_static_from_elts_p): New function. + Whether a constructor node is a valid static constant initializer + if all its elements are. + (initializer_constant_valid_p) : Use it. + * output.h: Declare it. + * expr.c (categorize_ctor_elements_1): Return whether the constructor + is a valid constant initializer instead of computing the number of + non-constant elements. Use constructor_static_from_elts_p for this + purpose. Replace the head comment with an indication that this is a + helper for categorize_ctor_elements. + (categorize_ctor_elements): Same interface change as for the _1 + helper. Former head comment from this helper moved here, adjusted to + account for the interface changes. + (mostly_zeros_p): Adjust call to categorize_ctor_elements. + (all_zeros_p): Likewise. + * gimplify.c (gimplify_init_constructor): Decide whether we can make + static versions of the constructor from the categorize_ctor_elements + return value instead of the formerly computed number of non-constant + elements. + 2006-07-18 Paolo Bonzini * configure: Regenerate. diff --git a/gcc/expr.c b/gcc/expr.c index e46e3e787bd..48ec0ef6f67 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4531,28 +4531,24 @@ store_expr (tree exp, rtx target, int call_param_p) 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. - * if a type is a union, and the initializer from the constructor - is not the largest element in the union, then set *p_must_clear. */ +/* Helper for categorize_ctor_elements. Identical interface. */ -static void +static bool categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, - HOST_WIDE_INT *p_nc_elts, HOST_WIDE_INT *p_elt_count, bool *p_must_clear) { unsigned HOST_WIDE_INT idx; - HOST_WIDE_INT nz_elts, nc_elts, elt_count; + HOST_WIDE_INT nz_elts, elt_count; tree value, purpose; + /* Whether CTOR is a valid constant initializer, in accordance with what + initializer_constant_valid_p does. If inferred from the constructor + elements, true until proven otherwise. */ + bool const_from_elts_p = constructor_static_from_elts_p (ctor); + bool const_p = const_from_elts_p ? true : TREE_STATIC (ctor); + nz_elts = 0; - nc_elts = 0; elt_count = 0; FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, purpose, value) @@ -4574,11 +4570,16 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, { case CONSTRUCTOR: { - HOST_WIDE_INT nz = 0, nc = 0, ic = 0; - categorize_ctor_elements_1 (value, &nz, &nc, &ic, p_must_clear); + HOST_WIDE_INT nz = 0, ic = 0; + + bool const_elt_p + = categorize_ctor_elements_1 (value, &nz, &ic, p_must_clear); + nz_elts += mult * nz; - nc_elts += mult * nc; - elt_count += mult * ic; + elt_count += mult * ic; + + if (const_from_elts_p && const_p) + const_p = const_elt_p; } break; @@ -4617,8 +4618,10 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, default: nz_elts += mult; elt_count += mult; - if (!initializer_constant_valid_p (value, TREE_TYPE (value))) - nc_elts += mult; + + if (const_from_elts_p && const_p) + const_p = initializer_constant_valid_p (value, TREE_TYPE (value)) + != NULL_TREE; break; } } @@ -4660,22 +4663,33 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, } *p_nz_elts += nz_elts; - *p_nc_elts += nc_elts; *p_elt_count += elt_count; + + return const_p; } -void +/* Examine CTOR to discover: + * how many scalar fields are set to nonzero values, + and place it in *P_NZ_ELTS; + * how many scalar fields in total are in CTOR, + and place it in *P_ELT_COUNT. + * if a type is a union, and the initializer from the constructor + is not the largest element in the union, then set *p_must_clear. + + Return whether or not CTOR is a valid static constant initializer, the same + as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0". */ + +bool categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts, - HOST_WIDE_INT *p_nc_elts, HOST_WIDE_INT *p_elt_count, bool *p_must_clear) { *p_nz_elts = 0; - *p_nc_elts = 0; *p_elt_count = 0; *p_must_clear = false; - categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts, p_elt_count, - p_must_clear); + + return + categorize_ctor_elements_1 (ctor, p_nz_elts, p_elt_count, p_must_clear); } /* Count the number of scalars in TYPE. Return -1 on overflow or @@ -4777,10 +4791,10 @@ mostly_zeros_p (tree exp) if (TREE_CODE (exp) == CONSTRUCTOR) { - HOST_WIDE_INT nz_elts, nc_elts, count, elts; + HOST_WIDE_INT nz_elts, count, elts; bool must_clear; - categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count, &must_clear); + categorize_ctor_elements (exp, &nz_elts, &count, &must_clear); if (must_clear) return 1; @@ -4800,10 +4814,10 @@ all_zeros_p (tree exp) if (TREE_CODE (exp) == CONSTRUCTOR) { - HOST_WIDE_INT nz_elts, nc_elts, count; + HOST_WIDE_INT nz_elts, count; bool must_clear; - categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count, &must_clear); + categorize_ctor_elements (exp, &nz_elts, &count, &must_clear); return nz_elts == 0; } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index a5e7e6686b1..16e4d3c6e07 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2940,8 +2940,8 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, { 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; + HOST_WIDE_INT num_nonzero_elements; + bool cleared, valid_const_initializer; /* Aggregate types must lower constructors to initialization of individual elements. The exception is that a CONSTRUCTOR node @@ -2949,13 +2949,16 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, if (VEC_empty (constructor_elt, elts)) break; - categorize_ctor_elements (ctor, &num_nonzero_elements, - &num_nonconstant_elements, - &num_ctor_elements, &cleared); + /* Fetch information about the constructor to direct later processing. + We might want to make static versions of it in various cases, and + can only do so if it known to be a valid constant initializer. */ + valid_const_initializer + = categorize_ctor_elements (ctor, &num_nonzero_elements, + &num_ctor_elements, &cleared); /* If a const aggregate variable is being initialized, then it should never be a lose to promote the variable to be static. */ - if (num_nonconstant_elements == 0 + if (valid_const_initializer && num_nonzero_elements > 1 && TREE_READONLY (object) && TREE_CODE (object) == VAR_DECL) @@ -3012,7 +3015,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, for sparse arrays, though, as it's more efficient to follow the standard CONSTRUCTOR behavior of memset followed by individual element initialization. */ - if (num_nonconstant_elements == 0 && !cleared) + if (valid_const_initializer && !cleared) { HOST_WIDE_INT size = int_size_in_bytes (type); unsigned int align; diff --git a/gcc/output.h b/gcc/output.h index 6d518c45803..3cfe32c93cf 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -280,6 +280,13 @@ extern void output_shared_constant_pool (void); extern void output_object_blocks (void); +/* Whether a constructor CTOR is a valid static constant initializer if all + its elements are. This used to be internal to initializer_constant_valid_p + and has been exposed to let other functions like categorize_ctor_elements + evaluate the property while walking a constructor for other purposes. */ + +extern bool constructor_static_from_elts_p (tree); + /* Return nonzero if VALUE is a valid constant-valued expression for use in initializing a static variable; one that can be an element of a "constant" initializer. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0828f4aaa2a..f73f2e60644 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-07-18 Olivier Hainque + + * gnat.dg/outer_agg_bitfield_constructor.adb: New test. + * gnat.dg/nested_agg_bitfield_constructor.adb: New test. + 2006-07-18 Volker Reichelt PR c/28286 diff --git a/gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb b/gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb new file mode 100644 index 00000000000..6015900c5aa --- /dev/null +++ b/gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb @@ -0,0 +1,34 @@ +-- { dg-do compile } +-- { dg-options "-gnatws" } +-- (bits of "Header" unused) + +procedure Nested_Agg_Bitfield_Constructor is + + type Uint64 is mod 2 ** 64; + type Uint16 is mod 2 ** 16; + + type Time_Stamp is record + Sec : Uint64; + Year : Uint16; + end record; + + type Msg_Header is record + Stamp : Time_Stamp; + end record; + for Msg_Header use record + Stamp at 0 range 0 .. 64+16-1; + end record; + for Msg_Header'Size use 80; + + type Msg is record + Header : Msg_Header; + end record; + + for Msg use record + Header at 0 range 0 .. 191; + end record; + + M : Msg := (Header => (Stamp => (2, 4))); +begin + null; +end; diff --git a/gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb b/gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb new file mode 100644 index 00000000000..6658042e963 --- /dev/null +++ b/gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb @@ -0,0 +1,44 @@ +-- { dg-do run } + +procedure Outer_Agg_Bitfield_Constructor is + + type Mod_64 is mod 2 ** 64; + for Mod_64'Size use 64; + + type Uint_16 is range 0 .. 2 ** 16 - 1; + for Uint_16'Size use 16; + + type Values_Type is record + M64 : Mod_64; + U16 : Uint_16; + end record; + + for Values_Type use record + M64 at 0 range 0 .. 63; + U16 at 8 range 0 .. 15; + end record; + + type Wrapper_Type is record + Values : Values_Type; + end record; + + for Wrapper_Type use record + Values at 0 range 0 .. 79; + end record; + + M : constant := 2; + U : constant := 4; + + W : Wrapper_Type := (Values => (M, U)); + + procedure Check (O : Wrapper_Type) is + begin + if O.Values.M64 /= M or else O.Values.U16 /= U then + raise Program_Error; + end if; + end; +begin + Check (W); +end; + + diff --git a/gcc/tree.h b/gcc/tree.h index 12e2f592b32..dfea92adc1d 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3924,8 +3924,20 @@ extern int fields_length (tree); extern bool initializer_zerop (tree); -extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, - HOST_WIDE_INT *, bool *); +/* Examine CTOR to discover: + * how many scalar fields are set to nonzero values, + and place it in *P_NZ_ELTS; + * how many scalar fields in total are in CTOR, + and place it in *P_ELT_COUNT. + * if a type is a union, and the initializer from the constructor + is not the largest element in the union, then set *p_must_clear. + + Return whether or not CTOR is a valid static constant initializer, the same + as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0". */ + +extern bool categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, + bool *); + extern HOST_WIDE_INT count_type_elements (tree, bool); /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0. */ diff --git a/gcc/varasm.c b/gcc/varasm.c index 9dcc3b442cf..1f5f43a1b4e 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -3699,6 +3699,20 @@ output_addressed_constants (tree exp) } } +/* Whether a constructor CTOR is a valid static constant initializer if all + its elements are. This used to be internal to initializer_constant_valid_p + and has been exposed to let other functions like categorize_ctor_elements + evaluate the property while walking a constructor for other purposes. */ + +bool +constructor_static_from_elts_p (tree ctor) +{ + return (TREE_CONSTANT (ctor) + && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE + || TREE_CODE (TREE_TYPE (ctor)) == RECORD_TYPE) + && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor))); +} + /* Return nonzero if VALUE is a valid constant-valued expression for use in initializing a static variable; one that can be an element of a "constant" initializer. @@ -3719,10 +3733,7 @@ initializer_constant_valid_p (tree value, tree endtype) switch (TREE_CODE (value)) { case CONSTRUCTOR: - if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE - || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE) - && TREE_CONSTANT (value) - && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (value))) + if (constructor_static_from_elts_p (value)) { unsigned HOST_WIDE_INT idx; tree elt; -- 2.11.0