* doc/tm.texi (TARGET_VECTORIZE_BUILTIN_CONVERSION): New target hook.
authordorit <dorit@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 11 Feb 2007 11:46:07 +0000 (11:46 +0000)
committerdorit <dorit@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 11 Feb 2007 11:46:07 +0000 (11:46 +0000)
        * targhooks.c (default_builtin_vectorized_conversion): New.
        * targhooks.h (default_builtin_vectorized_function): New declaration.
        * target.h (struct vectorize): Add builtin_conversion field.
        * tree-vectorizer.h (type_conversion_vec_info_type): New enum
        stmt_vec_info_type value.
        (vectorizable_conversion): New declaration.
        * tree-vect-analyze.c (vect_analyze_operations): Add
        vectorizable_conversion call.
        * target-def.h (TARGET_VECTORIZE_BUILTIN_CONVERSION): New.
        * tree-vect-transform.c (vectorizable_conversion): New function.
        (vect_transform_stmt): Add case for type_conversion_vec_info_type.
        * tree-vect-generic.c (expand_vector_operations_1): Consider correct
        mode.
        * config/rs6000/rs6000.c (rs6000_builtin_conversion): New.
        (TARGET_VECTORIZE_BUILTIN_CONVERSION): Defined.
        (rs6000_expand_builtin): Add handling a case of ALTIVEC_BUILTIN_VCFUX or
        ALTIVEC_BUILTIN_VCFSX.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121818 138bc75d-0d04-0410-961f-82ee72b054a4

15 files changed:
gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/doc/tm.texi
gcc/target-def.h
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-113.c
gcc/testsuite/gcc.dg/vect/vect-93.c
gcc/testsuite/gcc.dg/vect/vect-iv-11.c
gcc/tree-vect-analyze.c
gcc/tree-vect-generic.c
gcc/tree-vect-transform.c
gcc/tree-vectorizer.h

index a0078e3..c7fce63 100644 (file)
@@ -1,3 +1,26 @@
+2007-02-11  Tehila Meyzels  <tehila@il.ibm.com>
+           Ira Rosen  <irar@il.ibm.com>
+           Dorit Nuzman  <dorit@il.ibm.com>
+
+       * doc/tm.texi (TARGET_VECTORIZE_BUILTIN_CONVERSION): New target hook.
+       * targhooks.c (default_builtin_vectorized_conversion): New.
+       * targhooks.h (default_builtin_vectorized_function): New declaration.
+       * target.h (struct vectorize): Add builtin_conversion field.
+       * tree-vectorizer.h (type_conversion_vec_info_type): New enum
+       stmt_vec_info_type value.
+       (vectorizable_conversion): New declaration.
+       * tree-vect-analyze.c (vect_analyze_operations): Add
+       vectorizable_conversion call.
+       * target-def.h (TARGET_VECTORIZE_BUILTIN_CONVERSION): New.
+       * tree-vect-transform.c (vectorizable_conversion): New function.
+       (vect_transform_stmt): Add case for type_conversion_vec_info_type.
+       * tree-vect-generic.c (expand_vector_operations_1): Consider correct
+       mode.
+       * config/rs6000/rs6000.c (rs6000_builtin_conversion): New.
+       (TARGET_VECTORIZE_BUILTIN_CONVERSION): Defined.
+       (rs6000_expand_builtin): Add handling a case of ALTIVEC_BUILTIN_VCFUX or
+       ALTIVEC_BUILTIN_VCFSX.
+
 2007-02-10  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        PR target/30634
index 6fa2b66..4ed383f 100644 (file)
@@ -716,6 +716,7 @@ static int rs6000_use_sched_lookahead_guard (rtx);
 static tree rs6000_builtin_mask_for_load (void);
 static tree rs6000_builtin_mul_widen_even (tree);
 static tree rs6000_builtin_mul_widen_odd (tree);
+static tree rs6000_builtin_conversion (enum tree_code, tree);
 
 static void def_builtin (int, const char *, tree, int);
 static void rs6000_init_builtins (void);
@@ -981,6 +982,8 @@ static const char alt_reg_names[][8] =
 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN rs6000_builtin_mul_widen_even
 #undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD
 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD rs6000_builtin_mul_widen_odd
+#undef TARGET_VECTORIZE_BUILTIN_CONVERSION
+#define TARGET_VECTORIZE_BUILTIN_CONVERSION rs6000_builtin_conversion
 
 #undef TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS rs6000_init_builtins
@@ -1677,6 +1680,30 @@ rs6000_builtin_mask_for_load (void)
     return 0;
 }
 
+/* Implement targetm.vectorize.builtin_conversion.  */
+static tree
+rs6000_builtin_conversion (enum tree_code code, tree type)
+{
+  if (!TARGET_ALTIVEC)
+    return NULL_TREE;
+  
+  switch (code)
+    {
+    case FLOAT_EXPR:
+      switch (TYPE_MODE (type))
+       {
+       case V4SImode:
+         return TYPE_UNSIGNED (type) ? 
+           rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFUX] :
+           rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFSX];
+       default:
+         return NULL_TREE;
+       }
+    default:
+      return NULL_TREE;
+    }
+}
+
 /* Implement targetm.vectorize.builtin_mul_widen_even.  */
 static tree
 rs6000_builtin_mul_widen_even (tree type)
@@ -8151,6 +8178,21 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
 
       return target;
     }
+  
+  if (fcode == ALTIVEC_BUILTIN_VCFUX
+      || fcode == ALTIVEC_BUILTIN_VCFSX)
+    {
+      if (!TREE_CHAIN (arglist)) 
+       {
+         tree t, arg0;
+         t = NULL_TREE;
+         t = tree_cons (NULL_TREE, integer_zero_node, t);
+         arg0 = TREE_VALUE (arglist);
+         t = tree_cons (NULL_TREE, arg0, t);
+         arglist = t;
+         TREE_OPERAND (exp, 1) = t;
+       }
+    }   
 
   if (TARGET_ALTIVEC)
     {
index ebb3f2c..ad17909 100644 (file)
@@ -5384,6 +5384,21 @@ preserved (e.g. used only by a reduction computation). Otherwise, the
 @code{widen_mult_hi/lo} idioms will be used.
 @end deftypefn
 
+@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_CONVERSION (enum tree_code @var{code}, tree @var{type})
+This hook should return the DECL of a function that implements conversion of the
+input vector of type @var{type}.
+If @var{type} is an integral type, the result of the conversion is a vector of
+floating-point type of the same size.
+If @var{type} is a floating-point type, the result of the conversion is a vector
+of integral type of the same size.
+@var{code} specifies how the conversion is to be applied
+(truncation, rounding, etc.).
+
+If this hook is defined, the autovectorizer will use the
+@code{TARGET_VECTORIZE_BUILTIN_CONVERSION} target hook when vectorizing
+conversion. Otherwise, it will return @code{NULL_TREE}.
+@end deftypefn
+
 @deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION (enum built_in_function @var{code}, tree @var{vec_type_out}, tree @var{vec_type_in})
 This hook should return the decl of a function that implements the vectorized
 variant of the builtin function with builtin function code @var{code} or
index e13b493..27c5883 100644 (file)
@@ -345,6 +345,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD 0
 #define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION default_builtin_vectorized_function
+#define TARGET_VECTORIZE_BUILTIN_CONVERSION default_builtin_vectorized_conversion
 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN 0
 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD 0
 
@@ -352,6 +353,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   {                                                                    \
     TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD,                            \
     TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION,                      \
+    TARGET_VECTORIZE_BUILTIN_CONVERSION,                               \
     TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN,                            \
     TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD                             \
   }
index 2d8d69b..e8694f2 100644 (file)
@@ -397,6 +397,10 @@ struct gcc_target
        function, or NULL_TREE if not available.  */
     tree (* builtin_vectorized_function) (unsigned, tree, tree);
 
+    /* Returns a code for builtin that realizes vectorized version of
+       conversion, or NULL_TREE if not available.  */
+    tree (* builtin_conversion) (unsigned, tree);
+
     /* Target builtin that implements vector widening multiplication.
        builtin_mul_widen_eve computes the element-by-element products 
        for the even elements, and builtin_mul_widen_odd computes the
index ed4d890..fe00079 100644 (file)
@@ -329,6 +329,15 @@ default_builtin_vectorized_function (enum built_in_function fn ATTRIBUTE_UNUSED,
   return NULL_TREE;
 }
 
+/* Vectorized conversion.  */
+
+tree
+default_builtin_vectorized_conversion (enum tree_code code ATTRIBUTE_UNUSED,
+                                      tree type ATTRIBUTE_UNUSED)
+{
+  return NULL_TREE;
+}
+
 bool
 hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false (
        CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
index 0b4ded9..b6bd700 100644 (file)
@@ -59,6 +59,8 @@ extern bool default_narrow_bitfield (void);
 
 extern tree default_builtin_vectorized_function (enum built_in_function, tree, tree);
 
+extern tree default_builtin_vectorized_conversion (enum tree_code, tree);
+
 /* These are here, and not in hooks.[ch], because not all users of
    hooks.h include tm.h, and thus we don't have CUMULATIVE_ARGS.  */
 
index 70106bc..8f912c2 100644 (file)
@@ -1,3 +1,13 @@
+2007-02-11  Tehila Meyzels <tehila@il.ibm.com>
+           Dorit Nuzman  <dorit@il.ibm.com>
+
+       * gcc.dg/vect/vect-intfloat-conversion.c-1:  New test.
+       * gcc.dg/vect/vect-intfloat-conversion.c-2:  New test.
+       * gcc.dg/vect/vect-93.c: Another loop gets vectorized  on powerpc.
+       * gcc.dg/vect/vect-113.c: Likewise.
+
+       * gcc.dg/vect/vect-iv-11.c: A loop gets vectorized.
+
 2007-02-10  Richard Henderson  <rth@redhat.com>
 
        * lib/target-supports.exp (check_effective_target_tls): Redefine
index e09a16b..3b3d1db 100644 (file)
@@ -11,7 +11,7 @@ main1 (void)
   int i;
   float a[N];
 
-  /* Induction.  */
+  /* Induction and type conversion.  */
   for ( i = 0; i < N; i++) 
   {
     a[i] = i;
@@ -32,5 +32,5 @@ int main (void)
   return main1 ();
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target powerpc*-*-* } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
index af2f166..a084922 100644 (file)
@@ -65,12 +65,21 @@ int main (void)
   return 0;
 }
 
-/* in main1 */
-/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
+/* 2 loops vectorized in main1, 2 loops vectorized in main:
+   the first loop in main requires vectorization of conversions,
+   the second loop in main requires vectorization of misaliged load:  */
+
+/* main && main1 together: */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 2 "vect" { target powerpc*-*-* } } } */
 /* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 2 "vect" { target vect_no_align } } } */
 /* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 3 "vect" { xfail vect_no_align } } } */
 
-/* in main */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_align } } } */
+/* in main1: */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target {! powerpc*-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target vect_no_align } } } */
+
+/* in main: */
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target vect_no_align } } } */
 /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail vect_no_align } } } */
+
 /* { dg-final { cleanup-tree-dump "vect" } } */
index 2caadec..bcf2e36 100644 (file)
@@ -28,5 +28,5 @@ int main (void)
   return 0;
 } 
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
index 4d74d18..7ee0703 100644 (file)
@@ -315,6 +315,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
 
              ok = (vectorizable_type_promotion (stmt, NULL, NULL)
                    || vectorizable_type_demotion (stmt, NULL, NULL)
+                   || vectorizable_conversion (stmt, NULL, NULL)
                    || vectorizable_operation (stmt, NULL, NULL)
                    || vectorizable_assignment (stmt, NULL, NULL)
                    || vectorizable_load (stmt, NULL, NULL)
index 82d4814..db7a0ce 100644 (file)
@@ -405,7 +405,10 @@ expand_vector_operations_1 (block_stmt_iterator *bsi)
       && TREE_CODE_CLASS (code) != tcc_binary)
     return;
 
-  if (code == NOP_EXPR || code == VIEW_CONVERT_EXPR)
+  if (code == NOP_EXPR 
+      || code == FLOAT_EXPR
+      || code == FIX_TRUNC_EXPR
+      || code == VIEW_CONVERT_EXPR)
     return;
   
   gcc_assert (code != CONVERT_EXPR);
index d7488b1..e901d00 100644 (file)
@@ -1951,6 +1951,157 @@ vectorizable_call (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
 }
 
 
+/* Function vectorizable_conversion.
+
+Check if STMT performs a conversion operation, that can be vectorized. 
+If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
+stmt to replace it, put it in VEC_STMT, and insert it at BSI.
+Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
+
+bool
+vectorizable_conversion (tree stmt, block_stmt_iterator * bsi,
+                                  tree * vec_stmt)
+{
+  tree vec_dest;
+  tree scalar_dest;
+  tree operation;
+  tree op0;
+  tree vec_oprnd0 = 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;
+  tree new_temp;
+  tree def, def_stmt;
+  enum vect_def_type dt0;
+  tree new_stmt;
+  int nunits_in;
+  int nunits_out;
+  int ncopies, j;
+  tree vectype_out, vectype_in;
+  tree rhs_type, lhs_type;
+  tree builtin_decl, params;
+  stmt_vec_info prev_stmt_info;
+
+  /* Is STMT a vectorizable conversion?   */
+
+  if (!STMT_VINFO_RELEVANT_P (stmt_info))
+    return false;
+
+  gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_loop_def);
+
+  if (STMT_VINFO_LIVE_P (stmt_info))
+    {
+      /* FORNOW: not yet supported.  */
+      if (vect_print_dump_info (REPORT_DETAILS))
+       fprintf (vect_dump, "value used after loop.");
+      return false;
+    }
+
+  if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
+    return false;
+
+  if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
+    return false;
+
+  operation = GIMPLE_STMT_OPERAND (stmt, 1);
+  code = TREE_CODE (operation);
+  if (code != FIX_TRUNC_EXPR && code != FLOAT_EXPR)
+    return false;
+
+  /* Check types of lhs and rhs */
+  op0 = TREE_OPERAND (operation, 0);
+  rhs_type = TREE_TYPE (op0);
+  vectype_in = get_vectype_for_scalar_type (rhs_type);
+  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
+
+  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)
+    return false;
+
+  /* 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;
+
+  /* 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);
+
+  if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt0))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+       fprintf (vect_dump, "use not simple.");
+      return false;
+    }
+
+  /* Supportable by target?  */
+  if (!targetm.vectorize.builtin_conversion (code, vectype_in))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        fprintf (vect_dump, "op not supported by target.");
+      return false;
+    }
+
+  if (!vec_stmt)               /* transformation not required.  */
+    {
+      STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
+      return true;
+    }
+
+    /** Transform.  **/
+
+  if (vect_print_dump_info (REPORT_DETAILS))
+    fprintf (vect_dump, "transform conversion.");
+
+  /* Handle def.  */
+  vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
+
+  prev_stmt_info = NULL;
+  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);
+      params = build_tree_list (NULL_TREE, vec_oprnd0);
+
+      builtin_decl =
+       targetm.vectorize.builtin_conversion (code, vectype_in);
+      new_stmt = build_function_call_expr (builtin_decl, params);
+
+      /* Arguments are ready. create the new vector stmt.  */
+      new_stmt = build2 (GIMPLE_MODIFY_STMT, void_type_node, 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);
+    }
+  return true;
+}
+
+
 /* Function vectorizable_assignment.
 
    Check if STMT performs an assignment (copy) that can be vectorized. 
@@ -4098,6 +4249,11 @@ vect_transform_stmt (tree stmt, block_stmt_iterator *bsi, bool *strided_store)
        gcc_assert (done);
        break;
 
+      case type_conversion_vec_info_type:
+       done = vectorizable_conversion (stmt, bsi, &vec_stmt);
+       gcc_assert (done);
+       break;
+
       case op_vec_info_type:
        done = vectorizable_operation (stmt, bsi, &vec_stmt);
        gcc_assert (done);
index b523d88..dd41f2b 100644 (file)
@@ -168,7 +168,8 @@ enum stmt_vec_info_type {
   condition_vec_info_type,
   reduc_vec_info_type,
   type_promotion_vec_info_type,
-  type_demotion_vec_info_type
+  type_demotion_vec_info_type,
+  type_conversion_vec_info_type
 };
 
 /* Indicates whether/how a variable is used in the loop.  */
@@ -411,6 +412,8 @@ extern bool vectorizable_store (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_operation (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_type_promotion (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_type_demotion (tree, block_stmt_iterator *, tree *);
+extern bool vectorizable_conversion (tree, block_stmt_iterator *, 
+                                    tree *);
 extern bool vectorizable_assignment (tree, block_stmt_iterator *, tree *);
 extern tree vectorizable_function (tree, tree, tree);
 extern bool vectorizable_call (tree, block_stmt_iterator *, tree *);