This is the mail archive of the gcc-bugs@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]

[Bug target/29599] [4.1/4.2/4.3 Regression] ICE when building the kernel on SH4



------- Comment #2 from kkojima at gcc dot gnu dot org  2006-12-06 00:40 -------
I've looked at what is going on.  The variable "block" is
placed at sfp - 4 where sfp is the software frame pointer.
Then the expression (unsigned long) buf - 0x80000000 is
sfp - 0x80000000 - 4.  The cse pass folds the constant
part of this expression with simplify_const_binary_operation.
As simplify_const_binary_operation computes it as 64-bit
HOST_WIDE_INT constant and returns
gen_int_mode (- 0x80000000 - 4, SImode).
Since gen_int_mode ( , SImode) truncates the constant to 32-bit,
it returns (const_int 2147483644 [0x7ffffffc]).
Thus 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
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 HOST_WIDE_INT with ignoring the mode of destination,
the first insn of the insns is

(set (hard-reg:SI) (const_int 0x80000008))

However, movsi_ie which is the constant load pattern of SH
checks it source with general_movsrc_operand which is
essentially general_operand predicate and 0x80000008 is
out of range as a SImode constant.  Thus the above set insn
fails to be recognised.

I thought that if eliminate_regs_in_insn took account of
the mode of the destination, then it'll generate
(set (hard-reg:SI) (const_int 0xffffffff80000008)) instead
of the above set insn.

--- ORIG/trunk/gcc/reload1.c    2006-11-19 10:41:46.000000000 +0900
+++ LOCAL/trunk/gcc/reload1.c   2006-12-04 08:29:43.000000000 +0900
@@ -3093,7 +3093,15 @@ eliminate_regs_in_insn (rtx insn, int re
        if (ep->from_rtx == reg && ep->can_eliminate)
          {
            rtx to_rtx = ep->to_rtx;
+           unsigned int width = GET_MODE_BITSIZE (GET_MODE (reg));
+
            offset += ep->offset;
+           if (width < HOST_BITS_PER_WIDE_INT)
+             {
+               offset &= ((HOST_WIDE_INT) 1 << width) - 1;
+               if (offset &  ((HOST_WIDE_INT) 1 << (width - 1)))
+                 offset |= ((HOST_WIDE_INT) (-1) << width);
+             }

            if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
              to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)),

I'm not sure that this is in the right direction, and it
seems to be too invasive anyway.

SH target modifies the operands of move insns in
prepare_move_operands if needed.  I guess the it'd be
appropriate to handle this issue.  Here is a patch in
testing now:

--- ORIG/trunk/gcc/config/sh/sh.c       2006-12-03 10:58:32.000000000 +0900
+++ LOCAL/trunk/gcc/config/sh/sh.c      2006-12-04 22:57:42.000000000 +0900
@@ -1345,6 +1345,20 @@ prepare_move_operands (rtx operands[], e
        }
     }

+  /* Reload might make move insn from const_int to a register of
+     which mode is narrower than HOST_WIDE_INT where the value of
+     const_int is out of range for that mode.  See PR 29599.  */
+  if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT
+      && GET_CODE (operands[1]) == CONST_INT)
+    {
+      unsigned int width = GET_MODE_BITSIZE (mode);
+      HOST_WIDE_INT val = INTVAL (operands[1]);
+
+      val &= ((HOST_WIDE_INT) 1 << width) - 1;
+      if (val & ((HOST_WIDE_INT) 1 << (width - 1)))
+       operands[1] = GEN_INT (((HOST_WIDE_INT) (-1) << width) | val);
+    }
+
   return 0;
 }



-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29599


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