]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386-protos.h (ix86_expand_adjust_ufix_to_sfix_si): New prototype.
authorJakub Jelinek <jakub@redhat.com>
Tue, 1 Nov 2011 20:16:20 +0000 (21:16 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 1 Nov 2011 20:16:20 +0000 (21:16 +0100)
* config/i386/i386-protos.h (ix86_expand_adjust_ufix_to_sfix_si): New
prototype.
* config/i386/i386.c (ix86_expand_adjust_ufix_to_sfix_si): New
function.
* config/i386/sse.md (fixuns_trunc<mode><sseintvecmodelower>2): Use
it.
(ssepackfltmode): New mode attr.
(vec_pack_ufix_trunc_<mode>): New expander.

From-SVN: r180743

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

index 41a1b96208e168a345bfe88e2ac2e6a959ba736a..5f3343364589c84defde7f20bcdf07c752e94d1a 100644 (file)
@@ -1,3 +1,14 @@
+2011-11-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/i386/i386-protos.h (ix86_expand_adjust_ufix_to_sfix_si): New
+       prototype.
+       * config/i386/i386.c (ix86_expand_adjust_ufix_to_sfix_si): New
+       function.
+       * config/i386/sse.md (fixuns_trunc<mode><sseintvecmodelower>2): Use
+       it.
+       (ssepackfltmode): New mode attr.
+       (vec_pack_ufix_trunc_<mode>): New expander.
+
 2011-10-30  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (floatsi<mode>2_vector_sse_with_temp splitter):
index bdac6ff06664f4c198c7de0de7d58e99de24e534..5486e618dc85079a2548e8ae5ea3e47f3b8e2248 100644 (file)
@@ -109,6 +109,7 @@ extern void ix86_expand_convert_uns_sixf_sse (rtx, rtx);
 extern void ix86_expand_convert_uns_sidf_sse (rtx, rtx);
 extern void ix86_expand_convert_uns_sisf_sse (rtx, rtx);
 extern void ix86_expand_convert_sign_didf_sse (rtx, rtx);
+extern rtx ix86_expand_adjust_ufix_to_sfix_si (rtx);
 extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code);
 extern void ix86_expand_fp_absneg_operator (enum rtx_code, enum machine_mode,
                                            rtx[]);
index 4e34f25e62200485df76343b141f1fcdba99d7a9..c9e0adbb1b33bb9a68ce57101c836d42b9b6ff55 100644 (file)
@@ -17016,6 +17016,46 @@ ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
     emit_move_insn (target, fp_hi);
 }
 
+/* Adjust a V*SFmode/V*DFmode value VAL so that *sfix_trunc* resp. fix_trunc*
+   pattern can be used on it instead of *ufix_trunc* resp. fixuns_trunc*.
+   This is done by subtracting 0x1p32 from VAL if VAL is greater or equal
+   (non-signalling) than 0x1p31.  */
+
+rtx
+ix86_expand_adjust_ufix_to_sfix_si (rtx val)
+{
+  REAL_VALUE_TYPE MTWO32r, TWO31r;
+  rtx two31r, mtwo32r, tmp[3];
+  enum machine_mode mode = GET_MODE (val);
+  enum machine_mode scalarmode = GET_MODE_INNER (mode);
+  rtx (*cmp) (rtx, rtx, rtx, rtx);
+  int i;
+
+  for (i = 0; i < 3; i++)
+    tmp[i] = gen_reg_rtx (mode);
+  real_ldexp (&TWO31r, &dconst1, 31);
+  two31r = const_double_from_real_value (TWO31r, scalarmode);
+  two31r = ix86_build_const_vector (mode, 1, two31r);
+  two31r = force_reg (mode, two31r);
+  real_ldexp (&MTWO32r, &dconstm1, 32);
+  mtwo32r = const_double_from_real_value (MTWO32r, scalarmode);
+  mtwo32r = ix86_build_const_vector (mode, 1, mtwo32r);
+  mtwo32r = force_reg (mode, mtwo32r);
+  switch (mode)
+    {
+    case V8SFmode: cmp = gen_avx_cmpv8sf3; break;
+    case V4SFmode: cmp = gen_avx_cmpv4sf3; break;
+    case V4DFmode: cmp = gen_avx_cmpv4df3; break;
+    case V2DFmode: cmp = gen_avx_cmpv2df3; break;
+    default: gcc_unreachable ();
+    }
+  emit_insn (cmp (tmp[0], val, two31r, GEN_INT (29)));
+  tmp[1] = expand_simple_binop (mode, AND, tmp[0], mtwo32r, tmp[1],
+                               0, OPTAB_DIRECT);
+  return expand_simple_binop (mode, PLUS, val, tmp[1], tmp[2],
+                             0, OPTAB_DIRECT);
+}
+
 /* A subroutine of ix86_build_signbit_mask.  If VECT is true,
    then replicate the value for all elements of the vector
    register.  */
index 7d1cf293f281a546b18f567374a74b6d08ebae45..33c2e94b3693b9156192caf13ab27b8a82bafe07 100644 (file)
    (set_attr "mode" "TI")])
 
 (define_expand "fixuns_trunc<mode><sseintvecmodelower>2"
-  [(set (match_dup 4)
-       (unspec:VF1
-         [(match_operand:VF1 1 "register_operand" "")
-          (match_dup 2)
-          (const_int 29)] UNSPEC_PCMP))
-   (set (match_dup 5)
-       (and:VF1 (match_dup 4) (match_dup 3)))
-   (set (match_dup 6)
-       (plus:VF1 (match_dup 1) (match_dup 5)))
-   (set (match_operand:<sseintvecmode> 0 "register_operand" "")
-       (fix:<sseintvecmode> (match_dup 6)))]
+  [(match_operand:<sseintvecmode> 0 "register_operand" "")
+   (match_operand:VF1 1 "register_operand" "")]
   "TARGET_AVX"
 {
-  REAL_VALUE_TYPE MTWO32r, TWO31r;
-  int i;
-
-  real_ldexp (&TWO31r, &dconst1, 31);
-  operands[2] = const_double_from_real_value (TWO31r, SFmode);
-  operands[2] = ix86_build_const_vector (<MODE>mode, 1, operands[2]);
-  operands[2] = force_reg (<MODE>mode, operands[2]);
-  real_ldexp (&MTWO32r, &dconstm1, 32);
-  operands[3] = const_double_from_real_value (MTWO32r, SFmode);
-  operands[3] = ix86_build_const_vector (<MODE>mode, 1, operands[3]);
-  operands[3] = force_reg (<MODE>mode, operands[3]);
-  for (i = 4; i < 7; i++)
-    operands[i] = gen_reg_rtx (<MODE>mode);
+  rtx tmp = ix86_expand_adjust_ufix_to_sfix_si (operands[1]);
+  emit_insn (gen_fix_trunc<mode><sseintvecmodelower>2 (operands[0], tmp));
+  DONE;
 })
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   DONE;
 })
 
+(define_mode_attr ssepackfltmode
+  [(V4DF "V8SI") (V2DF "V4SI")])
+
+(define_expand "vec_pack_ufix_trunc_<mode>"
+  [(match_operand:<ssepackfltmode> 0 "register_operand" "")
+   (match_operand:VF2 1 "register_operand" "")
+   (match_operand:VF2 2 "register_operand" "")]
+  "TARGET_AVX"
+{
+  rtx tmp[2];
+  tmp[0] = ix86_expand_adjust_ufix_to_sfix_si (operands[1]);
+  tmp[1] = ix86_expand_adjust_ufix_to_sfix_si (operands[2]);
+  emit_insn (gen_vec_pack_sfix_trunc_<mode> (operands[0], tmp[0], tmp[1]));
+  DONE;
+})
+
 (define_expand "vec_pack_sfix_v4df"
   [(match_operand:V8SI 0 "register_operand" "")
    (match_operand:V4DF 1 "nonimmediate_operand" "")