From: dorit Date: Sun, 11 Feb 2007 11:46:07 +0000 (+0000) Subject: * doc/tm.texi (TARGET_VECTORIZE_BUILTIN_CONVERSION): New target hook. X-Git-Tag: upstream/4.9.2~50450 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9d8bf4aaa54e04d9e4f1c39121f7b89e11c4202b;p=platform%2Fupstream%2Flinaro-gcc.git * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121818 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a0078e3..c7fce63 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2007-02-11 Tehila Meyzels + Ira Rosen + Dorit Nuzman + + * 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 PR target/30634 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 6fa2b66..4ed383f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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) { diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index ebb3f2c..ad17909 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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 diff --git a/gcc/target-def.h b/gcc/target-def.h index e13b493..27c5883 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -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 \ } diff --git a/gcc/target.h b/gcc/target.h index 2d8d69b..e8694f2 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -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 diff --git a/gcc/targhooks.c b/gcc/targhooks.c index ed4d890..fe00079 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -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, diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 0b4ded9..b6bd700 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 70106bc..8f912c2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2007-02-11 Tehila Meyzels + Dorit Nuzman + + * 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 * lib/target-supports.exp (check_effective_target_tls): Redefine diff --git a/gcc/testsuite/gcc.dg/vect/vect-113.c b/gcc/testsuite/gcc.dg/vect/vect-113.c index e09a16b..3b3d1db 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-113.c +++ b/gcc/testsuite/gcc.dg/vect/vect-113.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-93.c b/gcc/testsuite/gcc.dg/vect/vect-93.c index af2f166..a084922 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-93.c +++ b/gcc/testsuite/gcc.dg/vect/vect-93.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-iv-11.c b/gcc/testsuite/gcc.dg/vect/vect-iv-11.c index 2caadec..bcf2e36 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-iv-11.c +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-11.c @@ -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" } } */ diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index 4d74d18..7ee0703 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -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) diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 82d4814..db7a0ce 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -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); diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index d7488b1..e901d00 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -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); diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index b523d88..dd41f2b 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -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 *);