On Mon, 2009-11-09 at 14:13 +0000, Ian Bolton wrote:
> Dave Hudson wrote:
> > I've been working on gcc for an ISA (Ubicom32) that seems to have some
> > similarities to the problem you're seeing (we have some regs that can
> > be
> > used for many things but not all) and was seeing a ton a pointless
> > moves
> > introduced by reload.
> >
> > I've ended up trying quite a few different strategies including
> > defining
> > different cover classes and the strategy we're now using is to leave
> > the
> > cover classes the same way you have them but found that the most
> > critical thing was to ensure that REGNO_REG_CLASS was returning a
> > minimal class correctly. Once I had this right then IRA started to do
> > the right thing most of the time (-Os still isn't great but -O2 usually
> > looks very good now). We still see some problems but they're usually a
> > result of reload messing things up or suboptimal handling of
> > auto-incrementing in MEMs.
>
> Thanks for the info, Dave.
>
> Given that C_REGS = r0-r31, BOTTOM_REGS = r0-r15, TOP_CREGS = r16-r31,
> when you say "minimal class", does that mean that I should change my
> macro from this:
>
> /* Map a register number to a register class. */
> #define REGNO_REG_CLASS(REGNO) \
> (BOTTOM_C_REG_P (REGNO) ? BOTTOM_REGS : \
> (REGNO) == LINK_POINTER_REGNUM ? LINK_REGS : \
> C_REG_P (REGNO) ? C_REGS : \
> D_REG_P (REGNO) ? D_REGS : \
> CSR_REG_P (REGNO) ? CSR_REGS : \
> (unsigned)(REGNO) < FIRST_PSEUDO_REGISTER ? INTERNAL_REGS : ALL_REGS)
>
> to this (see C_REG_P line for change):
>
> /* Map a register number to a register class. */
> #define REGNO_REG_CLASS(REGNO) \
> (BOTTOM_C_REG_P (REGNO) ? BOTTOM_REGS : \
> (REGNO) == LINK_POINTER_REGNUM ? LINK_REGS : \
> C_REG_P (REGNO) ? TOP_CREGS : \
> D_REG_P (REGNO) ? D_REGS : \
> CSR_REG_P (REGNO) ? CSR_REGS : \
> (unsigned)(REGNO) < FIRST_PSEUDO_REGISTER ? INTERNAL_REGS : ALL_REGS)
>
> I made the change and nothing noticeable happened, but maybe once I fix
> whatever else needs fixing then the second version of the macro will be
> better?
I think this looks more like what I had to do. FWIW I found it easier
to use an array in our port rather than using a cascading conditional
sequence (I can't remember which port I got that idea from):
#define REG_CLASS_CONTENTS \
{ \
{0x00000000, 0x00000000}, /* No regs */ \
{0x0000ffff, 0x00000000}, /* DATA_REGS */ \
{0x00010000, 0x00000000}, /* FDPIC_REG */ \
{0x20fe0000, 0x00000000}, /* ADDRESS_REGS */ \
{0x20ff0000, 0x00000000}, /* ALL_ADDRESS_REGS */ \
{0x0a000000, 0x00000000}, /* ACC_LO_REGS */ \
{0x0f000000, 0x00000000}, /* ACC_REGS */ \
{0x40000000, 0x00000000}, /* CC_REG */ \
{0x0f00ffff, 0x00000000}, /* DATA_ACC_REGS */ \
{0x10000000, 0x00000000}, /* SOURGE3_REG */ \
{0x80000000, 0x0000007f}, /* SPECIAL_REGS */ \
{0xbfffffff, 0x0000007f}, /* GENERAL_REGS */ \
{0xbfffffff, 0x0000007f} /* ALL_REGS */ \
}
extern enum reg_class const
ubicom32_regclass_map[FIRST_PSEUDO_REGISTER];
/* A C expression whose value is a register class containing hard
register
REGNO. In general there is more than one such class; choose a class
which
is "minimal", meaning that no smaller class also contains the
register. */
#define REGNO_REG_CLASS(REGNO) (ubicom32_regclass_map[REGNO])
and:
enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER] =
{
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
DATA_REGS,
FDPIC_REG,
ADDRESS_REGS,
ADDRESS_REGS,
ADDRESS_REGS,
ADDRESS_REGS,
ADDRESS_REGS,
ADDRESS_REGS,
ADDRESS_REGS,
ACC_REGS,
ACC_LO_REGS,
ACC_REGS,
ACC_LO_REGS,
SOURCE3_REG,
ADDRESS_REGS,
NO_REGS, /* CC_REG must be NO_REGS */
SPECIAL_REGS,
SPECIAL_REGS,
SPECIAL_REGS,
SPECIAL_REGS,
SPECIAL_REGS,
SPECIAL_REGS,
SPECIAL_REGS,
SPECIAL_REGS
};