diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-01-26 02:48:01 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-01-26 02:48:01 +0000 |
commit | e20e49db580a259576a778c70d0360c2fdfe0a1c (patch) | |
tree | 8f729514e4450856c50071a4d4fd1e43842ed815 /gcc/combine.c | |
parent | 7c3461b76f3552a3123e78aa88b16397f7aefb9c (diff) | |
download | gcc-e20e49db580a259576a778c70d0360c2fdfe0a1c.tar.gz |
PR rtl-optimization/25703
* combine.c (try_combine): Handle zero_extract and strict_low_part
of non-lowpart SUBREGs for constant reg_subword_p set optimization.
* gcc.target/i386/20060125-1.c: New test case.
* gcc.target/i386/20060125-2.c: New test case.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110242 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/combine.c')
-rw-r--r-- | gcc/combine.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index 0ec45808a8a..2c90be5a2e4 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1951,40 +1951,38 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) int offset = -1; int width = 0; - if (GET_CODE (dest) == STRICT_LOW_PART) - { - width = GET_MODE_BITSIZE (GET_MODE (XEXP (dest, 0))); - offset = 0; - } - else if (GET_CODE (dest) == ZERO_EXTRACT) + if (GET_CODE (dest) == ZERO_EXTRACT) { if (GET_CODE (XEXP (dest, 1)) == CONST_INT && GET_CODE (XEXP (dest, 2)) == CONST_INT) { width = INTVAL (XEXP (dest, 1)); offset = INTVAL (XEXP (dest, 2)); - + dest = XEXP (dest, 0); if (BITS_BIG_ENDIAN) - offset = GET_MODE_BITSIZE (GET_MODE (XEXP (dest, 0))) - - width - offset; + offset = GET_MODE_BITSIZE (GET_MODE (dest)) - width - offset; } } - else if (subreg_lowpart_p (dest)) + else { + if (GET_CODE (dest) == STRICT_LOW_PART) + dest = XEXP (dest, 0); width = GET_MODE_BITSIZE (GET_MODE (dest)); offset = 0; } - /* ??? Preserve the original logic to handle setting the high word - of double-word pseudos, where inner is half the size of outer - but not the lowpart. This could be generalized by handling - SUBREG_BYTE, WORDS_BIG_ENDIAN and BYTES_BIG_ENDIAN ourselves. - Unfortunately this logic is tricky to get right and probably - not worth the effort. */ - else if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp))) - == 2 * GET_MODE_BITSIZE (GET_MODE (dest))) + + if (offset >= 0) { - width = GET_MODE_BITSIZE (GET_MODE (dest)); - offset = width; + /* If this is the low part, we're done. */ + if (subreg_lowpart_p (dest)) + ; + /* Handle the case where inner is twice the size of outer. */ + else if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp))) + == 2 * GET_MODE_BITSIZE (GET_MODE (dest))) + offset += GET_MODE_BITSIZE (GET_MODE (dest)); + /* Otherwise give up for now. */ + else + offset = -1; } if (offset >= 0) |