@@ -1,3 +1,12 @@
+2013-12-02 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.
+
2013-11-22 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/59061
@@ -1,3 +1,8 @@
+2013-12-02 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.
+
2013-11-22 Jakub Jelinek <jakub@redhat.com>
* c-c++-common/asan/no-redundant-instrumentation-7.c: Fix
b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c
new file mode 100644
@@ -0,0 +1,48 @@
+/* { 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
+foo1(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 ("");
+ }
+
+ foo1 (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" } } */
+
b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-u32.c
new file mode 100644
@@ -0,0 +1,48 @@
+/* { 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
+foo1(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 ("");
+ }
+
+ foo1 (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;
@@ -661,6 +663,50 @@ 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;
+ }
+
+ if (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)))
+ {
+ gimple new_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt));
+ /* Check if the already created pattern stmt is what we need. */
+ if (!is_gimple_assign (new_stmt)
+ || gimple_assign_rhs_code (new_stmt) != NOP_EXPR
+ || TREE_TYPE (gimple_assign_lhs (new_stmt)) != half_type0)
+ return NULL;
+
+ stmts->safe_push (def_stmt);
+ *oprnd = gimple_assign_lhs (new_stmt);
+ }
+ else
+ {
+ tree old_oprnd = gimple_assign_rhs1 (def_stmt);
+ tree new_oprnd = make_ssa_name (half_type0, NULL);
+ gimple new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd,
+ old_oprnd, NULL_TREE);
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)) = new_stmt;
+ stmts->safe_push (def_stmt);
+ *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. */
@@ -2504,12 +2504,7 @@ vectorizable_conversion (gimple stmt,
gimple_stmt_iterator *gsi,
if (supportable_widening_operation (code, stmt, vectype_out, vectype_in,
&code1, &code2, &multi_step_cvt,
&interm_types))
- {
- /* Binary widening operation can only be supported directly by the
- architecture. */
- gcc_assert (!(multi_step_cvt && op_type == binary_op));
- break;
- }
+ break;
if (code != FLOAT_EXPR