From d367387cf1ba680dd02786332cf71ffa70b8d9a6 Mon Sep 17 00:00:00 2001 From: Cong Hou Date: Fri, 18 Apr 2014 15:46:49 -0400 Subject: [PATCH] tree-vect-patterns.c (vect_recog_widen_mult_pattern): Enhance the widen-mult pattern by handling two operands with different sizes. 2014-04-18 Cong Hou * tree-vect-patterns.c (vect_recog_widen_mult_pattern): Enhance the widen-mult pattern by handling two operands with different sizes. * tree-vect-stmts.c (vectorizable_conversion): Allow multi-steps conversions after widening mult operation. (supportable_widening_operation): Likewise. 2014-04-18 Cong Hou * gcc.dg/vect/vect-widen-mult-u8-s16-s32.c: New test. * gcc.dg/vect/vect-widen-mult-u8-u32.c: New test. From-SVN: r209524 --- gcc/ChangeLog | 9 ++ gcc/testsuite/ChangeLog | 5 + .../gcc.dg/vect/vect-widen-mult-u8-s16-s32.c | 48 ++++++++++ .../gcc.dg/vect/vect-widen-mult-u8-u32.c | 48 ++++++++++ gcc/tree-vect-patterns.c | 93 +++++++++++++++++-- 5 files changed, 193 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c create mode 100644 gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-u32.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5221338c22d..bbf468aec6b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-04-18 Cong Hou + + * tree-vect-patterns.c (vect_recog_widen_mult_pattern): Enhance + the widen-mult pattern by handling two operands with different + sizes. + * tree-vect-stmts.c (vectorizable_conversion): Allow multi-steps + conversions after widening mult operation. + (supportable_widening_operation): Likewise. + 2014-04-18 Jan Hubicka * ipa-inline.h (INLINE_HINT_known_hot): New hint. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d1ad53cb3d1..a1071cd55d9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-04-18 Cong Hou + + * gcc.dg/vect/vect-widen-mult-u8-s16-s32.c: New test. + * gcc.dg/vect/vect-widen-mult-u8-u32.c: New test. + 2014-04-18 Bill Schmidt * gcc.dg/vmx/merge-vsx.c: Add V4SI and V4SF tests. diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c new file mode 100644 index 00000000000..ae485499971 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c @@ -0,0 +1,48 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include "tree-vect.h" + +#define N 64 + +unsigned char X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); +short Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); +int result[N]; + +/* unsigned char * short -> int widening-mult. */ +__attribute__ ((noinline)) int +foo (int len) { + int i; + + for (i=0; i +#include "tree-vect.h" + +#define N 64 + +unsigned char X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); +unsigned char Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); +unsigned int result[N]; + +/* unsigned char-> unsigned int widening-mult. */ +__attribute__ ((noinline)) int +foo (int len) { + int i; + + for (i=0; i + If the result of WIDEN_MULT needs to be converted to a larger type, the + returned stmt will be this type conversion stmt. */ static gimple @@ -606,8 +610,8 @@ vect_recog_widen_mult_pattern (vec *stmts, gimple def_stmt0, def_stmt1; tree oprnd0, oprnd1; tree type, half_type0, half_type1; - gimple pattern_stmt; - tree vectype, vectype_out = NULL_TREE; + gimple new_stmt = NULL, pattern_stmt = NULL; + tree vectype, vecitype; tree var; enum tree_code dummy_code; int dummy_int; @@ -661,6 +665,33 @@ vect_recog_widen_mult_pattern (vec *stmts, return NULL; } + /* If the two arguments have different sizes, convert the one with + the smaller type into the larger type. */ + if (TYPE_PRECISION (half_type0) != TYPE_PRECISION (half_type1)) + { + tree* oprnd = NULL; + gimple def_stmt = NULL; + + if (TYPE_PRECISION (half_type0) < TYPE_PRECISION (half_type1)) + { + def_stmt = def_stmt0; + half_type0 = half_type1; + oprnd = &oprnd0; + } + else + { + def_stmt = def_stmt1; + half_type1 = half_type0; + oprnd = &oprnd1; + } + + tree old_oprnd = gimple_assign_rhs1 (def_stmt); + tree new_oprnd = make_ssa_name (half_type0, NULL); + new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, + old_oprnd, NULL_TREE); + *oprnd = new_oprnd; + } + /* Handle unsigned case. Look for S6 u_prod_T = (unsigned TYPE) prod_T; Use unsigned TYPE as the type for WIDEN_MULT_EXPR. */ @@ -692,6 +723,15 @@ vect_recog_widen_mult_pattern (vec *stmts, if (!types_compatible_p (half_type0, half_type1)) return NULL; + /* If TYPE is more than twice larger than HALF_TYPE, we use WIDEN_MULT + to get an intermediate result of type ITYPE. In this case we need + to build a statement to convert this intermediate result to type TYPE. */ + tree itype = type; + if (TYPE_PRECISION (type) > TYPE_PRECISION (half_type0) * 2) + itype = build_nonstandard_integer_type + (GET_MODE_BITSIZE (TYPE_MODE (half_type0)) * 2, + TYPE_UNSIGNED (type)); + /* Pattern detected. */ if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, @@ -699,23 +739,56 @@ vect_recog_widen_mult_pattern (vec *stmts, /* Check target support */ vectype = get_vectype_for_scalar_type (half_type0); - vectype_out = get_vectype_for_scalar_type (type); + vecitype = get_vectype_for_scalar_type (itype); if (!vectype - || !vectype_out + || !vecitype || !supportable_widening_operation (WIDEN_MULT_EXPR, last_stmt, - vectype_out, vectype, + vecitype, vectype, &dummy_code, &dummy_code, &dummy_int, &dummy_vec)) return NULL; *type_in = vectype; - *type_out = vectype_out; + *type_out = get_vectype_for_scalar_type (type); /* Pattern supported. Create a stmt to be used to replace the pattern: */ - var = vect_recog_temp_ssa_var (type, NULL); + var = vect_recog_temp_ssa_var (itype, NULL); pattern_stmt = gimple_build_assign_with_ops (WIDEN_MULT_EXPR, var, oprnd0, oprnd1); + stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); + loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo); + bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo); + STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo) = NULL; + + /* If the original two operands have different sizes, we may need to convert + the smaller one into the larget type. If this is the case, at this point + the new stmt is already built. */ + if (new_stmt) + { + append_pattern_def_seq (stmt_vinfo, new_stmt); + stmt_vec_info new_stmt_info + = new_stmt_vec_info (new_stmt, loop_vinfo, bb_vinfo); + set_vinfo_for_stmt (new_stmt, new_stmt_info); + STMT_VINFO_VECTYPE (new_stmt_info) = vectype; + } + + /* If ITYPE is not TYPE, we need to build a type convertion stmt to convert + the result of the widen-mult operation into type TYPE. */ + if (itype != type) + { + append_pattern_def_seq (stmt_vinfo, pattern_stmt); + stmt_vec_info pattern_stmt_info + = new_stmt_vec_info (pattern_stmt, loop_vinfo, bb_vinfo); + set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info); + STMT_VINFO_VECTYPE (pattern_stmt_info) = vecitype; + pattern_stmt + = gimple_build_assign_with_ops (NOP_EXPR, + vect_recog_temp_ssa_var (type, NULL), + gimple_assign_lhs (pattern_stmt), + NULL_TREE); + } + if (dump_enabled_p ()) dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM, pattern_stmt, 0);