This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
combine/rotate tweek
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com, patches at x86-64 dot org
- Subject: combine/rotate tweek
- From: Jan Hubicka <jh at suse dot cz>
- Date: Wed, 8 Nov 2000 23:31:47 +0100
Hi
For some purpose kernel defines swapping of endianity for short as:
#define ___swab16(x) \
((__u16)( \
(((__u16)(x) & (__u16)0x00ffU) << 8) | \
(((__u16)(x) & (__u16)0xff00U) >> 8) ))
That gets recognized as rotate by combine (the recognized in fold-const is
blocked by the redundant ands). Problem is that when parameters is SUBREGed
integer, it goes crazy, since the subreg is propagated over one shift and over
the other.
After seeing this number of times in the kernel compilation I've got irritated
enought to teach combine.c to do it (and fix the kernel header).
The code matches few extra times during gcc compilation, so probably kernel
developers are not only getting inovative ideas about encoding rotates.
I am just in the middle of bootstrap and will run the regression testing over
night and let you know in the case of problems.
Honza
Wed Nov 8 23:25:48 MET 2000 Jan Hubicka <jh@suse.cz>
* combine.c (simbplify_logical): Recognize rotates of SUBREGs.
Index: gcc/gcc/combine.c
===================================================================
RCS file: /home/cvs/Repository/gcc/gcc/combine.c,v
retrieving revision 1.3
diff -c -3 -p -r1.3 combine.c
*** gcc/gcc/combine.c 2000/11/06 14:30:16 1.3
--- gcc/gcc/combine.c 2000/11/08 22:24:39
*************** simplify_logical (x, last)
*** 5434,5449 ****
/* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the
mode size to (rotate A CX). */
! if (((GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
! || (GET_CODE (op1) == ASHIFT && GET_CODE (op0) == LSHIFTRT))
! && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
! && GET_CODE (XEXP (op0, 1)) == CONST_INT
! && GET_CODE (XEXP (op1, 1)) == CONST_INT
! && (INTVAL (XEXP (op0, 1)) + INTVAL (XEXP (op1, 1))
! == GET_MODE_BITSIZE (mode)))
! return gen_rtx_ROTATE (mode, XEXP (op0, 0),
! (GET_CODE (op0) == ASHIFT
! ? XEXP (op0, 1) : XEXP (op1, 1)));
/* If OP0 is (ashiftrt (plus ...) C), it might actually be
a (sign_extend (plus ...)). If so, OP1 is a CONST_INT, and the PLUS
--- 5434,5477 ----
/* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the
mode size to (rotate A CX). */
! {
! /* In case original register was subregged, we get something like:
! (ior (lshift (subreg (reg) 0))
! (subreg (ashift (reg)) 0))
! Match even this case. */
! rtx rop0, rop1, srop1, srop0;
!
! /* Get ASHIFT first. */
! if (GET_CODE (op0) == LSHIFTRT)
! rop0 = op0, rop1 = op1;
! else
! rop0 = op1, rop1 = op0;
!
! /* Skip posssible SUBREG for LSHIFT. */
! if (GET_CODE (rop1) == SUBREG && SUBREG_WORD (rop1) == 0
! && (GET_MODE_SIZE (mode)
! <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (rop1)))))
! srop1 = SUBREG_REG (rop1);
! else
! srop1 = rop1;
!
! if (GET_CODE (rop0) == LSHIFTRT && GET_CODE (srop1) == ASHIFT
! && GET_CODE (XEXP (rop0, 1)) == CONST_INT
! && GET_CODE (XEXP (srop1, 1)) == CONST_INT
! && (INTVAL (XEXP (rop0, 1)) + INTVAL (XEXP (srop1, 1))
! == GET_MODE_BITSIZE (mode))
! /* In case we skipped SUBREG, verify that there is an matching
! SUBREG on the oposite side. */
! && (srop1 == rop1
! || (GET_CODE (XEXP (rop0, 0)) == SUBREG
! && SUBREG_WORD (XEXP (rop0, 0)) == 0
! && (GET_MODE_SIZE (mode)
! <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (rop0, 0)))))))
! && rtx_equal_p (srop1 == rop1
! ? XEXP (rop0, 0) : SUBREG_REG (XEXP (rop0, 0)),
! XEXP (srop1, 0)))
! return gen_rtx_ROTATE (mode, XEXP (srop1, 0), XEXP (srop1, 1));
! }
/* If OP0 is (ashiftrt (plus ...) C), it might actually be
a (sign_extend (plus ...)). If so, OP1 is a CONST_INT, and the PLUS