OSDN Git Service

2005-08-08 Paolo Bonzini <bonzini@gnu.org>
authorbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 3 Apr 2006 11:20:07 +0000 (11:20 +0000)
committerbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 3 Apr 2006 11:20:07 +0000 (11:20 +0000)
    Dale Johannesen  <dalej@apple.com>

PR target/19653
* regclass.c (struct reg_pref): Update documentation.
(regclass): Set prefclass to NO_REGS if memory is the best option.
(record_reg_classes): Cope with a prefclass set to NO_REGS.
* reload.c (find_reloads): Take PREFERRED_OUTPUT_RELOAD_CLASS
into account.  For non-registers, equate an empty preferred
reload class to a `!' in the constraint; move the if clause to
do so after those that reject the insn.
(push_reload): Allow PREFERRED_*_RELOAD_CLASS to liberally
return NO_REGS.
(find_dummy_reload): Likewise.
* doc/tm.texi (Register Classes): Document what it means
if PREFERRED_*_RELOAD_CLASS return NO_REGS.
* config/i386/i386.c (ix86_preferred_reload_class): Force
using SSE registers (and return NO_REGS for floating-point
constants) if math is done with SSE.
(ix86_preferred_output_reload_class): New.
* config/i386/i386-protos.h (ix86_preferred_output_reload_class): New.
* config/i386/i386.h (PREFERRED_OUTPUT_RELOAD_CLASS): New.
* config/i386/i386.md: Remove # register preferences.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@112637 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/doc/tm.texi
gcc/regclass.c
gcc/reload.c

index 97507f1..ebf0227 100644 (file)
@@ -1,3 +1,27 @@
+2005-08-08  Paolo Bonzini  <bonzini@gnu.org>
+           Dale Johannesen  <dalej@apple.com>
+
+       PR target/19653
+       * regclass.c (struct reg_pref): Update documentation.
+       (regclass): Set prefclass to NO_REGS if memory is the best option.
+       (record_reg_classes): Cope with a prefclass set to NO_REGS.
+       * reload.c (find_reloads): Take PREFERRED_OUTPUT_RELOAD_CLASS
+       into account.  For non-registers, equate an empty preferred
+       reload class to a `!' in the constraint; move the if clause to
+       do so after those that reject the insn.
+       (push_reload): Allow PREFERRED_*_RELOAD_CLASS to liberally
+       return NO_REGS.
+       (find_dummy_reload): Likewise.
+       * doc/tm.texi (Register Classes): Document what it means
+       if PREFERRED_*_RELOAD_CLASS return NO_REGS.
+       * config/i386/i386.c (ix86_preferred_reload_class): Force
+       using SSE registers (and return NO_REGS for floating-point
+       constants) if math is done with SSE.
+       (ix86_preferred_output_reload_class): New.
+       * config/i386/i386-protos.h (ix86_preferred_output_reload_class): New.
+       * config/i386/i386.h (PREFERRED_OUTPUT_RELOAD_CLASS): New.
+       * config/i386/i386.md: Remove # register preferences.
+
 2006-04-02  Sebastian Pop  <pop@cri.ensmp.fr>
 
        PR bootstrap/26992
 2006-04-02  Sebastian Pop  <pop@cri.ensmp.fr>
 
        PR bootstrap/26992
index ed9d4f3..315487e 100644 (file)
@@ -142,6 +142,7 @@ extern int ix86_secondary_memory_needed (enum reg_class, enum reg_class,
 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 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_memory_move_cost (enum machine_mode, enum reg_class, int);
 extern int ix86_mode_needed (int, rtx);
 extern void emit_i387_cw_initialization (int);
 extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int);
 extern int ix86_mode_needed (int, rtx);
 extern void emit_i387_cw_initialization (int);
index da4b135..84b19b9 100644 (file)
@@ -16361,15 +16361,28 @@ ix86_free_from_memory (enum machine_mode mode)
 enum reg_class
 ix86_preferred_reload_class (rtx x, enum reg_class class)
 {
 enum reg_class
 ix86_preferred_reload_class (rtx x, enum reg_class class)
 {
+  enum machine_mode mode = GET_MODE (x);
+
   /* We're only allowed to return a subclass of CLASS.  Many of the 
      following checks fail for NO_REGS, so eliminate that early.  */
   if (class == NO_REGS)
     return NO_REGS;
 
   /* All classes can load zeros.  */
   /* We're only allowed to return a subclass of CLASS.  Many of the 
      following checks fail for NO_REGS, so eliminate that early.  */
   if (class == NO_REGS)
     return NO_REGS;
 
   /* All classes can load zeros.  */
-  if (x == CONST0_RTX (GET_MODE (x)))
+  if (x == CONST0_RTX (mode))
     return class;
 
     return class;
 
+  /* Force constants into memory if we are loading a (non-zero) constant into
+     an MMX or SSE register.  This is because there are no MMX/SSE instructions
+     to load from a constant.  */
+  if (CONSTANT_P (x)
+      && (MAYBE_MMX_CLASS_P (class) || MAYBE_SSE_CLASS_P (class)))
+    return NO_REGS;
+
+  /* Prefer SSE regs only, if we can use them for math.  */
+  if (TARGET_SSE_MATH && !TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (mode))
+    return SSE_CLASS_P (class) ? class : NO_REGS;
+
   /* Floating-point constants need more complex checks.  */
   if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
     {
   /* Floating-point constants need more complex checks.  */
   if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
     {
@@ -16381,8 +16394,6 @@ ix86_preferred_reload_class (rtx x, enum reg_class class)
         zero above.  We only want to wind up preferring 80387 registers if
         we plan on doing computation with them.  */
       if (TARGET_80387
         zero above.  We only want to wind up preferring 80387 registers if
         we plan on doing computation with them.  */
       if (TARGET_80387
-         && (TARGET_MIX_SSE_I387 
-             || !(TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (x))))
          && standard_80387_constant_p (x))
        {
          /* Limit class to non-sse.  */
          && standard_80387_constant_p (x))
        {
          /* Limit class to non-sse.  */
@@ -16398,10 +16409,6 @@ ix86_preferred_reload_class (rtx x, enum reg_class class)
 
       return NO_REGS;
     }
 
       return NO_REGS;
     }
-  if (MAYBE_MMX_CLASS_P (class) && CONSTANT_P (x))
-    return NO_REGS;
-  if (MAYBE_SSE_CLASS_P (class) && CONSTANT_P (x))
-    return NO_REGS;
 
   /* Generally when we see PLUS here, it's the function invariant
      (plus soft-fp const_int).  Which can only be computed into general
 
   /* Generally when we see PLUS here, it's the function invariant
      (plus soft-fp const_int).  Which can only be computed into general
@@ -16423,6 +16430,33 @@ ix86_preferred_reload_class (rtx x, enum reg_class class)
   return class;
 }
 
   return class;
 }
 
+/* Discourage putting floating-point values in SSE registers unless
+   SSE math is being used, and likewise for the 387 registers.  */
+enum reg_class
+ix86_preferred_output_reload_class (rtx x, enum reg_class class)
+{
+  enum machine_mode mode = GET_MODE (x);
+
+  /* Restrict the output reload class to the register bank that we are doing
+     math on.  If we would like not to return a subset of CLASS, reject this
+     alternative: if reload cannot do this, it will still use its choice.  */
+  mode = GET_MODE (x);
+  if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
+    return MAYBE_SSE_CLASS_P (class) ? SSE_REGS : NO_REGS;
+
+  if (TARGET_80387 && SCALAR_FLOAT_MODE_P (mode))
+    {
+      if (class == FP_TOP_SSE_REGS)
+       return FP_TOP_REG;
+      else if (class == FP_SECOND_SSE_REGS)
+       return FP_SECOND_REG;
+      else
+       return FLOAT_CLASS_P (class) ? class : NO_REGS;
+    }
+
+  return class;
+}
+
 /* If we are copying between general and FP registers, we need a memory
    location. The same is true for SSE and MMX registers.
 
 /* If we are copying between general and FP registers, we need a memory
    location. The same is true for SSE and MMX registers.
 
index fc8f626..b783913 100644 (file)
@@ -669,7 +669,9 @@ extern int x86_prefetch_sse;
 
 #define STACK_REGS
 #define IS_STACK_MODE(MODE)                                    \
 
 #define STACK_REGS
 #define IS_STACK_MODE(MODE)                                    \
-  ((MODE) == DFmode || (MODE) == SFmode || (MODE) == XFmode)   \
+  (((MODE) == SFmode && (!TARGET_SSE || !TARGET_SSE_MATH))     \
+   || ((MODE) == DFmode && (!TARGET_SSE2 || !TARGET_SSE_MATH))  \
+   || (MODE) == XFmode)
 
 /* Number of actual hardware registers.
    The hardware registers are assigned numbers for the compiler
 
 /* Number of actual hardware registers.
    The hardware registers are assigned numbers for the compiler
@@ -1222,6 +1224,12 @@ enum reg_class
 #define PREFERRED_RELOAD_CLASS(X, CLASS) \
    ix86_preferred_reload_class ((X), (CLASS))
 
 #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.  */
+
+#define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \
+   ix86_preferred_output_reload_class ((X), (CLASS))
+
 /* If we are copying between general and FP registers, we need a memory
    location. The same is true for SSE and MMX registers.  */
 #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
 /* If we are copying between general and FP registers, we need a memory
    location. The same is true for SSE and MMX registers.  */
 #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
index 827bf4e..ef3f36b 100644 (file)
 
 (define_insn "*cmpfp_i_mixed"
   [(set (reg:CCFP FLAGS_REG)
 
 (define_insn "*cmpfp_i_mixed"
   [(set (reg:CCFP FLAGS_REG)
-       (compare:CCFP (match_operand 0 "register_operand" "f#x,x#f")
-                     (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
+       (compare:CCFP (match_operand 0 "register_operand" "f,x")
+                     (match_operand 1 "nonimmediate_operand" "f,xm")))]
   "TARGET_MIX_SSE_I387
    && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])"
   "TARGET_MIX_SSE_I387
    && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])"
 
 (define_insn "*cmpfp_iu_mixed"
   [(set (reg:CCFPU FLAGS_REG)
 
 (define_insn "*cmpfp_iu_mixed"
   [(set (reg:CCFPU FLAGS_REG)
-       (compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f")
-                      (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
+       (compare:CCFPU (match_operand 0 "register_operand" "f,x")
+                      (match_operand 1 "nonimmediate_operand" "f,xm")))]
   "TARGET_MIX_SSE_I387
    && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])"
   "TARGET_MIX_SSE_I387
    && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])"
 
 (define_insn "*pushsf"
   [(set (match_operand:SF 0 "push_operand" "=<,<,<")
 
 (define_insn "*pushsf"
   [(set (match_operand:SF 0 "push_operand" "=<,<,<")
-       (match_operand:SF 1 "general_no_elim_operand" "f#rx,rFm#fx,x#rf"))]
+       (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
   "!TARGET_64BIT"
 {
   /* Anything else should be already split before reg-stack.  */
   "!TARGET_64BIT"
 {
   /* Anything else should be already split before reg-stack.  */
 
 (define_insn "*pushsf_rex64"
   [(set (match_operand:SF 0 "push_operand" "=X,X,X")
 
 (define_insn "*pushsf_rex64"
   [(set (match_operand:SF 0 "push_operand" "=X,X,X")
-       (match_operand:SF 1 "nonmemory_no_elim_operand" "f#rx,rF#fx,x#rf"))]
+       (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
   "TARGET_64BIT"
 {
   /* Anything else should be already split before reg-stack.  */
   "TARGET_64BIT"
 {
   /* Anything else should be already split before reg-stack.  */
 
 (define_insn "*movsf_1"
   [(set (match_operand:SF 0 "nonimmediate_operand"
 
 (define_insn "*movsf_1"
   [(set (match_operand:SF 0 "nonimmediate_operand"
-         "=f#xr,m   ,f#xr,r#xf  ,m    ,x#rf,x#rf,x#rf ,m   ,!*y,!rm,!*y")
+         "=f,m   ,f,r,m    ,x,x,x,m   ,!*y,!rm,!*y")
        (match_operand:SF 1 "general_operand"
        (match_operand:SF 1 "general_operand"
-         "fm#rx,f#rx,G   ,rmF#fx,Fr#fx,C   ,x   ,xm#rf,x#rf,rm ,*y ,*y"))]
+         "fm,f,G   ,rmF,Fr,C   ,x   ,xm,x,rm ,*y ,*y"))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))
    && (reload_in_progress || reload_completed
        || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))
    && (reload_in_progress || reload_completed
        || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
 
 (define_insn "*pushdf_nointeger"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
 
 (define_insn "*pushdf_nointeger"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
-       (match_operand:DF 1 "general_no_elim_operand" "f#Y,Fo#fY,*r#fY,Y#f"))]
+       (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))]
   "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
 {
   /* This insn should be already split before reg-stack.  */
   "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
 {
   /* This insn should be already split before reg-stack.  */
 
 (define_insn "*pushdf_integer"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<")
 
 (define_insn "*pushdf_integer"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<")
-       (match_operand:DF 1 "general_no_elim_operand" "f#rY,rFo#fY,Y#rf"))]
+       (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))]
   "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
 {
   /* This insn should be already split before reg-stack.  */
   "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
 {
   /* This insn should be already split before reg-stack.  */
 
 (define_insn "*movdf_nointeger"
   [(set (match_operand:DF 0 "nonimmediate_operand"
 
 (define_insn "*movdf_nointeger"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-                       "=f#Y,m  ,f#Y,*r  ,o  ,Y*x#f,Y*x#f,Y*x#f ,m    ")
+                       "=f,m  ,f,*r  ,o  ,Y*x,Y*x,Y*x,m    ")
        (match_operand:DF 1 "general_operand"
        (match_operand:DF 1 "general_operand"
-                       "fm#Y,f#Y,G  ,*roF,F*r,C    ,Y*x#f,mY*x#f,Y*x#f"))]
+                       "fm,f,G  ,*roF,F*r,C    ,Y*x,mY*x,Y*x"))]
   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
    && (reload_in_progress || reload_completed
   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
    && (reload_in_progress || reload_completed
 
 (define_insn "*movdf_integer"
   [(set (match_operand:DF 0 "nonimmediate_operand"
 
 (define_insn "*movdf_integer"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-               "=f#Yr,m   ,f#Yr,r#Yf  ,o    ,Y*x#rf,Y*x#rf,Y*x#rf,m")
+               "=f,m   ,f,r,o    ,Y*x,Y*x,Y*x,m")
        (match_operand:DF 1 "general_operand"
        (match_operand:DF 1 "general_operand"
-               "fm#Yr,f#Yr,G   ,roF#Yf,Fr#Yf,C     ,Y*x#rf,m     ,Y*x#rf"))]
+               "fm,f,G   ,roF,Fr,C     ,Y*x,m     ,Y*x"))]
   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
    && (reload_in_progress || reload_completed
   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
    && (reload_in_progress || reload_completed
 
 (define_insn "*pushxf_integer"
   [(set (match_operand:XF 0 "push_operand" "=<,<")
 
 (define_insn "*pushxf_integer"
   [(set (match_operand:XF 0 "push_operand" "=<,<")
-       (match_operand:XF 1 "general_no_elim_operand" "f#r,ro#f"))]
+       (match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
   "!optimize_size"
 {
   /* This insn should be already split before reg-stack.  */
   "!optimize_size"
 {
   /* This insn should be already split before reg-stack.  */
    (set_attr "mode" "XF,XF,XF,SI,SI")])
 
 (define_insn "*movxf_integer"
    (set_attr "mode" "XF,XF,XF,SI,SI")])
 
 (define_insn "*movxf_integer"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
-       (match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
+  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
+       (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
   "!optimize_size
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && (reload_in_progress || reload_completed
   "!optimize_size
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && (reload_in_progress || reload_completed
 })
 
 (define_insn "*extendsfdf2_mixed"
 })
 
 (define_insn "*extendsfdf2_mixed"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,m#fY,Y#f")
-        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm#Y,f#Y,mY#f")))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y")
+        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))]
   "TARGET_SSE2 && TARGET_MIX_SSE_I387
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
 {
   "TARGET_SSE2 && TARGET_MIX_SSE_I387
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
 {
 })
 
 (define_insn "*truncxfsf2_mixed"
 })
 
 (define_insn "*truncxfsf2_mixed"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf")
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
        (float_truncate:SF
         (match_operand:XF 1 "register_operand" "f,f,f,f")))
    (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
        (float_truncate:SF
         (match_operand:XF 1 "register_operand" "f,f,f,f")))
    (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
    (set_attr "mode" "SF")])
 
 (define_insn "*truncxfsf2_i387"
    (set_attr "mode" "SF")])
 
 (define_insn "*truncxfsf2_i387"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#r,?r#f")
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r")
        (float_truncate:SF
         (match_operand:XF 1 "register_operand" "f,f,f")))
    (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
        (float_truncate:SF
         (match_operand:XF 1 "register_operand" "f,f,f")))
    (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
 })
 
 (define_insn "*truncxfdf2_mixed"
 })
 
 (define_insn "*truncxfdf2_mixed"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y")
        (float_truncate:DF
         (match_operand:XF 1 "register_operand" "f,f,f,f")))
    (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
        (float_truncate:DF
         (match_operand:XF 1 "register_operand" "f,f,f,f")))
    (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
    (set_attr "mode" "DF")])
 
 (define_insn "*truncxfdf2_i387"
    (set_attr "mode" "DF")])
 
 (define_insn "*truncxfdf2_i387"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#r,?r#f")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r")
        (float_truncate:DF
         (match_operand:XF 1 "register_operand" "f,f,f")))
    (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
        (float_truncate:DF
         (match_operand:XF 1 "register_operand" "f,f,f")))
    (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
   "")
 
 (define_insn "*floatsisf2_mixed"
   "")
 
 (define_insn "*floatsisf2_mixed"
-  [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f")
+  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
        (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_MIX_SSE_I387"
   "@
        (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_MIX_SSE_I387"
   "@
   "")
 
 (define_insn "*floatdisf2_mixed"
   "")
 
 (define_insn "*floatdisf2_mixed"
-  [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f")
+  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
        (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_64BIT && TARGET_MIX_SSE_I387"
   "@
        (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_64BIT && TARGET_MIX_SSE_I387"
   "@
   "")
 
 (define_insn "*floatsidf2_mixed"
   "")
 
 (define_insn "*floatsidf2_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
        (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
        (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
   "")
 
 (define_insn "*floatdidf2_mixed"
   "")
 
 (define_insn "*floatdidf2_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
        (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
        (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
   "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
 
 (define_insn "*absnegsf2_mixed"
   "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
 
 (define_insn "*absnegsf2_mixed"
-  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x#f,x#f,f#x,rm")
+  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x,x,f,rm")
        (match_operator:SF 3 "absneg_operator"
        (match_operator:SF 3 "absneg_operator"
-         [(match_operand:SF 1 "nonimmediate_operand" "0   ,x#f,0  ,0")]))
+         [(match_operand:SF 1 "nonimmediate_operand" "0   ,x,0  ,0")]))
    (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm  ,0  ,X  ,X"))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
    (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm  ,0  ,X  ,X"))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
   "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
 
 (define_insn "*absnegdf2_mixed"
   "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
 
 (define_insn "*absnegdf2_mixed"
-  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y#f,Y#f,f#Y,rm")
+  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,f,rm")
        (match_operator:DF 3 "absneg_operator"
        (match_operator:DF 3 "absneg_operator"
-         [(match_operand:DF 1 "nonimmediate_operand" "0   ,Y#f,0  ,0")]))
+         [(match_operand:DF 1 "nonimmediate_operand" "0   ,Y,0  ,0")]))
    (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym  ,0  ,X  ,X"))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
    (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym  ,0  ,X  ,X"))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
 (define_insn "*fp_jcc_1_mixed"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
 (define_insn "*fp_jcc_1_mixed"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
-                       [(match_operand 1 "register_operand" "f#x,x#f")
-                        (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
+                       [(match_operand 1 "register_operand" "f,x")
+                        (match_operand 2 "nonimmediate_operand" "f,xm")])
          (label_ref (match_operand 3 "" ""))
          (pc)))
    (clobber (reg:CCFP FPSR_REG))
          (label_ref (match_operand 3 "" ""))
          (pc)))
    (clobber (reg:CCFP FPSR_REG))
 (define_insn "*fp_jcc_2_mixed"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
 (define_insn "*fp_jcc_2_mixed"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
-                       [(match_operand 1 "register_operand" "f#x,x#f")
-                        (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
+                       [(match_operand 1 "register_operand" "f,x")
+                        (match_operand 2 "nonimmediate_operand" "f,xm")])
          (pc)
          (label_ref (match_operand 3 "" ""))))
    (clobber (reg:CCFP FPSR_REG))
          (pc)
          (label_ref (match_operand 3 "" ""))))
    (clobber (reg:CCFP FPSR_REG))
 ;; so use special patterns for add and mull.
 
 (define_insn "*fop_sf_comm_mixed"
 ;; so use special patterns for add and mull.
 
 (define_insn "*fop_sf_comm_mixed"
-  [(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
+  [(set (match_operand:SF 0 "register_operand" "=f,x")
        (match_operator:SF 3 "binary_fp_operator"
                        [(match_operand:SF 1 "nonimmediate_operand" "%0,0")
        (match_operator:SF 3 "binary_fp_operator"
                        [(match_operand:SF 1 "nonimmediate_operand" "%0,0")
-                        (match_operand:SF 2 "nonimmediate_operand" "fm#x,xm#f")]))]
+                        (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))]
   "TARGET_MIX_SSE_I387
    && COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
   "TARGET_MIX_SSE_I387
    && COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
   [(set (match_operand:SF 0 "register_operand" "=f,f,x")
        (match_operator:SF 3 "binary_fp_operator"
                        [(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
   [(set (match_operand:SF 0 "register_operand" "=f,f,x")
        (match_operator:SF 3 "binary_fp_operator"
                        [(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
-                        (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm#f")]))]
+                        (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))]
   "TARGET_MIX_SSE_I387
    && !COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
   "TARGET_MIX_SSE_I387
    && !COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
    (set_attr "mode" "<MODE>")])
 
 (define_insn "*fop_df_comm_mixed"
    (set_attr "mode" "<MODE>")])
 
 (define_insn "*fop_df_comm_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,Y")
        (match_operator:DF 3 "binary_fp_operator"
                        [(match_operand:DF 1 "nonimmediate_operand" "%0,0")
        (match_operator:DF 3 "binary_fp_operator"
                        [(match_operand:DF 1 "nonimmediate_operand" "%0,0")
-                        (match_operand:DF 2 "nonimmediate_operand" "fm#Y,Ym#f")]))]
+                        (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))]
   "TARGET_SSE2 && TARGET_MIX_SSE_I387
    && COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
   "TARGET_SSE2 && TARGET_MIX_SSE_I387
    && COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
    (set_attr "mode" "DF")])
 
 (define_insn "*fop_df_1_mixed"
    (set_attr "mode" "DF")])
 
 (define_insn "*fop_df_1_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,f#Y,Y#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,f,Y")
        (match_operator:DF 3 "binary_fp_operator"
                        [(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
        (match_operator:DF 3 "binary_fp_operator"
                        [(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
-                        (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym#f")]))]
+                        (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))]
   "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
    && !COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
   "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
    && !COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
 })
 
 (define_insn "*sqrtsf2_mixed"
 })
 
 (define_insn "*sqrtsf2_mixed"
-  [(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
-       (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0#x,xm#f")))]
+  [(set (match_operand:SF 0 "register_operand" "=f,x")
+       (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))]
   "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
   "@
    fsqrt
   "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
   "@
    fsqrt
 })
 
 (define_insn "*sqrtdf2_mixed"
 })
 
 (define_insn "*sqrtdf2_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
-       (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0#Y,Ym#f")))]
+  [(set (match_operand:DF 0 "register_operand" "=f,Y")
+       (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))]
   "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
    fsqrt
   "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
    fsqrt
   "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
 
 (define_insn "*movsfcc_1_387"
   "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
 
 (define_insn "*movsfcc_1_387"
-  [(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f")
+  [(set (match_operand:SF 0 "register_operand" "=f,f,r,r")
        (if_then_else:SF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
        (if_then_else:SF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
-                     (match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
-                     (match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
+                     (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0")
+                     (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))]
   "TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
   "TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
   "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
 
 (define_insn "*movdfcc_1"
   "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
 
 (define_insn "*movdfcc_1"
-  [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r")
        (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
        (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
-                     (match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
-                     (match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
+                     (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
+                     (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
   "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
   "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
    (set_attr "mode" "DF")])
 
 (define_insn "*movdfcc_1_rex64"
    (set_attr "mode" "DF")])
 
 (define_insn "*movdfcc_1_rex64"
-  [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,r#f,r#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,f,r,r")
        (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
        (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
-                     (match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f")
-                     (match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))]
+                     (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
+                     (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
   "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
   "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
index b1dae11..2e7632e 100644 (file)
@@ -2404,12 +2404,22 @@ register, so @code{PREFERRED_RELOAD_CLASS} returns @code{NO_REGS} when
 into any kind of register, code generation will be better if
 @code{LEGITIMATE_CONSTANT_P} makes the constant illegitimate instead
 of using @code{PREFERRED_RELOAD_CLASS}.
 into any kind of register, code generation will be better if
 @code{LEGITIMATE_CONSTANT_P} makes the constant illegitimate instead
 of using @code{PREFERRED_RELOAD_CLASS}.
+
+If an insn has pseudos in it after register allocation, reload will go
+through the alternatives and call repeatedly @code{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 defmac
 
 @defmac PREFERRED_OUTPUT_RELOAD_CLASS (@var{x}, @var{class})
 Like @code{PREFERRED_RELOAD_CLASS}, but for output reloads instead of
 input reloads.  If you don't define this macro, the default is to use
 @var{class}, unchanged.
 @end defmac
 
 @defmac PREFERRED_OUTPUT_RELOAD_CLASS (@var{x}, @var{class})
 Like @code{PREFERRED_RELOAD_CLASS}, but for output reloads instead of
 input reloads.  If you don't define this macro, the default is to use
 @var{class}, unchanged.
+
+You can also use @code{PREFERRED_OUTPUT_RELOAD_CLASS} to discourage
+reload from using some alternatives, like @code{PREFERRED_RELOAD_CLASS}.
 @end defmac
 
 @defmac LIMIT_RELOAD_CLASS (@var{mode}, @var{class})
 @end defmac
 
 @defmac LIMIT_RELOAD_CLASS (@var{mode}, @var{class})
index f76fdcd..1f1e6c2 100644 (file)
@@ -811,7 +811,8 @@ struct costs
 /* Structure used to record preferences of given pseudo.  */
 struct reg_pref
 {
 /* Structure used to record preferences of given pseudo.  */
 struct reg_pref
 {
-  /* (enum reg_class) prefclass is the preferred class.  */
+  /* (enum reg_class) prefclass is the preferred class.  May be
+     NO_REGS if no class is better than memory.  */
   char prefclass;
 
   /* altclass is a register class that we should use for allocating
   char prefclass;
 
   /* altclass is a register class that we should use for allocating
@@ -1314,6 +1315,10 @@ regclass (rtx f, int nregs)
                best = reg_class_subunion[(int) best][class];
            }
 
                best = reg_class_subunion[(int) best][class];
            }
 
+         /* If no register class is better than memory, use memory. */
+         if (p->mem_cost < best_cost)
+           best = NO_REGS;
+
          /* Record the alternate register class; i.e., a class for which
             every register in it is better than using memory.  If adding a
             class would make a smaller class (i.e., no union of just those
          /* Record the alternate register class; i.e., a class for which
             every register in it is better than using memory.  If adding a
             class would make a smaller class (i.e., no union of just those
@@ -1524,7 +1529,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                     to what we would add if this register were not in the
                     appropriate class.  */
 
                     to what we would add if this register were not in the
                     appropriate class.  */
 
-                 if (reg_pref)
+                 if (reg_pref && reg_pref[REGNO (op)].prefclass != NO_REGS)
                    alt_cost
                      += (may_move_in_cost[mode]
                          [(unsigned char) reg_pref[REGNO (op)].prefclass]
                    alt_cost
                      += (may_move_in_cost[mode]
                          [(unsigned char) reg_pref[REGNO (op)].prefclass]
@@ -1750,7 +1755,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                     to what we would add if this register were not in the
                     appropriate class.  */
 
                     to what we would add if this register were not in the
                     appropriate class.  */
 
-                 if (reg_pref)
+                 if (reg_pref && reg_pref[REGNO (op)].prefclass != NO_REGS)
                    alt_cost
                      += (may_move_in_cost[mode]
                          [(unsigned char) reg_pref[REGNO (op)].prefclass]
                    alt_cost
                      += (may_move_in_cost[mode]
                          [(unsigned char) reg_pref[REGNO (op)].prefclass]
@@ -1836,7 +1841,8 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
          int class;
          unsigned int nr;
 
          int class;
          unsigned int nr;
 
-         if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0)
+         if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0
+             && reg_pref[regno].prefclass != NO_REGS)
            {
              enum reg_class pref = reg_pref[regno].prefclass;
 
            {
              enum reg_class pref = reg_pref[regno].prefclass;
 
index 9bfb748..f3023ae 100644 (file)
@@ -1184,15 +1184,24 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
   /* Narrow down the class of register wanted if that is
      desirable on this machine for efficiency.  */
 
   /* Narrow down the class of register wanted if that is
      desirable on this machine for efficiency.  */
-  if (in != 0)
-    class = PREFERRED_RELOAD_CLASS (in, class);
+  {
+    enum reg_class preferred_class = class;
+
+    if (in != 0)
+      preferred_class = PREFERRED_RELOAD_CLASS (in, class);
 
   /* Output reloads may need analogous treatment, different in detail.  */
 #ifdef PREFERRED_OUTPUT_RELOAD_CLASS
 
   /* Output reloads may need analogous treatment, different in detail.  */
 #ifdef PREFERRED_OUTPUT_RELOAD_CLASS
-  if (out != 0)
-    class = PREFERRED_OUTPUT_RELOAD_CLASS (out, class);
+    if (out != 0)
+      preferred_class = PREFERRED_OUTPUT_RELOAD_CLASS (out, preferred_class);
 #endif
 
 #endif
 
+    /* Discard what the target said if we cannot do it.  */
+    if (preferred_class != NO_REGS
+       || (optional && type == RELOAD_FOR_OUTPUT))
+      class = preferred_class;
+  }
+
   /* Make sure we use a class that can handle the actual pseudo
      inside any subreg.  For example, on the 386, QImode regs
      can appear within SImode subregs.  Although GENERAL_REGS
   /* Make sure we use a class that can handle the actual pseudo
      inside any subreg.  For example, on the 386, QImode regs
      can appear within SImode subregs.  Although GENERAL_REGS
@@ -1885,7 +1894,11 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
 
   /* Narrow down the reg class, the same way push_reload will;
      otherwise we might find a dummy now, but push_reload won't.  */
 
   /* Narrow down the reg class, the same way push_reload will;
      otherwise we might find a dummy now, but push_reload won't.  */
-  class = PREFERRED_RELOAD_CLASS (in, class);
+  {
+    enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, class);
+    if (class != NO_REGS)
+      class = preferred_class;
+  }
 
   /* See if OUT will do.  */
   if (REG_P (out)
 
   /* See if OUT will do.  */
   if (REG_P (out)
@@ -3401,22 +3414,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    losers++;
                }
 
                    losers++;
                }
 
-             /* If we can't reload this value at all, reject this
-                alternative.  Note that we could also lose due to
-                LIMIT_RELOAD_RELOAD_CLASS, but we don't check that
-                here.  */
-
-             if (! CONSTANT_P (operand)
-                 && (enum reg_class) this_alternative[i] != NO_REGS
-                 && (PREFERRED_RELOAD_CLASS (operand,
-                                             (enum reg_class) this_alternative[i])
-                     == NO_REGS))
-               bad = 1;
-
              /* Alternative loses if it requires a type of reload not
                 permitted for this insn.  We can always reload SCRATCH
                 and objects with a REG_UNUSED note.  */
              /* Alternative loses if it requires a type of reload not
                 permitted for this insn.  We can always reload SCRATCH
                 and objects with a REG_UNUSED note.  */
-             else if (GET_CODE (operand) != SCRATCH
+             if (GET_CODE (operand) != SCRATCH
                       && modified[i] != RELOAD_READ && no_output_reloads
                       && ! find_reg_note (insn, REG_UNUSED, operand))
                bad = 1;
                       && modified[i] != RELOAD_READ && no_output_reloads
                       && ! find_reg_note (insn, REG_UNUSED, operand))
                bad = 1;
@@ -3424,6 +3425,28 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                       && ! const_to_mem)
                bad = 1;
 
                       && ! const_to_mem)
                bad = 1;
 
+             /* If we can't reload this value at all, reject this
+                alternative.  Note that we could also lose due to
+                LIMIT_RELOAD_CLASS, but we don't check that
+                here.  */
+
+             if (! CONSTANT_P (operand)
+                 && (enum reg_class) this_alternative[i] != NO_REGS)
+               {
+                 if (PREFERRED_RELOAD_CLASS
+                       (operand, (enum reg_class) this_alternative[i])
+                     == NO_REGS)
+                   reject = 600;
+
+#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
+                 if (operand_type[i] == RELOAD_FOR_OUTPUT
+                     && PREFERRED_OUTPUT_RELOAD_CLASS
+                          (operand, (enum reg_class) this_alternative[i])
+                        == NO_REGS)
+                   reject = 600;
+#endif
+               }
+
              /* We prefer to reload pseudos over reloading other things,
                 since such reloads may be able to be eliminated later.
                 If we are reloading a SCRATCH, we won't be generating any
              /* We prefer to reload pseudos over reloading other things,
                 since such reloads may be able to be eliminated later.
                 If we are reloading a SCRATCH, we won't be generating any