machmode.h (mode_for_vector): Declare.
authorRichard Guenther <rguenther@suse.de>
Thu, 7 Oct 2010 14:36:38 +0000 (14:36 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 7 Oct 2010 14:36:38 +0000 (14:36 +0000)
2010-10-07  Richard Guenther  <rguenther@suse.de>

* machmode.h (mode_for_vector): Declare.
* stor-layout.c (mode_for_vector): New function, split out from ...
(layout_type): ... here.
* tree-vectorizer.h (current_vector_size): Declare.
* tree-vect-stmts.c (perm_mask_for_reverse): Check if the
mask vector type is available.
(get_vectype_for_scalar_type): Rename to ...
(get_vectype_for_scalar_type_and_size): ... this.  Get a vector
size argument.
(get_vectype_for_scalar_type): New wrapper around
get_vectype_for_scalar_type_and_size using current_vector_size.
(get_same_sized_vectype): Use get_vectype_for_scalar_type_and_size.
* tree-vect-loop.c (vect_analyze_loop_2): Split out core part
of vect_analyze_loop here.
(vect_analyze_loop): Loop over vector sizes calling vect_analyze_loop_3.
* tree-vect-slp.c (vect_slp_analyze_bb): Set current_vector_size
to autodetect.
* config/i386/i386.c (ix86_vectorize_builtin_conversion): Fix
V8SF to V8SI conversion builtin.

From-SVN: r165116

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/machmode.h
gcc/stor-layout.c
gcc/tree-vect-loop.c
gcc/tree-vect-slp.c
gcc/tree-vect-stmts.c
gcc/tree-vectorizer.h

index 94eada1f1cf55f1b52722411ccc9e7b952591d3e..ffc280eff7d5c0c531ec2096b2a8ad9ef847730f 100644 (file)
@@ -1,3 +1,25 @@
+2010-10-07  Richard Guenther  <rguenther@suse.de>
+
+       * machmode.h (mode_for_vector): Declare.
+       * stor-layout.c (mode_for_vector): New function, split out from ...
+       (layout_type): ... here.
+       * tree-vectorizer.h (current_vector_size): Declare.
+       * tree-vect-stmts.c (perm_mask_for_reverse): Check if the
+       mask vector type is available.
+       (get_vectype_for_scalar_type): Rename to ...
+       (get_vectype_for_scalar_type_and_size): ... this.  Get a vector
+       size argument.
+       (get_vectype_for_scalar_type): New wrapper around
+       get_vectype_for_scalar_type_and_size using current_vector_size.
+       (get_same_sized_vectype): Use get_vectype_for_scalar_type_and_size.
+       * tree-vect-loop.c (vect_analyze_loop_2): Split out core part
+       of vect_analyze_loop here.
+       (vect_analyze_loop): Loop over vector sizes calling vect_analyze_loop_3.
+       * tree-vect-slp.c (vect_slp_analyze_bb): Set current_vector_size
+       to autodetect.
+       * config/i386/i386.c (ix86_vectorize_builtin_conversion): Fix
+       V8SF to V8SI conversion builtin.
+
 2010-10-07  Richard Guenther  <rguenther@suse.de>
 
        * target.def (autovectorize_vector_sizes): New target hook.
index 39308cf59188bbf65d6d18548a1dc27f8a0d12a8..33510a77c59f0106c043166203b2652c15c5379d 100644 (file)
@@ -26272,7 +26272,7 @@ ix86_vectorize_builtin_conversion (unsigned int code,
            case V8SFmode:
              return (TYPE_UNSIGNED (src_type)
                      ? NULL_TREE
-                     : ix86_builtins[IX86_BUILTIN_CVTDQ2PS]);
+                     : ix86_builtins[IX86_BUILTIN_CVTDQ2PS256]);
            default:
              return NULL_TREE;
            }
index 936a36e6a0dc32cb7134cdc7ba7d8135e9a8cecd..3ab7a8101ec4b46a17b73f3b8b54e056f305c17d 100644 (file)
@@ -241,6 +241,11 @@ extern enum machine_mode smallest_mode_for_size (unsigned int,
 
 extern enum machine_mode int_mode_for_mode (enum machine_mode);
 
+/* Return a mode that is suitable for representing a vector,
+   or BLKmode on failure.  */
+
+extern enum machine_mode mode_for_vector (enum machine_mode, unsigned);
+
 /* Find the best mode to use to access a bit field.  */
 
 extern enum machine_mode get_best_mode (int, int, unsigned int,
index 7ffef4d849199c07b31acf7851c7393cc00b9593..5796ea1f09a1641185fa0baf3eed1fa598688b0b 100644 (file)
@@ -470,6 +470,50 @@ int_mode_for_mode (enum machine_mode mode)
   return mode;
 }
 
+/* Find a mode that is suitable for representing a vector with
+   NUNITS elements of mode INNERMODE.  Returns BLKmode if there
+   is no suitable mode.  */
+
+enum machine_mode
+mode_for_vector (enum machine_mode innermode, unsigned nunits)
+{
+  enum machine_mode mode;
+
+  /* First, look for a supported vector type.  */
+  if (SCALAR_FLOAT_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_FLOAT;
+  else if (SCALAR_FRACT_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_FRACT;
+  else if (SCALAR_UFRACT_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_UFRACT;
+  else if (SCALAR_ACCUM_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_ACCUM;
+  else if (SCALAR_UACCUM_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_UACCUM;
+  else
+    mode = MIN_MODE_VECTOR_INT;
+
+  /* Do not check vector_mode_supported_p here.  We'll do that
+     later in vector_type_mode.  */
+  for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
+    if (GET_MODE_NUNITS (mode) == nunits
+       && GET_MODE_INNER (mode) == innermode)
+      break;
+
+  /* For integers, try mapping it to a same-sized scalar mode.  */
+  if (mode == VOIDmode
+      && GET_MODE_CLASS (innermode) == MODE_INT)
+    mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
+                         MODE_INT, 0);
+
+  if (mode == VOIDmode
+      || (GET_MODE_CLASS (mode) == MODE_INT
+         && !have_regs_of_mode[mode]))
+    return BLKmode;
+
+  return mode;
+}
+
 /* Return the alignment of MODE. This will be bounded by 1 and
    BIGGEST_ALIGNMENT.  */
 
@@ -1848,44 +1892,8 @@ layout_type (tree type)
 
        /* Find an appropriate mode for the vector type.  */
        if (TYPE_MODE (type) == VOIDmode)
-         {
-           enum machine_mode innermode = TYPE_MODE (innertype);
-           enum machine_mode mode;
-
-           /* First, look for a supported vector type.  */
-           if (SCALAR_FLOAT_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_FLOAT;
-           else if (SCALAR_FRACT_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_FRACT;
-           else if (SCALAR_UFRACT_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_UFRACT;
-           else if (SCALAR_ACCUM_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_ACCUM;
-           else if (SCALAR_UACCUM_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_UACCUM;
-           else
-             mode = MIN_MODE_VECTOR_INT;
-
-           /* Do not check vector_mode_supported_p here.  We'll do that
-              later in vector_type_mode.  */
-           for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
-             if (GET_MODE_NUNITS (mode) == nunits
-                 && GET_MODE_INNER (mode) == innermode)
-               break;
-
-           /* For integers, try mapping it to a same-sized scalar mode.  */
-           if (mode == VOIDmode
-               && GET_MODE_CLASS (innermode) == MODE_INT)
-             mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
-                                   MODE_INT, 0);
-
-           if (mode == VOIDmode ||
-               (GET_MODE_CLASS (mode) == MODE_INT
-                && !have_regs_of_mode[mode]))
-             SET_TYPE_MODE (type, BLKmode);
-           else
-             SET_TYPE_MODE (type, mode);
-         }
+         SET_TYPE_MODE (type,
+                        mode_for_vector (TYPE_MODE (innertype), nunits));
 
        TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
         TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
index 95b36f76f15adf605e978463117efebc1dea8473..d7a864a0196dfcb73ff67d166386aef9a69beace 100644 (file)
@@ -1371,41 +1371,18 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
 }
 
 
-/* Function vect_analyze_loop.
+/* Function vect_analyze_loop_2.
 
    Apply a set of analyses on LOOP, and create a loop_vec_info struct
    for it.  The different analyses will record information in the
    loop_vec_info struct.  */
-loop_vec_info
-vect_analyze_loop (struct loop *loop)
+static bool
+vect_analyze_loop_2 (loop_vec_info loop_vinfo)
 {
   bool ok, dummy;
-  loop_vec_info loop_vinfo;
   int max_vf = MAX_VECTORIZATION_FACTOR;
   int min_vf = 2;
 
-  if (vect_print_dump_info (REPORT_DETAILS))
-    fprintf (vect_dump, "===== analyze_loop_nest =====");
-
-  if (loop_outer (loop)
-      && loop_vec_info_for_loop (loop_outer (loop))
-      && LOOP_VINFO_VECTORIZABLE_P (loop_vec_info_for_loop (loop_outer (loop))))
-    {
-      if (vect_print_dump_info (REPORT_DETAILS))
-       fprintf (vect_dump, "outer-loop already vectorized.");
-      return NULL;
-    }
-
-  /* Check the CFG characteristics of the loop (nesting, entry/exit, etc.  */
-
-  loop_vinfo = vect_analyze_loop_form (loop);
-  if (!loop_vinfo)
-    {
-      if (vect_print_dump_info (REPORT_DETAILS))
-       fprintf (vect_dump, "bad loop form.");
-      return NULL;
-    }
-
   /* Find all data references in the loop (which correspond to vdefs/vuses)
      and analyze their evolution in the loop.  Also adjust the minimal
      vectorization factor according to the loads and stores.
@@ -1418,8 +1395,7 @@ vect_analyze_loop (struct loop *loop)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "bad data references.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
 
   /* Classify all cross-iteration scalar data-flow cycles.
@@ -1436,8 +1412,7 @@ vect_analyze_loop (struct loop *loop)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "unexpected pattern.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
 
   /* Analyze data dependences between the data-refs in the loop
@@ -1451,8 +1426,7 @@ vect_analyze_loop (struct loop *loop)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "bad data dependence.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
 
   ok = vect_determine_vectorization_factor (loop_vinfo);
@@ -1460,15 +1434,13 @@ vect_analyze_loop (struct loop *loop)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
         fprintf (vect_dump, "can't determine vectorization factor.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
   if (max_vf < LOOP_VINFO_VECT_FACTOR (loop_vinfo))
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "bad data dependence.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
 
   /* Analyze the alignment of the data-refs in the loop.
@@ -1479,8 +1451,7 @@ vect_analyze_loop (struct loop *loop)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "bad data alignment.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
 
   /* Analyze the access patterns of the data-refs in the loop (consecutive,
@@ -1491,8 +1462,7 @@ vect_analyze_loop (struct loop *loop)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "bad data access.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
 
   /* Prune the list of ddrs to be tested at run-time by versioning for alias.
@@ -1504,8 +1474,7 @@ vect_analyze_loop (struct loop *loop)
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "too long list of versioning for alias "
                            "run-time tests.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
 
   /* This pass will decide on using loop versioning and/or loop peeling in
@@ -1516,8 +1485,7 @@ vect_analyze_loop (struct loop *loop)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
         fprintf (vect_dump, "bad data alignment.");
-      destroy_loop_vec_info (loop_vinfo, true);
-      return NULL;
+      return false;
     }
 
   /* Check the SLP opportunities in the loop, analyze and build SLP trees.  */
@@ -1539,13 +1507,70 @@ vect_analyze_loop (struct loop *loop)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "bad operation or unsupported loop bound.");
-      destroy_loop_vec_info (loop_vinfo, true);
+      return false;
+    }
+
+  return true;
+}
+
+/* Function vect_analyze_loop.
+
+   Apply a set of analyses on LOOP, and create a loop_vec_info struct
+   for it.  The different analyses will record information in the
+   loop_vec_info struct.  */
+loop_vec_info
+vect_analyze_loop (struct loop *loop)
+{
+  loop_vec_info loop_vinfo;
+  unsigned int vector_sizes;
+
+  /* Autodetect first vector size we try.  */
+  current_vector_size = 0;
+  vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
+
+  if (vect_print_dump_info (REPORT_DETAILS))
+    fprintf (vect_dump, "===== analyze_loop_nest =====");
+
+  if (loop_outer (loop)
+      && loop_vec_info_for_loop (loop_outer (loop))
+      && LOOP_VINFO_VECTORIZABLE_P (loop_vec_info_for_loop (loop_outer (loop))))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+       fprintf (vect_dump, "outer-loop already vectorized.");
       return NULL;
     }
 
-  LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
+  while (1)
+    {
+      /* Check the CFG characteristics of the loop (nesting, entry/exit).  */
+      loop_vinfo = vect_analyze_loop_form (loop);
+      if (!loop_vinfo)
+       {
+         if (vect_print_dump_info (REPORT_DETAILS))
+           fprintf (vect_dump, "bad loop form.");
+         return NULL;
+       }
 
-  return loop_vinfo;
+      if (vect_analyze_loop_2 (loop_vinfo))
+       {
+         LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
+
+         return loop_vinfo;
+       }
+
+      destroy_loop_vec_info (loop_vinfo, true);
+
+      vector_sizes &= ~current_vector_size;
+      if (vector_sizes == 0
+         || current_vector_size == 0)
+       return NULL;
+
+      /* Try the next biggest vector size.  */
+      current_vector_size = 1 << floor_log2 (vector_sizes);
+      if (vect_print_dump_info (REPORT_DETAILS))
+       fprintf (vect_dump, "***** Re-trying analysis with "
+                "vector size %d\n", current_vector_size);
+    }
 }
 
 
index 4739538348cd6779e598816120374c6e0e5fdb9e..2dbe328ba2502be689193adda1e1d2c280de7e34 100644 (file)
@@ -1643,6 +1643,7 @@ vect_slp_analyze_bb (basic_block bb)
   int max_vf = MAX_VECTORIZATION_FACTOR;
   bool data_dependence_in_bb = false;
 
+  current_vector_size = 0;
 
   if (vect_print_dump_info (REPORT_DETAILS))
     fprintf (vect_dump, "===vect_slp_analyze_bb===\n");
index 8fba200f874201c4abf4da173e051badb6eab681..6d0c1126d59ee2091e80ccbe69c32460a419389f 100644 (file)
@@ -3455,7 +3455,8 @@ perm_mask_for_reverse (tree vectype, tree *mask)
 
   mask_type = get_vectype_for_scalar_type (mask_element_type);
   nunits = TYPE_VECTOR_SUBPARTS (vectype);
-  if (TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
+  if (!mask_type
+      || TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
     return NULL;
 
   for (i = 0; i < nunits; i++)
@@ -4784,13 +4785,13 @@ free_stmt_vec_info (gimple stmt)
 }
 
 
-/* Function get_vectype_for_scalar_type.
+/* Function get_vectype_for_scalar_type_and_size.
 
-   Returns the vector type corresponding to SCALAR_TYPE as supported
+   Returns the vector type corresponding to SCALAR_TYPE  and SIZE as supported
    by the target.  */
 
-tree
-get_vectype_for_scalar_type (tree scalar_type)
+static tree
+get_vectype_for_scalar_type_and_size (tree scalar_type, unsigned size)
 {
   enum machine_mode inner_mode = TYPE_MODE (scalar_type);
   enum machine_mode simd_mode;
@@ -4818,7 +4819,12 @@ get_vectype_for_scalar_type (tree scalar_type)
       && GET_MODE_CLASS (inner_mode) != MODE_FLOAT)
     return NULL_TREE;
 
-  simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
+  /* If no size was supplied use the mode the target prefers.   Otherwise
+     lookup a vector mode of the specified size.  */
+  if (size == 0)
+    simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
+  else
+    simd_mode = mode_for_vector (inner_mode, size / nbytes);
   nunits = GET_MODE_SIZE (simd_mode) / nbytes;
   if (nunits <= 1)
     return NULL_TREE;
@@ -4850,15 +4856,35 @@ get_vectype_for_scalar_type (tree scalar_type)
   return vectype;
 }
 
+unsigned int current_vector_size;
+
+/* Function get_vectype_for_scalar_type.
+
+   Returns the vector type corresponding to SCALAR_TYPE as supported
+   by the target.  */
+
+tree
+get_vectype_for_scalar_type (tree scalar_type)
+{
+  tree vectype;
+  vectype = get_vectype_for_scalar_type_and_size (scalar_type,
+                                                 current_vector_size);
+  if (vectype
+      && current_vector_size == 0)
+    current_vector_size = GET_MODE_SIZE (TYPE_MODE (vectype));
+  return vectype;
+}
+
 /* Function get_same_sized_vectype
 
    Returns a vector type corresponding to SCALAR_TYPE of size
    VECTOR_TYPE if supported by the target.  */
 
 tree
-get_same_sized_vectype (tree scalar_type, tree vector_type ATTRIBUTE_UNUSED)
+get_same_sized_vectype (tree scalar_type, tree vector_type)
 {
-  return get_vectype_for_scalar_type (scalar_type);
+  return get_vectype_for_scalar_type_and_size
+          (scalar_type, GET_MODE_SIZE (TYPE_MODE (vector_type)));
 }
 
 /* Function vect_is_simple_use.
index b438dbc1c1b8feb38bd567d0049e782bc0f414d1..389e80a0551c70ceae1c9afbefe3d852dc0b00b3 100644 (file)
@@ -779,6 +779,7 @@ extern LOC find_loop_location (struct loop *);
 extern bool vect_can_advance_ivs_p (loop_vec_info);
 
 /* In tree-vect-stmts.c.  */
+extern unsigned int current_vector_size;
 extern tree get_vectype_for_scalar_type (tree);
 extern tree get_same_sized_vectype (tree, tree);
 extern bool vect_is_simple_use (tree, loop_vec_info, bb_vec_info, gimple *,