This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch RFA] Fix rtl-optimization/29599
- From: Kaz Kojima <kkojima at rr dot iij4u dot or dot jp>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 09 Feb 2007 14:37:54 +0900 (JST)
- Subject: [patch RFA] Fix rtl-optimization/29599
PR rtl-optimization/29599 is an ice-on-valid-code problem found
for SH. Alex suggests that it needs a fix of the generic part of
the compiler. I'd like to sketch what is going on in the faulty
case.
A reduced testcase is
struct scatterlist
{
unsigned long page;
int offset;
};
void mmc_blk_issue_rq (void)
{
int blocks;
struct scatterlist sg;
void *buf = &blocks;
memory_set (&sg, 0, sizeof (sg));
sg.page = ((unsigned long) buf - 0x80000000) >> 12;
sg.offset = (unsigned long) buf & 1 << 12;
if (blocks)
foo ();
}
which results an unrecognizable insn error at
(insn 65 23 25 3 (set (reg:SI 2 r2 [166])
(const_int 2147483656 [0x80000008])) -1 (nil)
(nil))
for SH.
In this case, the variable "block" is placed at sfp - 4 where
sfp is the software frame pointer of SH and the expression
(unsigned long) buf - 0x80000000 is sfp - 0x80000000 - 4.
In cse pass, the constant part - 0x80000000 - 4 is simplified
with simplify_const_binary_operation and the result is truncated
to 32-bit according to the MODE argument which is SImode in this
case. Thus it returns (const_int 2147483644 [0x7ffffffc]) and
cse makes a REG_EQUAL note below:
(insn 30 29 32 3 (set (reg:SI 168)
(plus:SI (reg/f:SI 159 [ buf.1 ])
(reg:SI 167))) 35 {*addsi3_compact} (nil)
(expr_list:REG_EQUAL (plus:SI (reg/f:SI 153 sfp)
(const_int 2147483644 [0x7ffffffc]))
(nil)))
When reloading, eliminate_regs_in_insn tries to replace sfp
with sp + 12 where sp is the hard stack pointer register of SH
and changes the above insn 30 to the insns
(set (hard-reg:SI) (const_int 0x7ffffffc + 12))
(set (hard-reg':SI) (plus:SI (hard-reg:SI) (reg:SI sp)))
Since eliminate_regs_in_insn computes the constant offset
as a HOST_WIDE_INT with ignoring the mode of destination,
the first insn of the above insns is changed to
(set (hard-reg:SI) (const_int 0x80000008))
and the constant load pattern of SH rejects 0x80000008 as a bad
value and this set insn fails to be recognised.
The attached patch is to take account of the mode of destination
when eliminate_regs_in_insn computes the offset.
It's tested with bootstrap and the top level "make -k check" on
i686-pc-linux-gnu with no new failures. OK for trunk and 4.2?
Regards,
kaz
--
:ADDPATCH rtl-optimization:
2007-02-09 Kaz Kojima <kkojima@gcc.gnu.org>
PR rtl-optimization/29599
* reload1.c (eliminate_regs_in_insn): Take the destination
mode into account when computing the offset.
--- ORIG/trunk/gcc/reload1.c 2007-01-29 09:36:53.000000000 +0900
+++ LOCAL/trunk/gcc/reload1.c 2007-02-08 20:05:49.000000000 +0900
@@ -1,7 +1,7 @@
/* Reload pseudo regs into hard regs for insns that require hard regs.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
- Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -3100,6 +3100,7 @@ eliminate_regs_in_insn (rtx insn, int re
{
rtx to_rtx = ep->to_rtx;
offset += ep->offset;
+ offset = trunc_int_for_mode (offset, GET_MODE (reg));
if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)),