Commit d367387c by Cong Hou Committed by Cong Hou

tree-vect-patterns.c (vect_recog_widen_mult_pattern): Enhance the widen-mult…

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  <congh@google.com>

        * 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  <congh@google.com>

        * 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
parent b6d627e4
2014-04-18 Cong Hou <congh@google.com>
* 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 <hubicka@ucw.cz>
* ipa-inline.h (INLINE_HINT_known_hot): New hint.
......
2014-04-18 Cong Hou <congh@google.com>
* 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 <wschmidt@linux.vnet.ibm.com>
* gcc.dg/vmx/merge-vsx.c: Add V4SI and V4SF tests.
......
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#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<len; i++) {
result[i] = X[i] * Y[i];
}
}
int main (void)
{
int i;
check_vect ();
for (i=0; i<N; i++) {
X[i] = i;
Y[i] = 64-i;
__asm__ volatile ("");
}
foo (N);
for (i=0; i<N; i++) {
if (result[i] != X[i] * Y[i])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_hi_to_si || vect_unpack } } } } */
/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected" 1 "vect" { target vect_widen_mult_hi_to_si_pattern } } } */
/* { dg-final { scan-tree-dump-times "pattern recognized" 1 "vect" { target vect_widen_mult_hi_to_si_pattern } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#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<len; i++) {
result[i] = X[i] * Y[i];
}
}
int main (void)
{
int i;
check_vect ();
for (i=0; i<N; i++) {
X[i] = i;
Y[i] = 64-i;
__asm__ volatile ("");
}
foo (N);
for (i=0; i<N; i++) {
if (result[i] != X[i] * Y[i])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */
/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected" 1 "vect" { target vect_widen_mult_qi_to_hi_pattern } } } */
/* { dg-final { scan-tree-dump-times "pattern recognized" 1 "vect" { target vect_widen_mult_qi_to_hi_pattern } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -529,7 +529,8 @@ vect_handle_widen_op_by_const (gimple stmt, enum tree_code code,
Try to find the following pattern:
type a_t, b_t;
type1 a_t;
type2 b_t;
TYPE a_T, b_T, prod_T;
S1 a_t = ;
......@@ -538,11 +539,12 @@ vect_handle_widen_op_by_const (gimple stmt, enum tree_code code,
S4 b_T = (TYPE) b_t;
S5 prod_T = a_T * b_T;
where type 'TYPE' is at least double the size of type 'type'.
where type 'TYPE' is at least double the size of type 'type1' and 'type2'.
Also detect unsigned cases:
unsigned type a_t, b_t;
unsigned type1 a_t;
unsigned type2 b_t;
unsigned TYPE u_prod_T;
TYPE a_T, b_T, prod_T;
......@@ -596,6 +598,8 @@ vect_handle_widen_op_by_const (gimple stmt, enum tree_code code,
* Return value: A new stmt that will be used to replace the sequence of
stmts that constitute the pattern. In this case it will be:
WIDEN_MULT <a_t, b_t>
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<gimple> *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<gimple> *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<gimple> *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<gimple> *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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment