]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/24659 (Conversions are not vectorized)
authorUros Bizjak <uros@gcc.gnu.org>
Thu, 17 May 2007 06:31:05 +0000 (08:31 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Thu, 17 May 2007 06:31:05 +0000 (08:31 +0200)
PR tree-optimization/24659
        * optabs.h (enum optab_index): Add OTI_vec_unpacks_float_hi,
OTI_vec_unpacks_float_lo, OTI_vec_unpacku_float_hi,
OTI_vec_unpacku_float_lo, OTI_vec_pack_sfix_trunc and
OTI_vec_pack_ufix_trunc.
(vec_unpacks_float_hi_optab): Define new macro.
(vec_unpacks_float_lo_optab): Ditto.
(vec_unpacku_float_hi_optab): Ditto.
(vec_unpacku_float_lo_optab): Ditto.
(vec_pack_sfix_trunc_optab): Ditto.
(vec_pack_ufix_trunc_optab): Ditto.
* genopinit.c (optabs): Implement vec_unpack[s|u]_[hi|lo]_optab
and vec_pack_[s|u]fix_trunc_optab using
vec_unpack[s|u]_[hi\lo]_* and vec_pack_[u|s]fix_trunc_* patterns
* tree-vectorizer.c (supportable_widening_operation): Handle
FLOAT_EXPR and CONVERT_EXPR.  Update comment.
(supportable_narrowing_operation): New function.
* tree-vectorizer.h (supportable_narrowing_operation): Prototype.
* tree-vect-transform.c (vectorizable_conversion): Handle
(nunits_in == nunits_out / 2) and (nunits_out == nunits_in / 2) cases.
(vect_gen_widened_results_half): Move before vectorizable_conversion.
(vectorizable_type_demotion): Call supportable_narrowing_operation()
to check for target support.
* optabs.c (optab_for_tree_code) Return vec_unpack[s|u]_float_hi_optab
for VEC_UNPACK_FLOAT_HI_EXPR, vec_unpack[s|u]_float_lo_optab
for VEC_UNPACK_FLOAT_LO_EXPR and vec_pack_[u|s]fix_trunc_optab
for VEC_PACK_FIX_TRUNC_EXPR.
(expand_binop): Special case mode of the result for
vec_pack_[u|s]fix_trunc_optab.
(init_optabs): Initialize vec_unpack[s|u]_[hi|lo]_optab and
vec_pack_[u|s]fix_trunc_optab.

* tree.def (VEC_UNPACK_FLOAT_HI_EXPR, VEC_UNPACK_FLOAT_LO_EXPR,
VEC_PACK_FIX_TRUNC_EXPR): New tree codes.
* tree-pretty-print.c (dump_generic_node): Handle
VEC_UNPACK_FLOAT_HI_EXPR, VEC_UNPACK_FLOAT_LO_EXPR and
VEC_PACK_FIX_TRUNC_EXPR.
(op_prio): Ditto.
* expr.c (expand_expr_real_1): Ditto.
* tree-inline.c (estimate_num_insns_1): Ditto.
* tree-vect-generic.c (expand_vector_operations_1): Ditto.

* config/i386/sse.md (vec_unpacks_float_hi_v8hi): New expander.
(vec_unpacks_float_lo_v8hi): Ditto.
(vec_unpacku_float_hi_v8hi): Ditto.
(vec_unpacku_float_lo_v8hi): Ditto.
(vec_unpacks_float_hi_v4si): Ditto.
(vec_unpacks_float_lo_v4si): Ditto.
(vec_pack_sfix_trunc_v2df): Ditto.

* doc/c-tree.texi (Expression trees) [VEC_UNPACK_FLOAT_HI_EXPR]:
Document.
[VEC_UNPACK_FLOAT_LO_EXPR]: Ditto.
[VEC_PACK_FIX_TRUNC_EXPR]: Ditto.
* doc/md.texi (Standard Names) [vec_pack_sfix_trunc]: Document.
[vec_pack_ufix_trunc]: Ditto.
[vec_unpacks_float_hi]: Ditto.
[vec_unpacks_float_lo]: Ditto.
[vec_unpacku_float_hi]: Ditto.
[vec_unpacku_float_lo]: Ditto.

testsuite/ChangeLog:

PR tree-optimization/24659
* gcc.dg/vect/vect-floatint-conversion-2.c: New test.
* gcc.dg/vect/vect-intfloat-conversion-1.c: Require vect_float,
not vect_int target.
* gcc.dg/vect/vect-intfloat-conversion-2.c: Require vect_float,
not vect_int target.  Loop is vectorized for vect_intfloat_cvt
targets.
* gcc.dg/vect/vect-intfloat-conversion-3.c: New test.
* gcc.dg/vect/vect-intfloat-conversion-4a.c: New test.
* gcc.dg/vect/vect-intfloat-conversion-4b.c: New test.

From-SVN: r124784

22 files changed:
gcc/ChangeLog
gcc/config/i386/sse.md
gcc/doc/c-tree.texi
gcc/doc/md.texi
gcc/expr.c
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-floatint-conversion-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-1.c
gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-2.c
gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-4a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-4b.c [new file with mode: 0644]
gcc/tree-inline.c
gcc/tree-pretty-print.c
gcc/tree-vect-generic.c
gcc/tree-vect-transform.c
gcc/tree-vectorizer.c
gcc/tree-vectorizer.h
gcc/tree.def

index 9c6808c4c7b8f4127df0477bc7fbf88b08fc459c..f50bdc5ff9a9d6b8e2390422f5cb312cbdf99423 100644 (file)
@@ -1,3 +1,66 @@
+2007-05-17  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR tree-optimization/24659
+       * optabs.h (enum optab_index): Add OTI_vec_unpacks_float_hi,
+       OTI_vec_unpacks_float_lo, OTI_vec_unpacku_float_hi,
+       OTI_vec_unpacku_float_lo, OTI_vec_pack_sfix_trunc and
+       OTI_vec_pack_ufix_trunc.
+       (vec_unpacks_float_hi_optab): Define new macro.
+       (vec_unpacks_float_lo_optab): Ditto.
+       (vec_unpacku_float_hi_optab): Ditto.
+       (vec_unpacku_float_lo_optab): Ditto.
+       (vec_pack_sfix_trunc_optab): Ditto.
+       (vec_pack_ufix_trunc_optab): Ditto.
+       * genopinit.c (optabs): Implement vec_unpack[s|u]_[hi|lo]_optab
+       and vec_pack_[s|u]fix_trunc_optab using
+       vec_unpack[s|u]_[hi\lo]_* and vec_pack_[u|s]fix_trunc_* patterns
+       * tree-vectorizer.c (supportable_widening_operation): Handle
+       FLOAT_EXPR and CONVERT_EXPR.  Update comment.
+       (supportable_narrowing_operation): New function.
+       * tree-vectorizer.h (supportable_narrowing_operation): Prototype.
+       * tree-vect-transform.c (vectorizable_conversion): Handle
+       (nunits_in == nunits_out / 2) and (nunits_out == nunits_in / 2) cases.
+       (vect_gen_widened_results_half): Move before vectorizable_conversion.
+       (vectorizable_type_demotion): Call supportable_narrowing_operation()
+       to check for target support.
+       * optabs.c (optab_for_tree_code) Return vec_unpack[s|u]_float_hi_optab
+       for VEC_UNPACK_FLOAT_HI_EXPR, vec_unpack[s|u]_float_lo_optab
+       for VEC_UNPACK_FLOAT_LO_EXPR and vec_pack_[u|s]fix_trunc_optab
+       for VEC_PACK_FIX_TRUNC_EXPR.
+       (expand_binop): Special case mode of the result for
+       vec_pack_[u|s]fix_trunc_optab.
+       (init_optabs): Initialize vec_unpack[s|u]_[hi|lo]_optab and
+       vec_pack_[u|s]fix_trunc_optab.
+
+       * tree.def (VEC_UNPACK_FLOAT_HI_EXPR, VEC_UNPACK_FLOAT_LO_EXPR,
+       VEC_PACK_FIX_TRUNC_EXPR): New tree codes.
+       * tree-pretty-print.c (dump_generic_node): Handle
+       VEC_UNPACK_FLOAT_HI_EXPR, VEC_UNPACK_FLOAT_LO_EXPR and
+       VEC_PACK_FIX_TRUNC_EXPR.
+       (op_prio): Ditto.
+       * expr.c (expand_expr_real_1): Ditto.
+       * tree-inline.c (estimate_num_insns_1): Ditto.
+       * tree-vect-generic.c (expand_vector_operations_1): Ditto.
+
+       * config/i386/sse.md (vec_unpacks_float_hi_v8hi): New expander.
+       (vec_unpacks_float_lo_v8hi): Ditto.
+       (vec_unpacku_float_hi_v8hi): Ditto.
+       (vec_unpacku_float_lo_v8hi): Ditto.
+       (vec_unpacks_float_hi_v4si): Ditto.
+       (vec_unpacks_float_lo_v4si): Ditto.
+       (vec_pack_sfix_trunc_v2df): Ditto.
+
+       * doc/c-tree.texi (Expression trees) [VEC_UNPACK_FLOAT_HI_EXPR]:
+       Document.
+       [VEC_UNPACK_FLOAT_LO_EXPR]: Ditto.
+       [VEC_PACK_FIX_TRUNC_EXPR]: Ditto.
+       * doc/md.texi (Standard Names) [vec_pack_sfix_trunc]: Document.
+       [vec_pack_ufix_trunc]: Ditto.
+       [vec_unpacks_float_hi]: Ditto.
+       [vec_unpacks_float_lo]: Ditto.
+       [vec_unpacku_float_hi]: Ditto.
+       [vec_unpacku_float_lo]: Ditto.
+
 2007-05-16  Uros Bizjak  <ubizjak@gmail.com>
 
        * soft-fp/README: Update for new files.
 
 2007-05-16  Paolo Bonzini  <bonzini@gnu.org>
 
-        * config/i386/i386.c (legitimize_tls_address): Mark __tls_get_addr
-        calls as pure.
+       * config/i386/i386.c (legitimize_tls_address): Mark __tls_get_addr
+       calls as pure.
 
 2007-05-16  Eric Christopher  <echristo@apple.com>
 
        * config/rs6000/rs6000.c (rs6000_emit_prologue): Move altivec register
-        saving after stack push. Set sp_offset whenever we push.
-        (rs6000_emit_epilogue): Move altivec register restore before stack push.
+       saving after stack push. Set sp_offset whenever we push.
+       (rs6000_emit_epilogue): Move altivec register restore before
+       stack push.
 
 2007-05-16  Richard Sandiford  <richard@codesourcery.com>
 
        dumps.
 
 2007-05-08  Sandra Loosemore  <sandra@codesourcery.com>
-            Nigel Stephens  <nigel@mips.com>
+           Nigel Stephens  <nigel@mips.com>
 
        * config/mips/mips.h (MAX_FPRS_PER_FMT): Renamed from FP_INC.
        Update comments and all uses.
        * configure: Regenerate.
        * config.in: Regenerate.
 
-2007-05-07   Naveen.H.S  <naveen.hs@kpitcummins.com>
+2007-05-07  Naveen.H.S  <naveen.hs@kpitcummins.com>
 
        * config/m32c/muldiv.md (mulhisi3_c): Limit the mode of the 2nd
        operand to HI mode.
        PR middle-end/22156
        Temporarily revert:
        2007-04-06  Andreas Tobler  <a.tobler@schweiz.org>
-        * tree-sra.c (sra_build_elt_assignment): Initialize min/maxshift.
+       * tree-sra.c (sra_build_elt_assignment): Initialize min/maxshift.
        2007-04-05  Alexandre Oliva  <aoliva@redhat.com>
        * tree-sra.c (try_instantiate_multiple_fields): Needlessly
        initialize align to silence bogus warning.
        PR tree-optimization/30965
        PR tree-optimization/30978
        * Makefile.in (tree-ssa-forwprop.o): Depend on $(FLAGS_H).
-        * tree-ssa-forwprop.c (forward_propagate_into_cond_1): Remove.
-        (find_equivalent_equality_comparison): Likewise.
-        (simplify_cond): Likewise.
-        (get_prop_source_stmt): New helper.
-        (get_prop_dest_stmt): Likewise.
+       * tree-ssa-forwprop.c (forward_propagate_into_cond_1): Remove.
+       (find_equivalent_equality_comparison): Likewise.
+       (simplify_cond): Likewise.
+       (get_prop_source_stmt): New helper.
+       (get_prop_dest_stmt): Likewise.
        (can_propagate_from): Likewise.
        (remove_prop_source_from_use): Likewise.
-        (combine_cond_expr_cond): Likewise.
-        (forward_propagate_comparison): New function.
-        (forward_propagate_into_cond): Rewrite to use fold for
-        tree combining.
+       (combine_cond_expr_cond): Likewise.
+       (forward_propagate_comparison): New function.
+       (forward_propagate_into_cond): Rewrite to use fold for
+       tree combining.
        (tree_ssa_forward_propagate_single_use_vars): Call
        forward_propagate_comparison to propagate comparisons.
 
index 63f0eac53b6f88e91ab7835caf1c1e45acf3c4ea..aa581ac1443115a7c96f050d75baf4c896da6fc1 100644 (file)
            (parallel [(const_int 0) (const_int 1)]))))]
   "TARGET_SSE2")
 
+(define_expand "vec_unpacks_float_hi_v8hi"
+  [(match_operand:V4SF 0 "register_operand" "")
+   (match_operand:V8HI 1 "register_operand" "")]
+  "TARGET_SSE2"
+{
+  rtx tmp = gen_reg_rtx (V4SImode);
+
+  emit_insn (gen_vec_unpacks_hi_v8hi (tmp, operands[1]));
+  emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+  DONE;
+})
+
+(define_expand "vec_unpacks_float_lo_v8hi"
+  [(match_operand:V4SF 0 "register_operand" "")
+   (match_operand:V8HI 1 "register_operand" "")]
+  "TARGET_SSE2"
+{
+  rtx tmp = gen_reg_rtx (V4SImode);
+
+  emit_insn (gen_vec_unpacks_lo_v8hi (tmp, operands[1]));
+  emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+  DONE;
+})
+
+(define_expand "vec_unpacku_float_hi_v8hi"
+  [(match_operand:V4SF 0 "register_operand" "")
+   (match_operand:V8HI 1 "register_operand" "")]
+  "TARGET_SSE2"
+{
+  rtx tmp = gen_reg_rtx (V4SImode);
+
+  emit_insn (gen_vec_unpacku_hi_v8hi (tmp, operands[1]));
+  emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+  DONE;
+})
+
+(define_expand "vec_unpacku_float_lo_v8hi"
+  [(match_operand:V4SF 0 "register_operand" "")
+   (match_operand:V8HI 1 "register_operand" "")]
+  "TARGET_SSE2"
+{
+  rtx tmp = gen_reg_rtx (V4SImode);
+
+  emit_insn (gen_vec_unpacku_lo_v8hi (tmp, operands[1]));
+  emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+  DONE;
+})
+
+(define_expand "vec_unpacks_float_hi_v4si"
+  [(set (match_dup 2)
+       (vec_select:V4SI
+         (match_operand:V4SI 1 "nonimmediate_operand" "")
+         (parallel [(const_int 2)
+                    (const_int 3)
+                    (const_int 2)
+                    (const_int 3)])))
+   (set (match_operand:V2DF 0 "register_operand" "")
+        (float:V2DF
+         (vec_select:V2SI
+         (match_dup 2)
+           (parallel [(const_int 0) (const_int 1)]))))]
+ "TARGET_SSE2"
+{
+ operands[2] = gen_reg_rtx (V4SImode);
+})
+
+(define_expand "vec_unpacks_float_lo_v4si"
+  [(set (match_operand:V2DF 0 "register_operand" "")
+       (float:V2DF
+         (vec_select:V2SI
+           (match_operand:V4SI 1 "nonimmediate_operand" "")
+           (parallel [(const_int 0) (const_int 1)]))))]
+  "TARGET_SSE2")
+
 (define_expand "vec_pack_trunc_v2df"
   [(match_operand:V4SF 0 "register_operand" "")
    (match_operand:V2DF 1 "nonimmediate_operand" "")
   DONE;
 })
 
+(define_expand "vec_pack_sfix_trunc_v2df"
+  [(match_operand:V4SI 0 "register_operand" "")
+   (match_operand:V2DF 1 "nonimmediate_operand" "")
+   (match_operand:V2DF 2 "nonimmediate_operand" "")]
+  "TARGET_SSE2"
+{
+  rtx r1, r2;
+
+  r1 = gen_reg_rtx (V4SImode);
+  r2 = gen_reg_rtx (V4SImode);
+
+  emit_insn (gen_sse2_cvttpd2dq (r1, operands[1]));
+  emit_insn (gen_sse2_cvttpd2dq (r2, operands[2]));
+  emit_insn (gen_sse2_punpcklqdq (gen_lowpart (V2DImode, operands[0]),
+                                 gen_lowpart (V2DImode, r1),
+                                 gen_lowpart (V2DImode, r2)));
+  DONE;
+})
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;; Parallel double-precision floating point element swizzling
   "TARGET_SSE2"
 {
   rtx op1, op2, h1, l1, h2, l2, h3, l3;
-                                                                                
+
   op1 = gen_lowpart (V16QImode, operands[1]);
   op2 = gen_lowpart (V16QImode, operands[2]);
   h1 = gen_reg_rtx (V16QImode);
   l2 = gen_reg_rtx (V16QImode);
   h3 = gen_reg_rtx (V16QImode);
   l3 = gen_reg_rtx (V16QImode);
-                                                                                
+
   emit_insn (gen_vec_interleave_highv16qi (h1, op1, op2));
   emit_insn (gen_vec_interleave_lowv16qi (l1, op1, op2));
   emit_insn (gen_vec_interleave_highv16qi (h2, l1, h1));
   emit_insn (gen_vec_interleave_lowv16qi (operands[0], l3, h3));
   DONE;
 })
-                                                                                
+
 ;; Reduce:
 ;;      op1 = abcdefgh
 ;;      op2 = ijklmnop
   "TARGET_SSE2"
 {
   rtx op1, op2, h1, l1, h2, l2;
-                                                                                
+
   op1 = gen_lowpart (V8HImode, operands[1]);
   op2 = gen_lowpart (V8HImode, operands[2]);
   h1 = gen_reg_rtx (V8HImode);
   l1 = gen_reg_rtx (V8HImode);
   h2 = gen_reg_rtx (V8HImode);
   l2 = gen_reg_rtx (V8HImode);
-                                                                                
+
   emit_insn (gen_vec_interleave_highv8hi (h1, op1, op2));
   emit_insn (gen_vec_interleave_lowv8hi (l1, op1, op2));
   emit_insn (gen_vec_interleave_highv8hi (h2, l1, h1));
   emit_insn (gen_vec_interleave_lowv8hi (operands[0], l2, h2));
   DONE;
 })
-                                                                                
+
 ;; Reduce:
 ;;     op1 = abcd
 ;;     op2 = efgh
   "TARGET_SSE2"
 {
   rtx op1, op2, h1, l1;
-                                                                                
+
   op1 = gen_lowpart (V4SImode, operands[1]);
   op2 = gen_lowpart (V4SImode, operands[2]);
   h1 = gen_reg_rtx (V4SImode);
   l1 = gen_reg_rtx (V4SImode);
-                                                                                
+
   emit_insn (gen_vec_interleave_highv4si (h1, op1, op2));
   emit_insn (gen_vec_interleave_lowv4si (l1, op1, op2));
   emit_insn (gen_vec_interleave_lowv4si (operands[0], l1, h1));
index 60482e4626c06732be9024306e51239005a16088..bd4c62308ee5f0e86108a0a1a45262c4122febd7 100644 (file)
@@ -1983,8 +1983,11 @@ This macro returns the attributes on the type @var{type}.
 @tindex VEC_WIDEN_MULT_LO_EXPR
 @tindex VEC_UNPACK_HI_EXPR
 @tindex VEC_UNPACK_LO_EXPR
+@tindex VEC_UNPACK_FLOAT_HI_EXPR
+@tindex VEC_UNPACK_FLOAT_LO_EXPR
 @tindex VEC_PACK_TRUNC_EXPR
 @tindex VEC_PACK_SAT_EXPR
+@tindex VEC_PACK_FIX_TRUNC_EXPR
 @tindex VEC_EXTRACT_EVEN_EXPR 
 @tindex VEC_EXTRACT_ODD_EXPR
 @tindex VEC_INTERLEAVE_HIGH_EXPR
@@ -2846,6 +2849,17 @@ high @code{N/2} elements of the vector are extracted and widened (promoted).
 In the case of @code{VEC_UNPACK_LO_EXPR} the low @code{N/2} elements of the
 vector are extracted and widened (promoted).
 
+@item VEC_UNPACK_FLOAT_HI_EXPR
+@item VEC_UNPACK_FLOAT_LO_EXPR
+These nodes represent unpacking of the high and low parts of the input vector,
+where the values are converted from fixed point to floating point.  The
+single operand is a vector that contains @code{N} elements of the same
+integral type.  The result is a vector that contains half as many elements
+of a floating point type whose size is twice as wide.  In the case of
+@code{VEC_UNPACK_HI_EXPR} the high @code{N/2} elements of the vector are
+extracted, converted and widened.  In the case of @code{VEC_UNPACK_LO_EXPR}
+the low @code{N/2} elements of the vector are extracted, converted and widened.
+
 @item VEC_PACK_TRUNC_EXPR
 This node represents packing of truncated elements of the two input vectors
 into the output vector.  Input operands are vectors that contain the same
@@ -2862,6 +2876,15 @@ vector that contains twice as many elements of an integral type whose size
 is half as wide.  The elements of the two vectors are demoted and merged
 (concatenated) to form the output vector.
 
+@item VEC_PACK_FIX_TRUNC_EXPR
+This node represents packing of elements of the two input vectors into the
+output vector, where the values are converted from floating point
+to fixed point.  Input operands are vectors that contain the same number
+of elements of a floating point type.  The result is a vector that contains
+twice as many elements of an integral type whose size is half as wide.  The
+elements of the two vectors are merged (concatenated) to form the output
+vector.
+
 @item VEC_EXTRACT_EVEN_EXPR
 @item VEC_EXTRACT_ODD_EXPR
 These nodes represent extracting of the even/odd elements of the two input 
index 53c5769f7887b1f0f151dedc88afd4af5a636c47..029657d3fe0e615d87bf84d5a3521d007db53b7d 100644 (file)
@@ -3607,6 +3607,14 @@ Operand 0 is the resulting vector in which the elements of the two input
 vectors are concatenated after narrowing them down using signed/unsigned
 saturating arithmetic.
 
+@cindex @code{vec_pack_sfix_trunc_@var{m}} instruction pattern
+@cindex @code{vec_pack_ufix_trunc_@var{m}} instruction pattern
+@item @samp{vec_pack_sfix_trunc_@var{m}}, @samp{vec_pack_ufix_trunc_@var{m}}
+Narrow, convert to signed/unsigned integral type and merge the elements
+of two vectors.  Operands 1 and 2 are vectors of the same mode having N
+floating point elements of size S.  Operand 0 is the resulting vector
+in which 2*N elements of size N/2 are concatenated.
+
 @cindex @code{vec_unpacks_hi_@var{m}} instruction pattern
 @cindex @code{vec_unpacks_lo_@var{m}} instruction pattern
 @item @samp{vec_unpacks_hi_@var{m}}, @samp{vec_unpacks_lo_@var{m}}
@@ -3624,11 +3632,24 @@ integral elements.  The input vector (operand 1) has N elements of size S.
 Widen (promote) the high/low elements of the vector using zero extension and
 place the resulting N/2 values of size 2*S in the output vector (operand 0).
 
+@cindex @code{vec_unpacks_float_hi_@var{m}} instruction pattern
+@cindex @code{vec_unpacks_float_lo_@var{m}} instruction pattern
+@cindex @code{vec_unpacku_float_hi_@var{m}} instruction pattern
+@cindex @code{vec_unpacku_float_lo_@var{m}} instruction pattern
+@item @samp{vec_unpacks_float_hi_@var{m}}, @samp{vec_unpacks_float_lo_@var{m}}
+@itemx @samp{vec_unpacku_float_hi_@var{m}}, @samp{vec_unpacku_float_lo_@var{m}}
+Extract, convert to floating point type and widen the high/low part of a
+vector of signed/unsigned integral elements.  The input vector (operand 1)
+has N elements of size S.  Convert the high/low elements of the vector using
+floating point conversion and place the resulting N/2 values of size 2*S in
+the output vector (operand 0).
+
 @cindex @code{vec_widen_umult_hi_@var{m}} instruction pattern
 @cindex @code{vec_widen_umult_lo__@var{m}} instruction pattern
 @cindex @code{vec_widen_smult_hi_@var{m}} instruction pattern
 @cindex @code{vec_widen_smult_lo_@var{m}} instruction pattern
-@item @samp{vec_widen_umult_hi_@var{m}}, @samp{vec_widen_umult_lo_@var{m}}, @samp{vec_widen_smult_hi_@var{m}}, @samp{vec_widen_smult_lo_@var{m}}
+@item @samp{vec_widen_umult_hi_@var{m}}, @samp{vec_widen_umult_lo_@var{m}}
+@itemx @samp{vec_widen_smult_hi_@var{m}}, @samp{vec_widen_smult_lo_@var{m}}
 Signed/Unsigned widening multiplication.  The two inputs (operands 1 and 2)
 are vectors with N signed/unsigned elements of size S.  Multiply the high/low
 elements of the two vectors, and put the N/2 products of size 2*S in the
index 846c9f696ee27accd4db499fadc3a89264325804..9286ffab7c246135d2aac44040c6a58e00645fc4 100644 (file)
@@ -9001,6 +9001,21 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        return temp;
       }
 
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+    case VEC_UNPACK_FLOAT_LO_EXPR:
+      {
+       op0 = expand_normal (TREE_OPERAND (exp, 0));
+       /* The signedness is determined from input operand.  */
+       this_optab = optab_for_tree_code (code,
+                                         TREE_TYPE (TREE_OPERAND (exp, 0)));
+       temp = expand_widen_pattern_expr
+         (exp, op0, NULL_RTX, NULL_RTX,
+          target, TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
+
+       gcc_assert (temp);
+       return temp;
+      }
+
     case VEC_WIDEN_MULT_HI_EXPR:
     case VEC_WIDEN_MULT_LO_EXPR:
       {
@@ -9016,6 +9031,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
     case VEC_PACK_TRUNC_EXPR:
     case VEC_PACK_SAT_EXPR:
+    case VEC_PACK_FIX_TRUNC_EXPR:
       {
        mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
        goto binop;
index a137750f9485c5b4883a491836f15bb975bec5a3..a16d0e17c6bc10238d83580415fce3fd0091d0c4 100644 (file)
@@ -233,9 +233,15 @@ static const char * const optabs[] =
   "vec_unpacks_lo_optab->handlers[$A].insn_code = CODE_FOR_$(vec_unpacks_lo_$a$)",
   "vec_unpacku_hi_optab->handlers[$A].insn_code = CODE_FOR_$(vec_unpacku_hi_$a$)",
   "vec_unpacku_lo_optab->handlers[$A].insn_code = CODE_FOR_$(vec_unpacku_lo_$a$)",
+  "vec_unpacks_float_hi_optab->handlers[$A].insn_code = CODE_FOR_$(vec_unpacks_float_hi_$a$)",
+  "vec_unpacks_float_lo_optab->handlers[$A].insn_code = CODE_FOR_$(vec_unpacks_float_lo_$a$)",
+  "vec_unpacku_float_hi_optab->handlers[$A].insn_code = CODE_FOR_$(vec_unpacku_float_hi_$a$)",
+  "vec_unpacku_float_lo_optab->handlers[$A].insn_code = CODE_FOR_$(vec_unpacku_float_lo_$a$)",
   "vec_pack_trunc_optab->handlers[$A].insn_code = CODE_FOR_$(vec_pack_trunc_$a$)",
   "vec_pack_ssat_optab->handlers[$A].insn_code = CODE_FOR_$(vec_pack_ssat_$a$)",
-  "vec_pack_usat_optab->handlers[$A].insn_code = CODE_FOR_$(vec_pack_usat_$a$)"
+  "vec_pack_usat_optab->handlers[$A].insn_code = CODE_FOR_$(vec_pack_usat_$a$)",
+  "vec_pack_sfix_trunc_optab->handlers[$A].insn_code = CODE_FOR_$(vec_pack_sfix_trunc_$a$)",
+  "vec_pack_ufix_trunc_optab->handlers[$A].insn_code = CODE_FOR_$(vec_pack_ufix_trunc_$a$)"
 };
 
 static void gen_insn (rtx);
index ef58aee11a8f28e45912558eccea1334d4fb25c1..d659132c1e9c1f91272d664cebd1d962ead039f0 100644 (file)
@@ -340,12 +340,26 @@ optab_for_tree_code (enum tree_code code, tree type)
       return TYPE_UNSIGNED (type) ? 
        vec_unpacku_lo_optab : vec_unpacks_lo_optab;
 
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+      /* The signedness is determined from input operand.  */
+      return TYPE_UNSIGNED (type) ?
+       vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
+
+    case VEC_UNPACK_FLOAT_LO_EXPR:
+      /* The signedness is determined from input operand.  */
+      return TYPE_UNSIGNED (type) ? 
+       vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
+
     case VEC_PACK_TRUNC_EXPR:
       return vec_pack_trunc_optab;
 
     case VEC_PACK_SAT_EXPR:
       return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
 
+    case VEC_PACK_FIX_TRUNC_EXPR:
+      return TYPE_UNSIGNED (type) ?
+       vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
+
     default:
       break;
     }
@@ -1375,7 +1389,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       if (binoptab == vec_pack_trunc_optab 
          || binoptab == vec_pack_usat_optab
-          || binoptab == vec_pack_ssat_optab)
+         || binoptab == vec_pack_ssat_optab
+         || binoptab == vec_pack_ufix_trunc_optab
+         || binoptab == vec_pack_sfix_trunc_optab)
        {
          /* The mode of the result is different then the mode of the
             arguments.  */
@@ -5565,9 +5581,15 @@ init_optabs (void)
   vec_unpacks_lo_optab = init_optab (UNKNOWN);
   vec_unpacku_hi_optab = init_optab (UNKNOWN);
   vec_unpacku_lo_optab = init_optab (UNKNOWN);
+  vec_unpacks_float_hi_optab = init_optab (UNKNOWN);
+  vec_unpacks_float_lo_optab = init_optab (UNKNOWN);
+  vec_unpacku_float_hi_optab = init_optab (UNKNOWN);
+  vec_unpacku_float_lo_optab = init_optab (UNKNOWN);
   vec_pack_trunc_optab = init_optab (UNKNOWN);
   vec_pack_usat_optab = init_optab (UNKNOWN);
   vec_pack_ssat_optab = init_optab (UNKNOWN);
+  vec_pack_ufix_trunc_optab = init_optab (UNKNOWN);
+  vec_pack_sfix_trunc_optab = init_optab (UNKNOWN);
 
   powi_optab = init_optab (UNKNOWN);
 
index 60dcc159729df4c3a881ce7362097a66fcb631b2..7df2669e2ae1cf401e691dd82ac05539bc846b16 100644 (file)
@@ -298,11 +298,24 @@ enum optab_index
      elements.  */
   OTI_vec_unpacku_hi,
   OTI_vec_unpacku_lo,
+
+  /* Extract, convert to floating point and widen the high/low part of
+     a vector of signed or unsigned integer elements.  */
+  OTI_vec_unpacks_float_hi,
+  OTI_vec_unpacks_float_lo,
+  OTI_vec_unpacku_float_hi,
+  OTI_vec_unpacku_float_lo,
+
   /* Narrow (demote) and merge the elements of two vectors.  */
   OTI_vec_pack_trunc,
   OTI_vec_pack_usat,
   OTI_vec_pack_ssat,
 
+  /* Convert to signed/unsigned integer, narrow and merge elements
+     of two vectors of floating point elements.  */
+  OTI_vec_pack_sfix_trunc,
+  OTI_vec_pack_ufix_trunc,
+
   /* Perform a raise to the power of integer.  */
   OTI_powi,
 
@@ -446,9 +459,15 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define vec_unpacks_lo_optab (optab_table[OTI_vec_unpacks_lo])
 #define vec_unpacku_hi_optab (optab_table[OTI_vec_unpacku_hi])
 #define vec_unpacku_lo_optab (optab_table[OTI_vec_unpacku_lo])
+#define vec_unpacks_float_hi_optab (optab_table[OTI_vec_unpacks_float_hi])
+#define vec_unpacks_float_lo_optab (optab_table[OTI_vec_unpacks_float_lo])
+#define vec_unpacku_float_hi_optab (optab_table[OTI_vec_unpacku_float_hi])
+#define vec_unpacku_float_lo_optab (optab_table[OTI_vec_unpacku_float_lo])
 #define vec_pack_trunc_optab (optab_table[OTI_vec_pack_trunc])
 #define vec_pack_ssat_optab (optab_table[OTI_vec_pack_ssat])
 #define vec_pack_usat_optab (optab_table[OTI_vec_pack_usat])
+#define vec_pack_sfix_trunc_optab (optab_table[OTI_vec_pack_sfix_trunc])
+#define vec_pack_ufix_trunc_optab (optab_table[OTI_vec_pack_ufix_trunc])
 
 #define powi_optab (optab_table[OTI_powi])
 
index 8d4c6ca204c49bcd58bcea2565cd473d6d91f36c..2c0203004365403b9807fea13a14b797d95cfed6 100644 (file)
@@ -1,3 +1,16 @@
+2007-05-17  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR tree-optimization/24659
+       * gcc.dg/vect/vect-floatint-conversion-2.c: New test.
+       * gcc.dg/vect/vect-intfloat-conversion-1.c: Require vect_float,
+       not vect_int target.
+       * gcc.dg/vect/vect-intfloat-conversion-2.c: Require vect_float,
+       not vect_int target.  Loop is vectorized for vect_intfloat_cvt
+       targets.
+       * gcc.dg/vect/vect-intfloat-conversion-3.c: New test.
+       * gcc.dg/vect/vect-intfloat-conversion-4a.c: New test.
+       * gcc.dg/vect/vect-intfloat-conversion-4b.c: New test.
+
 2007-05-16  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.dg/torture/fp-int-convert-float128.c: Do not xfail for i?86-*-*
        * g++.dg/expr/bitfield8.C: New test.
 
 2007-04-17  Joseph Myers  <joseph@codesourcery.com>
-            Richard Sandiford  <richard@codesourcery.com>
+           Richard Sandiford  <richard@codesourcery.com>
 
        * lib/target-supports.exp (check_profiling_available): Return 0
        for uClibc with -p or -pg.
diff --git a/gcc/testsuite/gcc.dg/vect/vect-floatint-conversion-2.c b/gcc/testsuite/gcc.dg/vect/vect-floatint-conversion-2.c
new file mode 100644 (file)
index 0000000..5d115ff
--- /dev/null
@@ -0,0 +1,40 @@
+/* { dg-require-effective-target vect_double } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 32
+
+int
+main1 ()
+{
+  int i;
+  double db[N] = {0.4,3.5,6.6,9.4,12.5,15.6,18.4,21.5,24.6,27.4,30.5,33.6,36.4,39.5,42.6,45.4,0.5,3.6,6.4,9.5,12.6,15.4,18.5,21.6,24.4,27.5,30.6,33.4,36.5,39.6,42.4,45.5};
+  int ia[N];
+
+  /* double -> int */
+  for (i = 0; i < N; i++)
+    {
+      ia[i] = (int) db[i];
+    }
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    {
+      if (ia[i] != (int) db[i])
+       abort ();
+    }
+
+  return 0;
+}
+
+int
+main (void)
+{
+  check_vect ();
+
+  return main1 ();
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_floatint_cvt } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
index 85a993a34c889778c218c93e96a4de135b98521d..48f91d903b34c8eae7c4807b9d0ecccdc86d14ba 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_float } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
index c189e54ca7df17b854956613a117b86251e2d0fd..0723f8af810eef13d4905f8f0a89bc188e025cc2 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_float } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -36,5 +36,5 @@ int main (void)
   return main1 ();
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target powerpc*-*-* i?86-*-* x86_64-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_intfloat_cvt } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-3.c b/gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-3.c
new file mode 100644 (file)
index 0000000..e496e40
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-require-effective-target vect_double } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 32
+
+int main1 ()
+{
+  int i;
+  int ib[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45};
+  double da[N];
+
+  /* int -> double */
+  for (i = 0; i < N; i++)
+    {
+      da[i] = (double) ib[i];  
+    }
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    {
+      if (da[i] != (double) ib[i]) 
+        abort (); 
+    }   
+
+  return 0;
+}
+
+int main (void)
+{ 
+  check_vect ();
+  
+  return main1 ();
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_intfloat_cvt } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-4a.c b/gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-4a.c
new file mode 100644 (file)
index 0000000..e34f345
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-require-effective-target vect_float } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 32
+
+int main1 ()
+{
+  int i;
+  short sb[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,0,-3,-6,-9,-12,-15,-18,-21,-24,-27,-30,-33,-36,-39,-42,-45};
+  float fa[N];
+
+  /* short -> float */
+  for (i = 0; i < N; i++)
+    {
+      fa[i] = (float) sb[i];   
+    }
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    {
+      if (fa[i] != (float) sb[i]) 
+        abort (); 
+    }   
+
+  return 0;
+}
+
+int main (void)
+{ 
+  check_vect ();
+  
+  return main1 ();
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_intfloat_cvt } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-4b.c b/gcc/testsuite/gcc.dg/vect/vect-intfloat-conversion-4b.c
new file mode 100644 (file)
index 0000000..72e7bf6
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-require-effective-target vect_float } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 32
+
+int main1 ()
+{
+  int i;
+  unsigned short usb[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,0,65533,65530,65527,65524,65521,65518,65515,65512,65509,65506,65503,65500,65497,65494,65491};
+  float fa[N];
+
+  /* unsigned short -> float */
+  for (i = 0; i < N; i++)
+    {
+      fa[i] = (float) usb[i];  
+    }
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    {
+      if (fa[i] != (float) usb[i]) 
+        abort (); 
+    }   
+
+  return 0;
+}
+
+int main (void)
+{ 
+  check_vect ();
+  
+  return main1 ();
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_intfloat_cvt } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
index a6dfc683d59e250b5405aca3a35c96a0504edd0d..799b4f3fb6e3abc55bd9defbc8d91e861daa3275 100644 (file)
@@ -2148,8 +2148,11 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case VEC_WIDEN_MULT_LO_EXPR:
     case VEC_UNPACK_HI_EXPR:
     case VEC_UNPACK_LO_EXPR:
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+    case VEC_UNPACK_FLOAT_LO_EXPR:
     case VEC_PACK_TRUNC_EXPR:
     case VEC_PACK_SAT_EXPR:
+    case VEC_PACK_FIX_TRUNC_EXPR:
 
     case WIDEN_MULT_EXPR:
 
index 09d203fa29b1733ed42b0ebcf19e739815048fc8..991b1e11654c967532cbbe99e6f5d4163800a162 100644 (file)
@@ -1943,6 +1943,18 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_string (buffer, " > ");
       break;
 
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+      pp_string (buffer, " VEC_UNPACK_FLOAT_HI_EXPR < ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_string (buffer, " > ");
+      break;
+
+    case VEC_UNPACK_FLOAT_LO_EXPR:
+      pp_string (buffer, " VEC_UNPACK_FLOAT_LO_EXPR < ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_string (buffer, " > ");
+      break;
+
     case VEC_PACK_TRUNC_EXPR:
       pp_string (buffer, " VEC_PACK_TRUNC_EXPR < ");
       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
@@ -1950,7 +1962,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
       pp_string (buffer, " > ");
       break;
-                                                                                
+
     case VEC_PACK_SAT_EXPR:
       pp_string (buffer, " VEC_PACK_SAT_EXPR < ");
       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
@@ -1958,7 +1970,15 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
       pp_string (buffer, " > ");
       break;
-                                                                                
+
+    case VEC_PACK_FIX_TRUNC_EXPR:
+      pp_string (buffer, " VEC_PACK_FIX_TRUNC_EXPR < ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_string (buffer, ", ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+      pp_string (buffer, " > ");
+      break;
+
     case BLOCK:
       {
        tree t;
@@ -2352,6 +2372,8 @@ op_prio (tree op)
     case VEC_RSHIFT_EXPR:
     case VEC_UNPACK_HI_EXPR:
     case VEC_UNPACK_LO_EXPR:
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+    case VEC_UNPACK_FLOAT_LO_EXPR:
     case VEC_PACK_TRUNC_EXPR:
     case VEC_PACK_SAT_EXPR:
       return 16;
index 0b9b91f6d9adaac22beb5564a4831303febb212e..e955c44743cec86c9ae2bb15775e45b4a344b898 100644 (file)
@@ -421,8 +421,11 @@ expand_vector_operations_1 (block_stmt_iterator *bsi)
       || code == VEC_WIDEN_MULT_LO_EXPR
       || code == VEC_UNPACK_HI_EXPR
       || code == VEC_UNPACK_LO_EXPR
+      || code == VEC_UNPACK_FLOAT_HI_EXPR
+      || code == VEC_UNPACK_FLOAT_LO_EXPR
       || code == VEC_PACK_TRUNC_EXPR
-      || code == VEC_PACK_SAT_EXPR)
+      || code == VEC_PACK_SAT_EXPR
+      || code == VEC_PACK_FIX_TRUNC_EXPR)
     type = TREE_TYPE (TREE_OPERAND (rhs, 0));
 
   /* Optabs will try converting a negation into a subtraction, so
index 875731da3606fe0f8db2e4625aa915e18946dbf0..30e7211354cfb33bbec09becac048e59b78bb406 100644 (file)
@@ -210,7 +210,7 @@ vect_create_addr_base_for_vector_ref (tree stmt,
    accessed in the loop by STMT, along with the def-use update chain to 
    appropriately advance the pointer through the loop iterations. Also set
    aliasing information for the pointer.  This vector pointer is used by the
-   callers to this function to create a memory reference expression for vector 
+   callers to this function to create a memory reference expression for vector
    load/store access.
 
    Input:
@@ -1931,6 +1931,64 @@ vectorizable_call (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
 }
 
 
+/* Function vect_gen_widened_results_half
+
+   Create a vector stmt whose code, type, number of arguments, and result
+   variable are CODE, VECTYPE, OP_TYPE, and VEC_DEST, and its arguments are 
+   VEC_OPRND0 and VEC_OPRND1. The new vector stmt is to be inserted at BSI.
+   In the case that CODE is a CALL_EXPR, this means that a call to DECL
+   needs to be created (DECL is a function-decl of a target-builtin).
+   STMT is the original scalar stmt that we are vectorizing.  */
+
+static tree
+vect_gen_widened_results_half (enum tree_code code, tree vectype, tree decl,
+                               tree vec_oprnd0, tree vec_oprnd1, int op_type,
+                               tree vec_dest, block_stmt_iterator *bsi,
+                              tree stmt)
+{ 
+  tree expr; 
+  tree new_stmt; 
+  tree new_temp; 
+  tree sym; 
+  ssa_op_iter iter;
+  /* Generate half of the widened result:  */ 
+  if (code == CALL_EXPR) 
+    {  
+      /* Target specific support  */ 
+      if (op_type == binary_op)
+       expr = build_call_expr (decl, 2, vec_oprnd0, vec_oprnd1);
+      else
+       expr = build_call_expr (decl, 1, vec_oprnd0);
+    } 
+  else 
+    { 
+      /* Generic support */ 
+      gcc_assert (op_type == TREE_CODE_LENGTH (code)); 
+      if (op_type == binary_op) 
+        expr = build2 (code, vectype, vec_oprnd0, vec_oprnd1); 
+      else  
+        expr = build1 (code, vectype, vec_oprnd0); 
+    } 
+  new_stmt = build_gimple_modify_stmt (vec_dest, expr);
+  new_temp = make_ssa_name (vec_dest, new_stmt); 
+  GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp; 
+  vect_finish_stmt_generation (stmt, new_stmt, bsi); 
+
+  if (code == CALL_EXPR)
+    {
+      FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, SSA_OP_ALL_VIRTUALS)
+        {
+          if (TREE_CODE (sym) == SSA_NAME)
+            sym = SSA_NAME_VAR (sym);
+          mark_sym_for_renaming (sym);
+        }
+    }
+
+  return new_stmt;
+}
+
+
 /* Function vectorizable_conversion.
 
 Check if STMT performs a conversion operation, that can be vectorized. 
@@ -1946,21 +2004,24 @@ vectorizable_conversion (tree stmt, block_stmt_iterator * bsi,
   tree scalar_dest;
   tree operation;
   tree op0;
-  tree vec_oprnd0 = NULL_TREE;
+  tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
-  enum tree_code code;
+  enum tree_code code, code1 = CODE_FOR_nothing, code2 = CODE_FOR_nothing;
+  tree decl1 = NULL_TREE, decl2 = NULL_TREE;
   tree new_temp;
   tree def, def_stmt;
   enum vect_def_type dt0;
   tree new_stmt;
+  stmt_vec_info prev_stmt_info;
   int nunits_in;
   int nunits_out;
-  int ncopies, j;
   tree vectype_out, vectype_in;
+  int ncopies, j;
+  tree expr;
   tree rhs_type, lhs_type;
   tree builtin_decl;
-  stmt_vec_info prev_stmt_info;
+  enum { NARROW, NONE, WIDEN } modifier;
 
   /* Is STMT a vectorizable conversion?   */
 
@@ -1998,23 +2059,36 @@ vectorizable_conversion (tree stmt, block_stmt_iterator * bsi,
   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
   lhs_type = TREE_TYPE (scalar_dest);
   vectype_out = get_vectype_for_scalar_type (lhs_type);
-  gcc_assert (STMT_VINFO_VECTYPE (stmt_info) == vectype_out);
   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
 
-  /* FORNOW: need to extend to support short<->float conversions as well.  */
-  if (nunits_out != nunits_in)
+  /* FORNOW */
+  if (nunits_in == nunits_out / 2)
+    modifier = NARROW;
+  else if (nunits_out == nunits_in)
+    modifier = NONE;
+  else if (nunits_out == nunits_in / 2)
+    modifier = WIDEN;
+  else
     return false;
 
+  if (modifier == NONE)
+    gcc_assert (STMT_VINFO_VECTYPE (stmt_info) == vectype_out);
+
   /* Bail out if the types are both integral or non-integral */
   if ((INTEGRAL_TYPE_P (rhs_type) && INTEGRAL_TYPE_P (lhs_type))
       || (!INTEGRAL_TYPE_P (rhs_type) && !INTEGRAL_TYPE_P (lhs_type)))
     return false;
 
+  if (modifier == NARROW)
+    ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
+  else
+    ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
+
   /* Sanity check: make sure that at least one copy of the vectorized stmt
      needs to be generated.  */
-  ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
   gcc_assert (ncopies >= 1);
 
+  /* Check the operands of the operation.  */
   if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt0))
     {
       if (vect_print_dump_info (REPORT_DETAILS))
@@ -2023,21 +2097,31 @@ vectorizable_conversion (tree stmt, block_stmt_iterator * bsi,
     }
 
   /* Supportable by target?  */
-  if (!targetm.vectorize.builtin_conversion (code, vectype_in))
+  if ((modifier == NONE
+       && !targetm.vectorize.builtin_conversion (code, vectype_in))
+      || (modifier == WIDEN
+         && !supportable_widening_operation (code, stmt, vectype_in,
+                                             &decl1, &decl2,
+                                             &code1, &code2))
+      || (modifier == NARROW
+         && !supportable_narrowing_operation (code, stmt, vectype_in,
+                                              &code1)))
     {
       if (vect_print_dump_info (REPORT_DETAILS))
         fprintf (vect_dump, "op not supported by target.");
       return false;
     }
 
+  if (modifier != NONE)
+    STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
+
   if (!vec_stmt)               /* transformation not required.  */
     {
       STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
       return true;
     }
 
-    /** Transform.  **/
-
+  /** Transform.  **/
   if (vect_print_dump_info (REPORT_DETAILS))
     fprintf (vect_dump, "transform conversion.");
 
@@ -2045,37 +2129,113 @@ vectorizable_conversion (tree stmt, block_stmt_iterator * bsi,
   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
 
   prev_stmt_info = NULL;
-  for (j = 0; j < ncopies; j++)
+  switch (modifier)
     {
-      tree sym;
-      ssa_op_iter iter;
+    case NONE:
+      for (j = 0; j < ncopies; j++)
+       {
+         tree sym;
+         ssa_op_iter iter;
 
-      if (j == 0)
-       vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
-      else
-       vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd0);
+         if (j == 0)
+           vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
+         else
+           vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd0);
 
-      builtin_decl =
-       targetm.vectorize.builtin_conversion (code, vectype_in);
-      new_stmt = build_call_expr (builtin_decl, 1, vec_oprnd0);
+         builtin_decl =
+           targetm.vectorize.builtin_conversion (code, vectype_in);
+         new_stmt = build_call_expr (builtin_decl, 1, vec_oprnd0);
 
-      /* Arguments are ready. create the new vector stmt.  */
-      new_stmt = build_gimple_modify_stmt (vec_dest, new_stmt);
-      new_temp = make_ssa_name (vec_dest, new_stmt);
-      GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
-      vect_finish_stmt_generation (stmt, new_stmt, bsi);
-      FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, SSA_OP_ALL_VIRTUALS)
-        {
-          if (TREE_CODE (sym) == SSA_NAME)
-            sym = SSA_NAME_VAR (sym);
-          mark_sym_for_renaming (sym);
-        }
+         /* Arguments are ready. create the new vector stmt.  */
+         new_stmt = build_gimple_modify_stmt (vec_dest, new_stmt);
+         new_temp = make_ssa_name (vec_dest, new_stmt);
+         GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
+         vect_finish_stmt_generation (stmt, new_stmt, bsi);
+         FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, SSA_OP_ALL_VIRTUALS)
+           {
+             if (TREE_CODE (sym) == SSA_NAME)
+               sym = SSA_NAME_VAR (sym);
+             mark_sym_for_renaming (sym);
+           }
 
-      if (j == 0)
-       STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
-      else
-       STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
-      prev_stmt_info = vinfo_for_stmt (new_stmt);
+         if (j == 0)
+           STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+         else
+           STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+         prev_stmt_info = vinfo_for_stmt (new_stmt);
+       }
+      break;
+
+    case WIDEN:
+      /* In case the vectorization factor (VF) is bigger than the number
+        of elements that we can fit in a vectype (nunits), we have to
+        generate more than one vector stmt - i.e - we need to "unroll"
+        the vector stmt by a factor VF/nunits.  */
+      for (j = 0; j < ncopies; j++)
+       {
+         if (j == 0)
+           vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
+         else
+           vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd0);
+
+         STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
+
+         /* Generate first half of the widened result:  */
+         new_stmt
+           = vect_gen_widened_results_half (code1, vectype_out, decl1, 
+                                            vec_oprnd0, vec_oprnd1,
+                                            unary_op, vec_dest, bsi, stmt);
+         if (j == 0)
+           STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
+         else
+           STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+         prev_stmt_info = vinfo_for_stmt (new_stmt);
+
+         /* Generate second half of the widened result:  */
+         new_stmt
+           = vect_gen_widened_results_half (code2, vectype_out, decl2,
+                                            vec_oprnd0, vec_oprnd1,
+                                            unary_op, vec_dest, bsi, stmt);
+         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+         prev_stmt_info = vinfo_for_stmt (new_stmt);
+       }
+      break;
+
+    case NARROW:
+      /* In case the vectorization factor (VF) is bigger than the number
+        of elements that we can fit in a vectype (nunits), we have to
+        generate more than one vector stmt - i.e - we need to "unroll"
+        the vector stmt by a factor VF/nunits.  */
+      for (j = 0; j < ncopies; j++)
+       {
+         /* Handle uses.  */
+         if (j == 0)
+           {
+             vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
+             vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd0);
+           }
+         else
+           {
+             vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd1);
+             vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd0);
+           }
+
+         /* Arguments are ready. Create the new vector stmt.  */
+         expr = build2 (code1, vectype_out, vec_oprnd0, vec_oprnd1);
+         new_stmt = build_gimple_modify_stmt (vec_dest, expr);
+         new_temp = make_ssa_name (vec_dest, new_stmt);
+         GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
+         vect_finish_stmt_generation (stmt, new_stmt, bsi);
+
+         if (j == 0)
+           STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
+         else
+           STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+
+         prev_stmt_info = vinfo_for_stmt (new_stmt);
+       }
+
+      *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
     }
   return true;
 }
@@ -2525,7 +2685,7 @@ vectorizable_operation (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
 
 bool
 vectorizable_type_demotion (tree stmt, block_stmt_iterator *bsi,
-                             tree *vec_stmt)
+                           tree *vec_stmt)
 {
   tree vec_dest;
   tree scalar_dest;
@@ -2534,7 +2694,7 @@ vectorizable_type_demotion (tree stmt, block_stmt_iterator *bsi,
   tree vec_oprnd0=NULL, vec_oprnd1=NULL;
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
-  enum tree_code code;
+  enum tree_code code, code1 = CODE_FOR_nothing;
   tree new_temp;
   tree def, def_stmt;
   enum vect_def_type dt0;
@@ -2548,8 +2708,6 @@ vectorizable_type_demotion (tree stmt, block_stmt_iterator *bsi,
   tree expr;
   tree vectype_in;
   tree scalar_type;
-  optab optab;
-  enum machine_mode vec_mode;
 
   if (!STMT_VINFO_RELEVANT_P (stmt_info))
     return false;
@@ -2607,13 +2765,7 @@ vectorizable_type_demotion (tree stmt, block_stmt_iterator *bsi,
     }
 
   /* Supportable by target?  */
-  code = VEC_PACK_TRUNC_EXPR;
-  optab = optab_for_tree_code (code, vectype_in);
-  if (!optab)
-    return false;
-
-  vec_mode = TYPE_MODE (vectype_in);
-  if (optab->handlers[(int) vec_mode].insn_code == CODE_FOR_nothing)
+  if (!supportable_narrowing_operation (code, stmt, vectype_in, &code1))
     return false;
 
   STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
@@ -2652,7 +2804,7 @@ vectorizable_type_demotion (tree stmt, block_stmt_iterator *bsi,
        }
 
       /* Arguments are ready. Create the new vector stmt.  */
-      expr = build2 (code, vectype_out, vec_oprnd0, vec_oprnd1);
+      expr = build2 (code1, vectype_out, vec_oprnd0, vec_oprnd1);
       new_stmt = build_gimple_modify_stmt (vec_dest, expr);
       new_temp = make_ssa_name (vec_dest, new_stmt);
       GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
@@ -2671,64 +2823,6 @@ vectorizable_type_demotion (tree stmt, block_stmt_iterator *bsi,
 }
 
 
-/* Function vect_gen_widened_results_half
-
-   Create a vector stmt whose code, type, number of arguments, and result
-   variable are CODE, VECTYPE, OP_TYPE, and VEC_DEST, and its arguments are 
-   VEC_OPRND0 and VEC_OPRND1. The new vector stmt is to be inserted at BSI.
-   In the case that CODE is a CALL_EXPR, this means that a call to DECL
-   needs to be created (DECL is a function-decl of a target-builtin).
-   STMT is the original scalar stmt that we are vectorizing.  */
-
-static tree
-vect_gen_widened_results_half (enum tree_code code, tree vectype, tree decl,
-                               tree vec_oprnd0, tree vec_oprnd1, int op_type,
-                               tree vec_dest, block_stmt_iterator *bsi,
-                              tree stmt)
-{ 
-  tree expr; 
-  tree new_stmt; 
-  tree new_temp; 
-  tree sym; 
-  ssa_op_iter iter;
-  /* Generate half of the widened result:  */ 
-  if (code == CALL_EXPR) 
-    {  
-      /* Target specific support  */ 
-      if (op_type == binary_op)
-       expr = build_call_expr (decl, 2, vec_oprnd0, vec_oprnd1);
-      else
-       expr = build_call_expr (decl, 1, vec_oprnd0);
-    } 
-  else 
-    { 
-      /* Generic support */ 
-      gcc_assert (op_type == TREE_CODE_LENGTH (code)); 
-      if (op_type == binary_op) 
-        expr = build2 (code, vectype, vec_oprnd0, vec_oprnd1); 
-      else  
-        expr = build1 (code, vectype, vec_oprnd0); 
-    } 
-  new_stmt = build_gimple_modify_stmt (vec_dest, expr);
-  new_temp = make_ssa_name (vec_dest, new_stmt); 
-  GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp; 
-  vect_finish_stmt_generation (stmt, new_stmt, bsi); 
-
-  if (code == CALL_EXPR)
-    {
-      FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, SSA_OP_ALL_VIRTUALS)
-        {
-          if (TREE_CODE (sym) == SSA_NAME)
-            sym = SSA_NAME_VAR (sym);
-          mark_sym_for_renaming (sym);
-        }
-    }
-
-  return new_stmt;
-}
-
-
 /* Function vectorizable_type_promotion
 
    Check if STMT performs a binary or unary operation that involves
@@ -2785,7 +2879,8 @@ vectorizable_type_promotion (tree stmt, block_stmt_iterator *bsi,
 
   operation = GIMPLE_STMT_OPERAND (stmt, 1);
   code = TREE_CODE (operation);
-  if (code != NOP_EXPR && code != WIDEN_MULT_EXPR)
+  if (code != NOP_EXPR && code != CONVERT_EXPR
+      && code != WIDEN_MULT_EXPR)
     return false;
 
   op0 = TREE_OPERAND (operation, 0);
index fc501261591e3db214513ba66c6066eb1c22867f..df884f4224236d550f11d94ad2125a0d59483b80 100644 (file)
@@ -1736,10 +1736,10 @@ vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, tree *def_stmt,
    widening operation that is supported by the target platform in 
    vector form (i.e., when operating on arguments of type VECTYPE).
     
-   The two kinds of widening operations we currently support are
-   NOP and WIDEN_MULT. This function checks if these operations
-   are supported by the target platform either directly (via vector 
-   tree-codes), or via target builtins.
+   Widening operations we currently support are NOP (CONVERT), FLOAT
+   and WIDEN_MULT.  This function checks if these operations are supported
+   by the target platform either directly (via vector tree-codes), or via
+   target builtins.
 
    Output:
    - CODE1 and CODE2 are codes of vector operations to be used when 
@@ -1815,6 +1815,7 @@ supportable_widening_operation (enum tree_code code, tree stmt, tree vectype,
       break;
 
     case NOP_EXPR:
+    case CONVERT_EXPR:
       if (BYTES_BIG_ENDIAN)
         {
           c1 = VEC_UNPACK_HI_EXPR;
@@ -1827,6 +1828,19 @@ supportable_widening_operation (enum tree_code code, tree stmt, tree vectype,
         }
       break;
 
+    case FLOAT_EXPR:
+      if (BYTES_BIG_ENDIAN)
+        {
+          c1 = VEC_UNPACK_FLOAT_HI_EXPR;
+          c2 = VEC_UNPACK_FLOAT_LO_EXPR;
+        }
+      else
+        {
+          c2 = VEC_UNPACK_FLOAT_HI_EXPR;
+          c1 = VEC_UNPACK_FLOAT_LO_EXPR;
+        }
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -1851,6 +1865,63 @@ supportable_widening_operation (enum tree_code code, tree stmt, tree vectype,
 }
 
 
+/* Function supportable_narrowing_operation
+
+   Check whether an operation represented by the code CODE is a 
+   narrowing operation that is supported by the target platform in 
+   vector form (i.e., when operating on arguments of type VECTYPE).
+    
+   Narrowing operations we currently support are NOP (CONVERT) and
+   FIX_TRUNC. This function checks if these operations are supported by
+   the target platform directly via vector tree-codes.
+
+   Output:
+   - CODE1 is the code of a vector operation to be used when 
+   vectorizing the operation, if available.  */
+
+bool
+supportable_narrowing_operation (enum tree_code code,
+                                tree stmt, tree vectype,
+                                enum tree_code *code1)
+{
+  enum machine_mode vec_mode;
+  enum insn_code icode1;
+  optab optab1;
+  tree expr = GIMPLE_STMT_OPERAND (stmt, 1);
+  tree type = TREE_TYPE (expr);
+  tree narrow_vectype = get_vectype_for_scalar_type (type);
+  enum tree_code c1;
+
+  switch (code)
+    {
+    case NOP_EXPR:
+    case CONVERT_EXPR:
+      c1 = VEC_PACK_TRUNC_EXPR;
+      break;
+
+    case FIX_TRUNC_EXPR:
+      c1 = VEC_PACK_FIX_TRUNC_EXPR;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  *code1 = c1;
+  optab1 = optab_for_tree_code (c1, vectype);
+
+  if (!optab1)
+    return false;
+
+  vec_mode = TYPE_MODE (vectype);
+  if ((icode1 = optab1->handlers[(int) vec_mode].insn_code) == CODE_FOR_nothing
+      || insn_data[icode1].operand[0].mode != TYPE_MODE (narrow_vectype))
+    return false;
+
+  return true;
+}
+
+
 /* Function reduction_code_for_scalar_code
 
    Input:
index 8d80aeb2ba705457f7abfec70fcb9b595a8b6287..dd8e2b8ad56dd89ea276e408bf370c2404b19ee4 100644 (file)
@@ -398,6 +398,9 @@ extern enum dr_alignment_support vect_supportable_dr_alignment
 extern bool reduction_code_for_scalar_code (enum tree_code, enum tree_code *);
 extern bool supportable_widening_operation (enum tree_code, tree, tree,
   tree *, tree *, enum tree_code *, enum tree_code *);
+extern bool supportable_narrowing_operation (enum tree_code, tree, tree,
+                                            enum tree_code *);
+
 /* Creation and deletion of loop and stmt info structs.  */
 extern loop_vec_info new_loop_vec_info (struct loop *loop);
 extern void destroy_loop_vec_info (loop_vec_info);
index feeab3fce1fe4491d5939e0637d715724f713ddf..e1f5fef063e03424d3910cb132dbf94310cd01d0 100644 (file)
@@ -1085,13 +1085,20 @@ DEFTREECODE (GIMPLE_MODIFY_STMT, "gimple_modify_stmt", tcc_gimple_stmt, 2)
 DEFTREECODE (VEC_WIDEN_MULT_HI_EXPR, "widen_mult_hi_expr", tcc_binary, 2)
 DEFTREECODE (VEC_WIDEN_MULT_LO_EXPR, "widen_mult_hi_expr", tcc_binary, 2)
 
-/* Unpack (extract and promote/widen) the high/low elements of the input vector
-   into the output vector. The input vector has twice as many elements
-   as the output vector, that are half the size of the elements
+/* Unpack (extract and promote/widen) the high/low elements of the input
+   vector into the output vector.  The input vector has twice as many
+   elements as the output vector, that are half the size of the elements
    of the output vector.  This is used to support type promotion. */
 DEFTREECODE (VEC_UNPACK_HI_EXPR, "vec_unpack_hi_expr", tcc_unary, 1)
 DEFTREECODE (VEC_UNPACK_LO_EXPR, "vec_unpack_lo_expr", tcc_unary, 1)
 
+/* Unpack (extract) the high/low elements of the input vector, convert
+   fixed point values to floating point and widen elements into the
+   output vector.  The input vector has twice as many elements as the output
+   vector, that are half the size of the elements of the output vector.  */
+DEFTREECODE (VEC_UNPACK_FLOAT_HI_EXPR, "vec_unpack_float_hi_expr", tcc_unary, 1)
+DEFTREECODE (VEC_UNPACK_FLOAT_LO_EXPR, "vec_unpack_float_lo_expr", tcc_unary, 1)
+
 /* Pack (demote/narrow and merge) the elements of the two input vectors
    into the output vector using truncation/saturation.
    The elements of the input vectors are twice the size of the elements of the
@@ -1099,6 +1106,12 @@ DEFTREECODE (VEC_UNPACK_LO_EXPR, "vec_unpack_lo_expr", tcc_unary, 1)
 DEFTREECODE (VEC_PACK_TRUNC_EXPR, "vec_pack_trunc_expr", tcc_binary, 2)
 DEFTREECODE (VEC_PACK_SAT_EXPR, "vec_pack_sat_expr", tcc_binary, 2)
 
+/* Convert floating point values of the two input vectors to integer
+   and pack (narrow and merge) the elements into the output vector. The
+   elements of the input vector are twice the size of the elements of
+   the output vector.  */
+DEFTREECODE (VEC_PACK_FIX_TRUNC_EXPR, "vec_pack_fix_trunc_expr", tcc_binary, 2)
+
 /* Extract even/odd fields from vectors.  */
 DEFTREECODE (VEC_EXTRACT_EVEN_EXPR, "vec_extracteven_expr", tcc_binary, 2)
 DEFTREECODE (VEC_EXTRACT_ODD_EXPR, "vec_extractodd_expr", tcc_binary, 2)