Commit 953d0c90 by Richard Sandiford

tree.h (categorize_ctor_elements): Remove comment.

gcc/
	* tree.h (categorize_ctor_elements): Remove comment.  Fix long line.
	(count_type_elements): Delete.
	(complete_ctor_at_level_p): Declare.
	* expr.c (flexible_array_member_p): New function, split out from...
	(count_type_elements): ...here.  Make static.  Replace allow_flexarr
	parameter with for_ctor_p.  When for_ctor_p is true, return the
	number of elements that should appear in the top-level constructor,
	otherwise return an estimate of the number of scalars.
	(categorize_ctor_elements): Replace p_must_clear with p_complete.
	(categorize_ctor_elements_1): Likewise.  Use complete_ctor_at_level_p.
	(complete_ctor_at_level_p): New function, borrowing union logic
	from old categorize_ctor_elements_1.
	(mostly_zeros_p): Return true if the constructor is not complete.
	(all_zeros_p): Update call to categorize_ctor_elements.
	* gimplify.c (gimplify_init_constructor): Update call to
	categorize_ctor_elements.  Don't call count_type_elements.
	Unconditionally prevent clearing for variable-sized types,
	otherwise rely on categorize_ctor_elements to detect
	incomplete initializers.

gcc/cp/
	* typeck2.c (split_nonconstant_init_1): Pass the initializer directly,
	rather than a pointer to it.  Return true if the whole of the value
	was initialized by the generated statements.  Use
	complete_ctor_at_level_p instead of count_type_elements.

gcc/testsuite/
2011-07-12  Chung-Lin Tang  <cltang@codesourcery.com>

	* gcc.target/arm/pr48183.c: New test.

From-SVN: r176228
parent 9111c715
2011-07-13 Richard Sandiford <richard.sandiford@linaro.org>
* tree.h (categorize_ctor_elements): Remove comment. Fix long line.
(count_type_elements): Delete.
(complete_ctor_at_level_p): Declare.
* expr.c (flexible_array_member_p): New function, split out from...
(count_type_elements): ...here. Make static. Replace allow_flexarr
parameter with for_ctor_p. When for_ctor_p is true, return the
number of elements that should appear in the top-level constructor,
otherwise return an estimate of the number of scalars.
(categorize_ctor_elements): Replace p_must_clear with p_complete.
(categorize_ctor_elements_1): Likewise. Use complete_ctor_at_level_p.
(complete_ctor_at_level_p): New function, borrowing union logic
from old categorize_ctor_elements_1.
(mostly_zeros_p): Return true if the constructor is not complete.
(all_zeros_p): Update call to categorize_ctor_elements.
* gimplify.c (gimplify_init_constructor): Update call to
categorize_ctor_elements. Don't call count_type_elements.
Unconditionally prevent clearing for variable-sized types,
otherwise rely on categorize_ctor_elements to detect
incomplete initializers.
2011-07-13 Richard Guenther <rguenther@suse.de> 2011-07-13 Richard Guenther <rguenther@suse.de>
* tree-vrp.c (simplify_conversion_using_ranges): Make sure * tree-vrp.c (simplify_conversion_using_ranges): Make sure
......
2011-07-13 Richard Sandiford <richard.sandiford@linaro.org>
* typeck2.c (split_nonconstant_init_1): Pass the initializer directly,
rather than a pointer to it. Return true if the whole of the value
was initialized by the generated statements. Use
complete_ctor_at_level_p instead of count_type_elements.
2011-07-12 Diego Novillo <dnovillo@google.com> 2011-07-12 Diego Novillo <dnovillo@google.com>
* name-lookup.h (cp_binding_level): Rename from cxx_scope. * name-lookup.h (cp_binding_level): Rename from cxx_scope.
......
...@@ -481,18 +481,20 @@ cxx_incomplete_type_error (const_tree value, const_tree type) ...@@ -481,18 +481,20 @@ cxx_incomplete_type_error (const_tree value, const_tree type)
/* The recursive part of split_nonconstant_init. DEST is an lvalue /* The recursive part of split_nonconstant_init. DEST is an lvalue
expression to which INIT should be assigned. INIT is a CONSTRUCTOR. */ expression to which INIT should be assigned. INIT is a CONSTRUCTOR.
Return true if the whole of the value was initialized by the
generated statements. */
static void static bool
split_nonconstant_init_1 (tree dest, tree *initp) split_nonconstant_init_1 (tree dest, tree init)
{ {
unsigned HOST_WIDE_INT idx; unsigned HOST_WIDE_INT idx;
tree init = *initp;
tree field_index, value; tree field_index, value;
tree type = TREE_TYPE (dest); tree type = TREE_TYPE (dest);
tree inner_type = NULL; tree inner_type = NULL;
bool array_type_p = false; bool array_type_p = false;
HOST_WIDE_INT num_type_elements, num_initialized_elements; bool complete_p = true;
HOST_WIDE_INT num_split_elts = 0;
switch (TREE_CODE (type)) switch (TREE_CODE (type))
{ {
...@@ -504,7 +506,6 @@ split_nonconstant_init_1 (tree dest, tree *initp) ...@@ -504,7 +506,6 @@ split_nonconstant_init_1 (tree dest, tree *initp)
case RECORD_TYPE: case RECORD_TYPE:
case UNION_TYPE: case UNION_TYPE:
case QUAL_UNION_TYPE: case QUAL_UNION_TYPE:
num_initialized_elements = 0;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx,
field_index, value) field_index, value)
{ {
...@@ -527,13 +528,14 @@ split_nonconstant_init_1 (tree dest, tree *initp) ...@@ -527,13 +528,14 @@ split_nonconstant_init_1 (tree dest, tree *initp)
sub = build3 (COMPONENT_REF, inner_type, dest, field_index, sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE); NULL_TREE);
split_nonconstant_init_1 (sub, &value); if (!split_nonconstant_init_1 (sub, value))
complete_p = false;
num_split_elts++;
} }
else if (!initializer_constant_valid_p (value, inner_type)) else if (!initializer_constant_valid_p (value, inner_type))
{ {
tree code; tree code;
tree sub; tree sub;
HOST_WIDE_INT inner_elements;
/* FIXME: Ordered removal is O(1) so the whole function is /* FIXME: Ordered removal is O(1) so the whole function is
worst-case quadratic. This could be fixed using an aside worst-case quadratic. This could be fixed using an aside
...@@ -557,21 +559,9 @@ split_nonconstant_init_1 (tree dest, tree *initp) ...@@ -557,21 +559,9 @@ split_nonconstant_init_1 (tree dest, tree *initp)
code = build_stmt (input_location, EXPR_STMT, code); code = build_stmt (input_location, EXPR_STMT, code);
add_stmt (code); add_stmt (code);
inner_elements = count_type_elements (inner_type, true); num_split_elts++;
if (inner_elements < 0)
num_initialized_elements = -1;
else if (num_initialized_elements >= 0)
num_initialized_elements += inner_elements;
continue;
} }
} }
num_type_elements = count_type_elements (type, true);
/* If all elements of the initializer are non-constant and
have been split out, we don't need the empty CONSTRUCTOR. */
if (num_type_elements > 0
&& num_type_elements == num_initialized_elements)
*initp = NULL;
break; break;
case VECTOR_TYPE: case VECTOR_TYPE:
...@@ -583,6 +573,7 @@ split_nonconstant_init_1 (tree dest, tree *initp) ...@@ -583,6 +573,7 @@ split_nonconstant_init_1 (tree dest, tree *initp)
code = build2 (MODIFY_EXPR, type, dest, cons); code = build2 (MODIFY_EXPR, type, dest, cons);
code = build_stmt (input_location, EXPR_STMT, code); code = build_stmt (input_location, EXPR_STMT, code);
add_stmt (code); add_stmt (code);
num_split_elts += CONSTRUCTOR_NELTS (init);
} }
break; break;
...@@ -592,6 +583,8 @@ split_nonconstant_init_1 (tree dest, tree *initp) ...@@ -592,6 +583,8 @@ split_nonconstant_init_1 (tree dest, tree *initp)
/* The rest of the initializer is now a constant. */ /* The rest of the initializer is now a constant. */
TREE_CONSTANT (init) = 1; TREE_CONSTANT (init) = 1;
return complete_p && complete_ctor_at_level_p (TREE_TYPE (init),
num_split_elts, inner_type);
} }
/* A subroutine of store_init_value. Splits non-constant static /* A subroutine of store_init_value. Splits non-constant static
...@@ -607,7 +600,8 @@ split_nonconstant_init (tree dest, tree init) ...@@ -607,7 +600,8 @@ split_nonconstant_init (tree dest, tree init)
if (TREE_CODE (init) == CONSTRUCTOR) if (TREE_CODE (init) == CONSTRUCTOR)
{ {
code = push_stmt_list (); code = push_stmt_list ();
split_nonconstant_init_1 (dest, &init); if (split_nonconstant_init_1 (dest, init))
init = NULL_TREE;
code = pop_stmt_list (code); code = pop_stmt_list (code);
DECL_INITIAL (dest) = init; DECL_INITIAL (dest) = init;
TREE_READONLY (dest) = 0; TREE_READONLY (dest) = 0;
......
...@@ -3731,9 +3731,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ...@@ -3731,9 +3731,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case ARRAY_TYPE: case ARRAY_TYPE:
{ {
struct gimplify_init_ctor_preeval_data preeval_data; struct gimplify_init_ctor_preeval_data preeval_data;
HOST_WIDE_INT num_type_elements, num_ctor_elements; HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
HOST_WIDE_INT num_nonzero_elements; bool cleared, complete_p, valid_const_initializer;
bool cleared, valid_const_initializer;
/* Aggregate types must lower constructors to initialization of /* Aggregate types must lower constructors to initialization of
individual elements. The exception is that a CONSTRUCTOR node individual elements. The exception is that a CONSTRUCTOR node
...@@ -3750,7 +3749,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ...@@ -3750,7 +3749,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
can only do so if it known to be a valid constant initializer. */ can only do so if it known to be a valid constant initializer. */
valid_const_initializer valid_const_initializer
= categorize_ctor_elements (ctor, &num_nonzero_elements, = categorize_ctor_elements (ctor, &num_nonzero_elements,
&num_ctor_elements, &cleared); &num_ctor_elements, &complete_p);
/* If a const aggregate variable is being initialized, then it /* If a const aggregate variable is being initialized, then it
should never be a lose to promote the variable to be static. */ should never be a lose to promote the variable to be static. */
...@@ -3788,26 +3787,29 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ...@@ -3788,26 +3787,29 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
parts in, then generate code for the non-constant parts. */ parts in, then generate code for the non-constant parts. */
/* TODO. There's code in cp/typeck.c to do this. */ /* TODO. There's code in cp/typeck.c to do this. */
num_type_elements = count_type_elements (type, true); if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
/* store_constructor will ignore the clearing of variable-sized
/* If count_type_elements could not determine number of type elements objects. Initializers for such objects must explicitly set
for a constant-sized object, assume clearing is needed. every field that needs to be set. */
Don't do this for variable-sized objects, as store_constructor cleared = false;
will ignore the clearing of variable-sized objects. */ else if (!complete_p)
if (num_type_elements < 0 && int_size_in_bytes (type) >= 0) /* If the constructor isn't complete, clear the whole object
beforehand.
??? This ought not to be needed. For any element not present
in the initializer, we should simply set them to zero. Except
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. */
cleared = true; cleared = true;
/* If there are "lots" of zeros, then block clear the object first. */ else if (num_ctor_elements - num_nonzero_elements
else if (num_type_elements - num_nonzero_elements
> CLEAR_RATIO (optimize_function_for_speed_p (cfun)) > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
&& num_nonzero_elements < num_type_elements/4) && num_nonzero_elements < num_ctor_elements / 4)
cleared = true; /* If there are "lots" of zeros, it's more efficient to clear
/* ??? This bit ought not be needed. For any element not present the memory and then set the nonzero elements. */
in the initializer, we should simply set them to zero. Except
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; cleared = true;
else
cleared = false;
/* If there are "lots" of initialized elements, and all of them /* If there are "lots" of initialized elements, and all of them
are valid address constants, then the entire initializer can are valid address constants, then the entire initializer can
......
2011-07-13 Chung-Lin Tang <cltang@codesourcery.com>
* gcc.target/arm/pr48183.c: New test.
2011-07-13 Richard Guenther <rguenther@suse.de> 2011-07-13 Richard Guenther <rguenther@suse.de>
* gcc.dg/torture/20110713-1.c: New testcase. * gcc.dg/torture/20110713-1.c: New testcase.
......
/* testsuite/gcc.target/arm/pr48183.c */
/* { dg-do compile } */
/* { dg-require-effective-target arm_neon_ok } */
/* { dg-options "-O -g" } */
/* { dg-add-options arm_neon } */
#include <arm_neon.h>
void move_16bit_to_32bit (int32_t *dst, const short *src, unsigned n)
{
unsigned i;
int16x4x2_t input;
int32x4x2_t mid;
int32x4x2_t output;
for (i = 0; i < n/2; i += 8) {
input = vld2_s16(src + i);
mid.val[0] = vmovl_s16(input.val[0]);
mid.val[1] = vmovl_s16(input.val[1]);
output.val[0] = vshlq_n_s32(mid.val[0], 8);
output.val[1] = vshlq_n_s32(mid.val[1], 8);
vst2q_s32((int32_t *)dst + i, output);
}
}
...@@ -4804,21 +4804,10 @@ extern bool initializer_zerop (const_tree); ...@@ -4804,21 +4804,10 @@ extern bool initializer_zerop (const_tree);
extern VEC(tree,gc) *ctor_to_vec (tree); extern VEC(tree,gc) *ctor_to_vec (tree);
/* Examine CTOR to discover: extern bool categorize_ctor_elements (const_tree, HOST_WIDE_INT *,
* how many scalar fields are set to nonzero values, HOST_WIDE_INT *, bool *);
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 extern bool complete_ctor_at_level_p (const_tree, HOST_WIDE_INT, const_tree);
as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0". */
extern bool categorize_ctor_elements (const_tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
bool *);
extern HOST_WIDE_INT count_type_elements (const_tree, bool);
/* integer_zerop (tree x) is nonzero if X is an integer constant of value 0. */ /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment