Hi There is a bug in the function vect_recog_dot_prod_pattern() in tree-vect-patterns.c. This function checks if a loop is of dot production pattern. Specifically, according to the comment of this function:
/* Try to find the following pattern: type x_t, y_t; TYPE1 prod; TYPE2 sum = init; loop: sum_0 = phi <init, sum_1> S1 x_t = ... S2 y_t = ... S3 x_T = (TYPE1) x_t; S4 y_T = (TYPE1) y_t; S5 prod = x_T * y_T; [S6 prod = (TYPE2) prod; #optional] S7 sum_1 = prod + sum_0; where 'TYPE1' is exactly double the size of type 'type', and 'TYPE2' is the same size of 'TYPE1' or bigger. This is a special case of a reduction computation. */ This function should check if x_t and y_t have the same type (type) which has the half size of TYPE1. The corresponding code is shown below: oprnd0 = gimple_assign_rhs1 (stmt); oprnd1 = gimple_assign_rhs2 (stmt); if (!types_compatible_p (TREE_TYPE (oprnd0), prod_type) || !types_compatible_p (TREE_TYPE (oprnd1), prod_type)) return NULL; if (!type_conversion_p (oprnd0, stmt, true, &half_type0, &def_stmt, &promotion) || !promotion) return NULL; oprnd00 = gimple_assign_rhs1 (def_stmt); /*======================V see here! */ if (!type_conversion_p (oprnd0, stmt, true, &half_type1, &def_stmt, &promotion) || !promotion) return NULL; oprnd01 = gimple_assign_rhs1 (def_stmt); if (!types_compatible_p (half_type0, half_type1)) return NULL; if (TYPE_PRECISION (prod_type) != TYPE_PRECISION (half_type0) * 2) return NULL; Here the function uses x_T (oprnd0) to check the type of y_t, which is incorrect. The fix is simple: just replace it by oprnd1. The failed test case for this bug is shown below: int foo(short *a, int *b, int n) { int sum = 0; for (int i = 0; i < n; ++i) sum += a[i] * b[i]; return sum; } thanks, Cong Index: gcc/tree-vect-patterns.c =================================================================== --- gcc/tree-vect-patterns.c (revision 200988) +++ gcc/tree-vect-patterns.c (working copy) @@ -397,7 +397,7 @@ vect_recog_dot_prod_pattern (vec<gimple> || !promotion) return NULL; oprnd00 = gimple_assign_rhs1 (def_stmt); - if (!type_conversion_p (oprnd0, stmt, true, &half_type1, &def_stmt, + if (!type_conversion_p (oprnd1, stmt, true, &half_type1, &def_stmt, &promotion) || !promotion) return NULL;