re PR rtl-optimization/11059 (empty union optimization ice)
PR optimization/11059 * expr.c (can_store_by_pieces): Return true if length is zero. (store_by_pieces): If length is zero and endp is two, abort, othwerise, if length is zero and endp is not two, return "to". (clear_by_pieces): Do nothing if length is zero. (clear_storage): Do nothing if length is zero. (store_constructor): Simplify code when size is zero, or the target has already been cleared. This avoids emitting a blockage instruction when initializing empty structures. * g++.dg/opt/emptyunion.C: New testcase. From-SVN: r69049
This commit is contained in:
parent
cf633f5be8
commit
2c430630da
|
@ -1,3 +1,15 @@
|
|||
2003-07-07 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR optimization/11059
|
||||
* expr.c (can_store_by_pieces): Return true if length is zero.
|
||||
(store_by_pieces): If length is zero and endp is two, abort,
|
||||
othwerise, if length is zero and endp is not two, return "to".
|
||||
(clear_by_pieces): Do nothing if length is zero.
|
||||
(clear_storage): Do nothing if length is zero.
|
||||
(store_constructor): Simplify code when size is zero, or the
|
||||
target has already been cleared. This avoids emitting a
|
||||
blockage instruction when initializing empty structures.
|
||||
|
||||
2003-07-07 Andreas Jaeger <aj@suse.de>
|
||||
|
||||
* mips-tfile.c: Convert prototypes to ISO C90.
|
||||
|
|
35
gcc/expr.c
35
gcc/expr.c
|
@ -2669,6 +2669,9 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
|
|||
int reverse;
|
||||
rtx cst;
|
||||
|
||||
if (len == 0)
|
||||
return 1;
|
||||
|
||||
if (! STORE_BY_PIECES_P (len, align))
|
||||
return 0;
|
||||
|
||||
|
@ -2744,6 +2747,13 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
|
|||
{
|
||||
struct store_by_pieces data;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
if (endp == 2)
|
||||
abort ();
|
||||
return to;
|
||||
}
|
||||
|
||||
if (! STORE_BY_PIECES_P (len, align))
|
||||
abort ();
|
||||
to = protect_from_queue (to, 1);
|
||||
|
@ -2792,6 +2802,9 @@ clear_by_pieces (rtx to, unsigned HOST_WIDE_INT len, unsigned int align)
|
|||
{
|
||||
struct store_by_pieces data;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
data.constfun = clear_by_pieces_1;
|
||||
data.constfundata = NULL;
|
||||
data.len = len;
|
||||
|
@ -2956,7 +2969,9 @@ clear_storage (rtx object, rtx size)
|
|||
object = protect_from_queue (object, 1);
|
||||
size = protect_from_queue (size, 0);
|
||||
|
||||
if (GET_CODE (size) == CONST_INT
|
||||
if (GET_CODE (size) == CONST_INT && INTVAL (size) == 0)
|
||||
;
|
||||
else if (GET_CODE (size) == CONST_INT
|
||||
&& CLEAR_BY_PIECES_P (INTVAL (size), align))
|
||||
clear_by_pieces (object, INTVAL (size), align);
|
||||
else if (clear_storage_via_clrstr (object, size, align))
|
||||
|
@ -4892,11 +4907,13 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
|
|||
{
|
||||
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. */
|
||||
if ((TREE_CODE (type) == UNION_TYPE
|
||||
|| TREE_CODE (type) == QUAL_UNION_TYPE)
|
||||
&& ! cleared
|
||||
&& ! CONSTRUCTOR_ELTS (exp))
|
||||
else if ((TREE_CODE (type) == UNION_TYPE
|
||||
|| TREE_CODE (type) == QUAL_UNION_TYPE)
|
||||
&& ! CONSTRUCTOR_ELTS (exp))
|
||||
/* If the constructor is empty, clear the union. */
|
||||
{
|
||||
clear_storage (target, expr_size (exp));
|
||||
|
@ -4907,7 +4924,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
|
|||
set the initial value as zero so we can fold the value into
|
||||
a constant. But if more than one register is involved,
|
||||
this probably loses. */
|
||||
else if (! cleared && GET_CODE (target) == REG && TREE_STATIC (exp)
|
||||
else if (GET_CODE (target) == REG && TREE_STATIC (exp)
|
||||
&& GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
|
||||
{
|
||||
emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
|
||||
|
@ -4919,10 +4936,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
|
|||
clear the whole structure first. Don't do this if TARGET is a
|
||||
register whose mode size isn't equal to SIZE since clear_storage
|
||||
can't handle this case. */
|
||||
else if (! cleared && size > 0
|
||||
&& ((list_length (CONSTRUCTOR_ELTS (exp))
|
||||
!= fields_length (type))
|
||||
|| mostly_zeros_p (exp))
|
||||
else if (((list_length (CONSTRUCTOR_ELTS (exp)) != fields_length (type))
|
||||
|| mostly_zeros_p (exp))
|
||||
&& (GET_CODE (target) != REG
|
||||
|| ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
|
||||
== size)))
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2003-07-07 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR optimization/11059
|
||||
* g++.dg/opt/emptyunion.C: New testcase.
|
||||
|
||||
2003-07-07 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// PR optimization/11059
|
||||
// This testcase ICEd because clear_by_pieces was called with zero length.
|
||||
// { dg-do compile }
|
||||
// { dg-options "-O2" }
|
||||
|
||||
union uni {};
|
||||
|
||||
int main() {
|
||||
uni *h;
|
||||
|
||||
h = (uni *)new uni();
|
||||
}
|
||||
|
Loading…
Reference in New Issue