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

Re: More info on alpha bug


On Mon, Oct 20, 1997 at 04:46:32PM -0700, H.J. Lu wrote:
> The problem is the way how gcc works on alpha. Although alpha is
> 64 bit, gcc still uses 32 bit operations on many 64 bit integers.
> It converts them back and forth between 32 bit/64 bit. As the
> result, the return value of slen () is computed as 32 bit and sign
> extened to 64 bit upon return. But between inlining and 32 bit/64 bit
> coverting, srclen is stored as 32 bit integer on stack.

Ok, I've got this figured out now.  This is actually a follow on bug
to the one fixed by

Sat Mar 15 07:17:12 1997  Richard Henderson  <rth@tamu.edu>

        * reload.h (eliminate_regs): Add STORING arg.
        * reload1.c (eliminate_regs): Likewise.
        (eliminate_regs, case SET): Pass that we are storing to recursive call.
        (eliminate_regs, case SUBREG): If storing and same number of words,
        use larger mode.
        * caller-save.c, dbxout.c, dwarfout.c, dwarf2out.c, reload.c, sdbout.c:
        Change all calls to eliminate_regs.

(I also found the test case for this one, if anyone is interested.)

In the previous example, reload lost track of the width of the significant
data in the pseudo, spilled as SI, reloaded as DI.  The solution I came
to with Kenner at the time is to always spill full registers.

In this example, the above code kicks in and widens the destination of
the store, but the source stays in SImode.  This leads to 

  (set (mem:DI (plus (reg $30) (const_int 120)))
       (reg:SI $1)))

which somehow fails to choke the backend and yields an SImode store in
the assembly.

My solution, then, is to notice when the original DEST and eliminated
DEST differ in mode, and if they do, emit a (possibly paradoxical) 
subreg of SRC. 

I don't know if this is better or worse than adjusting the mode of SRC
directly, but I have the idea that the size of references to registers
should be consistent one to the next, with subreg thrown in if necessary
to hide the differences.


r~
Mon Oct 27 18:18:00 1997  Richard Henderson  <rth@cygnus.com>

	* reload1.c (eliminate_regs [SET]): If [SUBREG] widened the mode of
	DEST for the spill, adjust mode of SRC to compensate.


Index: reload1.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/reload1.c,v
retrieving revision 1.3
diff -u -p -d -r1.3 reload1.c
--- reload1.c	1997/08/19 16:04:17	1.3
+++ reload1.c	1997/10/28 02:17:41
@@ -3271,6 +3271,12 @@ eliminate_regs (x, mem_mode, insn, stori
 	    && GET_CODE (insn) != INSN_LIST)
 	  emit_insn_after (gen_rtx (CLOBBER, VOIDmode, SET_DEST (x)), insn);
 
+	/* If SET_DEST was a partial-word subreg, NEW0 may have been widened
+	   to spill the entire register (see SUBREG case above).  If the 
+	   widths of SET_DEST and NEW0 no longer match, adjust NEW1.  */
+	if (GET_MODE (SET_DEST (x)) != GET_MODE (new0))
+	  new1 = gen_rtx (SUBREG, GET_MODE (new0), new1, 0);
+
 	if (new0 != SET_DEST (x) || new1 != SET_SRC (x))
 	  return gen_rtx (SET, VOIDmode, new0, new1);
       }

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