[PATCH] Add vec_pack_ufix_trunc_{v4df,v2df} expanders (take 2)
Jakub Jelinek
jakub@redhat.com
Tue Nov 1 13:36:00 GMT 2011
On Tue, Nov 01, 2011 at 11:16:07AM +0100, Uros Bizjak wrote:
> On Tue, Nov 1, 2011 at 10:07 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>
> > Similarly to the V{4,8}SFmode -> unsigned V{4,8}SImode conversion
> > support for AVX this one adds V{2,4}DFmode -> unsigned V{4,8}SImode
> > conversion.
> >
> > Ok for trunk?
>
> Please put expander function into i386.c. IMO, this expander can be
> better written using variable mode and indirect functions.
Like this?
Advantage is that fixuns_trunc<mode><sseintvecmodelower>2 pattern can use
the helper too and shrink, disadvantage is that the stmts in the new
pattern are now in vcmppd; vandpd; vaddpd; vcmppd; vandpd; vaddpd order
instead of vcmppd; vcmppd; vandpd; vandpd; vaddpd; vaddpd; (not sure why
the scheduler didn't change it, but on the other side it is scheduler's
job).
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.
--- gcc/config/i386/i386-protos.h.jj 2011-10-25 08:13:31.000000000 +0200
+++ gcc/config/i386/i386-protos.h 2011-11-01 14:18:59.000000000 +0100
@@ -109,6 +109,7 @@ extern void ix86_expand_convert_uns_sixf
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[]);
--- gcc/config/i386/i386.c.jj 2011-10-31 20:44:13.000000000 +0100
+++ gcc/config/i386/i386.c 2011-11-01 14:26:31.000000000 +0100
@@ -17016,6 +17016,46 @@ ix86_expand_convert_uns_sisf_sse (rtx ta
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. */
--- gcc/config/i386/sse.md.jj 2011-11-01 09:04:37.000000000 +0100
+++ gcc/config/i386/sse.md 2011-11-01 14:25:52.000000000 +0100
@@ -2323,32 +2323,13 @@ (define_insn "fix_truncv4sfv4si2"
(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;
})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -3127,6 +3108,22 @@ (define_expand "vec_pack_sfix_trunc_v2df
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" "")
Jakub
More information about the Gcc-patches
mailing list