i386.md (FIST_ROUNDING): New int iterator.
authorUros Bizjak <ubizjak@gmail.com>
Tue, 19 Jun 2012 18:24:26 +0000 (20:24 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Tue, 19 Jun 2012 18:24:26 +0000 (20:24 +0200)
* config/i386/i386.md (FIST_ROUNDING): New int iterator.
(rounding): Handle UNSPEC_FIST_{FLOOR,CEIL}.
(ROUNDING): Ditto.
(*fist<mode>2_<rounding>_1): Macroize insn from
*fist<mode>2_{floor,ceil}_1 using FIST_ROUNDING int iterator.
(fistdi2_<rounding>): Macroize insn from
fistdi2_{floor,ceil} using FIST_ROUNDING int iterator.
(fistdi2_<rounding>_with_temp and splitters): Macroize insn and
corresponding splitters from fistdi2_{floor,ceil} and corresponding
splitters using FIST_ROUNDING int iterator.
(fist<mode>2_<rounding>): Macroize insn from
fist<mode>2_{floor,ceil} using FIST_ROUNDING int iterator.
(fist<mode>2_<rounding>_with_temp and splitters): Macroize insn and
corresponding splitters from fist<mode>2_{floor,ceil} and corresponding
splitters using FIST_ROUNDING int iterator.
(l<rounding>xf<mode>2): Macroize expander from l{floor,ceil}xf<mode>2
using FIST_ROUNDING int iterator.

From-SVN: r188789

gcc/ChangeLog
gcc/config/i386/i386.md

index 8b32819..3e1d8bb 100644 (file)
@@ -1,3 +1,23 @@
+2012-06-19  Uros Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/i386.md (FIST_ROUNDING): New int iterator.
+       (rounding): Handle UNSPEC_FIST_{FLOOR,CEIL}.
+       (ROUNDING): Ditto.
+       (*fist<mode>2_<rounding>_1): Macroize insn from
+       *fist<mode>2_{floor,ceil}_1 using FIST_ROUNDING int iterator.
+       (fistdi2_<rounding>): Macroize insn from
+       fistdi2_{floor,ceil} using FIST_ROUNDING int iterator.
+       (fistdi2_<rounding>_with_temp and splitters): Macroize insn and
+       corresponding splitters from fistdi2_{floor,ceil} and corresponding
+       splitters using FIST_ROUNDING int iterator.
+       (fist<mode>2_<rounding>): Macroize insn from
+       fist<mode>2_{floor,ceil} using FIST_ROUNDING int iterator.
+       (fist<mode>2_<rounding>_with_temp and splitters): Macroize insn and
+       corresponding splitters from fist<mode>2_{floor,ceil} and corresponding
+       splitters using FIST_ROUNDING int iterator.
+       (l<rounding>xf<mode>2): Macroize expander from l{floor,ceil}xf<mode>2
+       using FIST_ROUNDING int iterator.
+
 2012-06-19  Richard Henderson  <rth@redhat.com>
 
        * config/i386/i386-protos.h (ix86_expand_sse2_mulv4si3): Declare.
index 153eb0b..1dce880 100644 (file)
         UNSPEC_FRNDINT_CEIL
         UNSPEC_FRNDINT_TRUNC])
 
+(define_int_iterator FIST_ROUNDING
+       [UNSPEC_FIST_FLOOR
+        UNSPEC_FIST_CEIL])
+
 (define_int_attr rounding
        [(UNSPEC_FRNDINT_FLOOR "floor")
         (UNSPEC_FRNDINT_CEIL "ceil")
-        (UNSPEC_FRNDINT_TRUNC "trunc")])
+        (UNSPEC_FRNDINT_TRUNC "trunc")
+        (UNSPEC_FIST_FLOOR "floor")
+        (UNSPEC_FIST_CEIL "ceil")])
 
 (define_int_attr ROUNDING
        [(UNSPEC_FRNDINT_FLOOR "FLOOR")
         (UNSPEC_FRNDINT_CEIL "CEIL")
-        (UNSPEC_FRNDINT_TRUNC "TRUNC")])
+        (UNSPEC_FRNDINT_TRUNC "TRUNC")
+        (UNSPEC_FIST_FLOOR "FLOOR")
+        (UNSPEC_FIST_CEIL "CEIL")])
 
 ;; Rounding mode control word calculation could clobber FLAGS_REG.
 (define_insn_and_split "frndintxf2_<rounding>"
   DONE;
 })
 
-(define_insn_and_split "*fist<mode>2_floor_1"
-  [(set (match_operand:SWI248x 0 "nonimmediate_operand")
-       (unspec:SWI248x [(match_operand:XF 1 "register_operand")]
-                       UNSPEC_FIST_FLOOR))
-   (clobber (reg:CC FLAGS_REG))]
+(define_expand "ceilxf2"
+  [(use (match_operand:XF 0 "register_operand"))
+   (use (match_operand:XF 1 "register_operand"))]
   "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations
-   && can_create_pseudo_p ()"
-  "#"
-  "&& 1"
-  [(const_int 0)]
+   && flag_unsafe_math_optimizations"
 {
-  ix86_optimize_mode_switching[I387_FLOOR] = 1;
+  if (optimize_insn_for_size_p ())
+    FAIL;
+  emit_insn (gen_frndintxf2_ceil (operands[0], operands[1]));
+  DONE;
+})
 
-  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
+(define_expand "ceil<mode>2"
+  [(use (match_operand:MODEF 0 "register_operand"))
+   (use (match_operand:MODEF 1 "register_operand"))]
+  "(TARGET_USE_FANCY_MATH_387
+    && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+       || TARGET_MIX_SSE_I387)
+    && flag_unsafe_math_optimizations)
+   || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
+       && !flag_trapping_math)"
+{
+  if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
+      && !flag_trapping_math)
     {
-      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]));
+      if (TARGET_ROUND)
+       emit_insn (gen_sse4_1_round<mode>2
+                  (operands[0], operands[1], GEN_INT (ROUND_CEIL)));
+      else if (optimize_insn_for_size_p ())
+       FAIL;
+      else if (TARGET_64BIT || (<MODE>mode != DFmode))
+       ix86_expand_floorceil (operands[0], operands[1], false);
+      else
+       ix86_expand_floorceildf_32 (operands[0], operands[1], false);
     }
-  DONE;
-}
-  [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "floor")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "fistdi2_floor"
-  [(set (match_operand:DI 0 "memory_operand" "=m")
-       (unspec:DI [(match_operand:XF 1 "register_operand" "f")]
-                  UNSPEC_FIST_FLOOR))
-   (use (match_operand:HI 2 "memory_operand" "m"))
-   (use (match_operand:HI 3 "memory_operand" "m"))
-   (clobber (match_scratch:XF 4 "=&1f"))]
-  "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations"
-  "* return output_fix_trunc (insn, operands, false);"
-  [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "floor")
-   (set_attr "mode" "DI")])
-
-(define_insn "fistdi2_floor_with_temp"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
-       (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
-                  UNSPEC_FIST_FLOOR))
-   (use (match_operand:HI 2 "memory_operand" "m,m"))
-   (use (match_operand:HI 3 "memory_operand" "m,m"))
-   (clobber (match_operand:DI 4 "memory_operand" "=X,m"))
-   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
-  "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations"
-  "#"
-  [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "floor")
-   (set_attr "mode" "DI")])
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand")
-       (unspec:DI [(match_operand:XF 1 "register_operand")]
-                  UNSPEC_FIST_FLOOR))
-   (use (match_operand:HI 2 "memory_operand"))
-   (use (match_operand:HI 3 "memory_operand"))
-   (clobber (match_operand:DI 4 "memory_operand"))
-   (clobber (match_scratch 5))]
-  "reload_completed"
-  [(parallel [(set (match_dup 4)
-                  (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
-             (use (match_dup 2))
-             (use (match_dup 3))
-             (clobber (match_dup 5))])
-   (set (match_dup 0) (match_dup 4))])
-
-(define_split
-  [(set (match_operand:DI 0 "memory_operand")
-       (unspec:DI [(match_operand:XF 1 "register_operand")]
-                  UNSPEC_FIST_FLOOR))
-   (use (match_operand:HI 2 "memory_operand"))
-   (use (match_operand:HI 3 "memory_operand"))
-   (clobber (match_operand:DI 4 "memory_operand"))
-   (clobber (match_scratch 5))]
-  "reload_completed"
-  [(parallel [(set (match_dup 0)
-                  (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
-             (use (match_dup 2))
-             (use (match_dup 3))
-             (clobber (match_dup 5))])])
-
-(define_insn "fist<mode>2_floor"
-  [(set (match_operand:SWI24 0 "memory_operand" "=m")
-       (unspec:SWI24 [(match_operand:XF 1 "register_operand" "f")]
-                     UNSPEC_FIST_FLOOR))
-   (use (match_operand:HI 2 "memory_operand" "m"))
-   (use (match_operand:HI 3 "memory_operand" "m"))]
-  "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations"
-  "* return output_fix_trunc (insn, operands, false);"
-  [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "floor")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "fist<mode>2_floor_with_temp"
-  [(set (match_operand:SWI24 0 "nonimmediate_operand" "=m,?r")
-       (unspec:SWI24 [(match_operand:XF 1 "register_operand" "f,f")]
-                     UNSPEC_FIST_FLOOR))
-   (use (match_operand:HI 2 "memory_operand" "m,m"))
-   (use (match_operand:HI 3 "memory_operand" "m,m"))
-   (clobber (match_operand:SWI24 4 "memory_operand" "=X,m"))]
-  "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations"
-  "#"
-  [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "floor")
-   (set_attr "mode" "<MODE>")])
-
-(define_split
-  [(set (match_operand:SWI24 0 "register_operand")
-       (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
-                     UNSPEC_FIST_FLOOR))
-   (use (match_operand:HI 2 "memory_operand"))
-   (use (match_operand:HI 3 "memory_operand"))
-   (clobber (match_operand:SWI24 4 "memory_operand"))]
-  "reload_completed"
-  [(parallel [(set (match_dup 4)
-                  (unspec:SWI24 [(match_dup 1)] UNSPEC_FIST_FLOOR))
-             (use (match_dup 2))
-             (use (match_dup 3))])
-   (set (match_dup 0) (match_dup 4))])
+  else
+    {
+      rtx op0, op1;
 
-(define_split
-  [(set (match_operand:SWI24 0 "memory_operand")
-       (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
-                     UNSPEC_FIST_FLOOR))
-   (use (match_operand:HI 2 "memory_operand"))
-   (use (match_operand:HI 3 "memory_operand"))
-   (clobber (match_operand:SWI24 4 "memory_operand"))]
-  "reload_completed"
-  [(parallel [(set (match_dup 0)
-                  (unspec:SWI24 [(match_dup 1)] UNSPEC_FIST_FLOOR))
-             (use (match_dup 2))
-             (use (match_dup 3))])])
+      if (optimize_insn_for_size_p ())
+       FAIL;
 
-(define_expand "lfloorxf<mode>2"
-  [(parallel [(set (match_operand:SWI248x 0 "nonimmediate_operand")
-                  (unspec:SWI248x [(match_operand:XF 1 "register_operand")]
-                                  UNSPEC_FIST_FLOOR))
-             (clobber (reg:CC FLAGS_REG))])]
-  "TARGET_USE_FANCY_MATH_387
-   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
-   && flag_unsafe_math_optimizations")
+      op0 = gen_reg_rtx (XFmode);
+      op1 = gen_reg_rtx (XFmode);
+      emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+      emit_insn (gen_frndintxf2_ceil (op0, op1));
 
-(define_expand "lfloor<MODEF:mode><SWI48:mode>2"
-  [(match_operand:SWI48 0 "nonimmediate_operand")
-   (match_operand:MODEF 1 "register_operand")]
-  "SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH
-   && !flag_trapping_math"
-{
-  if (TARGET_64BIT && optimize_insn_for_size_p ())
-    FAIL;
-  ix86_expand_lfloorceil (operands[0], operands[1], true);
+      emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+    }
   DONE;
 })
 
-(define_expand "ceilxf2"
+(define_expand "btruncxf2"
   [(use (match_operand:XF 0 "register_operand"))
    (use (match_operand:XF 1 "register_operand"))]
   "TARGET_USE_FANCY_MATH_387
 {
   if (optimize_insn_for_size_p ())
     FAIL;
-  emit_insn (gen_frndintxf2_ceil (operands[0], operands[1]));
+  emit_insn (gen_frndintxf2_trunc (operands[0], operands[1]));
   DONE;
 })
 
-(define_expand "ceil<mode>2"
+(define_expand "btrunc<mode>2"
   [(use (match_operand:MODEF 0 "register_operand"))
    (use (match_operand:MODEF 1 "register_operand"))]
   "(TARGET_USE_FANCY_MATH_387
     {
       if (TARGET_ROUND)
        emit_insn (gen_sse4_1_round<mode>2
-                  (operands[0], operands[1], GEN_INT (ROUND_CEIL)));
+                  (operands[0], operands[1], GEN_INT (ROUND_TRUNC)));
       else if (optimize_insn_for_size_p ())
        FAIL;
       else if (TARGET_64BIT || (<MODE>mode != DFmode))
-       ix86_expand_floorceil (operands[0], operands[1], false);
+       ix86_expand_trunc (operands[0], operands[1]);
       else
-       ix86_expand_floorceildf_32 (operands[0], operands[1], false);
+       ix86_expand_truncdf_32 (operands[0], operands[1]);
     }
   else
     {
       op0 = gen_reg_rtx (XFmode);
       op1 = gen_reg_rtx (XFmode);
       emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
-      emit_insn (gen_frndintxf2_ceil (op0, op1));
+      emit_insn (gen_frndintxf2_trunc (op0, op1));
 
       emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
     }
   DONE;
 })
 
-(define_insn_and_split "*fist<mode>2_ceil_1"
+;; Rounding mode control word calculation could clobber FLAGS_REG.
+(define_insn_and_split "frndintxf2_mask_pm"
+  [(set (match_operand:XF 0 "register_operand")
+       (unspec:XF [(match_operand:XF 1 "register_operand")]
+                  UNSPEC_FRNDINT_MASK_PM))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_USE_FANCY_MATH_387
+   && flag_unsafe_math_optimizations
+   && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(const_int 0)]
+{
+  ix86_optimize_mode_switching[I387_MASK_PM] = 1;
+
+  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]));
+  DONE;
+}
+  [(set_attr "type" "frndint")
+   (set_attr "i387_cw" "mask_pm")
+   (set_attr "mode" "XF")])
+
+(define_insn "frndintxf2_mask_pm_i387"
+  [(set (match_operand:XF 0 "register_operand" "=f")
+       (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+                  UNSPEC_FRNDINT_MASK_PM))
+   (use (match_operand:HI 2 "memory_operand" "m"))
+   (use (match_operand:HI 3 "memory_operand" "m"))]
+  "TARGET_USE_FANCY_MATH_387
+   && flag_unsafe_math_optimizations"
+  "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
+  [(set_attr "type" "frndint")
+   (set_attr "i387_cw" "mask_pm")
+   (set_attr "mode" "XF")])
+
+(define_expand "nearbyintxf2"
+  [(use (match_operand:XF 0 "register_operand"))
+   (use (match_operand:XF 1 "register_operand"))]
+  "TARGET_USE_FANCY_MATH_387
+   && flag_unsafe_math_optimizations"
+{
+  emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1]));
+  DONE;
+})
+
+(define_expand "nearbyint<mode>2"
+  [(use (match_operand:MODEF 0 "register_operand"))
+   (use (match_operand:MODEF 1 "register_operand"))]
+  "TARGET_USE_FANCY_MATH_387
+   && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+       || TARGET_MIX_SSE_I387)
+   && flag_unsafe_math_optimizations"
+{
+  rtx op0 = gen_reg_rtx (XFmode);
+  rtx op1 = gen_reg_rtx (XFmode);
+
+  emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
+
+  emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+  DONE;
+})
+
+;; Rounding mode control word calculation could clobber FLAGS_REG.
+(define_insn_and_split "*fist<mode>2_<rounding>_1"
   [(set (match_operand:SWI248x 0 "nonimmediate_operand")
        (unspec:SWI248x [(match_operand:XF 1 "register_operand")]
-                       UNSPEC_FIST_CEIL))
+                       FIST_ROUNDING))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_USE_FANCY_MATH_387
    && flag_unsafe_math_optimizations
   "&& 1"
   [(const_int 0)]
 {
-  ix86_optimize_mode_switching[I387_CEIL] = 1;
+  ix86_optimize_mode_switching[I387_<ROUNDING>] = 1;
 
   operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
-  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
+  operands[3] = assign_386_stack_local (HImode, SLOT_CW_<ROUNDING>);
   if (memory_operand (operands[0], VOIDmode))
-    emit_insn (gen_fist<mode>2_ceil (operands[0], operands[1],
-                                    operands[2], operands[3]));
+    emit_insn (gen_fist<mode>2_<rounding> (operands[0], operands[1],
+                                          operands[2], operands[3]));
   else
     {
       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]));
+      emit_insn (gen_fist<mode>2_<rounding>_with_temp
+                 (operands[0], operands[1], operands[2],
+                  operands[3], operands[4]));
     }
   DONE;
 }
   [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "ceil")
+   (set_attr "i387_cw" "<rounding>")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "fistdi2_ceil"
+(define_insn "fistdi2_<rounding>"
   [(set (match_operand:DI 0 "memory_operand" "=m")
        (unspec:DI [(match_operand:XF 1 "register_operand" "f")]
-                  UNSPEC_FIST_CEIL))
+                  FIST_ROUNDING))
    (use (match_operand:HI 2 "memory_operand" "m"))
    (use (match_operand:HI 3 "memory_operand" "m"))
    (clobber (match_scratch:XF 4 "=&1f"))]
    && flag_unsafe_math_optimizations"
   "* return output_fix_trunc (insn, operands, false);"
   [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "ceil")
+   (set_attr "i387_cw" "<rounding>")
    (set_attr "mode" "DI")])
 
-(define_insn "fistdi2_ceil_with_temp"
+(define_insn "fistdi2_<rounding>_with_temp"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
        (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
-                  UNSPEC_FIST_CEIL))
+                  FIST_ROUNDING))
    (use (match_operand:HI 2 "memory_operand" "m,m"))
    (use (match_operand:HI 3 "memory_operand" "m,m"))
    (clobber (match_operand:DI 4 "memory_operand" "=X,m"))
    && flag_unsafe_math_optimizations"
   "#"
   [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "ceil")
+   (set_attr "i387_cw" "<rounding>")
    (set_attr "mode" "DI")])
 
 (define_split
   [(set (match_operand:DI 0 "register_operand")
        (unspec:DI [(match_operand:XF 1 "register_operand")]
-                  UNSPEC_FIST_CEIL))
+                  FIST_ROUNDING))
    (use (match_operand:HI 2 "memory_operand"))
    (use (match_operand:HI 3 "memory_operand"))
    (clobber (match_operand:DI 4 "memory_operand"))
    (clobber (match_scratch 5))]
   "reload_completed"
   [(parallel [(set (match_dup 4)
-                  (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
+                  (unspec:DI [(match_dup 1)] FIST_ROUNDING))
              (use (match_dup 2))
              (use (match_dup 3))
              (clobber (match_dup 5))])
 (define_split
   [(set (match_operand:DI 0 "memory_operand")
        (unspec:DI [(match_operand:XF 1 "register_operand")]
-                  UNSPEC_FIST_CEIL))
+                  FIST_ROUNDING))
    (use (match_operand:HI 2 "memory_operand"))
    (use (match_operand:HI 3 "memory_operand"))
    (clobber (match_operand:DI 4 "memory_operand"))
    (clobber (match_scratch 5))]
   "reload_completed"
   [(parallel [(set (match_dup 0)
-                  (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
+                  (unspec:DI [(match_dup 1)] FIST_ROUNDING))
              (use (match_dup 2))
              (use (match_dup 3))
              (clobber (match_dup 5))])])
 
-(define_insn "fist<mode>2_ceil"
+(define_insn "fist<mode>2_<rounding>"
   [(set (match_operand:SWI24 0 "memory_operand" "=m")
        (unspec:SWI24 [(match_operand:XF 1 "register_operand" "f")]
-                     UNSPEC_FIST_CEIL))
+                     FIST_ROUNDING))
    (use (match_operand:HI 2 "memory_operand" "m"))
    (use (match_operand:HI 3 "memory_operand" "m"))]
   "TARGET_USE_FANCY_MATH_387
    && flag_unsafe_math_optimizations"
   "* return output_fix_trunc (insn, operands, false);"
   [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "ceil")
+   (set_attr "i387_cw" "<rounding>")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "fist<mode>2_ceil_with_temp"
+(define_insn "fist<mode>2_<rounding>_with_temp"
   [(set (match_operand:SWI24 0 "nonimmediate_operand" "=m,?r")
        (unspec:SWI24 [(match_operand:XF 1 "register_operand" "f,f")]
-                     UNSPEC_FIST_CEIL))
+                     FIST_ROUNDING))
    (use (match_operand:HI 2 "memory_operand" "m,m"))
    (use (match_operand:HI 3 "memory_operand" "m,m"))
    (clobber (match_operand:SWI24 4 "memory_operand" "=X,m"))]
    && flag_unsafe_math_optimizations"
   "#"
   [(set_attr "type" "fistp")
-   (set_attr "i387_cw" "ceil")
+   (set_attr "i387_cw" "<rounding>")
    (set_attr "mode" "<MODE>")])
 
 (define_split
   [(set (match_operand:SWI24 0 "register_operand")
        (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
-                     UNSPEC_FIST_CEIL))
+                     FIST_ROUNDING))
    (use (match_operand:HI 2 "memory_operand"))
    (use (match_operand:HI 3 "memory_operand"))
    (clobber (match_operand:SWI24 4 "memory_operand"))]
   "reload_completed"
   [(parallel [(set (match_dup 4)
-                  (unspec:SWI24 [(match_dup 1)] UNSPEC_FIST_CEIL))
+                  (unspec:SWI24 [(match_dup 1)] FIST_ROUNDING))
              (use (match_dup 2))
              (use (match_dup 3))])
    (set (match_dup 0) (match_dup 4))])
 (define_split
   [(set (match_operand:SWI24 0 "memory_operand")
        (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
-                     UNSPEC_FIST_CEIL))
+                     FIST_ROUNDING))
    (use (match_operand:HI 2 "memory_operand"))
    (use (match_operand:HI 3 "memory_operand"))
    (clobber (match_operand:SWI24 4 "memory_operand"))]
   "reload_completed"
   [(parallel [(set (match_dup 0)
-                  (unspec:SWI24 [(match_dup 1)] UNSPEC_FIST_CEIL))
+                  (unspec:SWI24 [(match_dup 1)] FIST_ROUNDING))
              (use (match_dup 2))
              (use (match_dup 3))])])
 
-(define_expand "lceilxf<mode>2"
+(define_expand "l<rounding>xf<mode>2"
   [(parallel [(set (match_operand:SWI248x 0 "nonimmediate_operand")
                   (unspec:SWI248x [(match_operand:XF 1 "register_operand")]
-                                  UNSPEC_FIST_CEIL))
+                                  FIST_ROUNDING))
              (clobber (reg:CC FLAGS_REG))])]
   "TARGET_USE_FANCY_MATH_387
    && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
    && flag_unsafe_math_optimizations")
 
-(define_expand "lceil<MODEF:mode><SWI48:mode>2"
+(define_expand "lfloor<MODEF:mode><SWI48:mode>2"
   [(match_operand:SWI48 0 "nonimmediate_operand")
    (match_operand:MODEF 1 "register_operand")]
   "SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH
    && !flag_trapping_math"
 {
-  ix86_expand_lfloorceil (operands[0], operands[1], false);
-  DONE;
-})
-
-(define_expand "btruncxf2"
-  [(use (match_operand:XF 0 "register_operand"))
-   (use (match_operand:XF 1 "register_operand"))]
-  "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations"
-{
-  if (optimize_insn_for_size_p ())
+  if (TARGET_64BIT && optimize_insn_for_size_p ())
     FAIL;
-  emit_insn (gen_frndintxf2_trunc (operands[0], operands[1]));
-  DONE;
-})
-
-(define_expand "btrunc<mode>2"
-  [(use (match_operand:MODEF 0 "register_operand"))
-   (use (match_operand:MODEF 1 "register_operand"))]
-  "(TARGET_USE_FANCY_MATH_387
-    && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
-       || TARGET_MIX_SSE_I387)
-    && flag_unsafe_math_optimizations)
-   || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
-       && !flag_trapping_math)"
-{
-  if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
-      && !flag_trapping_math)
-    {
-      if (TARGET_ROUND)
-       emit_insn (gen_sse4_1_round<mode>2
-                  (operands[0], operands[1], GEN_INT (ROUND_TRUNC)));
-      else if (optimize_insn_for_size_p ())
-       FAIL;
-      else if (TARGET_64BIT || (<MODE>mode != DFmode))
-       ix86_expand_trunc (operands[0], operands[1]);
-      else
-       ix86_expand_truncdf_32 (operands[0], operands[1]);
-    }
-  else
-    {
-      rtx op0, op1;
-
-      if (optimize_insn_for_size_p ())
-       FAIL;
-
-      op0 = gen_reg_rtx (XFmode);
-      op1 = gen_reg_rtx (XFmode);
-      emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
-      emit_insn (gen_frndintxf2_trunc (op0, op1));
-
-      emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
-    }
-  DONE;
-})
-
-;; Rounding mode control word calculation could clobber FLAGS_REG.
-(define_insn_and_split "frndintxf2_mask_pm"
-  [(set (match_operand:XF 0 "register_operand")
-       (unspec:XF [(match_operand:XF 1 "register_operand")]
-                  UNSPEC_FRNDINT_MASK_PM))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations
-   && can_create_pseudo_p ()"
-  "#"
-  "&& 1"
-  [(const_int 0)]
-{
-  ix86_optimize_mode_switching[I387_MASK_PM] = 1;
-
-  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]));
-  DONE;
-}
-  [(set_attr "type" "frndint")
-   (set_attr "i387_cw" "mask_pm")
-   (set_attr "mode" "XF")])
-
-(define_insn "frndintxf2_mask_pm_i387"
-  [(set (match_operand:XF 0 "register_operand" "=f")
-       (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
-                  UNSPEC_FRNDINT_MASK_PM))
-   (use (match_operand:HI 2 "memory_operand" "m"))
-   (use (match_operand:HI 3 "memory_operand" "m"))]
-  "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations"
-  "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
-  [(set_attr "type" "frndint")
-   (set_attr "i387_cw" "mask_pm")
-   (set_attr "mode" "XF")])
-
-(define_expand "nearbyintxf2"
-  [(use (match_operand:XF 0 "register_operand"))
-   (use (match_operand:XF 1 "register_operand"))]
-  "TARGET_USE_FANCY_MATH_387
-   && flag_unsafe_math_optimizations"
-{
-  emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1]));
+  ix86_expand_lfloorceil (operands[0], operands[1], true);
   DONE;
 })
 
-(define_expand "nearbyint<mode>2"
-  [(use (match_operand:MODEF 0 "register_operand"))
-   (use (match_operand:MODEF 1 "register_operand"))]
-  "TARGET_USE_FANCY_MATH_387
-   && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
-       || TARGET_MIX_SSE_I387)
-   && flag_unsafe_math_optimizations"
+(define_expand "lceil<MODEF:mode><SWI48:mode>2"
+  [(match_operand:SWI48 0 "nonimmediate_operand")
+   (match_operand:MODEF 1 "register_operand")]
+  "SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH
+   && !flag_trapping_math"
 {
-  rtx op0 = gen_reg_rtx (XFmode);
-  rtx op1 = gen_reg_rtx (XFmode);
-
-  emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
-  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
-
-  emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+  ix86_expand_lfloorceil (operands[0], operands[1], false);
   DONE;
 })