, Patch #10, move PowerPC data structures & helper functions from rs6000.c to rs6000-internal.h
diff mbox series

Message ID 20190720161308.GA6730@ibm-toto.the-meissners.org
State New
Headers show
Series
  • , Patch #10, move PowerPC data structures & helper functions from rs6000.c to rs6000-internal.h
Related show

Commit Message

Michael Meissner July 20, 2019, 4:13 p.m. UTC
I will be iterating on patch #9 and sending out a replacement shortly.

This is patch #10.  It moves the various data structures from rs6000.c to
rs6000-internal.h.  In the future, it will allow us to move more things from
rs6000.c to other files.  In particular, I plan on adding a rs6000-prefixed.c
file that has the specific support for prefixed instructions.

It would also allow various functions for handling adressing and register
assignment, etc. that could also be moved to a separate file as well.

This patch just moves the data structure definitions and helper functions
(mode_supports_*) to rs6000-internal.h.  The static data structures are changed
to external, and definitions of the function are put in rs6000.c.  I did add 00
to the bit mask definitions for RELOAD_REG_* because I plan to add at least one
more mask (for DS-form addresses) in the future, and it will the values lined
up.

I have done a bootstrap on a little endian power8 system running Linux and
there were no regressions in the test suite.  Can I check this into the trunk?

2019-07-20  Michael Meissner  <meissner@linux.ibm.com>

	* config/rs6000/rs6000-internal.h (rs6000_hard_regno_mode_ok_p):
	Move various declarations relating to addressing and register
	allocation to rs6000-internal.h from rs6000.c so that in the
	future we can move things out of rs6000.c.  Make the static arrays
	global, and define them in rs6000.c.
	(enum rs6000_reg_type): Likewise.
	(reg_class_to_reg_type): Likewise.
	(IS_STD_REG_TYPE): Likewise.
	(IS_FP_VECT_REG_TYPE): Likewise.
	(enum rs6000_reload_reg_type): Likewise.
	(FIRST_RELOAD_REG_CLASS): Likewise.
	(LAST_RELOAD_REG_CLASS): Likewise.
	(struct reload_reg_map_type): Likewise.
	(reload_reg_map): Likewise.
	(RELOAD_REG_* macros): Likewise.
	(struct rs6000_reg_addr): Likewise.
	(reg_addr): Likewise.
	(mode_supports_pre_incdec_): Likewise.
	(mode_supports_pre_modify_p): Likewise.
	(mode_supports_vmx_dform): Likewise.
	(mode_supports_dq_form): Likewise.
	(mode_supports_prefixed_address_p): Likewise.
	* config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok_p): Likewise.
	(enum rs6000_reg_type): Likewise.
	(reg_class_to_reg_type): Likewise.
	(IS_STD_REG_TYPE): Likewise.
	(IS_FP_VECT_REG_TYPE): Likewise.
	(enum rs6000_reload_reg_type): Likewise.
	(FIRST_RELOAD_REG_CLASS): Likewise.
	(LAST_RELOAD_REG_CLASS): Likewise.
	(struct reload_reg_map_type): Likewise.
	(reload_reg_map): Likewise.
	(RELOAD_REG_* macros): Likewise.
	(struct rs6000_reg_addr): Likewise.
	(reg_addr): Likewise.
	(mode_supports_pre_incdec_): Likewise.
	(mode_supports_pre_modify_p): Likewise.
	(mode_supports_vmx_dform): Likewise.
	(mode_supports_dq_form): Likewise.
	(mode_supports_prefixed_address_p): Likewise.

Comments

David Edelsohn July 20, 2019, 4:28 p.m. UTC | #1
On Sat, Jul 20, 2019 at 12:13 PM Michael Meissner
<meissner@linux.ibm.com> wrote:
>
> I will be iterating on patch #9 and sending out a replacement shortly.
>
> This is patch #10.  It moves the various data structures from rs6000.c to
> rs6000-internal.h.  In the future, it will allow us to move more things from
> rs6000.c to other files.  In particular, I plan on adding a rs6000-prefixed.c
> file that has the specific support for prefixed instructions.
>
> It would also allow various functions for handling adressing and register
> assignment, etc. that could also be moved to a separate file as well.
>
> This patch just moves the data structure definitions and helper functions
> (mode_supports_*) to rs6000-internal.h.  The static data structures are changed
> to external, and definitions of the function are put in rs6000.c.  I did add 00
> to the bit mask definitions for RELOAD_REG_* because I plan to add at least one
> more mask (for DS-form addresses) in the future, and it will the values lined
> up.
>
> I have done a bootstrap on a little endian power8 system running Linux and
> there were no regressions in the test suite.  Can I check this into the trunk?

This patch needs to add rs6000-internal.h to tm_file in gcc/config.gcc
for all of the powerpc/rs6000 targets.  It also may need tm_p_file and
tm_d_file definitions.

Thanks, David

>
> 2019-07-20  Michael Meissner  <meissner@linux.ibm.com>
>
>         * config/rs6000/rs6000-internal.h (rs6000_hard_regno_mode_ok_p):
>         Move various declarations relating to addressing and register
>         allocation to rs6000-internal.h from rs6000.c so that in the
>         future we can move things out of rs6000.c.  Make the static arrays
>         global, and define them in rs6000.c.
>         (enum rs6000_reg_type): Likewise.
>         (reg_class_to_reg_type): Likewise.
>         (IS_STD_REG_TYPE): Likewise.
>         (IS_FP_VECT_REG_TYPE): Likewise.
>         (enum rs6000_reload_reg_type): Likewise.
>         (FIRST_RELOAD_REG_CLASS): Likewise.
>         (LAST_RELOAD_REG_CLASS): Likewise.
>         (struct reload_reg_map_type): Likewise.
>         (reload_reg_map): Likewise.
>         (RELOAD_REG_* macros): Likewise.
>         (struct rs6000_reg_addr): Likewise.
>         (reg_addr): Likewise.
>         (mode_supports_pre_incdec_): Likewise.
>         (mode_supports_pre_modify_p): Likewise.
>         (mode_supports_vmx_dform): Likewise.
>         (mode_supports_dq_form): Likewise.
>         (mode_supports_prefixed_address_p): Likewise.
>         * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok_p): Likewise.
>         (enum rs6000_reg_type): Likewise.
>         (reg_class_to_reg_type): Likewise.
>         (IS_STD_REG_TYPE): Likewise.
>         (IS_FP_VECT_REG_TYPE): Likewise.
>         (enum rs6000_reload_reg_type): Likewise.
>         (FIRST_RELOAD_REG_CLASS): Likewise.
>         (LAST_RELOAD_REG_CLASS): Likewise.
>         (struct reload_reg_map_type): Likewise.
>         (reload_reg_map): Likewise.
>         (RELOAD_REG_* macros): Likewise.
>         (struct rs6000_reg_addr): Likewise.
>         (reg_addr): Likewise.
>         (mode_supports_pre_incdec_): Likewise.
>         (mode_supports_pre_modify_p): Likewise.
>         (mode_supports_vmx_dform): Likewise.
>         (mode_supports_dq_form): Likewise.
>         (mode_supports_prefixed_address_p): Likewise.
>
> Index: gcc/config/rs6000/rs6000-internal.h
> ===================================================================
> --- gcc/config/rs6000/rs6000-internal.h (revision 273617)
> +++ gcc/config/rs6000/rs6000-internal.h (working copy)
> @@ -22,6 +22,134 @@
>  #ifndef GCC_RS6000_INTERNAL_H
>  #define GCC_RS6000_INTERNAL_H
>
> +/* Value is TRUE if register/mode pair is acceptable.  */
> +extern bool rs6000_hard_regno_mode_ok_p
> +  [NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
> +
> +/* Simplfy register classes into simpler classifications.  We assume
> +   GPR_REG_TYPE - FPR_REG_TYPE are ordered so that we can use a simple range
> +   check for standard register classes (gpr/floating/altivec/vsx) and
> +   floating/vector classes (float/altivec/vsx).  */
> +
> +enum rs6000_reg_type {
> +  NO_REG_TYPE,
> +  PSEUDO_REG_TYPE,
> +  GPR_REG_TYPE,
> +  VSX_REG_TYPE,
> +  ALTIVEC_REG_TYPE,
> +  FPR_REG_TYPE,
> +  SPR_REG_TYPE,
> +  CR_REG_TYPE
> +};
> +
> +/* Map register class to register type.  */
> +extern enum rs6000_reg_type reg_class_to_reg_type[N_REG_CLASSES];
> +
> +/* First/last register type for the 'normal' register types (i.e. general
> +   purpose, floating point, altivec, and VSX registers).  */
> +#define IS_STD_REG_TYPE(RTYPE) IN_RANGE(RTYPE, GPR_REG_TYPE, FPR_REG_TYPE)
> +
> +#define IS_FP_VECT_REG_TYPE(RTYPE) IN_RANGE(RTYPE, VSX_REG_TYPE, FPR_REG_TYPE)
> +
> +
> +/* Register classes we care about in secondary reload or go if legitimate
> +   address.  We only need to worry about GPR, FPR, and Altivec registers here,
> +   along an ANY field that is the OR of the 3 register classes.  */
> +
> +enum rs6000_reload_reg_type {
> +  RELOAD_REG_GPR,                      /* General purpose registers.  */
> +  RELOAD_REG_FPR,                      /* Traditional floating point regs.  */
> +  RELOAD_REG_VMX,                      /* Altivec (VMX) registers.  */
> +  RELOAD_REG_ANY,                      /* OR of GPR, FPR, Altivec masks.  */
> +  N_RELOAD_REG
> +};
> +
> +/* For setting up register classes, loop through the 3 register classes mapping
> +   into real registers, and skip the ANY class, which is just an OR of the
> +   bits.  */
> +#define FIRST_RELOAD_REG_CLASS RELOAD_REG_GPR
> +#define LAST_RELOAD_REG_CLASS  RELOAD_REG_VMX
> +
> +/* Map reload register type to a register in the register class.  */
> +struct reload_reg_map_type {
> +  const char *name;                    /* Register class name.  */
> +  int reg;                             /* Register in the register class.  */
> +};
> +
> +extern const struct reload_reg_map_type reload_reg_map[N_RELOAD_REG];
> +
> +/* Mask bits for each register class, indexed per mode.  Historically the
> +   compiler has been more restrictive which types can do PRE_MODIFY instead of
> +   PRE_INC and PRE_DEC, so keep track of sepaate bits for these two.  */
> +typedef unsigned char addr_mask_type;
> +
> +#define RELOAD_REG_VALID       0x0001  /* Mode valid in register..  */
> +#define RELOAD_REG_MULTIPLE    0x0002  /* Mode takes multiple registers.  */
> +#define RELOAD_REG_INDEXED     0x0004  /* Reg+reg addressing.  */
> +#define RELOAD_REG_OFFSET      0x0008  /* Reg+offset addressing. */
> +#define RELOAD_REG_PRE_INCDEC  0x0010  /* PRE_INC/PRE_DEC valid.  */
> +#define RELOAD_REG_PRE_MODIFY  0x0020  /* PRE_MODIFY valid.  */
> +#define RELOAD_REG_AND_M16     0x0040  /* AND -16 addressing.  */
> +#define RELOAD_REG_QUAD_OFFSET 0x0080  /* quad offset is limited.  */
> +
> +/* Register type masks based on the type, of valid addressing modes.  */
> +struct rs6000_reg_addr {
> +  enum insn_code reload_load;          /* INSN to reload for loading. */
> +  enum insn_code reload_store;         /* INSN to reload for storing.  */
> +  enum insn_code reload_fpr_gpr;       /* INSN to move from FPR to GPR.  */
> +  enum insn_code reload_gpr_vsx;       /* INSN to move from GPR to VSX.  */
> +  enum insn_code reload_vsx_gpr;       /* INSN to move from VSX to GPR.  */
> +  addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks.  */
> +  bool scalar_in_vmx_p;                        /* Scalar value can go in VMX.  */
> +};
> +
> +extern struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
> +
> +/* Helper function to say whether a mode supports PRE_INC or PRE_DEC.  */
> +static inline bool
> +mode_supports_pre_incdec_p (machine_mode mode)
> +{
> +  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_INCDEC)
> +         != 0);
> +}
> +
> +/* Helper function to say whether a mode supports PRE_MODIFY.  */
> +static inline bool
> +mode_supports_pre_modify_p (machine_mode mode)
> +{
> +  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_MODIFY)
> +         != 0);
> +}
> +
> +/* Return true if we have D-form addressing in altivec registers.  */
> +static inline bool
> +mode_supports_vmx_dform (machine_mode mode)
> +{
> +  return ((reg_addr[mode].addr_mask[RELOAD_REG_VMX] & RELOAD_REG_OFFSET) != 0);
> +}
> +
> +/* Return true if we have D-form addressing in VSX registers.  This addressing
> +   is more limited than normal d-form addressing in that the offset must be
> +   aligned on a 16-byte boundary.  */
> +static inline bool
> +mode_supports_dq_form (machine_mode mode)
> +{
> +  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_QUAD_OFFSET)
> +         != 0);
> +}
> +
> +/* Helper function to return whether a MODE can do prefixed loads/stores.
> +   VOIDmode is used when we are loading the pc-relative address into a base
> +   register, but we are not using it as part of a memory operation.  As modes
> +   add support for prefixed memory, they will be added here.  */
> +
> +static inline bool
> +mode_supports_prefixed_address_p (machine_mode mode)
> +{
> +  return mode == VOIDmode;
> +}
> +
> +
>  /* Structure used to define the rs6000 stack */
>  typedef struct rs6000_stack {
>    int reload_completed;                /* stack info won't change from here on */
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  (revision 273617)
> +++ gcc/config/rs6000/rs6000.c  (working copy)
> @@ -155,8 +155,7 @@ bool rs6000_returns_struct = false;
>  #endif
>
>  /* Value is TRUE if register/mode pair is acceptable.  */
> -static bool rs6000_hard_regno_mode_ok_p
> -  [NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
> +bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
>
>  /* Maximum number of registers needed for a given register class and mode.  */
>  unsigned char rs6000_class_max_nregs[NUM_MACHINE_MODES][LIM_REG_CLASSES];
> @@ -295,122 +294,22 @@ bool cpu_builtin_p = false;
>     don't link in rs6000-c.c, so we can't call it directly.  */
>  void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT, HOST_WIDE_INT);
>
> -/* Simplfy register classes into simpler classifications.  We assume
> -   GPR_REG_TYPE - FPR_REG_TYPE are ordered so that we can use a simple range
> -   check for standard register classes (gpr/floating/altivec/vsx) and
> -   floating/vector classes (float/altivec/vsx).  */
> -
> -enum rs6000_reg_type {
> -  NO_REG_TYPE,
> -  PSEUDO_REG_TYPE,
> -  GPR_REG_TYPE,
> -  VSX_REG_TYPE,
> -  ALTIVEC_REG_TYPE,
> -  FPR_REG_TYPE,
> -  SPR_REG_TYPE,
> -  CR_REG_TYPE
> -};
> -
>  /* Map register class to register type.  */
> -static enum rs6000_reg_type reg_class_to_reg_type[N_REG_CLASSES];
> -
> -/* First/last register type for the 'normal' register types (i.e. general
> -   purpose, floating point, altivec, and VSX registers).  */
> -#define IS_STD_REG_TYPE(RTYPE) IN_RANGE(RTYPE, GPR_REG_TYPE, FPR_REG_TYPE)
> -
> -#define IS_FP_VECT_REG_TYPE(RTYPE) IN_RANGE(RTYPE, VSX_REG_TYPE, FPR_REG_TYPE)
> -
> +enum rs6000_reg_type reg_class_to_reg_type[N_REG_CLASSES];
>
>  /* Register classes we care about in secondary reload or go if legitimate
>     address.  We only need to worry about GPR, FPR, and Altivec registers here,
>     along an ANY field that is the OR of the 3 register classes.  */
> -
> -enum rs6000_reload_reg_type {
> -  RELOAD_REG_GPR,                      /* General purpose registers.  */
> -  RELOAD_REG_FPR,                      /* Traditional floating point regs.  */
> -  RELOAD_REG_VMX,                      /* Altivec (VMX) registers.  */
> -  RELOAD_REG_ANY,                      /* OR of GPR, FPR, Altivec masks.  */
> -  N_RELOAD_REG
> -};
> -
> -/* For setting up register classes, loop through the 3 register classes mapping
> -   into real registers, and skip the ANY class, which is just an OR of the
> -   bits.  */
> -#define FIRST_RELOAD_REG_CLASS RELOAD_REG_GPR
> -#define LAST_RELOAD_REG_CLASS  RELOAD_REG_VMX
> -
> -/* Map reload register type to a register in the register class.  */
> -struct reload_reg_map_type {
> -  const char *name;                    /* Register class name.  */
> -  int reg;                             /* Register in the register class.  */
> -};
> -
> -static const struct reload_reg_map_type reload_reg_map[N_RELOAD_REG] = {
> +const struct reload_reg_map_type reload_reg_map[N_RELOAD_REG] = {
>    { "Gpr",     FIRST_GPR_REGNO },      /* RELOAD_REG_GPR.  */
>    { "Fpr",     FIRST_FPR_REGNO },      /* RELOAD_REG_FPR.  */
>    { "VMX",     FIRST_ALTIVEC_REGNO },  /* RELOAD_REG_VMX.  */
>    { "Any",     -1 },                   /* RELOAD_REG_ANY.  */
>  };
>
> -/* Mask bits for each register class, indexed per mode.  Historically the
> -   compiler has been more restrictive which types can do PRE_MODIFY instead of
> -   PRE_INC and PRE_DEC, so keep track of sepaate bits for these two.  */
> -typedef unsigned char addr_mask_type;
> -
> -#define RELOAD_REG_VALID       0x01    /* Mode valid in register..  */
> -#define RELOAD_REG_MULTIPLE    0x02    /* Mode takes multiple registers.  */
> -#define RELOAD_REG_INDEXED     0x04    /* Reg+reg addressing.  */
> -#define RELOAD_REG_OFFSET      0x08    /* Reg+offset addressing. */
> -#define RELOAD_REG_PRE_INCDEC  0x10    /* PRE_INC/PRE_DEC valid.  */
> -#define RELOAD_REG_PRE_MODIFY  0x20    /* PRE_MODIFY valid.  */
> -#define RELOAD_REG_AND_M16     0x40    /* AND -16 addressing.  */
> -#define RELOAD_REG_QUAD_OFFSET 0x80    /* quad offset is limited.  */
> -
> -/* Register type masks based on the type, of valid addressing modes.  */
> -struct rs6000_reg_addr {
> -  enum insn_code reload_load;          /* INSN to reload for loading. */
> -  enum insn_code reload_store;         /* INSN to reload for storing.  */
> -  enum insn_code reload_fpr_gpr;       /* INSN to move from FPR to GPR.  */
> -  enum insn_code reload_gpr_vsx;       /* INSN to move from GPR to VSX.  */
> -  enum insn_code reload_vsx_gpr;       /* INSN to move from VSX to GPR.  */
> -  addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks.  */
> -  bool scalar_in_vmx_p;                        /* Scalar value can go in VMX.  */
> -};
> -
> -static struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
> -
> -/* Helper function to say whether a mode supports PRE_INC or PRE_DEC.  */
> -static inline bool
> -mode_supports_pre_incdec_p (machine_mode mode)
> -{
> -  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_INCDEC)
> -         != 0);
> -}
> -
> -/* Helper function to say whether a mode supports PRE_MODIFY.  */
> -static inline bool
> -mode_supports_pre_modify_p (machine_mode mode)
> -{
> -  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_MODIFY)
> -         != 0);
> -}
> -
> -/* Return true if we have D-form addressing in altivec registers.  */
> -static inline bool
> -mode_supports_vmx_dform (machine_mode mode)
> -{
> -  return ((reg_addr[mode].addr_mask[RELOAD_REG_VMX] & RELOAD_REG_OFFSET) != 0);
> -}
> -
> -/* Return true if we have D-form addressing in VSX registers.  This addressing
> -   is more limited than normal d-form addressing in that the offset must be
> -   aligned on a 16-byte boundary.  */
> -static inline bool
> -mode_supports_dq_form (machine_mode mode)
> -{
> -  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_QUAD_OFFSET)
> -         != 0);
> -}
> +/* Various low level information needed for addressing formats, register
> +   allocation, etc. indexed by mode.  */
> +struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
>
>  /* Given that there exists at least one variable that is set (produced)
>     by OUT_INSN and read (consumed) by IN_INSN, return true iff
> @@ -13587,17 +13486,6 @@ rs6000_pltseq_template (rtx *operands, i
>  }
>  #endif
>
> -/* Helper function to return whether a MODE can do prefixed loads/stores.
> -   VOIDmode is used when we are loading the pc-relative address into a base
> -   register, but we are not using it as part of a memory operation.  As modes
> -   add support for prefixed memory, they will be added here.  */
> -
> -static bool
> -mode_supports_prefixed_address_p (machine_mode mode)
> -{
> -  return mode == VOIDmode;
> -}
> -
>  /* Function to return true if ADDR is a valid prefixed memory address that uses
>     mode MODE.  */
>
>
> --
> Michael Meissner, IBM
> IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
> email: meissner@linux.ibm.com, phone: +1 (978) 899-4797
Segher Boessenkool July 21, 2019, 5:41 p.m. UTC | #2
On Sat, Jul 20, 2019 at 12:13:08PM -0400, Michael Meissner wrote:
> I will be iterating on patch #9 and sending out a replacement shortly.
> 
> This is patch #10.  It moves the various data structures from rs6000.c to

I'll review this tomorrow, fwiw.

A general request: please don't send patches as replies to other emails.


Segher
Segher Boessenkool July 22, 2019, 5:42 a.m. UTC | #3
Hi!

On Sat, Jul 20, 2019 at 12:13:08PM -0400, Michael Meissner wrote:
> 2019-07-20  Michael Meissner  <meissner@linux.ibm.com>
> 
> 	* config/rs6000/rs6000-internal.h (rs6000_hard_regno_mode_ok_p):
> 	Move various declarations relating to addressing and register
> 	allocation to rs6000-internal.h from rs6000.c so that in the
> 	future we can move things out of rs6000.c.

Just say
  (rs6000_hard_regno_mode_ok_p): New declaration.
for the things that only had a definition before.

> 	Make the static arrays global,

That's not this entry.  Say that in the entries where it applies.

> 	and define them in rs6000.c.

Say that in the corresponding entry for rs6000.c .

> 	(enum rs6000_reg_type): Likewise.

This one always was a declaration.

(... ten gazillion "Likewise." ...)
Most of those are *not* the same thing.  Don't say "likewise" if not
the same comment applies.

If it is hard to write a proper changelog, your patch series probably
could use some restructuring.  Or sometimes the changelog you need just
is more work than you would prefer.

You don't necessarily have to keep the same order in the changelog as
in the patch, if that helps.  But roughly the same order helps review,
so please consider that too ;-)

> +/* Simplfy register classes into simpler classifications.  We assume

(Typo, not new, but still a typo :-) )

> +/* Register classes we care about in secondary reload or go if legitimate
> +   address.  We only need to worry about GPR, FPR, and Altivec registers here,
> +   along an ANY field that is the OR of the 3 register classes.  */

We haven't had GO_IF_LEGITIMATE_ADDRESS for ten years now, please don't
introduce new references to it ;-)

> +#define RELOAD_REG_VALID	0x0001	/* Mode valid in register..  */
> +#define RELOAD_REG_MULTIPLE	0x0002	/* Mode takes multiple registers.  */
> +#define RELOAD_REG_INDEXED	0x0004	/* Reg+reg addressing.  */
> +#define RELOAD_REG_OFFSET	0x0008	/* Reg+offset addressing. */
> +#define RELOAD_REG_PRE_INCDEC	0x0010	/* PRE_INC/PRE_DEC valid.  */
> +#define RELOAD_REG_PRE_MODIFY	0x0020	/* PRE_MODIFY valid.  */
> +#define RELOAD_REG_AND_M16	0x0040	/* AND -16 addressing.  */
> +#define RELOAD_REG_QUAD_OFFSET	0x0080	/* quad offset is limited.  */

Why all the extra zeroes?  If you introduce some 0x100 later, just leave
the 0x80 as 0x80 please, that is much more readable.


It's hard to tell whether the problem is factored sanely, or if this
creates a big mountain of spaghetti instead.  Can you show how this is
used later?

Normally, you send a whole series, and then perhaps many of the first
are preparatory only, but a reviewer can see where things are headed,
and *then* simple refactorings like this can make sense.  The way this
patch looks now you are just making a lot of data global.


Segher
Michael Meissner July 22, 2019, 6:34 p.m. UTC | #4
On Sat, Jul 20, 2019 at 12:28:34PM -0400, David Edelsohn wrote:
> This patch needs to add rs6000-internal.h to tm_file in gcc/config.gcc
> for all of the powerpc/rs6000 targets.  It also may need tm_p_file and
> tm_d_file definitions.

While I agree it would make things easier if the declarations are available to
everybody, why wasn't this an issue when rs6000-internal.h was created to allow
stuff to move out from rs6000.c to rs6000-logues.c?
Michael Meissner July 22, 2019, 6:36 p.m. UTC | #5
On Sun, Jul 21, 2019 at 12:41:51PM -0500, Segher Boessenkool wrote:
> On Sat, Jul 20, 2019 at 12:13:08PM -0400, Michael Meissner wrote:
> > I will be iterating on patch #9 and sending out a replacement shortly.
> > 
> > This is patch #10.  It moves the various data structures from rs6000.c to
> 
> I'll review this tomorrow, fwiw.
> 
> A general request: please don't send patches as replies to other emails.

In the past you had asked me to group patches under a single overview patch.  I
can go back to sending patches individually.
Michael Meissner July 22, 2019, 6:59 p.m. UTC | #6
On Mon, Jul 22, 2019 at 12:42:13AM -0500, Segher Boessenkool wrote:
> Hi!
> 
> On Sat, Jul 20, 2019 at 12:13:08PM -0400, Michael Meissner wrote:
> > 2019-07-20  Michael Meissner  <meissner@linux.ibm.com>
> > 
> > 	* config/rs6000/rs6000-internal.h (rs6000_hard_regno_mode_ok_p):
> > 	Move various declarations relating to addressing and register
> > 	allocation to rs6000-internal.h from rs6000.c so that in the
> > 	future we can move things out of rs6000.c.
> 
> Just say
>   (rs6000_hard_regno_mode_ok_p): New declaration.
> for the things that only had a definition before.
> 
> > 	Make the static arrays global,
> 
> That's not this entry.  Say that in the entries where it applies.
> 
> > 	and define them in rs6000.c.
> 
> Say that in the corresponding entry for rs6000.c .
> 
> > 	(enum rs6000_reg_type): Likewise.
> 
> This one always was a declaration.

This was a mechanical patch, just moving the swath of code from rs6000.c to
rs6000-internal.h.

> (... ten gazillion "Likewise." ...)
> Most of those are *not* the same thing.  Don't say "likewise" if not
> the same comment applies.
> 
> If it is hard to write a proper changelog, your patch series probably
> could use some restructuring.  Or sometimes the changelog you need just
> is more work than you would prefer.
> 
> You don't necessarily have to keep the same order in the changelog as
> in the patch, if that helps.  But roughly the same order helps review,
> so please consider that too ;-)

Well yes, while in general I would prefer to group things logically together
for ChangeLog, I don't tend to do it because as you say it makes it easier for
the review.

> We haven't had GO_IF_LEGITIMATE_ADDRESS for ten years now, please don't
> introduce new references to it ;-)

Yep.

> > +#define RELOAD_REG_VALID	0x0001	/* Mode valid in register..  */
> > +#define RELOAD_REG_MULTIPLE	0x0002	/* Mode takes multiple registers.  */
> > +#define RELOAD_REG_INDEXED	0x0004	/* Reg+reg addressing.  */
> > +#define RELOAD_REG_OFFSET	0x0008	/* Reg+offset addressing. */
> > +#define RELOAD_REG_PRE_INCDEC	0x0010	/* PRE_INC/PRE_DEC valid.  */
> > +#define RELOAD_REG_PRE_MODIFY	0x0020	/* PRE_MODIFY valid.  */
> > +#define RELOAD_REG_AND_M16	0x0040	/* AND -16 addressing.  */
> > +#define RELOAD_REG_QUAD_OFFSET	0x0080	/* quad offset is limited.  */
> 
> Why all the extra zeroes?  If you introduce some 0x100 later, just leave
> the 0x80 as 0x80 please, that is much more readable.

As I mentioned, I will be adding at least one new bit (RELOAD_REG_DS_OFFSET),
but I have potential patches that add a few more (those are still in flux), and
those would need the extra column.

I personally DO NOT find mask definitions like:

#define RELOAD_REG_VALID	0x01	/* Mode valid in register..  */
#define RELOAD_REG_MULTIPLE	0x02	/* Mode takes multiple registers.  */
#define RELOAD_REG_INDEXED	0x04	/* Reg+reg addressing.  */
#define RELOAD_REG_OFFSET	0x08	/* Reg+offset addressing. */
#define RELOAD_REG_PRE_INCDEC	0x10	/* PRE_INC/PRE_DEC valid.  */
#define RELOAD_REG_PRE_MODIFY	0x20	/* PRE_MODIFY valid.  */
#define RELOAD_REG_AND_M16	0x40	/* AND -16 addressing.  */
#define RELOAD_REG_QUAD_OFFSET	0x80	/* quad offset is limited.  */
#define RELOAD_REG_DS_OFFSET	0x100	/* bottom 2 bits must be zero.  */

to be readable.  So in change, I can go back to just:

#define RELOAD_REG_VALID	0x01	/* Mode valid in register..  */
#define RELOAD_REG_MULTIPLE	0x02	/* Mode takes multiple registers.  */
#define RELOAD_REG_INDEXED	0x04	/* Reg+reg addressing.  */
#define RELOAD_REG_OFFSET	0x08	/* Reg+offset addressing. */
#define RELOAD_REG_PRE_INCDEC	0x10	/* PRE_INC/PRE_DEC valid.  */
#define RELOAD_REG_PRE_MODIFY	0x20	/* PRE_MODIFY valid.  */
#define RELOAD_REG_AND_M16	0x40	/* AND -16 addressing.  */
#define RELOAD_REG_QUAD_OFFSET	0x80	/* quad offset is limited.  */

And in the next patch, change it all to:

#define RELOAD_REG_VALID	0x001	/* Mode valid in register..  */
#define RELOAD_REG_MULTIPLE	0x002	/* Mode takes multiple registers.  */
#define RELOAD_REG_INDEXED	0x004	/* Reg+reg addressing.  */
#define RELOAD_REG_OFFSET	0x008	/* Reg+offset addressing. */
#define RELOAD_REG_PRE_INCDEC	0x010	/* PRE_INC/PRE_DEC valid.  */
#define RELOAD_REG_PRE_MODIFY	0x020	/* PRE_MODIFY valid.  */
#define RELOAD_REG_AND_M16	0x040	/* AND -16 addressing.  */
#define RELOAD_REG_QUAD_OFFSET	0x080	/* quad offset is limited.  */
#define RELOAD_REG_DS_OFFSET    0x100	/* bottom 2 bits must be 0.  */

Some time later if I continue with the current code, that would be changed to:

#define RELOAD_REG_VALID	0x0001	/* Mode valid in register..  */
#define RELOAD_REG_MULTIPLE	0x0002	/* Mode takes multiple registers.  */
#define RELOAD_REG_INDEXED	0x0004	/* Reg+reg addressing.  */
#define RELOAD_REG_OFFSET	0x0008	/* Reg+offset addressing. */
#define RELOAD_REG_PRE_INCDEC	0x0010	/* PRE_INC/PRE_DEC valid.  */
#define RELOAD_REG_PRE_MODIFY	0x0020	/* PRE_MODIFY valid.  */
#define RELOAD_REG_AND_M16	0x0040	/* AND -16 addressing.  */
#define RELOAD_REG_QUAD_OFFSET	0x0080	/* DQ-form (bottom 4 bits 0).  */
#define RELOAD_REG_DS_OFFSET	0x0100	/* DS-form (bottom 2 bits 0).  */

/* The following are flags used in address decoding, but are not currently
   stored in the addr_mask field of reg_addr.  */
#define RELOAD_REG_SINGLE	0x0200	/* Address is a single register.  */
#define RELOAD_REG_IS_PREFIXED	0x0400	/* Address uses prefix encoding.  */
#define RELOAD_REG_NOT_PREFIXED	0x0800	/* Address does not use a prefix.  */
#define RELOAD_REG_PCREL_LOCAL	0x1000	/* Pc-relative to local symbol.  */
#define RELOAD_REG_PCREL_EXT	0x2000	/* Pc-relative to external symbol.  */
#define RELOAD_REG_LO_SUM	0x4000	/* Address uses LO_SUM (TOC, etc).  */

I was just trying to save a step since I was moving the definitions any way to
add the alignment.

> 
> It's hard to tell whether the problem is factored sanely, or if this
> creates a big mountain of spaghetti instead.  Can you show how this is
> used later?

The intention is to move bits to other files.  In particular, I want to create
a new rs6000-prefixed.c file that contains the bits specific to prefixed
addressing.  However, a lot of the bits need access to the reg_addr array.
When you have the reg_addr array, all of the mode_supports_* functions also
become useful in the other files.

In addition to reg_array, the code that determines if something is a
traditional instruction or a prefixed instruction needs the register type
classificiation (rs6000_reg_type).  The issue is in some instructions it
depends on whether the offset is an instruction using the DS encoding or D
encoding.  For example, loading floating point scalars to a traditional FPR
register uses the D encoding, but loading floating point scalars to an altivec
register uses the DS encoding.

However, longer term, it would be nice to move other things from rs6000.c to
other files, such as the functions that deal with p8 fusion, and the legitimate
address functions (which I still tend to mentally classify as GO_IF_LEGITIMATE
type functions, even as you mention, we no longer have GO_IF_LEGITIMATE*).

> Normally, you send a whole series, and then perhaps many of the first
> are preparatory only, but a reviewer can see where things are headed,
> and *then* simple refactorings like this can make sense.  The way this
> patch looks now you are just making a lot of data global.

This was intended to be just a mechanical patch to move things to the .h file.
Segher Boessenkool July 22, 2019, 7:50 p.m. UTC | #7
On Mon, Jul 22, 2019 at 02:34:53PM -0400, Michael Meissner wrote:
> On Sat, Jul 20, 2019 at 12:28:34PM -0400, David Edelsohn wrote:
> > This patch needs to add rs6000-internal.h to tm_file in gcc/config.gcc
> > for all of the powerpc/rs6000 targets.  It also may need tm_p_file and
> > tm_d_file definitions.
> 
> While I agree it would make things easier if the declarations are available to
> everybody, why wasn't this an issue when rs6000-internal.h was created to allow
> stuff to move out from rs6000.c to rs6000-logues.c?

AIUI it is mostly needed to get dependencies right?


Segher
Segher Boessenkool July 22, 2019, 7:55 p.m. UTC | #8
On Mon, Jul 22, 2019 at 02:36:00PM -0400, Michael Meissner wrote:
> On Sun, Jul 21, 2019 at 12:41:51PM -0500, Segher Boessenkool wrote:
> > On Sat, Jul 20, 2019 at 12:13:08PM -0400, Michael Meissner wrote:
> > > I will be iterating on patch #9 and sending out a replacement shortly.
> > > 
> > > This is patch #10.  It moves the various data structures from rs6000.c to
> > 
> > I'll review this tomorrow, fwiw.
> > 
> > A general request: please don't send patches as replies to other emails.
> 
> In the past you had asked me to group patches under a single overview patch.  I
> can go back to sending patches individually.

When you send a *series*, please send it as series; when you send
individual patches, please send them individually.  This is all about
how people will get it in their email, and how they will handle it.

This really *is* a series, just most patches do not exist yet, if I
understand correctly.  That is not ideal of course -- I cannot review
it as a series, because I don't have the later patches.  Sending the
patches as replies to weeks-old other patches is less than useful.


Segher
Segher Boessenkool July 22, 2019, 8:56 p.m. UTC | #9
On Mon, Jul 22, 2019 at 02:59:39PM -0400, Michael Meissner wrote:
> On Mon, Jul 22, 2019 at 12:42:13AM -0500, Segher Boessenkool wrote:
> > On Sat, Jul 20, 2019 at 12:13:08PM -0400, Michael Meissner wrote:
> > > 2019-07-20  Michael Meissner  <meissner@linux.ibm.com>
> > > 
> > > 	* config/rs6000/rs6000-internal.h (rs6000_hard_regno_mode_ok_p):
> > > 	Move various declarations relating to addressing and register
> > > 	allocation to rs6000-internal.h from rs6000.c so that in the
> > > 	future we can move things out of rs6000.c.
> > 
> > Just say
> >   (rs6000_hard_regno_mode_ok_p): New declaration.
> > for the things that only had a definition before.
> > 
> > > 	Make the static arrays global,
> > 
> > That's not this entry.  Say that in the entries where it applies.
> > 
> > > 	and define them in rs6000.c.
> > 
> > Say that in the corresponding entry for rs6000.c .
> > 
> > > 	(enum rs6000_reg_type): Likewise.
> > 
> > This one always was a declaration.
> 
> This was a mechanical patch, just moving the swath of code from rs6000.c to
> rs6000-internal.h.

And yet, your changelog should be correct ;-)

> So in change, I can go back to just:
> 
> #define RELOAD_REG_VALID	0x01	/* Mode valid in register..  */
> #define RELOAD_REG_MULTIPLE	0x02	/* Mode takes multiple registers.  */
> #define RELOAD_REG_INDEXED	0x04	/* Reg+reg addressing.  */
> #define RELOAD_REG_OFFSET	0x08	/* Reg+offset addressing. */
> #define RELOAD_REG_PRE_INCDEC	0x10	/* PRE_INC/PRE_DEC valid.  */
> #define RELOAD_REG_PRE_MODIFY	0x20	/* PRE_MODIFY valid.  */
> #define RELOAD_REG_AND_M16	0x40	/* AND -16 addressing.  */
> #define RELOAD_REG_QUAD_OFFSET	0x80	/* quad offset is limited.  */

Yes.  Just keep it as is.  This is supposed to be a move, not a change.

> Some time later if I continue with the current code, that would be changed to:

Maybe.  We'll see then.

> I was just trying to save a step since I was moving the definitions any way to
> add the alignment.

A move should not introduce any unnecessary changes.  This only is much
more work for everyone (you: you need to write extra changelog for it.
Me: I see there are extra changes, and now I have to check everything
else, too).

> > It's hard to tell whether the problem is factored sanely, or if this
> > creates a big mountain of spaghetti instead.  Can you show how this is
> > used later?
> 
> The intention is to move bits to other files.  In particular, I want to create
> a new rs6000-prefixed.c file that contains the bits specific to prefixed
> addressing.

That isn't a good split.  All addressing-related stuff in one file might
make sense, just like the rs6000-call.c split did (which was worthwhile
because all the huge builtin stuff naturally fit there as well).  But
only one kind of addressing?  Nope, that does not sound good.

> However, longer term, it would be nice to move other things from rs6000.c to
> other files, such as the functions that deal with p8 fusion, and the legitimate
> address functions (which I still tend to mentally classify as GO_IF_LEGITIMATE
> type functions, even as you mention, we no longer have GO_IF_LEGITIMATE*).

But only where that makes sense.  Dividing things is only good if a)
the division has an obvious, fundamental meaning; b) the interface
between that part and the rest is thin; c) there is something to actually
*win* from dividing things.

> > Normally, you send a whole series, and then perhaps many of the first
> > are preparatory only, but a reviewer can see where things are headed,
> > and *then* simple refactorings like this can make sense.  The way this
> > patch looks now you are just making a lot of data global.
> 
> This was intended to be just a mechanical patch to move things to the .h file.

That still needs an explanation: why is this a good thing, why do you
want that change?  Sometimes that is obvious of course, but here it is
not.  It would be a lot more obvious if there was more context.


Segher
Michael Meissner July 22, 2019, 10:37 p.m. UTC | #10
On Mon, Jul 22, 2019 at 03:56:26PM -0500, Segher Boessenkool wrote:
> That still needs an explanation: why is this a good thing, why do you
> want that change?  Sometimes that is obvious of course, but here it is
> not.  It would be a lot more obvious if there was more context.

The trouble is to get that much context really relies on about several
additional patches to get to the functions in particular that should be split
out.

As I implement stuff, I find myself neeting/wanting to access the stuff in
reg_addr in other files (predicates.md, and the new file rs6000-prefix.c).

In patch #9 in particular, I added yet another data stucture that was parallel
to the information in reg_addr (originally called rs6000_offset_format, but
based on your comments is now rs6000_insn_form for instruction format).

Then I needed functions that given were a hard register and the move insn and
it determined what instruction format (D/DS/DQ) was used so that we can decide
whether the instruction is traditional or prefixed.

I originally wrote with a lot of code to do that mapping, but once I added the
DS_OFFSET mask and about 10 lines of code to setup DS_OFFSET, it became much simpler.

But for now, I think I will just not worry about making rs6000.c smaller, and
instead do the main work there rather than trying to split it out.  I was
hoping the split would be quick, and it doesn't seem to be.  Splitting it out
is somewhat of a side issue to me, and it looks like it is impeding getting the
rest of the patches submitted.

But it would be nice to have that information available to the other .c files
as well as the .md files.
Segher Boessenkool July 25, 2019, 1:08 p.m. UTC | #11
Hi Mike,

On Mon, Jul 22, 2019 at 06:37:35PM -0400, Michael Meissner wrote:
> On Mon, Jul 22, 2019 at 03:56:26PM -0500, Segher Boessenkool wrote:
> > That still needs an explanation: why is this a good thing, why do you
> > want that change?  Sometimes that is obvious of course, but here it is
> > not.  It would be a lot more obvious if there was more context.
> 
> The trouble is to get that much context really relies on about several
> additional patches to get to the functions in particular that should be split
> out.

In the normal workflow, you send a series of patches when it is ready.
And if a series is not ready, you do not send it.

You can also give context just in the emails, or send a work-in-progress
patch just as FYI (please mark it clearly as such, then).  But without
context, how can I see if what a patch does is correct and useful?

> As I implement stuff, I find myself neeting/wanting to access the stuff in
> reg_addr in other files (predicates.md, and the new file rs6000-prefix.c).

Then you first need to question if things are split up in a useful way
the way things are, and then how it could be done better.

> But it would be nice to have that information available to the other .c files
> as well as the .md files.

If many other modules need the data, then either:
a) The module boundaries are not set nicely; or
b) This is a central data structure, and should be treated as one.


Segher

Patch
diff mbox series

Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	(revision 273617)
+++ gcc/config/rs6000/rs6000-internal.h	(working copy)
@@ -22,6 +22,134 @@ 
 #ifndef GCC_RS6000_INTERNAL_H
 #define GCC_RS6000_INTERNAL_H
 
+/* Value is TRUE if register/mode pair is acceptable.  */
+extern bool rs6000_hard_regno_mode_ok_p
+  [NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+
+/* Simplfy register classes into simpler classifications.  We assume
+   GPR_REG_TYPE - FPR_REG_TYPE are ordered so that we can use a simple range
+   check for standard register classes (gpr/floating/altivec/vsx) and
+   floating/vector classes (float/altivec/vsx).  */
+
+enum rs6000_reg_type {
+  NO_REG_TYPE,
+  PSEUDO_REG_TYPE,
+  GPR_REG_TYPE,
+  VSX_REG_TYPE,
+  ALTIVEC_REG_TYPE,
+  FPR_REG_TYPE,
+  SPR_REG_TYPE,
+  CR_REG_TYPE
+};
+
+/* Map register class to register type.  */
+extern enum rs6000_reg_type reg_class_to_reg_type[N_REG_CLASSES];
+
+/* First/last register type for the 'normal' register types (i.e. general
+   purpose, floating point, altivec, and VSX registers).  */
+#define IS_STD_REG_TYPE(RTYPE) IN_RANGE(RTYPE, GPR_REG_TYPE, FPR_REG_TYPE)
+
+#define IS_FP_VECT_REG_TYPE(RTYPE) IN_RANGE(RTYPE, VSX_REG_TYPE, FPR_REG_TYPE)
+
+
+/* Register classes we care about in secondary reload or go if legitimate
+   address.  We only need to worry about GPR, FPR, and Altivec registers here,
+   along an ANY field that is the OR of the 3 register classes.  */
+
+enum rs6000_reload_reg_type {
+  RELOAD_REG_GPR,			/* General purpose registers.  */
+  RELOAD_REG_FPR,			/* Traditional floating point regs.  */
+  RELOAD_REG_VMX,			/* Altivec (VMX) registers.  */
+  RELOAD_REG_ANY,			/* OR of GPR, FPR, Altivec masks.  */
+  N_RELOAD_REG
+};
+
+/* For setting up register classes, loop through the 3 register classes mapping
+   into real registers, and skip the ANY class, which is just an OR of the
+   bits.  */
+#define FIRST_RELOAD_REG_CLASS	RELOAD_REG_GPR
+#define LAST_RELOAD_REG_CLASS	RELOAD_REG_VMX
+
+/* Map reload register type to a register in the register class.  */
+struct reload_reg_map_type {
+  const char *name;			/* Register class name.  */
+  int reg;				/* Register in the register class.  */
+};
+
+extern const struct reload_reg_map_type reload_reg_map[N_RELOAD_REG];
+
+/* Mask bits for each register class, indexed per mode.  Historically the
+   compiler has been more restrictive which types can do PRE_MODIFY instead of
+   PRE_INC and PRE_DEC, so keep track of sepaate bits for these two.  */
+typedef unsigned char addr_mask_type;
+
+#define RELOAD_REG_VALID	0x0001	/* Mode valid in register..  */
+#define RELOAD_REG_MULTIPLE	0x0002	/* Mode takes multiple registers.  */
+#define RELOAD_REG_INDEXED	0x0004	/* Reg+reg addressing.  */
+#define RELOAD_REG_OFFSET	0x0008	/* Reg+offset addressing. */
+#define RELOAD_REG_PRE_INCDEC	0x0010	/* PRE_INC/PRE_DEC valid.  */
+#define RELOAD_REG_PRE_MODIFY	0x0020	/* PRE_MODIFY valid.  */
+#define RELOAD_REG_AND_M16	0x0040	/* AND -16 addressing.  */
+#define RELOAD_REG_QUAD_OFFSET	0x0080	/* quad offset is limited.  */
+
+/* Register type masks based on the type, of valid addressing modes.  */
+struct rs6000_reg_addr {
+  enum insn_code reload_load;		/* INSN to reload for loading. */
+  enum insn_code reload_store;		/* INSN to reload for storing.  */
+  enum insn_code reload_fpr_gpr;	/* INSN to move from FPR to GPR.  */
+  enum insn_code reload_gpr_vsx;	/* INSN to move from GPR to VSX.  */
+  enum insn_code reload_vsx_gpr;	/* INSN to move from VSX to GPR.  */
+  addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks.  */
+  bool scalar_in_vmx_p;			/* Scalar value can go in VMX.  */
+};
+
+extern struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
+
+/* Helper function to say whether a mode supports PRE_INC or PRE_DEC.  */
+static inline bool
+mode_supports_pre_incdec_p (machine_mode mode)
+{
+  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_INCDEC)
+	  != 0);
+}
+
+/* Helper function to say whether a mode supports PRE_MODIFY.  */
+static inline bool
+mode_supports_pre_modify_p (machine_mode mode)
+{
+  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_MODIFY)
+	  != 0);
+}
+
+/* Return true if we have D-form addressing in altivec registers.  */
+static inline bool
+mode_supports_vmx_dform (machine_mode mode)
+{
+  return ((reg_addr[mode].addr_mask[RELOAD_REG_VMX] & RELOAD_REG_OFFSET) != 0);
+}
+
+/* Return true if we have D-form addressing in VSX registers.  This addressing
+   is more limited than normal d-form addressing in that the offset must be
+   aligned on a 16-byte boundary.  */
+static inline bool
+mode_supports_dq_form (machine_mode mode)
+{
+  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_QUAD_OFFSET)
+	  != 0);
+}
+
+/* Helper function to return whether a MODE can do prefixed loads/stores.
+   VOIDmode is used when we are loading the pc-relative address into a base
+   register, but we are not using it as part of a memory operation.  As modes
+   add support for prefixed memory, they will be added here.  */
+
+static inline bool
+mode_supports_prefixed_address_p (machine_mode mode)
+{
+  return mode == VOIDmode;
+}
+
+
 /* Structure used to define the rs6000 stack */
 typedef struct rs6000_stack {
   int reload_completed;		/* stack info won't change from here on */
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 273617)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -155,8 +155,7 @@  bool rs6000_returns_struct = false;
 #endif
 
 /* Value is TRUE if register/mode pair is acceptable.  */
-static bool rs6000_hard_regno_mode_ok_p
-  [NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
 
 /* Maximum number of registers needed for a given register class and mode.  */
 unsigned char rs6000_class_max_nregs[NUM_MACHINE_MODES][LIM_REG_CLASSES];
@@ -295,122 +294,22 @@  bool cpu_builtin_p = false;
    don't link in rs6000-c.c, so we can't call it directly.  */
 void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT, HOST_WIDE_INT);
 
-/* Simplfy register classes into simpler classifications.  We assume
-   GPR_REG_TYPE - FPR_REG_TYPE are ordered so that we can use a simple range
-   check for standard register classes (gpr/floating/altivec/vsx) and
-   floating/vector classes (float/altivec/vsx).  */
-
-enum rs6000_reg_type {
-  NO_REG_TYPE,
-  PSEUDO_REG_TYPE,
-  GPR_REG_TYPE,
-  VSX_REG_TYPE,
-  ALTIVEC_REG_TYPE,
-  FPR_REG_TYPE,
-  SPR_REG_TYPE,
-  CR_REG_TYPE
-};
-
 /* Map register class to register type.  */
-static enum rs6000_reg_type reg_class_to_reg_type[N_REG_CLASSES];
-
-/* First/last register type for the 'normal' register types (i.e. general
-   purpose, floating point, altivec, and VSX registers).  */
-#define IS_STD_REG_TYPE(RTYPE) IN_RANGE(RTYPE, GPR_REG_TYPE, FPR_REG_TYPE)
-
-#define IS_FP_VECT_REG_TYPE(RTYPE) IN_RANGE(RTYPE, VSX_REG_TYPE, FPR_REG_TYPE)
-
+enum rs6000_reg_type reg_class_to_reg_type[N_REG_CLASSES];
 
 /* Register classes we care about in secondary reload or go if legitimate
    address.  We only need to worry about GPR, FPR, and Altivec registers here,
    along an ANY field that is the OR of the 3 register classes.  */
-
-enum rs6000_reload_reg_type {
-  RELOAD_REG_GPR,			/* General purpose registers.  */
-  RELOAD_REG_FPR,			/* Traditional floating point regs.  */
-  RELOAD_REG_VMX,			/* Altivec (VMX) registers.  */
-  RELOAD_REG_ANY,			/* OR of GPR, FPR, Altivec masks.  */
-  N_RELOAD_REG
-};
-
-/* For setting up register classes, loop through the 3 register classes mapping
-   into real registers, and skip the ANY class, which is just an OR of the
-   bits.  */
-#define FIRST_RELOAD_REG_CLASS	RELOAD_REG_GPR
-#define LAST_RELOAD_REG_CLASS	RELOAD_REG_VMX
-
-/* Map reload register type to a register in the register class.  */
-struct reload_reg_map_type {
-  const char *name;			/* Register class name.  */
-  int reg;				/* Register in the register class.  */
-};
-
-static const struct reload_reg_map_type reload_reg_map[N_RELOAD_REG] = {
+const struct reload_reg_map_type reload_reg_map[N_RELOAD_REG] = {
   { "Gpr",	FIRST_GPR_REGNO },	/* RELOAD_REG_GPR.  */
   { "Fpr",	FIRST_FPR_REGNO },	/* RELOAD_REG_FPR.  */
   { "VMX",	FIRST_ALTIVEC_REGNO },	/* RELOAD_REG_VMX.  */
   { "Any",	-1 },			/* RELOAD_REG_ANY.  */
 };
 
-/* Mask bits for each register class, indexed per mode.  Historically the
-   compiler has been more restrictive which types can do PRE_MODIFY instead of
-   PRE_INC and PRE_DEC, so keep track of sepaate bits for these two.  */
-typedef unsigned char addr_mask_type;
-
-#define RELOAD_REG_VALID	0x01	/* Mode valid in register..  */
-#define RELOAD_REG_MULTIPLE	0x02	/* Mode takes multiple registers.  */
-#define RELOAD_REG_INDEXED	0x04	/* Reg+reg addressing.  */
-#define RELOAD_REG_OFFSET	0x08	/* Reg+offset addressing. */
-#define RELOAD_REG_PRE_INCDEC	0x10	/* PRE_INC/PRE_DEC valid.  */
-#define RELOAD_REG_PRE_MODIFY	0x20	/* PRE_MODIFY valid.  */
-#define RELOAD_REG_AND_M16	0x40	/* AND -16 addressing.  */
-#define RELOAD_REG_QUAD_OFFSET	0x80	/* quad offset is limited.  */
-
-/* Register type masks based on the type, of valid addressing modes.  */
-struct rs6000_reg_addr {
-  enum insn_code reload_load;		/* INSN to reload for loading. */
-  enum insn_code reload_store;		/* INSN to reload for storing.  */
-  enum insn_code reload_fpr_gpr;	/* INSN to move from FPR to GPR.  */
-  enum insn_code reload_gpr_vsx;	/* INSN to move from GPR to VSX.  */
-  enum insn_code reload_vsx_gpr;	/* INSN to move from VSX to GPR.  */
-  addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks.  */
-  bool scalar_in_vmx_p;			/* Scalar value can go in VMX.  */
-};
-
-static struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
-
-/* Helper function to say whether a mode supports PRE_INC or PRE_DEC.  */
-static inline bool
-mode_supports_pre_incdec_p (machine_mode mode)
-{
-  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_INCDEC)
-	  != 0);
-}
-
-/* Helper function to say whether a mode supports PRE_MODIFY.  */
-static inline bool
-mode_supports_pre_modify_p (machine_mode mode)
-{
-  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_MODIFY)
-	  != 0);
-}
-
-/* Return true if we have D-form addressing in altivec registers.  */
-static inline bool
-mode_supports_vmx_dform (machine_mode mode)
-{
-  return ((reg_addr[mode].addr_mask[RELOAD_REG_VMX] & RELOAD_REG_OFFSET) != 0);
-}
-
-/* Return true if we have D-form addressing in VSX registers.  This addressing
-   is more limited than normal d-form addressing in that the offset must be
-   aligned on a 16-byte boundary.  */
-static inline bool
-mode_supports_dq_form (machine_mode mode)
-{
-  return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_QUAD_OFFSET)
-	  != 0);
-}
+/* Various low level information needed for addressing formats, register
+   allocation, etc. indexed by mode.  */
+struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
 
 /* Given that there exists at least one variable that is set (produced)
    by OUT_INSN and read (consumed) by IN_INSN, return true iff
@@ -13587,17 +13486,6 @@  rs6000_pltseq_template (rtx *operands, i
 }
 #endif
 
-/* Helper function to return whether a MODE can do prefixed loads/stores.
-   VOIDmode is used when we are loading the pc-relative address into a base
-   register, but we are not using it as part of a memory operation.  As modes
-   add support for prefixed memory, they will be added here.  */
-
-static bool
-mode_supports_prefixed_address_p (machine_mode mode)
-{
-  return mode == VOIDmode;
-}
-
 /* Function to return true if ADDR is a valid prefixed memory address that uses
    mode MODE.  */