tree.h (categorize_ctor_elements): Adjust prototype and add descriptive comment...

* 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) <CONSTRUCTOR value>: 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.

From-SVN: r115553
This commit is contained in:
Olivier Hainque 2006-07-18 13:07:28 +00:00 committed by Olivier Hainque
parent 57255173da
commit fe24d4852e
9 changed files with 197 additions and 42 deletions

View File

@ -1,3 +1,28 @@
2006-07-18 Olivier Hainque <hainque@adacore.com>
* 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) <CONSTRUCTOR value>: 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 <bonzini@gnu.org>
* configure: Regenerate.

View File

@ -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;
}

View File

@ -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;

View File

@ -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.

View File

@ -1,3 +1,8 @@
2006-07-18 Olivier Hainque <hainque@adacore.com>
* gnat.dg/outer_agg_bitfield_constructor.adb: New test.
* gnat.dg/nested_agg_bitfield_constructor.adb: New test.
2006-07-18 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c/28286

View File

@ -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;

View File

@ -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;

View File

@ -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. */

View File

@ -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;