Commit 32eed045 by Jakub Jelinek Committed by Jakub Jelinek

re PR middle-end/28755 (duplicate members of arrays)

	PR middle-end/28755
	* expr.c (expand_constructor): New function.
	(expand_expr_real_1) <case CONSTRUCTOR>: Call it.
	(expand_expr_real_1) <case ARRAY_REF>: Call it if VALUE is
	CONSTRUCTOR.

	* gcc.dg/pr28755.c: New test.

From-SVN: r128685
parent f2531eb6
2007-09-23 Jakub Jelinek <jakub@redhat.com>
PR middle-end/28755
* expr.c (expand_constructor): New function.
(expand_expr_real_1) <case CONSTRUCTOR>: Call it.
(expand_expr_real_1) <case ARRAY_REF>: Call it if VALUE is
CONSTRUCTOR.
2007-09-23 Richard Sandiford <rsandifo@nildram.co.uk> 2007-09-23 Richard Sandiford <rsandifo@nildram.co.uk>
* config/mips/mips.c (dump_constants_1): Generalize to include * config/mips/mips.c (dump_constants_1): Generalize to include
...@@ -6887,6 +6887,89 @@ expand_expr_addr_expr (tree exp, rtx target, enum machine_mode tmode, ...@@ -6887,6 +6887,89 @@ expand_expr_addr_expr (tree exp, rtx target, enum machine_mode tmode,
return result; return result;
} }
/* Generate code for computing CONSTRUCTOR EXP.
An rtx for the computed value is returned. If AVOID_TEMP_MEM
is TRUE, instead of creating a temporary variable in memory
NULL is returned and the caller needs to handle it differently. */
static rtx
expand_constructor (tree exp, rtx target, enum expand_modifier modifier,
bool avoid_temp_mem)
{
tree type = TREE_TYPE (exp);
enum machine_mode mode = TYPE_MODE (type);
/* Try to avoid creating a temporary at all. This is possible
if all of the initializer is zero.
FIXME: try to handle all [0..255] initializers we can handle
with memset. */
if (TREE_STATIC (exp)
&& !TREE_ADDRESSABLE (exp)
&& target != 0 && mode == BLKmode
&& all_zeros_p (exp))
{
clear_storage (target, expr_size (exp), BLOCK_OP_NORMAL);
return target;
}
/* All elts simple constants => refer to a constant in memory. But
if this is a non-BLKmode mode, let it store a field at a time
since that should make a CONST_INT or CONST_DOUBLE when we
fold. Likewise, if we have a target we can use, it is best to
store directly into the target unless the type is large enough
that memcpy will be used. If we are making an initializer and
all operands are constant, put it in memory as well.
FIXME: Avoid trying to fill vector constructors piece-meal.
Output them with output_constant_def below unless we're sure
they're zeros. This should go away when vector initializers
are treated like VECTOR_CST instead of arrays. */
if ((TREE_STATIC (exp)
&& ((mode == BLKmode
&& ! (target != 0 && safe_from_p (target, exp, 1)))
|| TREE_ADDRESSABLE (exp)
|| (host_integerp (TYPE_SIZE_UNIT (type), 1)
&& (! MOVE_BY_PIECES_P
(tree_low_cst (TYPE_SIZE_UNIT (type), 1),
TYPE_ALIGN (type)))
&& ! mostly_zeros_p (exp))))
|| ((modifier == EXPAND_INITIALIZER || modifier == EXPAND_CONST_ADDRESS)
&& TREE_CONSTANT (exp)))
{
rtx constructor;
if (avoid_temp_mem)
return NULL_RTX;
constructor = expand_expr_constant (exp, 1, modifier);
if (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER
&& modifier != EXPAND_SUM)
constructor = validize_mem (constructor);
return constructor;
}
/* Handle calls that pass values in multiple non-contiguous
locations. The Irix 6 ABI has examples of this. */
if (target == 0 || ! safe_from_p (target, exp, 1)
|| GET_CODE (target) == PARALLEL || modifier == EXPAND_STACK_PARM)
{
if (avoid_temp_mem)
return NULL_RTX;
target
= assign_temp (build_qualified_type (type, (TYPE_QUALS (type)
| (TREE_READONLY (exp)
* TYPE_QUAL_CONST))),
0, TREE_ADDRESSABLE (exp), 1);
}
store_constructor (exp, target, 0, int_expr_size (exp));
return target;
}
/* expand_expr: generate code for computing expression EXP. /* expand_expr: generate code for computing expression EXP.
An rtx for the computed value is returned. The value is never null. An rtx for the computed value is returned. The value is never null.
...@@ -7379,71 +7462,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -7379,71 +7462,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return const0_rtx; return const0_rtx;
} }
/* Try to avoid creating a temporary at all. This is possible return expand_constructor (exp, target, modifier, false);
if all of the initializer is zero.
FIXME: try to handle all [0..255] initializers we can handle
with memset. */
else if (TREE_STATIC (exp)
&& !TREE_ADDRESSABLE (exp)
&& target != 0 && mode == BLKmode
&& all_zeros_p (exp))
{
clear_storage (target, expr_size (exp), BLOCK_OP_NORMAL);
return target;
}
/* All elts simple constants => refer to a constant in memory. But
if this is a non-BLKmode mode, let it store a field at a time
since that should make a CONST_INT or CONST_DOUBLE when we
fold. Likewise, if we have a target we can use, it is best to
store directly into the target unless the type is large enough
that memcpy will be used. If we are making an initializer and
all operands are constant, put it in memory as well.
FIXME: Avoid trying to fill vector constructors piece-meal.
Output them with output_constant_def below unless we're sure
they're zeros. This should go away when vector initializers
are treated like VECTOR_CST instead of arrays.
*/
else if ((TREE_STATIC (exp)
&& ((mode == BLKmode
&& ! (target != 0 && safe_from_p (target, exp, 1)))
|| TREE_ADDRESSABLE (exp)
|| (host_integerp (TYPE_SIZE_UNIT (type), 1)
&& (! MOVE_BY_PIECES_P
(tree_low_cst (TYPE_SIZE_UNIT (type), 1),
TYPE_ALIGN (type)))
&& ! mostly_zeros_p (exp))))
|| ((modifier == EXPAND_INITIALIZER
|| modifier == EXPAND_CONST_ADDRESS)
&& TREE_CONSTANT (exp)))
{
rtx constructor = expand_expr_constant (exp, 1, modifier);
if (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER
&& modifier != EXPAND_SUM)
constructor = validize_mem (constructor);
return constructor;
}
else
{
/* Handle calls that pass values in multiple non-contiguous
locations. The Irix 6 ABI has examples of this. */
if (target == 0 || ! safe_from_p (target, exp, 1)
|| GET_CODE (target) == PARALLEL
|| modifier == EXPAND_STACK_PARM)
target
= assign_temp (build_qualified_type (type,
(TYPE_QUALS (type)
| (TREE_READONLY (exp)
* TYPE_QUAL_CONST))),
0, TREE_ADDRESSABLE (exp), 1);
store_constructor (exp, target, 0, int_expr_size (exp));
return target;
}
case MISALIGNED_INDIRECT_REF: case MISALIGNED_INDIRECT_REF:
case ALIGN_INDIRECT_REF: case ALIGN_INDIRECT_REF:
...@@ -7585,10 +7604,25 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -7585,10 +7604,25 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
field, value) field, value)
if (tree_int_cst_equal (field, index)) if (tree_int_cst_equal (field, index))
{ {
if (!TREE_SIDE_EFFECTS (value)) if (TREE_SIDE_EFFECTS (value))
return expand_expr (fold (value), target, tmode, break;
modifier);
break; if (TREE_CODE (value) == CONSTRUCTOR)
{
/* If VALUE is a CONSTRUCTOR, this
optimization is only useful if
this doesn't store the CONSTRUCTOR
into memory. If it does, it is more
efficient to just load the data from
the array directly. */
rtx ret = expand_constructor (value, target,
modifier, true);
if (ret == NULL_RTX)
break;
}
return expand_expr (fold (value), target, tmode,
modifier);
} }
} }
else if(TREE_CODE (init) == STRING_CST) else if(TREE_CODE (init) == STRING_CST)
......
2007-09-23 Jakub Jelinek <jakub@redhat.com>
PR middle-end/28755
* gcc.dg/pr28755.c: New test.
2007-09-23 Richard Sandiford <rsandifo@nildram.co.uk> 2007-09-23 Richard Sandiford <rsandifo@nildram.co.uk>
* lib/target-supports.exp (check_effective_target_nomips16): New * lib/target-supports.exp (check_effective_target_nomips16): New
/* PR middle-end/28755 */
/* { dg-do compile } */
/* { dg-options "-Os" } */
/* { dg-final { scan-assembler-times "2112543726\|7deadbee" 2 } } */
struct S
{
void *s1;
unsigned s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14;
};
const struct S array[] = {
{ (void *) 0, 60, 640, 2112543726, 39682, 48, 16, 33, 10, 96, 2, 0, 0, 4 },
{ (void *) 0, 60, 2112543726, 192, 18251, 16, 33, 10, 96, 2, 0, 0, 4, 212 }
};
void
foo (struct S *x)
{
x[0] = array[0];
x[5] = array[1];
}
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