This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
combine simplify fix for alphaev4
- From: Richard Henderson <rth at twiddle dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 11 Dec 2001 18:41:34 -0800
- Subject: combine simplify fix for alphaev4
Seen in a bootstrap:
A signed short int load looks like
ldq_u t1, mem
lda t2, addr+2
extqh t1, t2, t3
sra t3, 48, c
Where extqh is
(ashift:DI
(match_operand:DI 1 "reg_or_0_operand" "rJ")
(minus:DI (const_int 64)
(ashift:DI
(and:DI
(match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 7))
(const_int 3))))
If the address has known alignment, such as we might get from the
frame pointer, then combine can simplify this instruction to
(ashift:DI (reg:DI T1) (const_int N))
In this case, the address was 6 mod 8, so addr+2 is 0 mod 8, so
the N above is 64.
So now we have (ashift reg 64), which, since Alpha defines
SHIFT_COUNT_TRUNCATED, is a noop. But simplify_shift_const
refuses to simplify this case, even though it handles others.
This is the bug.
Back to the problem description, in trying to combine with
the following shift, we get (ashiftrt (ashift T1 64) 48)
which make_extraction simplifies to (ashift 16), which is
of course not what we wanted.
Bootstraped on alphaev4-linux.
r~
* combine.c (simplify_shift_const): Move SHIFT_COUNT_TRUNCATED
simplification above out of range check.
Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.242
diff -c -p -d -r1.242 combine.c
*** combine.c 2001/12/10 22:52:26 1.242
--- combine.c 2001/12/12 01:32:32
*************** merge_outer_ops (pop0, pconst0, op1, con
*** 8811,8825 ****
are ASHIFTRT and ROTATE, which are always done in their original mode, */
static rtx
! simplify_shift_const (x, code, result_mode, varop, input_count)
rtx x;
enum rtx_code code;
enum machine_mode result_mode;
rtx varop;
! int input_count;
{
enum rtx_code orig_code = code;
- int orig_count = input_count;
unsigned int count;
int signed_count;
enum machine_mode mode = result_mode;
--- 8811,8824 ----
are ASHIFTRT and ROTATE, which are always done in their original mode, */
static rtx
! simplify_shift_const (x, code, result_mode, varop, orig_count)
rtx x;
enum rtx_code code;
enum machine_mode result_mode;
rtx varop;
! int orig_count;
{
enum rtx_code orig_code = code;
unsigned int count;
int signed_count;
enum machine_mode mode = result_mode;
*************** simplify_shift_const (x, code, result_mo
*** 8833,8858 ****
int complement_p = 0;
rtx new;
/* If we were given an invalid count, don't do anything except exactly
what was requested. */
! if (input_count < 0 || input_count >= (int) GET_MODE_BITSIZE (mode))
{
if (x)
return x;
! return gen_rtx_fmt_ee (code, mode, varop, GEN_INT (input_count));
}
! count = input_count;
!
! /* Make sure and truncate the "natural" shift on the way in. We don't
! want to do this inside the loop as it makes it more difficult to
! combine shifts. */
! #ifdef SHIFT_COUNT_TRUNCATED
! if (SHIFT_COUNT_TRUNCATED)
! count %= GET_MODE_BITSIZE (mode);
! #endif
/* Unless one of the branches of the `if' in this loop does a `continue',
we will `break' the loop after the `if'. */
--- 8832,8857 ----
int complement_p = 0;
rtx new;
+ /* Make sure and truncate the "natural" shift on the way in. We don't
+ want to do this inside the loop as it makes it more difficult to
+ combine shifts. */
+ #ifdef SHIFT_COUNT_TRUNCATED
+ if (SHIFT_COUNT_TRUNCATED)
+ orig_count &= GET_MODE_BITSIZE (mode) - 1;
+ #endif
+
/* If we were given an invalid count, don't do anything except exactly
what was requested. */
! if (orig_count < 0 || orig_count >= (int) GET_MODE_BITSIZE (mode))
{
if (x)
return x;
! return gen_rtx_fmt_ee (code, mode, varop, GEN_INT (orig_count));
}
! count = orig_count;
/* Unless one of the branches of the `if' in this loop does a `continue',
we will `break' the loop after the `if'. */