Hi, In vectorizer's over-widening pattern recognition the last statement is expected to be a type demotion, but the check for that was incomplete. We now check that the resulting type is not bigger than the original type of the computation.
Bootstrapped and tested on powerpc64-suse-linux, tested on arm-linux-gnueabi (cross). Committed. Ira ChangeLog: PR tree-optimization/51301 * tree-vect-patterns.c (vect_recog_over_widening_pattern): Check that the last statement doesn't convert to a bigger type than the original type of the computation. testsuite/ChangeLog: PR tree-optimization/51301 * gcc.dg/vect/pr51301.c: New test. Index: tree-vect-patterns.c =================================================================== --- tree-vect-patterns.c (revision 181796) +++ tree-vect-patterns.c (working copy) @@ -1088,6 +1088,7 @@ vect_recog_over_widening_pattern (VEC (gimple, hea tree var = NULL_TREE, new_type = NULL_TREE, tmp, new_oprnd; bool first; struct loop *loop = (gimple_bb (stmt))->loop_father; + tree type = NULL; first = true; while (1) @@ -1150,6 +1151,7 @@ vect_recog_over_widening_pattern (VEC (gimple, hea print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM); } + type = gimple_expr_type (stmt); prev_stmt = stmt; stmt = use_stmt; @@ -1165,9 +1167,11 @@ vect_recog_over_widening_pattern (VEC (gimple, hea { use_lhs = gimple_assign_lhs (use_stmt); use_type = TREE_TYPE (use_lhs); - /* Support only type promotion or signedess change. */ + /* Support only type promotion or signedess change. Check that USE_TYPE + is not bigger than the original type. */ if (!INTEGRAL_TYPE_P (use_type) - || TYPE_PRECISION (new_type) > TYPE_PRECISION (use_type)) + || TYPE_PRECISION (new_type) > TYPE_PRECISION (use_type) + || TYPE_PRECISION (type) < TYPE_PRECISION (use_type)) return NULL; if (TYPE_UNSIGNED (new_type) != TYPE_UNSIGNED (use_type) Index: testsuite/gcc.dg/vect/pr51301.c =================================================================== --- testsuite/gcc.dg/vect/pr51301.c (revision 0) +++ testsuite/gcc.dg/vect/pr51301.c (revision 0) @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +typedef signed char int8_t; +typedef signed long long int64_t; +int64_t +f0a (int8_t * __restrict__ arg1) +{ + int idx; + int64_t result = 0; + for (idx = 0; idx < 416; idx += 1) + result += arg1[idx] << (arg1[idx] == arg1[idx]); + return result; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */