Discussion:
[PATCH] Fix PR63379
Richard Biener
2014-10-09 09:01:46 UTC
Permalink
This fixes SLP vectorization of a MIN/MAX reduction where we choose
a "neutral" element as the initial value of the first SLP group
member. That's of course wrong. Simply don't choose one in which
case the proper initial values will used.

Bootstrap / regtest running on x86_64-unknown-linux-gnu.

Richard.

2014-10-09 Richard Biener <***@suse.de>

PR tree-optimization/63379
* tree-vect-slp.c (vect_get_constant_vectors): Do not compute
a neutral operand for min/max.

* gcc.dg/vect/pr63379.c: New testcase.

Index: gcc/tree-vect-slp.c
===================================================================
--- gcc/tree-vect-slp.c (revision 215917)
+++ gcc/tree-vect-slp.c (working copy)
@@ -2395,13 +2395,8 @@ vect_get_constant_vectors (tree op, slp_
neutral_op = build_int_cst (TREE_TYPE (op), -1);
break;

- case MAX_EXPR:
- case MIN_EXPR:
- def_stmt = SSA_NAME_DEF_STMT (op);
- loop = (gimple_bb (stmt))->loop_father;
- neutral_op = PHI_ARG_DEF_FROM_EDGE (def_stmt,
- loop_preheader_edge (loop));
- break;
+ /* For MIN/MAX we don't have an easy neutral operand but
+ the initial values can be used fine here. */

default:
neutral_op = NULL;
Index: gcc/testsuite/gcc.dg/vect/pr63379.c
===================================================================
--- gcc/testsuite/gcc.dg/vect/pr63379.c (revision 0)
+++ gcc/testsuite/gcc.dg/vect/pr63379.c (working copy)
@@ -0,0 +1,43 @@
+/* PR tree-optimization/63379 */
+/* { dg-do run } */
+
+#include "tree-vect.h"
+
+extern void abort (void);
+
+typedef struct {
+ int x;
+ int y;
+} Point;
+
+Point pt_array[25];
+
+void __attribute__((noinline,noclone))
+generate_array(void)
+{
+ unsigned int i;
+ for (i = 0; i<25; i++)
+ {
+ pt_array[i].x = i;
+ pt_array[i].y = 1000+i;
+ }
+}
+
+int main()
+{
+ check_vect ();
+ generate_array ();
+ Point min_pt = pt_array[0];
+ Point *ptr, *ptr_end;
+ for (ptr = pt_array+1, ptr_end = pt_array+25; ptr != ptr_end; ++ptr)
+ {
+ min_pt.x = (min_pt.x < ptr->x) ? min_pt.x : ptr->x;
+ min_pt.y = (min_pt.y < ptr->y) ? min_pt.y : ptr->y;
+ }
+
+ if (min_pt.x != 0 || min_pt.y != 1000)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */

Loading...