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]

Re: [PING] Re: SUBREGs and objects with holes


On Mon, Aug 14, 2006 at 02:40:27PM -0700, Geoffrey Keating wrote:
> I think some general comments might be in order.
> 
> Firstly, I'm not very interested in any analysis that considers only  
> e500 and x86.  This routine is in generic code and should work for  
> all ports.  It should work even for ports that don't exist yet.  The  
> only way to be sure that a proposed solution is correct is to use  
> logic to verify that the routine works.  I do not think you can get  
> there by saying "let's try to detect each possible case".

Neither subreg_regno_offset() nor subreg_offset_representable_p() will work
correctly if the hard regs in question don't all have the same size.
Consider a target where registers 0-7 are 8 bits wide and register 8-11 are
16 bits wide. If you call subreg_offset_representable_p() with xregno=6,
xmode=SImode, ymode=HImode and offset=2, it will compute

nregs_xmode = hard_regno_nregs[xregno][xmode]; /* 3: regs 6, 7 and 8. */
nregs_ymode = hard_regno_nregs[xregno][ymode]; /* 2: regs 6 and 7. */

which means (nregs_xmode % nregs_ymode) is 1, triggering this:

gcc_assert ((nregs_xmode % nregs_ymode) == 0);

In subreg_regno_offset(), when called with xregno=6, xmode=DImode,
ymode=HImode and offset=4, it will compute

nregs_xmode = hard_regno_nregs[xregno][xmode]; /* 5: regs 6-10. */
nregs_ymode = hard_regno_nregs[xregno][ymode]; /* 2: regs 6-7. */
mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode); /* 4 */
y_offset = offset / GET_MODE_SIZE (ymode); /* 2 */
nregs_multiple =  nregs_xmode / nregs_ymode; /* 2 */
return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode; /* 2 */

but the correct return value is 3.

This particular problem can be solved by summing GET_MODE_SIZE
(reg_raw_mode[i]) starting with i = xregno, until you reach the offset, but
I can image problems with this on the e500, because the capacity of
registers depends on the mode, rather than on just the size of the mode.

The only interface a target offers to get all the required information is
HARD_REGNO_NREGS(). For example, when you have HARD_REGNO_NREGS (reg,
SImode) return 1 and HARD_REGNO_NREGS (reg, DFmode) also return 1, it tells
you that you can't represent subreg_regno_offset (reg, DFmode, 4, SImode).

Btw, is there a testcases for the x86 problem with holes in a subreg?

-- 
Rask Ingemann Lambertsen


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