diff options
author | Roger Sayle <sayle@gcc.gnu.org> | 2006-01-26 02:48:01 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2006-01-26 02:48:01 +0000 |
commit | d89b36e1a2179df76edf089cc2a11f5f3409cb72 (patch) | |
tree | 8f729514e4450856c50071a4d4fd1e43842ed815 /gcc/combine.c | |
parent | 51302a4168aced438d184aa0dce95c9766aefd97 (diff) | |
download | gcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.zip gcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.tar.gz gcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.tar.bz2 |
re PR rtl-optimization/25703 (ACATS cxa4024 failure)
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.
From-SVN: r110242
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 0ec4580..2c90be5 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) |