This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Refine store_constructor in bitfield cases
- From: kenner at vlsi1 dot ultra dot nyu dot edu (Richard Kenner)
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 30 Apr 04 08:12:51 EDT
- Subject: Refine store_constructor in bitfield cases
In cases of nested CONSTRUCTORs with bitfields in both cases, we can do
multiple CLOBBERs of a REG causing some stores to be lost. Also, SIZE is
being passed in bytes, but might not be full bytes, so the size == 0 test
isn't doing the right thing. I fixed it this way.
The testcase is a proprietary Ada program and it can't be reproduced in C.
Tested on x86_64-linux.
2004-04-30 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* expr.c (store_constructor): SIZE operand is now in bits; CLEARED
less than zero now means emitted CLOBBER already.
(store_constructor_field, expand_expr_real): Reflect above changes.
*** expr.c 25 Apr 2004 23:52:13 -0000 1.639
--- expr.c 30 Apr 2004 12:04:51 -0000
*************** store_constructor_field (rtx target, uns
*** 4516,4520 ****
}
! store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
}
else
--- 4516,4520 ----
}
! store_constructor (exp, target, cleared, bitsize);
}
else
*************** store_constructor_field (rtx target, uns
*** 4526,4531 ****
TARGET is either a REG or a MEM; we know it cannot conflict, since
safe_from_p has been called.
! CLEARED is true if TARGET is known to have been zero'd.
! SIZE is the number of bytes of TARGET we are allowed to modify: this
may not be the same as the size of EXP if we are assigning to a field
which has been packed to exclude padding bits. */
--- 4526,4533 ----
TARGET is either a REG or a MEM; we know it cannot conflict, since
safe_from_p has been called.
! CLEARED is positive if TARGET is known to have been zeroed, zero if
! this is the top level of calls to store_constructor, and negative
! if this is a recursive call but no clearing has been done.
! SIZE is the number of bits of TARGET we are allowed to modify: this
may not be the same as the size of EXP if we are assigning to a field
which has been packed to exclude padding bits. */
*************** store_constructor (tree exp, rtx target,
*** 4544,4549 ****
tree elt;
! /* If size is zero or the target is already cleared, do nothing. */
! if (size == 0 || cleared)
cleared = 1;
/* We either clear the aggregate or indicate the value is dead. */
--- 4546,4554 ----
tree elt;
! /* If this is not the top level, we don't do any initialization. */
! if (cleared)
! ;
! /* If the size is zero, pretend we've cleared it. */
! else if (size == 0)
cleared = 1;
/* We either clear the aggregate or indicate the value is dead. */
*************** store_constructor (tree exp, rtx target,
*** 4553,4557 ****
/* If the constructor is empty, clear the union. */
{
! clear_storage (target, expr_size (exp));
cleared = 1;
}
--- 4558,4562 ----
/* If the constructor is empty, clear the union. */
{
! clear_storage (target, GEN_INT (size / BITS_PER_UNIT));
cleared = 1;
}
*************** store_constructor (tree exp, rtx target,
*** 4576,4580 ****
|| mostly_zeros_p (exp))
&& (GET_CODE (target) != REG
! || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
== size)))
{
--- 4581,4585 ----
|| mostly_zeros_p (exp))
&& (GET_CODE (target) != REG
! || ((HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target))
== size)))
{
*************** store_constructor (tree exp, rtx target,
*** 4587,4596 ****
}
! clear_storage (xtarget, GEN_INT (size));
cleared = 1;
}
!
! if (! cleared)
! emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
/* Store each element of the constructor into
--- 4592,4603 ----
}
! clear_storage (xtarget, GEN_INT (size / BITS_PER_UNIT));
cleared = 1;
}
! else
! {
! emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
! cleared = -1;
! }
/* Store each element of the constructor into
*************** store_constructor (tree exp, rtx target,
*** 4613,4617 ****
continue;
! if (cleared && is_zeros_p (value))
continue;
--- 4620,4624 ----
continue;
! if (cleared > 0 && is_zeros_p (value))
continue;
*************** store_constructor (tree exp, rtx target,
*** 4823,4833 ****
emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
else
! clear_storage (target, GEN_INT (size));
}
- cleared = 1;
}
else if (REG_P (target))
! /* Inform later passes that the old value is dead. */
! emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
/* Store each element of the constructor into
--- 4830,4844 ----
emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
else
! clear_storage (target, GEN_INT (size / BITS_PER_UNIT));
!
! cleared = 1;
}
}
else if (REG_P (target))
! {
! /* Inform later passes that the old value is dead. */
! emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
! cleared = -1;
! }
/* Store each element of the constructor into
*************** store_constructor (tree exp, rtx target,
*** 4846,4850 ****
rtx xtarget = target;
! if (cleared && is_zeros_p (value))
continue;
--- 4857,4861 ----
rtx xtarget = target;
! if (cleared > 0 && is_zeros_p (value))
continue;
*************** store_constructor (tree exp, rtx target,
*** 4940,4945 ****
xtarget = adjust_address (xtarget, mode, 0);
if (TREE_CODE (value) == CONSTRUCTOR)
! store_constructor (value, xtarget, cleared,
! bitsize / BITS_PER_UNIT);
else
store_expr (value, xtarget, 0);
--- 4951,4955 ----
xtarget = adjust_address (xtarget, mode, 0);
if (TREE_CODE (value) == CONSTRUCTOR)
! store_constructor (value, xtarget, cleared, bitsize);
else
store_expr (value, xtarget, 0);
*************** store_constructor (tree exp, rtx target,
*** 5039,5044 ****
if (elt == NULL_TREE && size > 0)
{
! if (!cleared)
! clear_storage (target, GEN_INT (size));
return;
}
--- 5049,5054 ----
if (elt == NULL_TREE && size > 0)
{
! if (cleared <= 0)
! clear_storage (target, GEN_INT (size / BITS_PER_UNIT));
return;
}
*************** store_constructor (tree exp, rtx target,
*** 5080,5084 ****
if (bit_pos >= set_word_size || ibit == nbits)
{
! if (word != 0 || ! cleared)
{
rtx datum = gen_int_mode (word, mode);
--- 5090,5094 ----
if (bit_pos >= set_word_size || ibit == nbits)
{
! if (word != 0 || cleared <= 0)
{
rtx datum = gen_int_mode (word, mode);
*************** store_constructor (tree exp, rtx target,
*** 5105,5109 ****
}
}
! else if (!cleared)
/* Don't bother clearing storage if the set is all ones. */
if (TREE_CHAIN (elt) != NULL_TREE
--- 5115,5119 ----
}
}
! else if (cleared <= 0)
/* Don't bother clearing storage if the set is all ones. */
if (TREE_CHAIN (elt) != NULL_TREE
*************** store_constructor (tree exp, rtx target,
*** 5115,5119 ****
- tree_low_cst (TREE_PURPOSE (elt), 0) + 1
!= (HOST_WIDE_INT) nbits))))
! clear_storage (target, expr_size (exp));
for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
--- 5125,5129 ----
- tree_low_cst (TREE_PURPOSE (elt), 0) + 1
!= (HOST_WIDE_INT) nbits))))
! clear_storage (target, GEN_INT (size / BITS_PER_UNIT));
for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
*************** expand_expr_real (tree exp, rtx target,
*** 6743,6747 ****
0, TREE_ADDRESSABLE (exp), 1);
! store_constructor (exp, target, 0, int_expr_size (exp));
return target;
}
--- 6753,6758 ----
0, TREE_ADDRESSABLE (exp), 1);
! store_constructor (exp, target, 0,
! int_expr_size (exp) * BITS_PER_UNIT);
return target;
}