[PATCH] [vectorizer] Fixing a bug in tree-vect-patterns.c in GCC vectorizer.
Cong Hou
congh@google.com
Fri Sep 13 18:28:00 GMT 2013
A new test case is added to testsuite/gcc.dg/vect, which will fail
without this patch and pass with it. Bootstrap also get passed. No
additional test failure is introduced.
The new test case includes a dot product on two arrays with short and
int types. The loop will still be vectorized (using punpcklwd on array
with short type), but should not be recognized as a dot-product
pattern.
thanks,
Cong
Index: gcc/tree-vect-patterns.c
===================================================================
--- gcc/tree-vect-patterns.c (revision 202572)
+++ 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;
Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog (revision 202572)
+++ gcc/ChangeLog (working copy)
@@ -1,3 +1,9 @@
+2013-09-13 Cong Hou <congh@google.com>
+
+ * tree-vect-patterns.c (vect_recog_dot_prod_pattern): Fix a bug
+ when checking the dot production pattern. The type of rhs operand
+ of multiply is now checked correctly.
+
2013-09-13 Jan Hubicka <jh@suse.cz>
PR middle-end/58094
Index: gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s16c.c
===================================================================
--- gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s16c.c (revision 0)
+++ gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s16c.c (revision 0)
@@ -0,0 +1,73 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define DOT 43680
+
+signed short X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+signed int Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+
+/* (short, int)->int->int dot product.
+ Not detected as a dot-product pattern. */
+
+__attribute__ ((noinline)) int
+foo (int len)
+{
+ int i;
+ int result = 0;
+
+ for (i = 0; i < len; i++)
+ {
+ result += (X[i] * Y[i]);
+ }
+ return result;
+}
+
+
+/* (int, short)->int->int dot product.
+ Not detected as a dot-product pattern. */
+
+__attribute__ ((noinline)) int
+bar (int len)
+{
+ int i;
+ int result = 0;
+
+ for (i = 0; i < len; i++)
+ {
+ result += (Y[i] * X[i]);
+ }
+ return result;
+}
+
+int
+main (void)
+{
+ int i;
+ int dot;
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ X[i] = i;
+ Y[i] = N - i;
+ __asm__ volatile ("");
+ }
+
+ dot = foo (N);
+ if (dot != DOT)
+ abort ();
+
+ dot = bar (N);
+ if (dot != DOT)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" {
target vect_unpack } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
Index: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog (revision 202572)
+++ gcc/testsuite/ChangeLog (working copy)
@@ -1,3 +1,9 @@
+2013-09-13 Cong Hou <congh@google.com>
+
+ * gcc.dg/vect/vect-reduc-dot-s16c.c: Add a test case with dot product
+ on two arrays with short and int types. This should not be recognized
+ as a dot product pattern.
+
2013-09-13 Kai Tietz <ktietz@redhat.com>
gcc.target/i386/pr57848.c: New file.
On Wed, Sep 11, 2013 at 6:55 PM, Xinliang David Li <davidxl@google.com> wrote:
> Can you add a test case to the regression suite?
>
> When the type of arguments are unsigned short/unsigned int, GCC does
> not vectorize the loop anymore -- this is worth a separate bug to
> track. punpcklwd instruction can be used to do zero extension of the
> short type.
>
> David
>
> On Wed, Sep 11, 2013 at 6:16 PM, Cong Hou <congh@google.com> wrote:
>> 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;
More information about the Gcc-patches
mailing list