i386.h (enum ix86_entity): New.
authorUros Bizjak <uros@kss-loka.si>
Tue, 7 Jun 2005 23:58:55 +0000 (01:58 +0200)
committerRoger Sayle <sayle@gcc.gnu.org>
Tue, 7 Jun 2005 23:58:55 +0000 (23:58 +0000)
2005-06-07  Uros Bizjak  <uros@kss-loka.si>

* config/i386/i386.h (enum ix86_entity): New.
(enum ix86_stack_slot): New.
(OPTIMIZE_MODE_SWITCHING): Redefine to use
ix86_optimize_mode_switching[] array.
(NUM_MODES_FOR_MODE_SWITCHING): Redefine for 4 entities.
(MODE_NEEDED): Use ix86_mode_needed() function.
(EMIT_MODE_SET): Redefine for changed emit_i387_cw_initialization ()
function.
(struct machine_function): Use optimize_mode_switching[] array.

* config/i386/i386.c (MAX_386_STACK_LOCALS): Remove.
(ix86_mode_needed): New function.
(emit_i387_cw_initialization): Cleanup. Use mode to calculate
correct stack positions for stored control words.
(assign_386_stack_local): Use enum ix86_stack_slot. Change assert.
(ix86_expand_builtin) [IX86_BUILTIN_LDMXCSR]: Change constant to
SLOT_TEMP.
[IX86_BUILTIN_STMXCSR]: Same.

* config/i386/i386-protos.h (assign_stack_local): Change prototype.
(emit_i387_cw_initialization): Change prototype.
(ix86_mode_needed): New prototype.

* config/i386/i386.md (i387_cw attribute): Change order of elements.
(truncdfsf2, truncxfsf2, truncxfdf2, fix_trunc<mode>_fisttp_i387_1)
(*fix_trunc<mode>_i387_1, lrint<mode>2, *fist<mode>2_floor_1)
(*fist<mode>2_ceil_1): Change constant in call to
assign_386_stack_local to SLOT_TEMP.
(*fix_trunc<mode>_i387_1): Change constant in call to
assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_TRUNC.
Use new ix86_optimize_mode_switching[] array.
(frndintxf2_floor, *fist<mode>2_floor_1): Change constants in call to
assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_FLOOR.
Use new ix86_optimize_mode_switching[] array.
(frndintxf2_ceil, *fist<mode>2_ceil_1):  Change constants in call to
assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_CEIL.
Use new ix86_optimize_mode_switching[] array.
(frndintxf2_trunc): Change constants in call to
assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_TRUNC.
Use new ix86_optimize_mode_switching[] array.
(frndintxf2_mask_pm): Change constants in call to
assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_MASK_PM.
Use new ix86_optimize_mode_switching[] array.

(define_peephole2): Change constant from 17 to FLAGS_REG;

From-SVN: r100732

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index b504b101acbb84165201214ce500a1c7a0f721e6..6719fa8746ada296738230cf8bf65610404fbcf2 100644 (file)
@@ -1,3 +1,51 @@
+2005-06-07  Uros Bizjak  <uros@kss-loka.si>
+
+       * config/i386/i386.h (enum ix86_entity): New.
+       (enum ix86_stack_slot): New.
+       (OPTIMIZE_MODE_SWITCHING): Redefine to use
+       ix86_optimize_mode_switching[] array.
+       (NUM_MODES_FOR_MODE_SWITCHING): Redefine for 4 entities.
+       (MODE_NEEDED): Use ix86_mode_needed() function.
+       (EMIT_MODE_SET): Redefine for changed emit_i387_cw_initialization ()
+       function.
+       (struct machine_function): Use optimize_mode_switching[] array.
+
+       * config/i386/i386.c (MAX_386_STACK_LOCALS): Remove.
+       (ix86_mode_needed): New function.
+       (emit_i387_cw_initialization): Cleanup. Use mode to calculate
+       correct stack positions for stored control words.
+       (assign_386_stack_local): Use enum ix86_stack_slot. Change assert.
+       (ix86_expand_builtin) [IX86_BUILTIN_LDMXCSR]: Change constant to
+       SLOT_TEMP.
+       [IX86_BUILTIN_STMXCSR]: Same.
+
+       * config/i386/i386-protos.h (assign_stack_local): Change prototype.
+       (emit_i387_cw_initialization): Change prototype.
+       (ix86_mode_needed): New prototype.
+
+       * config/i386/i386.md (i387_cw attribute): Change order of elements.
+       (truncdfsf2, truncxfsf2, truncxfdf2, fix_trunc<mode>_fisttp_i387_1)
+       (*fix_trunc<mode>_i387_1, lrint<mode>2, *fist<mode>2_floor_1)
+       (*fist<mode>2_ceil_1): Change constant in call to
+       assign_386_stack_local to SLOT_TEMP.
+       (*fix_trunc<mode>_i387_1): Change constant in call to
+       assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_TRUNC.
+       Use new ix86_optimize_mode_switching[] array.
+       (frndintxf2_floor, *fist<mode>2_floor_1): Change constants in call to
+       assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_FLOOR.
+       Use new ix86_optimize_mode_switching[] array.
+       (frndintxf2_ceil, *fist<mode>2_ceil_1):  Change constants in call to
+       assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_CEIL.
+       Use new ix86_optimize_mode_switching[] array.
+       (frndintxf2_trunc): Change constants in call to
+       assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_TRUNC.
+       Use new ix86_optimize_mode_switching[] array.
+       (frndintxf2_mask_pm): Change constants in call to
+       assign_386_stack_local to SLOT_CW_STORED and SLOT_CW_MASK_PM.
+       Use new ix86_optimize_mode_switching[] array.
+
+       (define_peephole2): Change constant from 17 to FLAGS_REG;
+
 2005-06-07  Richard Henderson  <rth@redhat.com>
 
        PR rtl-opt/21528
index d8f15da9e4cdca18caad4fcd2105d1e6e40ee33d..df107d36190ae663d0c08ab42b1414166542b373 100644 (file)
@@ -163,7 +163,7 @@ extern void ix86_split_lshrdi (rtx *, rtx);
 extern rtx ix86_find_base_term (rtx);
 extern int ix86_check_movabs (rtx, int);
 
-extern rtx assign_386_stack_local (enum machine_mode, int);
+extern rtx assign_386_stack_local (enum machine_mode, enum ix86_stack_slot);
 extern int ix86_attr_length_immediate_default (rtx, int);
 extern int ix86_attr_length_address_default (rtx);
 
@@ -191,7 +191,8 @@ 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 int ix86_memory_move_cost (enum machine_mode, enum reg_class, int);
-extern void emit_i387_cw_initialization (rtx, rtx, int);
+extern int ix86_mode_needed (int, rtx);
+extern void emit_i387_cw_initialization (int);
 extern bool ix86_fp_jump_nontrivial_p (enum rtx_code);
 extern void x86_order_regs_for_local_alloc (void);
 extern void x86_function_profiler (FILE *, int);
index 70a35316dcaf7ec699359842c52dcdc35d3c20c7..f24a5cc7995ad5e7589714d74d6d379301e018b0 100644 (file)
@@ -732,7 +732,6 @@ rtx ix86_compare_op0 = NULL_RTX;
 rtx ix86_compare_op1 = NULL_RTX;
 rtx ix86_compare_emitted = NULL_RTX;
 
-#define MAX_386_STACK_LOCALS 3
 /* Size of the register save area.  */
 #define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
 
@@ -7321,41 +7320,103 @@ output_387_binary_op (rtx insn, rtx *operands)
   return buf;
 }
 
+/* Return needed mode for entity in optimize_mode_switching pass.  */
+
+int
+ix86_mode_needed (int entity, rtx insn)
+{
+  enum attr_i387_cw mode;
+
+  /* The mode UNINITIALIZED is used to store control word after a
+     function call or ASM pattern.  The mode ANY specify that function
+     has no requirements on the control word and make no changes in the
+     bits we are interested in.  */
+
+  if (CALL_P (insn)
+      || (NONJUMP_INSN_P (insn)
+         && (asm_noperands (PATTERN (insn)) >= 0
+             || GET_CODE (PATTERN (insn)) == ASM_INPUT)))
+    return I387_CW_UNINITIALIZED;
+
+  if (recog_memoized (insn) < 0)
+    return I387_CW_ANY;
+
+  mode = get_attr_i387_cw (insn);
+
+  switch (entity)
+    {
+    case I387_TRUNC:
+      if (mode == I387_CW_TRUNC)
+       return mode;
+      break;
+
+    case I387_FLOOR:
+      if (mode == I387_CW_FLOOR)
+       return mode;
+      break;
+
+    case I387_CEIL:
+      if (mode == I387_CW_CEIL)
+       return mode;
+      break;
+
+    case I387_MASK_PM:
+      if (mode == I387_CW_MASK_PM)
+       return mode;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return I387_CW_ANY;
+}
+
 /* Output code to initialize control word copies used by trunc?f?i and
    rounding patterns.  CURRENT_MODE is set to current control word,
    while NEW_MODE is set to new control word.  */
 
 void
-emit_i387_cw_initialization (rtx current_mode, rtx new_mode, int mode)
+emit_i387_cw_initialization (int mode)
 {
+  rtx stored_mode = assign_386_stack_local (HImode, SLOT_CW_STORED);
+  rtx new_mode;
+
+  int slot;
+
   rtx reg = gen_reg_rtx (HImode);
 
-  emit_insn (gen_x86_fnstcw_1 (current_mode));
-  emit_move_insn (reg, current_mode);
+  emit_insn (gen_x86_fnstcw_1 (stored_mode));
+  emit_move_insn (reg, stored_mode);
 
-  if (!TARGET_PARTIAL_REG_STALL && !optimize_size
-      && !TARGET_64BIT)
+  if (TARGET_64BIT || TARGET_PARTIAL_REG_STALL || optimize_size)
     {
       switch (mode)
        {
+       case I387_CW_TRUNC:
+         /* round toward zero (truncate) */
+         emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0c00)));
+         slot = SLOT_CW_TRUNC;
+         break;
+
        case I387_CW_FLOOR:
          /* round down toward -oo */
-         emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0x4)));
+         emit_insn (gen_andhi3 (reg, reg, GEN_INT (~0x0c00)));
+         emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0400)));
+         slot = SLOT_CW_FLOOR;
          break;
 
        case I387_CW_CEIL:
          /* round up toward +oo */
-         emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0x8)));
+         emit_insn (gen_andhi3 (reg, reg, GEN_INT (~0x0c00)));
+         emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0800)));
+         slot = SLOT_CW_CEIL;
          break;
 
-       case I387_CW_TRUNC:
-         /* round toward zero (truncate) */
-         emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0xc)));
-         break;
        case I387_CW_MASK_PM:
          /* mask precision exception for nearbyint() */
          emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0020)));
+         slot = SLOT_CW_MASK_PM;
          break;
 
        default:
@@ -7366,26 +7427,28 @@ emit_i387_cw_initialization (rtx current_mode, rtx new_mode, int mode)
     {
       switch (mode)
        {
+       case I387_CW_TRUNC:
+         /* round toward zero (truncate) */
+         emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0xc)));
+         slot = SLOT_CW_TRUNC;
+         break;
+
        case I387_CW_FLOOR:
          /* round down toward -oo */
-         emit_insn (gen_andhi3 (reg, reg, GEN_INT (~0x0c00)));
-         emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0400)));
+         emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0x4)));
+         slot = SLOT_CW_FLOOR;
          break;
 
        case I387_CW_CEIL:
          /* round up toward +oo */
-         emit_insn (gen_andhi3 (reg, reg, GEN_INT (~0x0c00)));
-         emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0800)));
-         break;
-
-       case I387_CW_TRUNC:
-         /* round toward zero (truncate) */
-         emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0c00)));
+         emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0x8)));
+         slot = SLOT_CW_CEIL;
          break;
-
        case I387_CW_MASK_PM:
          /* mask precision exception for nearbyint() */
          emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0020)));
+         slot = SLOT_CW_MASK_PM;
          break;
 
        default:
@@ -7393,6 +7456,9 @@ emit_i387_cw_initialization (rtx current_mode, rtx new_mode, int mode)
        }
     }
 
+  gcc_assert (slot < MAX_386_STACK_LOCALS);
+
+  new_mode = assign_386_stack_local (HImode, slot);
   emit_move_insn (new_mode, reg);
 }
 
@@ -12086,11 +12152,11 @@ ix86_init_machine_status (void)
    which slot to use.  */
 
 rtx
-assign_386_stack_local (enum machine_mode mode, int n)
+assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
 {
   struct stack_local_entry *s;
 
-  gcc_assert (n >= 0 && n < MAX_386_STACK_LOCALS);
+  gcc_assert (n < MAX_386_STACK_LOCALS);
 
   for (s = ix86_stack_locals; s; s = s->next)
     if (s->mode == mode && s->n == n)
@@ -14720,13 +14786,13 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
 
     case IX86_BUILTIN_LDMXCSR:
       op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
-      target = assign_386_stack_local (SImode, 0);
+      target = assign_386_stack_local (SImode, SLOT_TEMP);
       emit_move_insn (target, op0);
       emit_insn (gen_sse_ldmxcsr (target));
       return 0;
 
     case IX86_BUILTIN_STMXCSR:
-      target = assign_386_stack_local (SImode, 0);
+      target = assign_386_stack_local (SImode, SLOT_TEMP);
       emit_insn (gen_sse_stmxcsr (target));
       return copy_to_mode_reg (SImode, target);
 
index 49fc6079d2abcbebf1e598e8879f8c93c029412e..73ad10857335a79da2bdeffe388fac8f7b83537f 100644 (file)
@@ -2196,11 +2196,31 @@ extern rtx ix86_compare_emitted;
    Post-reload pass may be later used to eliminate the redundant fildcw if
    needed.  */
 
+enum ix86_entity
+{
+  I387_TRUNC = 0,
+  I387_FLOOR,
+  I387_CEIL,
+  I387_MASK_PM,
+  MAX_386_ENTITIES
+};
+
+enum ix86_stack_slot 
+{
+  SLOT_TEMP = 0,
+  SLOT_CW_STORED,
+  SLOT_CW_TRUNC,
+  SLOT_CW_FLOOR,
+  SLOT_CW_CEIL,
+  SLOT_CW_MASK_PM,
+  MAX_386_STACK_LOCALS
+};
 
 /* Define this macro if the port needs extra instructions inserted
    for mode switching in an optimizing compilation.  */
 
-#define OPTIMIZE_MODE_SWITCHING(ENTITY) ix86_optimize_mode_switching
+#define OPTIMIZE_MODE_SWITCHING(ENTITY) \
+   ix86_optimize_mode_switching[(ENTITY)]
 
 /* If you define `OPTIMIZE_MODE_SWITCHING', you have to define this as
    initializer for an array of integers.  Each initializer element N
@@ -2210,27 +2230,16 @@ extern rtx ix86_compare_emitted;
    starting counting at zero - determines the integer that is used to
    refer to the mode-switched entity in question.  */
 
-#define NUM_MODES_FOR_MODE_SWITCHING { I387_CW_ANY }
+#define NUM_MODES_FOR_MODE_SWITCHING \
+   { I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY }
 
 /* ENTITY is an integer specifying a mode-switched entity.  If
    `OPTIMIZE_MODE_SWITCHING' is defined, you must define this macro to
    return an integer value not larger than the corresponding element
    in `NUM_MODES_FOR_MODE_SWITCHING', to denote the mode that ENTITY
-   must be switched into prior to the execution of INSN. 
-   
-   The mode UNINITIALIZED is used to force re-load of possibly previously
-   stored control word after function call.  The mode ANY specify that
-   function has no requirements on the control word and make no changes
-   in the bits we are interested in.  */
-
-#define MODE_NEEDED(ENTITY, I)                                         \
-  (GET_CODE (I) == CALL_INSN                                           \
-   || (GET_CODE (I) == INSN && (asm_noperands (PATTERN (I)) >= 0       \
-                               || GET_CODE (PATTERN (I)) == ASM_INPUT))\
-   ? I387_CW_UNINITIALIZED                                             \
-   : recog_memoized (I) < 0                                            \
-   ? I387_CW_ANY                                                       \
-   : get_attr_i387_cw (I))
+   must be switched into prior to the execution of INSN. */
+
+#define MODE_NEEDED(ENTITY, I) ix86_mode_needed ((ENTITY), (I))
 
 /* This macro specifies the order in which modes for ENTITY are
    processed.  0 is the highest priority.  */
@@ -2243,10 +2252,9 @@ extern rtx ix86_compare_emitted;
 
 #define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE)                    \
   ((MODE) != I387_CW_ANY && (MODE) != I387_CW_UNINITIALIZED            \
-   ? emit_i387_cw_initialization (assign_386_stack_local (HImode, 1),  \
-                                 assign_386_stack_local (HImode, 2),   \
-                                 MODE), 0                              \
+   ? emit_i387_cw_initialization (MODE), 0                             \
    : 0)
+
 \f
 /* Avoid renaming of stack registers, as doing so in combination with
    scheduling just increases amount of live registers at time and in
@@ -2268,7 +2276,7 @@ struct machine_function GTY(())
   const char *some_ld_name;
   int save_varrargs_registers;
   int accesses_prev_frame;
-  int optimize_mode_switching;
+  int optimize_mode_switching[MAX_386_ENTITIES];
   /* Set by ix86_compute_frame_layout and used by prologue/epilogue expander to
      determine the style used.  */
   int use_fast_prologue_epilogue;
index cae0bc37a5dd56a32681b7f5de5cb456ab6b776f..39ed2b83f86abd2aa6f7f73b85f7297630313431 100644 (file)
 
 ;; Defines rounding mode of an FP operation.
 
-(define_attr "i387_cw" "floor,ceil,trunc,mask_pm,uninitialized,any"
+(define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any"
   (const_string "any"))
 
 ;; Describe a user's asm statement.
     ;
   else
     {
-      rtx temp = assign_386_stack_local (SFmode, 0);
+      rtx temp = assign_386_stack_local (SFmode, SLOT_TEMP);
       emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
       DONE;
     }
       DONE;
     }
   else
-    operands[2] = assign_386_stack_local (SFmode, 0);
+    operands[2] = assign_386_stack_local (SFmode, SLOT_TEMP);
 })
 
 (define_insn "*truncxfsf2_mixed"
       DONE;
     }
   else
-    operands[2] = assign_386_stack_local (DFmode, 0);
+    operands[2] = assign_386_stack_local (DFmode, SLOT_TEMP);
 })
 
 (define_insn "*truncxfdf2_mixed"
     emit_insn (gen_fix_trunc<mode>_i387_fisttp (operands[0], operands[1]));
   else
     {
-      operands[2] = assign_386_stack_local (<MODE>mode, 0);
+      operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
       emit_insn (gen_fix_trunc<mode>_i387_fisttp_with_temp (operands[0],
                                                            operands[1],
                                                            operands[2]));
   "&& 1"
   [(const_int 0)]
 {
-  ix86_optimize_mode_switching = 1;
-  operands[2] = assign_386_stack_local (HImode, 1);
-  operands[3] = assign_386_stack_local (HImode, 2);
+  ix86_optimize_mode_switching[I387_TRUNC] = 1;
+
+  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
   if (memory_operand (operands[0], VOIDmode))
     emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
                                         operands[2], operands[3]));
   else
     {
-      operands[4] = assign_386_stack_local (<MODE>mode, 0);
+      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
       emit_insn (gen_fix_trunc<mode>_i387_with_temp (operands[0], operands[1],
                                                     operands[2], operands[3],
                                                     operands[4]));
    (set (strict_low_part (match_dup 5))
        (match_dup 2))]
 {
-  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17);
+  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
   operands[5] = gen_lowpart (QImode, operands[3]);
   ix86_expand_clear (operands[3]);
 })
    (set (strict_low_part (match_dup 5))
        (match_dup 2))]
 {
-  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17);
+  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
   operands[5] = gen_lowpart (QImode, operands[3]);
   ix86_expand_clear (operands[3]);
 })
     emit_insn (gen_fist<mode>2 (operands[0], operands[1]));
   else
     {
-      operands[2] = assign_386_stack_local (<MODE>mode, 0);
+      operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
       emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1],
                                            operands[2]));
     }
   "&& 1"
   [(const_int 0)]
 {
-  ix86_optimize_mode_switching = 1;
+  ix86_optimize_mode_switching[I387_FLOOR] = 1;
 
-  operands[2] = assign_386_stack_local (HImode, 1);
-  operands[3] = assign_386_stack_local (HImode, 2);
+  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
 
   emit_insn (gen_frndintxf2_floor_i387 (operands[0], operands[1],
                                        operands[2], operands[3]));
   "&& 1"
   [(const_int 0)]
 {
-  ix86_optimize_mode_switching = 1;
-  operands[2] = assign_386_stack_local (HImode, 1);
-  operands[3] = assign_386_stack_local (HImode, 2);
+  ix86_optimize_mode_switching[I387_FLOOR] = 1;
+
+  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
   if (memory_operand (operands[0], VOIDmode))
     emit_insn (gen_fist<mode>2_floor (operands[0], operands[1],
                                      operands[2], operands[3]));
   else
     {
-      operands[4] = assign_386_stack_local (<MODE>mode, 0);
+      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
       emit_insn (gen_fist<mode>2_floor_with_temp (operands[0], operands[1],
                                                  operands[2], operands[3],
                                                  operands[4]));
   "&& 1"
   [(const_int 0)]
 {
-  ix86_optimize_mode_switching = 1;
+  ix86_optimize_mode_switching[I387_CEIL] = 1;
 
-  operands[2] = assign_386_stack_local (HImode, 1);
-  operands[3] = assign_386_stack_local (HImode, 2);
+  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
 
   emit_insn (gen_frndintxf2_ceil_i387 (operands[0], operands[1],
                                       operands[2], operands[3]));
   "&& 1"
   [(const_int 0)]
 {
-  ix86_optimize_mode_switching = 1;
-  operands[2] = assign_386_stack_local (HImode, 1);
-  operands[3] = assign_386_stack_local (HImode, 2);
+  ix86_optimize_mode_switching[I387_CEIL] = 1;
+
+  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
   if (memory_operand (operands[0], VOIDmode))
     emit_insn (gen_fist<mode>2_ceil (operands[0], operands[1],
                                     operands[2], operands[3]));
   else
     {
-      operands[4] = assign_386_stack_local (<MODE>mode, 0);
+      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
       emit_insn (gen_fist<mode>2_ceil_with_temp (operands[0], operands[1],
                                                 operands[2], operands[3],
                                                 operands[4]));
   "&& 1"
   [(const_int 0)]
 {
-  ix86_optimize_mode_switching = 1;
+  ix86_optimize_mode_switching[I387_TRUNC] = 1;
 
-  operands[2] = assign_386_stack_local (HImode, 1);
-  operands[3] = assign_386_stack_local (HImode, 2);
+  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
 
   emit_insn (gen_frndintxf2_trunc_i387 (operands[0], operands[1],
                                        operands[2], operands[3]));
   "&& 1"
   [(const_int 0)]
 {
-  ix86_optimize_mode_switching = 1;
+  ix86_optimize_mode_switching[I387_MASK_PM] = 1;
 
-  operands[2] = assign_386_stack_local (HImode, 1);
-  operands[3] = assign_386_stack_local (HImode, 2);
+  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+  operands[3] = assign_386_stack_local (HImode, SLOT_CW_MASK_PM);
 
   emit_insn (gen_frndintxf2_mask_pm_i387 (operands[0], operands[1],
                                          operands[2], operands[3]));