summaryrefslogtreecommitdiff
path: root/gcc/combine.c
diff options
context:
space:
mode:
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2006-01-26 02:48:01 +0000
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2006-01-26 02:48:01 +0000
commite20e49db580a259576a778c70d0360c2fdfe0a1c (patch)
tree8f729514e4450856c50071a4d4fd1e43842ed815 /gcc/combine.c
parent7c3461b76f3552a3123e78aa88b16397f7aefb9c (diff)
downloadgcc-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.c38
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)