This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)),


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]