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]

[PATCH] Hookize PREFERRED_RELOAD_CLASS


Hello.

  This patch turns PREFERRED_RELOAD_CLASS macro into a hook.

  The patch has been bootstrapped on and regression tested on
x86_64-unknown-linux-gnu for c.

  This patch is pre-approved and should be committed within a week if no
objections.

        * target.def (preferred_reload_class): New hook.
        * doc/tm.texi.in (TARGET_PREFERRED_RELOAD_CLASS): Document.
        * doc/tm.texi: Regenerate.
        * targhooks.c (default_preferred_reload_class): New function.
        * targhooks.h (default_preferred_reload_class): Declare.
        * reload.c (find_dummy_reload): Change preferred_class variable type
        from enum reg_class to reg_class_t. Use TARGET_PREFERRED_RELOAD_CLASS
        target hook.
        (find_reloads): Change goal_alternative array type from int to
        reg_class_t. Use TARGET_PREFERRED_RELOAD_CLASS target hook.
        (push_reload, find_reloads_address_part): Use
        TARGET_PREFERRED_RELOAD_CLASS target hook.
        * reload1.c (emit_input_reload_insns): Ditto.
        * ira-costs.c (copy_cost): Use TARGET_PREFERRED_RELOAD_CLASS target
        hook. Change rclass argument and secondary_class variable types from
        'enum reg_class' to reg_class_t.
        
        * config/i386/i386.h (PREFERRED_RELOAD_CLASS): Remove.
        * config/i386/i386.c (ix86_preferred_reload_class): Remove.
        * config/i386/i386.c (ix86_preferred_reload_class): Make static.
        Change regclass argument and result types from enum reg_class to
        reg_class_t.
        (TARGET_PREFERRED_RELOAD_CLASS): Define.


Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi     (revision 164959)
+++ gcc/doc/tm.texi     (working copy)
@@ -2581,6 +2581,40 @@
 This macro also has strict and non-strict variants.
 @end defmac
 
+@deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RELOAD_CLASS (rtx @var{x}, reg_class_t @var{rclass})
+A target hook that places additional restrictions on the register class
+to use when it is necessary to copy value @var{x} into a register in class
+@var{rclass}.  The value is a register class; perhaps @var{rclass}, or perhaps
+another, smaller class.
+
+The default version of this hook always returns value of @code{rclass} argument.
+
+Sometimes returning a more restrictive class makes better code.  For
+example, on the 68000, when @var{x} is an integer constant that is in range
+for a @samp{moveq} instruction, the value of this macro is always
+@code{DATA_REGS} as long as @var{rclass} includes the data registers.
+Requiring a data register guarantees that a @samp{moveq} will be used.
+
+One case where @code{TARGET_PREFERRED_RELOAD_CLASS} must not return
+@var{rclass} is if @var{x} is a legitimate constant which cannot be
+loaded into some register class.  By returning @code{NO_REGS} you can
+force @var{x} into a memory location.  For example, rs6000 can load
+immediate values into general-purpose registers, but does not have an
+instruction for loading an immediate value into a floating-point
+register, so @code{TARGET_PREFERRED_RELOAD_CLASS} returns @code{NO_REGS} when
+@var{x} is a floating-point constant.  If the constant can't be loaded
+into any kind of register, code generation will be better if
+@code{LEGITIMATE_CONSTANT_P} makes the constant illegitimate instead
+of using @code{TARGET_PREFERRED_RELOAD_CLASS}.
+
+If an insn has pseudos in it after register allocation, reload will go
+through the alternatives and call repeatedly @code{TARGET_PREFERRED_RELOAD_CLASS}
+to find the best one.  Returning @code{NO_REGS}, in this case, makes
+reload add a @code{!} in front of the constraint: the x86 back-end uses
+this feature to discourage usage of 387 registers when math is done in
+the SSE registers (and vice versa).
+@end deftypefn
+
 @defmac PREFERRED_RELOAD_CLASS (@var{x}, @var{class})
 A C expression that places additional restrictions on the register class
 to use when it is necessary to copy value @var{x} into a register in class
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in  (revision 164959)
+++ gcc/doc/tm.texi.in  (working copy)
@@ -2581,6 +2581,40 @@
 This macro also has strict and non-strict variants.
 @end defmac
 
+@hook TARGET_PREFERRED_RELOAD_CLASS
+A target hook that places additional restrictions on the register class
+to use when it is necessary to copy value @var{x} into a register in class
+@var{rclass}.  The value is a register class; perhaps @var{rclass}, or perhaps
+another, smaller class.
+
+The default version of this hook always returns value of @code{rclass} argument.
+
+Sometimes returning a more restrictive class makes better code.  For
+example, on the 68000, when @var{x} is an integer constant that is in range
+for a @samp{moveq} instruction, the value of this macro is always
+@code{DATA_REGS} as long as @var{rclass} includes the data registers.
+Requiring a data register guarantees that a @samp{moveq} will be used.
+
+One case where @code{TARGET_PREFERRED_RELOAD_CLASS} must not return
+@var{rclass} is if @var{x} is a legitimate constant which cannot be
+loaded into some register class.  By returning @code{NO_REGS} you can
+force @var{x} into a memory location.  For example, rs6000 can load
+immediate values into general-purpose registers, but does not have an
+instruction for loading an immediate value into a floating-point
+register, so @code{TARGET_PREFERRED_RELOAD_CLASS} returns @code{NO_REGS} when
+@var{x} is a floating-point constant.  If the constant can't be loaded
+into any kind of register, code generation will be better if
+@code{LEGITIMATE_CONSTANT_P} makes the constant illegitimate instead
+of using @code{TARGET_PREFERRED_RELOAD_CLASS}.
+
+If an insn has pseudos in it after register allocation, reload will go
+through the alternatives and call repeatedly @code{TARGET_PREFERRED_RELOAD_CLASS}
+to find the best one.  Returning @code{NO_REGS}, in this case, makes
+reload add a @code{!} in front of the constraint: the x86 back-end uses
+this feature to discourage usage of 387 registers when math is done in
+the SSE registers (and vice versa).
+@end deftypefn
+
 @defmac PREFERRED_RELOAD_CLASS (@var{x}, @var{class})
 A C expression that places additional restrictions on the register class
 to use when it is necessary to copy value @var{x} into a register in class
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c     (revision 164959)
+++ gcc/targhooks.c     (working copy)
@@ -1221,6 +1221,19 @@
 #endif
 }
 
+/* The default implementation of TARGET_PREFERRED_RELOAD_CLASS.  */
+
+reg_class_t
+default_preferred_reload_class (rtx x ATTRIBUTE_UNUSED,
+                               reg_class_t rclass)
+{
+#ifdef PREFERRED_RELOAD_CLASS 
+  return (reg_class_t) PREFERRED_RELOAD_CLASS (x, (enum reg_class) rclass);
+#else
+  return rclass;
+#endif
+}
+
 /* The default implementation of TARGET_CLASS_LIKELY_SPILLED_P.  */
 
 bool
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h     (revision 164959)
+++ gcc/targhooks.h     (working copy)
@@ -153,6 +153,7 @@
                                       reg_class_t);
 
 extern bool default_profile_before_prologue (void);
+extern reg_class_t default_preferred_reload_class (rtx, reg_class_t);
 extern bool default_class_likely_spilled_p (reg_class_t);
 
 extern enum unwind_info_type default_debug_unwind_info (void);
Index: gcc/target.def
===================================================================
--- gcc/target.def      (revision 164959)
+++ gcc/target.def      (working copy)
@@ -2023,7 +2023,16 @@
   secondary_reload_info *sri),
  default_secondary_reload)
 
+/* Given an rtx X being reloaded into a reg required to be in class CLASS,
+   return the class of reg to actually use.  */
 DEFHOOK
+(preferred_reload_class,
+ "",
+ reg_class_t,
+ (rtx x, reg_class_t rclass),
+ default_preferred_reload_class)
+
+DEFHOOK
 (class_likely_spilled_p,
  "",
  bool, (reg_class_t rclass),
Index: gcc/reload.c
===================================================================
--- gcc/reload.c        (revision 164959)
+++ gcc/reload.c        (working copy)
@@ -1227,7 +1227,7 @@
     enum reg_class preferred_class = rclass;
 
     if (in != 0)
-      preferred_class = PREFERRED_RELOAD_CLASS (in, rclass);
+      preferred_class = (enum reg_class) targetm.preferred_reload_class (in, rclass);
 
   /* Output reloads may need analogous treatment, different in detail.  */
 #ifdef PREFERRED_OUTPUT_RELOAD_CLASS
@@ -1963,9 +1963,9 @@
   /* Narrow down the reg class, the same way push_reload will;
      otherwise we might find a dummy now, but push_reload won't.  */
   {
-    enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, rclass);
+    reg_class_t preferred_class = targetm.preferred_reload_class (in, rclass);
     if (preferred_class != NO_REGS)
-      rclass = preferred_class;
+      rclass = (enum reg_class) preferred_class;
   }
 
   /* See if OUT will do.  */
@@ -2595,7 +2595,7 @@
   char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
   int this_alternative_matches[MAX_RECOG_OPERANDS];
   int swapped;
-  int goal_alternative[MAX_RECOG_OPERANDS];
+  reg_class_t goal_alternative[MAX_RECOG_OPERANDS];
   int this_alternative_number;
   int goal_alternative_number = 0;
   int operand_reloadnum[MAX_RECOG_OPERANDS];
@@ -3506,7 +3506,8 @@
                 precisely the same as in the code below that calls
                 force_const_mem.  */
              if (CONST_POOL_OK_P (operand)
-                 && ((PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
+                 && ((targetm.preferred_reload_class (operand,
+                                                      this_alternative[i])
                       == NO_REGS)
                      || no_input_reloads)
                  && operand_mode[i] != VOIDmode)
@@ -3534,7 +3535,7 @@
 
              if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS)
                {
-                 if (PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
+                 if (targetm.preferred_reload_class (operand, this_alternative[i])
                      == NO_REGS)
                    reject = 600;
 
@@ -3695,7 +3696,7 @@
            {
              goal_alternative_win[i] = this_alternative_win[i];
              goal_alternative_match_win[i] = this_alternative_match_win[i];
-             goal_alternative[i] = this_alternative[i];
+             goal_alternative[i] = (reg_class_t) this_alternative[i];
              goal_alternative_offmemok[i] = this_alternative_offmemok[i];
              goal_alternative_matches[i] = this_alternative_matches[i];
              goal_alternative_earlyclobber[i]
@@ -3722,7 +3723,7 @@
            {
              for (i = 0; i < noperands; i++)
                {
-                 goal_alternative[i] = this_alternative[i];
+                 goal_alternative[i] = (reg_class_t) this_alternative[i];
                  goal_alternative_win[i] = this_alternative_win[i];
                  goal_alternative_match_win[i]
                    = this_alternative_match_win[i];
@@ -3915,8 +3916,7 @@
          }
 
        if (CONST_POOL_OK_P (op)
-           && ((PREFERRED_RELOAD_CLASS (op,
-                                        (enum reg_class) goal_alternative[i])
+           && ((targetm.preferred_reload_class (op, goal_alternative[i])
                 == NO_REGS)
                || no_input_reloads)
            && mode != VOIDmode)
@@ -4094,7 +4094,7 @@
            /* If this is only for an output, the optional reload would not
               actually cause us to use a register now, just note that
               something is stored here.  */
-           && ((enum reg_class) goal_alternative[i] != NO_REGS
+           && (goal_alternative[i] != NO_REGS
                || modified[i] == RELOAD_WRITE)
            && ! no_input_reloads
            /* An optional output reload might allow to delete INSN later.
@@ -4168,8 +4168,7 @@
        if ((MEM_P (operand)
             || (REG_P (operand)
                 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
-           && ((enum reg_class) goal_alternative[goal_alternative_matches[i]]
-               != NO_REGS))
+           && (goal_alternative[goal_alternative_matches[i]] != NO_REGS))
          operand_reloadnum[i] = operand_reloadnum[goal_alternative_matches[i]]
            = push_reload (recog_data.operand[goal_alternative_matches[i]],
                           recog_data.operand[i],
@@ -6048,7 +6047,7 @@
 {
   if (CONSTANT_P (x)
       && (! LEGITIMATE_CONSTANT_P (x)
-         || PREFERRED_RELOAD_CLASS (x, rclass) == NO_REGS))
+         || targetm.preferred_reload_class (x, rclass) == NO_REGS))
     {
       x = force_const_mem (mode, x);
       find_reloads_address (mode, &x, XEXP (x, 0), &XEXP (x, 0),
@@ -6058,7 +6057,8 @@
   else if (GET_CODE (x) == PLUS
           && CONSTANT_P (XEXP (x, 1))
           && (! LEGITIMATE_CONSTANT_P (XEXP (x, 1))
-              || PREFERRED_RELOAD_CLASS (XEXP (x, 1), rclass) == NO_REGS))
+              || targetm.preferred_reload_class (XEXP (x, 1), rclass)
+                  == NO_REGS))
     {
       rtx tem;
 
Index: gcc/ira-costs.c
===================================================================
--- gcc/ira-costs.c     (revision 164959)
+++ gcc/ira-costs.c     (working copy)
@@ -131,11 +131,11 @@
    TO_P is FALSE) a register of class RCLASS in mode MODE.  X must not
    be a pseudo register.  */
 static int
-copy_cost (rtx x, enum machine_mode mode, enum reg_class rclass, bool to_p,
+copy_cost (rtx x, enum machine_mode mode, reg_class_t rclass, bool to_p,
           secondary_reload_info *prev_sri)
 {
   secondary_reload_info sri;
-  enum reg_class secondary_class = NO_REGS;
+  reg_class_t secondary_class = NO_REGS;
 
   /* If X is a SCRATCH, there is actually nothing to move since we are
      assuming optimal allocation.  */
@@ -143,21 +143,21 @@
     return 0;
 
   /* Get the class we will actually use for a reload.  */
-  rclass = PREFERRED_RELOAD_CLASS (x, rclass);
+  rclass = targetm.preferred_reload_class (x, rclass);
 
   /* If we need a secondary reload for an intermediate, the cost is
      that to load the input into the intermediate register, then to
      copy it.  */
   sri.prev_sri = prev_sri;
   sri.extra_cost = 0;
-  secondary_class
-    = (enum reg_class) targetm.secondary_reload (to_p, x, rclass, mode, &sri);
+  secondary_class = targetm.secondary_reload (to_p, x, rclass, mode, &sri);
 
   if (secondary_class != NO_REGS)
     {
       if (!move_cost[mode])
         init_move_cost (mode);
-      return (move_cost[mode][secondary_class][rclass] + sri.extra_cost
+      return (move_cost[mode][(int) secondary_class][(int) rclass]
+             + sri.extra_cost
              + copy_cost (x, mode, secondary_class, to_p, &sri));
     }
 
@@ -165,12 +165,14 @@
      the cost to move between the register classes, and use 2 for
      everything else (constants).  */
   if (MEM_P (x) || rclass == NO_REGS)
-    return sri.extra_cost + ira_memory_move_cost[mode][rclass][to_p != 0];
+    return sri.extra_cost
+          + ira_memory_move_cost[mode][(int) rclass][to_p != 0];
   else if (REG_P (x))
     {
       if (!move_cost[mode])
         init_move_cost (mode);
-      return (sri.extra_cost + move_cost[mode][REGNO_REG_CLASS (REGNO (x))][rclass]);
+      return (sri.extra_cost
+             + move_cost[mode][REGNO_REG_CLASS (REGNO (x))][(int) rclass]);
     }
   else
     /* If this is a constant, we may eventually want to call rtx_cost
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h      (revision 164959)
+++ gcc/config/i386/i386.h      (working copy)
@@ -1373,22 +1373,6 @@
        || (CLASS) == LEGACY_REGS || (CLASS) == INDEX_REGS)     \
    ? Q_REGS : (CLASS))
 
-/* Given an rtx X being reloaded into a reg required to be
-   in class CLASS, return the class of reg to actually use.
-   In general this is just CLASS; but on some machines
-   in some cases it is preferable to use a more restrictive class.
-   On the 80386 series, we prevent floating constants from being
-   reloaded into floating registers (since no move-insn can do that)
-   and we ensure that QImodes aren't reloaded into the esi or edi reg.  */
-
-/* Put float CONST_DOUBLE in the constant pool instead of fp regs.
-   QImode must go into class Q_REGS.
-   Narrow ALL_REGS to GENERAL_REGS.  This supports allowing movsf and
-   movdf to do mem-to-mem moves through integer regs.  */
-
-#define PREFERRED_RELOAD_CLASS(X, CLASS) \
-   ix86_preferred_reload_class ((X), (CLASS))
-
 /* Discourage putting floating-point values in SSE registers unless
    SSE math is being used, and likewise for the 387 registers.  */
 
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h       (revision 164959)
+++ gcc/config/i386/i386-protos.h       (working copy)
@@ -153,7 +153,6 @@
                                          enum machine_mode, int);
 extern bool ix86_cannot_change_mode_class (enum machine_mode,
                                           enum machine_mode, enum reg_class);
-extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class);
 extern enum reg_class ix86_preferred_output_reload_class (rtx, enum reg_class);
 extern int ix86_mode_needed (int, rtx);
 extern void emit_i387_cw_initialization (int);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c      (revision 164959)
+++ gcc/config/i386/i386.c      (working copy)
@@ -26602,12 +26602,15 @@
  return TARGET_SSE_MATH ? sse_fpmath_classes : no_sse_fpmath_classes;
 }
 
-/* Put float CONST_DOUBLE in the constant pool instead of fp regs.
+/* Implement TARGET_PREFERRED_RELOAD_CLASS.
+
+   Put float CONST_DOUBLE in the constant pool instead of fp regs.
    QImode must go into class Q_REGS.
    Narrow ALL_REGS to GENERAL_REGS.  This supports allowing movsf and
    movdf to do mem-to-mem moves through integer regs.  */
-enum reg_class
-ix86_preferred_reload_class (rtx x, enum reg_class regclass)
+
+static reg_class_t
+ix86_preferred_reload_class (rtx x, reg_class_t regclass)
 {
   enum machine_mode mode = GET_MODE (x);
 
@@ -33226,6 +33229,8 @@
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD ix86_secondary_reload
 
+#undef TARGET_PREFERRED_RELOAD_CLASS
+#define TARGET_PREFERRED_RELOAD_CLASS ix86_preferred_reload_class
 #undef TARGET_CLASS_LIKELY_SPILLED_P
 #define TARGET_CLASS_LIKELY_SPILLED_P ix86_class_likely_spilled_p
 
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c       (revision 164959)
+++ gcc/reload1.c       (working copy)
@@ -7500,8 +7500,8 @@
                  || (reg_equiv_constant
                      [REGNO (SUBREG_REG (oldequiv))] != 0)))
          || (CONSTANT_P (oldequiv)
-             && (PREFERRED_RELOAD_CLASS (oldequiv,
-                                         REGNO_REG_CLASS (REGNO (reloadreg)))
+             && (targetm.preferred_reload_class (oldequiv,
+                                                 REGNO_REG_CLASS (REGNO (reloadreg)))
                  == NO_REGS)))
        real_oldequiv = rl->in;
       gen_reload (reloadreg, real_oldequiv, rl->opnum,

Anatoly.
Anatoly.


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