Rewrite movsf/movdf/movdi patterns
authorMichael Meissner <meissner@gcc.gnu.org>
Thu, 8 Sep 1994 17:58:36 +0000 (17:58 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Thu, 8 Sep 1994 17:58:36 +0000 (17:58 +0000)
From-SVN: r8039

gcc/config/i386/i386.md

index f2fccf8..79d35d0 100644 (file)
   return AS2 (mov%B0,%1,%0);
 }")
 
-(define_insn ""
+(define_expand "movsf"
+  [(set (match_operand:SF 0 "general_operand" "")
+       (match_operand:SF 1 "general_operand" ""))]
+  ""
+  "
+{
+  /* Special case memory->memory moves */
+  if (TARGET_MOVE
+      && (reload_in_progress | reload_completed) == 0
+      && GET_CODE (operands[0]) == MEM
+      && GET_CODE (operands[1]) == MEM)
+    {
+      rtx (*genfunc) PROTO((rtx, rtx));
+      if (push_operand (operands[0], SFmode))
+       genfunc = (TARGET_386) ? gen_movsf_push386 : gen_movsf_push486_mem;
+      else
+       genfunc = gen_movsf_mem;
+
+      emit_insn ((*genfunc) (operands[0], operands[1]));
+      DONE;
+    }
+}")
+
+(define_insn "movsf_push386"
   [(set (match_operand:SF 0 "push_operand" "=<,<")
        (match_operand:SF 1 "general_operand" "gF,f"))]
-  ""
+  "TARGET_386 || !TARGET_MOVE"
   "*
 {
   if (STACK_REG_P (operands[1]))
   return AS1 (push%L1,%1);
 }")
 
-;; Allow MEM-MEM moves before reload.  The reload class for such a
-;; move will be ALL_REGS.  PREFERRED_RELOAD_CLASS will narrow this to
-;; GENERAL_REGS.  For the purposes of regclass, prefer FLOAT_REGS.
+(define_insn "movsf_push486"
+  [(set (match_operand:SF 0 "push_operand" "=<,<")
+       (match_operand:SF 1 "nonmemory_operand" "rF,f"))]
+  "!TARGET_386"
+  "*
+{
+  if (STACK_REG_P (operands[1]))
+    {
+      rtx xops[3];
+
+      if (! STACK_TOP_P (operands[1]))
+        abort ();
+
+      xops[0] = AT_SP (SFmode);
+      xops[1] = GEN_INT (4);
+      xops[2] = stack_pointer_rtx;
+
+      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
+
+      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
+        output_asm_insn (AS1 (fstp%S0,%0), xops);
+      else
+        output_asm_insn (AS1 (fst%S0,%0), xops);
+      RET;
+    }
+  return AS1 (push%L1,%1);
+}")
+
+(define_insn "movsf_push486_mem"
+  [(set (match_operand:SF 0 "push_operand" "=<")
+       (match_operand:SF 1 "memory_operand" "m"))
+   (clobber (match_scratch:SI 2 "=r"))]
+  "!TARGET_386"
+  "*
+{
+  output_asm_insn (AS2 (mov%L2,%1,%2), operands);
+  return AS1 (push%L2,%2);
+}")
+
+;; Special memory<->memory pattern that combine will recreate from the
+;; moves to pseudos.
+(define_insn "movsf_mem"
+  [(set (match_operand:SF 0 "memory_operand" "=m")
+       (match_operand:SF 1 "memory_operand" "m"))
+   (clobber (match_scratch:SI 2 "=r"))]
+  ""
+  "*
+{
+  output_asm_insn (AS2 (mov%L2,%1,%2), operands);
+  return AS2 (mov%L0,%2,%0);
+}")
 
-(define_insn "movsf"
+;; For the purposes of regclass, prefer FLOAT_REGS.
+(define_insn "movsf_normal"
   [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm")
        (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))]
-  ""
+  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
   "*
 {
   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
   return singlemove_string (operands);
 }")
 
-;;should change to handle the memory operands[1] without doing df push..
-(define_insn ""
+(define_insn "swapsf"
+  [(set (match_operand:SF 0 "register_operand" "f")
+       (match_operand:SF 1 "register_operand" "f"))
+   (set (match_dup 1)
+       (match_dup 0))]
+  ""
+  "*
+{
+  if (STACK_TOP_P (operands[0]))
+    return AS1 (fxch,%1);
+  else
+    return AS1 (fxch,%0);
+}")
+
+(define_expand "movdf"
+  [(set (match_operand:DF 0 "general_operand" "")
+       (match_operand:DF 1 "general_operand" ""))]
+  ""
+  "
+{
+  /* Special case memory->memory moves */
+  if (TARGET_MOVE
+      && (reload_in_progress | reload_completed) == 0
+      && GET_CODE (operands[0]) == MEM
+      && GET_CODE (operands[1]) == MEM)
+    {
+      rtx (*genfunc) PROTO((rtx, rtx));
+      if (push_operand (operands[0], DFmode))
+       genfunc = (TARGET_386) ? gen_movdf_push386 : gen_movdf_push486_mem;
+      else
+       genfunc = gen_movdf_mem;
+
+      emit_insn ((*genfunc) (operands[0], operands[1]));
+      DONE;
+    }
+}")
+
+(define_insn "movdf_push386"
   [(set (match_operand:DF 0 "push_operand" "=<,<")
        (match_operand:DF 1 "general_operand" "gF,f"))]
-  ""
+  "TARGET_386 || !TARGET_MOVE"
   "*
 {
   if (STACK_REG_P (operands[1]))
     return output_move_double (operands);
 }")
 
-(define_insn "swapdf"
-  [(set (match_operand:DF 0 "register_operand" "f")
-       (match_operand:DF 1 "register_operand" "f"))
-   (set (match_dup 1)
-       (match_dup 0))]
-  ""
+(define_insn "movdf_push486"
+  [(set (match_operand:DF 0 "push_operand" "=<,<")
+       (match_operand:DF 1 "nonmemory_operand" "rF,f"))]
+  "!TARGET_386"
   "*
 {
-  if (STACK_TOP_P (operands[0]))
-    return AS1 (fxch,%1);
+  if (STACK_REG_P (operands[1]))
+    {
+      rtx xops[3];
+
+      xops[0] = AT_SP (SFmode);
+      xops[1] = GEN_INT (8);
+      xops[2] = stack_pointer_rtx;
+
+      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
+
+      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
+        output_asm_insn (AS1 (fstp%Q0,%0), xops);
+      else
+        output_asm_insn (AS1 (fst%Q0,%0), xops);
+
+      RET;
+    }
   else
-    return AS1 (fxch,%0);
+    return output_move_double (operands);
 }")
 
-;; Allow MEM-MEM moves before reload.  The reload class for such a
-;; move will be ALL_REGS.  PREFERRED_RELOAD_CLASS will narrow this to
-;; GENERAL_REGS.  For the purposes of regclass, prefer FLOAT_REGS.
+(define_insn "movdf_push486_mem"
+  [(set (match_operand:DF 0 "push_operand" "=<,<")
+       (match_operand:DF 1 "general_operand" "o,o"))
+   (clobber (match_scratch:SI 2 "=&r,&r"))
+   (clobber (match_scratch:SI 3 "=&r,X"))]
+  "!TARGET_386"
+  "*
+{
+  rtx low[1], high[1], xop[4];
 
-(define_insn "movdf"
+  split_di (&operands[1], 1, low, high);
+  xop[0] = operands[2];
+  xop[1] = operands[3];
+  xop[2] = high[0];
+  xop[3] = low[0];
+
+  if (GET_CODE (operands[3]) == REG)
+    {                          /* 2 scratch registers available */
+      output_asm_insn (AS2 (mov%L0,%2,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%3,%1), xop);
+      output_asm_insn (AS1 (push%L0,%0), xop);
+      output_asm_insn (AS1 (push%L0,%1), xop);
+    }
+  else
+    {                          /* 1 scratch register */
+      output_asm_insn (AS2 (mov%L0,%2,%0), xop);
+      output_asm_insn (AS1 (push%L0,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%3,%0), xop);
+      output_asm_insn (AS1 (push%L0,%0), xop);
+    }
+
+  RET;
+}")
+
+(define_insn "movdf_mem"
+  [(set (match_operand:DF 0 "memory_operand" "=o,o")
+       (match_operand:DF 1 "memory_operand" "o,o"))
+   (clobber (match_scratch:SI 2 "=&r,&r"))
+   (clobber (match_scratch:SI 3 "=&r,X"))]
+  ""
+  "*
+{
+  rtx low[2], high[2], xop[6];
+
+  split_di (operands, 2, low, high);
+  xop[0] = operands[2];
+  xop[1] = operands[3];
+  xop[2] = high[0];
+  xop[3] = high[1];
+  xop[4] = low[0];
+  xop[5] = low[1];
+  if (GET_CODE (operands[3]) == REG)
+    {                          /* 2 scratch registers available */
+      output_asm_insn (AS2 (mov%L0,%5,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%3,%1), xop);
+      output_asm_insn (AS2 (mov%L0,%0,%4), xop);
+      output_asm_insn (AS2 (mov%L0,%1,%2), xop);
+    }
+  else
+    {                          /* 1 scratch register */
+      output_asm_insn (AS2 (mov%L0,%5,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%0,%4), xop);
+      output_asm_insn (AS2 (mov%L0,%3,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%0,%2), xop);
+    }
+
+  RET;
+}")
+
+;; For the purposes of regclass, prefer FLOAT_REGS.
+(define_insn "movdf_normal"
   [(set (match_operand:DF 0 "general_operand" "=*rfm,*rf,f,!*rm")
        (match_operand:DF 1 "general_operand" "*rf,*rfm,fG,fF"))]
-  ""
+  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
   "*
 {
   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
   return output_move_double (operands);
 }")
 
-(define_insn ""
+(define_insn "swapdf"
+  [(set (match_operand:DF 0 "register_operand" "f")
+       (match_operand:DF 1 "register_operand" "f"))
+   (set (match_dup 1)
+       (match_dup 0))]
+  ""
+  "*
+{
+  if (STACK_TOP_P (operands[0]))
+    return AS1 (fxch,%1);
+  else
+    return AS1 (fxch,%0);
+}")
+
+(define_expand "movxf"
+  [(set (match_operand:XF 0 "general_operand" "")
+       (match_operand:XF 1 "general_operand" ""))]
+  ""
+  "
+{
+  /* Special case memory->memory moves */
+  if (TARGET_MOVE
+      && (reload_in_progress | reload_completed) == 0
+      && GET_CODE (operands[0]) == MEM
+      && GET_CODE (operands[1]) == MEM)
+    {
+      rtx (*genfunc) PROTO((rtx, rtx));
+      if (push_operand (operands[0], XFmode))
+       genfunc = (TARGET_386) ? gen_movxf_push386 : gen_movxf_push486_mem;
+      else
+       genfunc = gen_movxf_mem;
+
+      emit_insn ((*genfunc) (operands[0], operands[1]));
+      DONE;
+    }
+}")
+
+(define_insn "movxf_push386"
   [(set (match_operand:XF 0 "push_operand" "=<,<")
        (match_operand:XF 1 "general_operand" "gF,f"))]
-  ""
+  "TARGET_386 || !TARGET_MOVE"
   "*
 {
   if (STACK_REG_P (operands[1]))
     return output_move_double (operands);
  }")
 
-(define_insn "swapxf"
-  [(set (match_operand:XF 0 "register_operand" "f")
-       (match_operand:XF 1 "register_operand" "f"))
-   (set (match_dup 1)
-       (match_dup 0))]
-  ""
+(define_insn "movxf_push486"
+  [(set (match_operand:XF 0 "push_operand" "=<,<")
+       (match_operand:XF 1 "nonmemory_operand" "rF,f"))]
+  "!TARGET_386"
   "*
 {
-  if (STACK_TOP_P (operands[0]))
-    return AS1 (fxch,%1);
+  if (STACK_REG_P (operands[1]))
+    {
+      rtx xops[3];
+
+      xops[0] = AT_SP (SFmode);
+      xops[1] = GEN_INT (12);
+      xops[2] = stack_pointer_rtx;
+
+      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
+      output_asm_insn (AS1 (fstp%T0,%0), xops);
+      if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
+       output_asm_insn (AS1 (fld%T0,%0), xops);
+
+      RET;
+    }
   else
-    return AS1 (fxch,%0);
+    return output_move_double (operands);
+ }")
+
+(define_insn "movxf_push486_mem"
+  [(set (match_operand:XF 0 "push_operand" "=<,<")
+       (match_operand:XF 1 "memory_operand" "o,o"))
+   (clobber (match_scratch:SI 2 "=&r,&r"))
+   (clobber (match_scratch:SI 3 "=&r,X"))]
+  "!TARGET_386"
+  "*
+{
+  rtx xop[5];
+
+  xop[0] = operands[2];
+  xop[1] = operands[3];
+  xop[2] = adj_offsettable_operand (operands[1], 8);
+  xop[3] = adj_offsettable_operand (operands[1], 4);
+  xop[4] = operands[1];
+
+  if (GET_CODE (operands[3]) == REG)
+    {                          /* 2 scratch registers available */
+      output_asm_insn (AS2 (mov%L0,%2,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%3,%1), xop);
+      output_asm_insn (AS1 (push%L0,%0), xop);
+      output_asm_insn (AS1 (push%L0,%1), xop);
+      output_asm_insn (AS2 (mov%L0,%4,%0), xop);
+      output_asm_insn (AS1 (push%L0,%0), xop);
+    }
+  else
+    {                          /* 1 scratch register */
+      output_asm_insn (AS2 (mov%L0,%2,%0), xop);
+      output_asm_insn (AS1 (push%L0,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%3,%0), xop);
+      output_asm_insn (AS1 (push%L0,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%4,%0), xop);
+      output_asm_insn (AS1 (push%L0,%0), xop);
+    }
+
+  RET;
 }")
 
-(define_insn "movxf"
+(define_insn "movxf_mem"
+  [(set (match_operand:XF 0 "memory_operand" "=o,o")
+       (match_operand:XF 1 "memory_operand" "o,o"))
+   (clobber (match_scratch:SI 2 "=&r,&r"))
+   (clobber (match_scratch:SI 3 "=&r,X"))]
+  "!TARGET_386"
+  "*
+{
+  rtx xop[8];
+
+  xop[0] = operands[2];
+  xop[1] = operands[3];
+  xop[2] = adj_offsettable_operand (operands[1], 8);
+  xop[3] = adj_offsettable_operand (operands[1], 4);
+  xop[4] = operands[1];
+  xop[5] = adj_offsettable_operand (operands[0], 8);
+  xop[6] = adj_offsettable_operand (operands[0], 4);
+  xop[7] = operands[0];
+
+  if (GET_CODE (operands[3]) == REG)
+    {                          /* 2 scratch registers available */
+      output_asm_insn (AS2 (mov%L0,%2,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%3,%1), xop);
+      output_asm_insn (AS2 (mov%L5,%5,%0), xop);
+      output_asm_insn (AS2 (mov%L6,%6,%1), xop);
+      output_asm_insn (AS2 (mov%L0,%4,%0), xop);
+      output_asm_insn (AS2 (mov%L7,%7,%0), xop);
+    }
+  else
+    {                          /* 1 scratch register */
+      output_asm_insn (AS2 (mov%L0,%2,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%5,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%3,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%6,%0), xop);
+      output_asm_insn (AS2 (mov%L0,%4,%0), xop);
+      output_asm_insn (AS2 (mov%L7,%7,%0), xop);
+    }
+
+  RET;
+}")
+
+(define_insn "movxf_normal"
   [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm")
        (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
-;;  [(set (match_operand:XF 0 "general_operand" "=*rf,*rfm,f,!*rm")
-;;     (match_operand:XF 1 "general_operand" "*rfm,*rf,fG,fF"))]
-  ""
+  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
   "*
 {
   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
   return output_move_double (operands);
 }")
 
-(define_insn ""
+(define_insn "swapxf"
+  [(set (match_operand:XF 0 "register_operand" "f")
+       (match_operand:XF 1 "register_operand" "f"))
+   (set (match_dup 1)
+       (match_dup 0))]
+  ""
+  "*
+{
+  if (STACK_TOP_P (operands[0]))
+    return AS1 (fxch,%1);
+  else
+    return AS1 (fxch,%0);
+}")
+
+(define_expand "movdi"
+  [(set (match_operand:DI 0 "general_operand" "")
+       (match_operand:DI 1 "general_operand" ""))]
+  ""
+  "
+{
+  /* Special case memory->memory moves */
+  if (TARGET_MOVE
+      && (reload_in_progress | reload_completed) == 0
+      && GET_CODE (operands[0]) == MEM
+      && GET_CODE (operands[1]) == MEM)
+    {
+      rtx (*genfunc) PROTO((rtx, rtx));
+      if (push_operand (operands[0], DImode))
+       genfunc = (TARGET_386) ? gen_movdi_push386 : gen_movdi_push486_mem;
+      else
+       genfunc = gen_movdi_mem;
+
+      emit_insn ((*genfunc) (operands[0], operands[1]));
+      DONE;
+    }
+}")
+
+(define_insn "movdi_push386"
   [(set (match_operand:DI 0 "push_operand" "=<")
-       (match_operand:DI 1 "general_operand" "roiF"))
-   (clobber (match_scratch:SI 2 "X"))
-   (clobber (match_scratch:SI 3 "X"))]
-  "TARGET_386"
+       (match_operand:DI 1 "general_operand" "roiF"))]
+  "TARGET_386 || !TARGET_MOVE"
   "* return output_move_double (operands);")
 
-(define_insn ""
-  [(set (match_operand:DI 0 "push_operand" "=<,<,<")
-       (match_operand:DI 1 "general_operand" "riF,o,o"))
-   (clobber (match_scratch:SI 2 "X,=&r,=&r"))
-   (clobber (match_scratch:SI 3 "X,=&r,X"))]
+(define_insn "movdi_push486"
+  [(set (match_operand:DI 0 "push_operand" "=<")
+       (match_operand:DI 1 "nonmemory_operand" "riF"))]
+  "!TARGET_386"
+  "* return output_move_double (operands);")
+
+(define_insn "movdi_push486_mem"
+  [(set (match_operand:DI 0 "push_operand" "=<,<")
+       (match_operand:DI 1 "memory_operand" "o,o"))
+   (clobber (match_scratch:SI 2 "=&r,=&r"))
+   (clobber (match_scratch:SI 3 "=&r,X"))]
   "!TARGET_386"
   "*
 {
   xop[2] = high[0];
   xop[3] = low[0];
 
-  if (GET_CODE (operands[1]) != MEM)
-    {
-      output_asm_insn (AS1 (push%L0,%2), xop);
-      output_asm_insn (AS1 (push%L0,%3), xop);
-    }
-  else if (GET_CODE (operands[3]) == REG)
+  if (GET_CODE (operands[3]) == REG)
     {                          /* 2 scratch registers available */
       output_asm_insn (AS2 (mov%L0,%2,%0), xop);
       output_asm_insn (AS2 (mov%L0,%3,%1), xop);
   RET;
 }")
 
-(define_insn "movdi"
-  [(set (match_operand:DI 0 "general_operand" "=r,rm,o,o")
-       (match_operand:DI 1 "general_operand" "m,riF,o,o"))
-   (clobber (match_scratch:SI 2 "X,X,=&r,=&r"))
-   (clobber (match_scratch:SI 3 "X,X,=&r,X"))]
+(define_insn "movdi_mem"
+  [(set (match_operand:DI 0 "memory_operand" "=o,o")
+       (match_operand:DI 1 "memory_operand" "o,o"))
+   (clobber (match_scratch:SI 2 "=&r,&r"))
+   (clobber (match_scratch:SI 3 "=&r,X"))]
   ""
   "*
 {
   rtx low[2], high[2], xop[6];
 
-  if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
-    return output_move_double (operands);
-
   split_di (operands, 2, low, high);
   xop[0] = operands[2];
   xop[1] = operands[3];
 
   RET;
 }")
-  
+
+(define_insn "movdi_normal"
+  [(set (match_operand:DI 0 "general_operand" "=r,rm")
+       (match_operand:DI 1 "general_operand" "m,riF"))]
+  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
+  "* return output_move_double (operands);")
+
 \f
 ;;- conversion instructions
 ;;- NONE
 
 (define_expand "fixuns_truncdfsi2"
   [(set (match_dup 4)
-       (match_operand:DF 1 "register_operand" ""))
+       (match_operand:DF 1 "general_operand" ""))
    (parallel [(set (match_dup 2)
                   (fix:DI (fix:DF (match_dup 4))))
              (clobber (match_dup 4))
 
 (define_expand "fixuns_truncsfsi2"
   [(set (match_dup 4)
-       (match_operand:SF 1 "register_operand" ""))
+       (match_operand:SF 1 "general_operand" ""))
    (parallel [(set (match_dup 2)
                   (fix:DI (fix:SF (match_dup 4))))
              (clobber (match_dup 4))
 ;; Signed conversion to DImode.
 
 (define_expand "fix_truncxfdi2"
-  [(set (match_dup 2)
-       (match_operand:XF 1 "register_operand" ""))
-   (parallel [(set (match_operand:DI 0 "general_operand" "")
-                  (fix:DI (fix:XF (match_dup 2))))
-             (clobber (match_dup 2))
-             (clobber (match_dup 3))
-             (clobber (match_dup 4))
-             (clobber (match_scratch:SI 5 ""))])]
+  [(set (match_operand:DI 0 "general_operand" "")
+       (fix:DI (match_operand:XF 1 "general_operand" "")))]
   "TARGET_80387"
   "
 {
-  operands[1] = copy_to_mode_reg (XFmode, operands[1]);
-  operands[2] = gen_reg_rtx (XFmode);
-  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
-  operands[4] = (rtx) assign_386_stack_local (SImode, 1);
+  if (operands[0])             /* prevent unused code message */
+    {
+      rtx reg = gen_reg_rtx (XFmode);
+      emit_insn (gen_movxf (reg, operands[1]));
+      emit_insn (gen_fix_truncxfdi2_internal (operands[0],
+                                             reg,
+                                             assign_386_stack_local (SImode, 0),
+                                             assign_386_stack_local (SImode, 1)));
+      DONE;
+    }
 }")
 
 (define_expand "fix_truncdfdi2"
-  [(set (match_dup 2)
-       (match_operand:DF 1 "register_operand" ""))
-   (parallel [(set (match_operand:DI 0 "general_operand" "")
-                  (fix:DI (fix:DF (match_dup 2))))
-             (clobber (match_dup 2))
-             (clobber (match_dup 3))
-             (clobber (match_dup 4))
-             (clobber (match_scratch:SI 5 ""))])]
+  [(set (match_operand:DI 0 "general_operand" "")
+       (fix:DI (match_operand:DF 1 "general_operand" "")))]
   "TARGET_80387"
   "
 {
-  operands[1] = copy_to_mode_reg (DFmode, operands[1]);
-  operands[2] = gen_reg_rtx (DFmode);
-  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
-  operands[4] = (rtx) assign_386_stack_local (SImode, 1);
+  if (operands[0])             /* prevent unused code message */
+    {
+      rtx reg = gen_reg_rtx (DFmode);
+      emit_insn (gen_movdf (reg, operands[1]));
+      emit_insn (gen_fix_truncdfdi2_internal (operands[0],
+                                             reg,
+                                             assign_386_stack_local (SImode, 0),
+                                             assign_386_stack_local (SImode, 1)));
+      DONE;
+    }
 }")
 
+
 (define_expand "fix_truncsfdi2"
-  [(set (match_dup 2)
-       (match_operand:SF 1 "register_operand" ""))
-   (parallel [(set (match_operand:DI 0 "general_operand" "")
-                  (fix:DI (fix:SF (match_dup 2))))
-             (clobber (match_dup 2))
-             (clobber (match_dup 3))
-             (clobber (match_dup 4))
-             (clobber (match_scratch:SI 5 ""))])]
+  [(set (match_operand:DI 0 "general_operand" "")
+       (fix:DI (match_operand:SF 1 "general_operand" "")))]
   "TARGET_80387"
   "
 {
-  operands[1] = copy_to_mode_reg (SFmode, operands[1]);
-  operands[2] = gen_reg_rtx (SFmode);
-  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
-  operands[4] = (rtx) assign_386_stack_local (SImode, 1);
+  if (operands[0])             /* prevent unused code message */
+    {
+      rtx reg = gen_reg_rtx (SFmode);
+      emit_insn (gen_movsf (reg, operands[1]));
+      emit_insn (gen_fix_truncsfdi2_internal (operands[0],
+                                             reg,
+                                             assign_386_stack_local (SImode, 0),
+                                             assign_386_stack_local (SImode, 1)));
+      DONE;
+    }
 }")
 
 ;; These match a signed conversion of either DFmode or SFmode to DImode.
 
-(define_insn ""
+(define_insn "fix_truncxfdi2_internal"
   [(set (match_operand:DI 0 "general_operand" "=rm")
        (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
    (clobber (match_dup 1))
   "TARGET_80387"
   "* return output_fix_trunc (insn, operands);")
 
-(define_insn ""
+(define_insn "fix_truncdfdi2_internal"
   [(set (match_operand:DI 0 "general_operand" "=rm")
        (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
    (clobber (match_dup 1))
   "TARGET_80387"
   "* return output_fix_trunc (insn, operands);")
 
-(define_insn ""
+(define_insn "fix_truncsfdi2_internal"
   [(set (match_operand:DI 0 "general_operand" "=rm")
        (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
    (clobber (match_dup 1))