From bb67d9c7cef80c80e817cafdd9ee2001cb29c9f7 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Thu, 7 Oct 2010 14:36:38 +0000 Subject: [PATCH] machmode.h (mode_for_vector): Declare. 2010-10-07 Richard Guenther * 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 | 22 ++++++++ gcc/config/i386/i386.c | 2 +- gcc/machmode.h | 5 ++ gcc/stor-layout.c | 84 ++++++++++++++++------------- gcc/tree-vect-loop.c | 119 +++++++++++++++++++++++++---------------- gcc/tree-vect-slp.c | 1 + gcc/tree-vect-stmts.c | 42 ++++++++++++--- gcc/tree-vectorizer.h | 1 + 8 files changed, 182 insertions(+), 94 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 94eada1f1cf..ffc280eff7d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2010-10-07 Richard Guenther + + * 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 * target.def (autovectorize_vector_sizes): New target hook. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 39308cf5918..33510a77c59 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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; } diff --git a/gcc/machmode.h b/gcc/machmode.h index 936a36e6a0d..3ab7a8101ec 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -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, diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 7ffef4d8491..5796ea1f09a 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -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)); diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 95b36f76f15..d7a864a0196 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -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); + } } diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 4739538348c..2dbe328ba25 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -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"); diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 8fba200f874..6d0c1126d59 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -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. diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index b438dbc1c1b..389e80a0551 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -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 *, -- 2.30.2