Commit 2c430630 by Roger Sayle Committed by Roger Sayle

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
parent cf633f5b
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> 2003-07-07 Andreas Jaeger <aj@suse.de>
* mips-tfile.c: Convert prototypes to ISO C90. * mips-tfile.c: Convert prototypes to ISO C90.
......
...@@ -2669,6 +2669,9 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len, ...@@ -2669,6 +2669,9 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
int reverse; int reverse;
rtx cst; rtx cst;
if (len == 0)
return 1;
if (! STORE_BY_PIECES_P (len, align)) if (! STORE_BY_PIECES_P (len, align))
return 0; return 0;
...@@ -2744,6 +2747,13 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len, ...@@ -2744,6 +2747,13 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
{ {
struct store_by_pieces data; struct store_by_pieces data;
if (len == 0)
{
if (endp == 2)
abort ();
return to;
}
if (! STORE_BY_PIECES_P (len, align)) if (! STORE_BY_PIECES_P (len, align))
abort (); abort ();
to = protect_from_queue (to, 1); to = protect_from_queue (to, 1);
...@@ -2792,6 +2802,9 @@ clear_by_pieces (rtx to, unsigned HOST_WIDE_INT len, unsigned int align) ...@@ -2792,6 +2802,9 @@ clear_by_pieces (rtx to, unsigned HOST_WIDE_INT len, unsigned int align)
{ {
struct store_by_pieces data; struct store_by_pieces data;
if (len == 0)
return;
data.constfun = clear_by_pieces_1; data.constfun = clear_by_pieces_1;
data.constfundata = NULL; data.constfundata = NULL;
data.len = len; data.len = len;
...@@ -2956,7 +2969,9 @@ clear_storage (rtx object, rtx size) ...@@ -2956,7 +2969,9 @@ clear_storage (rtx object, rtx size)
object = protect_from_queue (object, 1); object = protect_from_queue (object, 1);
size = protect_from_queue (size, 0); 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_P (INTVAL (size), align))
clear_by_pieces (object, INTVAL (size), align); clear_by_pieces (object, INTVAL (size), align);
else if (clear_storage_via_clrstr (object, 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) ...@@ -4892,11 +4907,13 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
{ {
tree elt; 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. */ /* We either clear the aggregate or indicate the value is dead. */
if ((TREE_CODE (type) == UNION_TYPE else if ((TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE) || TREE_CODE (type) == QUAL_UNION_TYPE)
&& ! cleared && ! CONSTRUCTOR_ELTS (exp))
&& ! CONSTRUCTOR_ELTS (exp))
/* If the constructor is empty, clear the union. */ /* If the constructor is empty, clear the union. */
{ {
clear_storage (target, expr_size (exp)); clear_storage (target, expr_size (exp));
...@@ -4907,7 +4924,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) ...@@ -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 set the initial value as zero so we can fold the value into
a constant. But if more than one register is involved, a constant. But if more than one register is involved,
this probably loses. */ 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) && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
{ {
emit_move_insn (target, CONST0_RTX (GET_MODE (target))); 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) ...@@ -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 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 register whose mode size isn't equal to SIZE since clear_storage
can't handle this case. */ can't handle this case. */
else if (! cleared && size > 0 else if (((list_length (CONSTRUCTOR_ELTS (exp)) != fields_length (type))
&& ((list_length (CONSTRUCTOR_ELTS (exp)) || mostly_zeros_p (exp))
!= fields_length (type))
|| mostly_zeros_p (exp))
&& (GET_CODE (target) != REG && (GET_CODE (target) != REG
|| ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target)) || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
== size))) == size)))
......
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> 2003-07-07 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
Eric Botcazou <ebotcazou@libertysurf.fr> Eric Botcazou <ebotcazou@libertysurf.fr>
......
// 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();
}
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