diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-07-07 18:54:28 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-07-07 18:54:28 +0000 |
commit | 2c430630da43fd1908fcb6c4b57d0a5221c86261 (patch) | |
tree | 6db930741a1591471ed698ee5312a1c604315210 | |
parent | cf633f5be8e81fa2314c0cdf74476dc5823e5df2 (diff) | |
download | gcc-2c430630da43fd1908fcb6c4b57d0a5221c86261.tar.gz |
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
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/expr.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/emptyunion.C | 13 |
4 files changed, 55 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c214ee95d8d..c5e3dfdb5f9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/expr.c b/gcc/expr.c index c32925a6bb4..87ada15337e 100644 --- a/gcc/expr.c +++ b/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))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 683cb294952..c81312a8ee2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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> diff --git a/gcc/testsuite/g++.dg/opt/emptyunion.C b/gcc/testsuite/g++.dg/opt/emptyunion.C new file mode 100644 index 00000000000..105faed5844 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/emptyunion.C @@ -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(); +} + |