diff options
author | Jakub Jelinek <jakub@redhat.com> | 2011-11-01 21:16:20 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2011-11-01 21:16:20 +0100 |
commit | 6bf39801d477bd03305ac582bac8331301808da9 (patch) | |
tree | 0827096870707eee3ffb4b7a8e94a2007a0e5531 | |
parent | 8d1788f2e16ff606fb2a8dc716b1f6f3006a2b38 (diff) | |
download | gcc-6bf39801d477bd03305ac582bac8331301808da9.zip gcc-6bf39801d477bd03305ac582bac8331301808da9.tar.gz gcc-6bf39801d477bd03305ac582bac8331301808da9.tar.bz2 |
i386-protos.h (ix86_expand_adjust_ufix_to_sfix_si): New prototype.
* 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
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 40 | ||||
-rw-r--r-- | gcc/config/i386/sse.md | 45 |
4 files changed, 73 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41a1b96..5f33433 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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): diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index bdac6ff..5486e61 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -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[]); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4e34f25..c9e0adb 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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. */ diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 7d1cf29..33c2e94 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -2323,32 +2323,13 @@ (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 @@ 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" "") |