For commutative BB SLP nodes, don't retry a swap on a lane if doing so
would turn the first-lane operand columns into a mixed child shape.
PR125800 is exactly this case, the first lane already has ADD and
BIT_FIELD_REF in separate columns, and swapping a parent there breaks
that and externalizes more nodes.
The new testcase restricts exact dump checks to non-partial-vector targets,
since those targets may lower the reduction via fold-left and produce
different dump output.
PR tree-optimization/125800
gcc/
* tree-vect-slp.cc (vect_build_slp_tree_2): Skip stmt_can_swap
for lanes that would create a mixed child shape on swap retry.
gcc/testsuite/
* gcc.dg/vect/pr125800.c: New test.
Signed-off-by: Zhongyao Chen <[email protected]>
---
gcc/testsuite/gcc.dg/vect/pr125800.c | 51 ++++++++++++++++++++++++++++
gcc/tree-vect-slp.cc | 33 ++++++++++++++++++
2 files changed, 84 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/vect/pr125800.c
diff --git a/gcc/testsuite/gcc.dg/vect/pr125800.c
b/gcc/testsuite/gcc.dg/vect/pr125800.c
new file mode 100644
index 00000000000..39cffc73c3f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr125800.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-O2 -ftree-vectorize -fno-vect-cost-model
-fdump-tree-slp1-details" } */
+
+void
+pr125800 (double *__restrict colY0, double *__restrict colY1,
+ const double *__restrict colA0, const double *__restrict colA1,
+ const double *__restrict colX0, const double *__restrict colX1,
+ int ncolA)
+{
+ double rsum00 = 0, isum00 = 0, rsum01 = 0, isum01 = 0;
+ double rsum10 = 0, isum10 = 0, rsum11 = 0, isum11 = 0;
+
+ for (int kcolA = 0; kcolA < ncolA; kcolA++)
+ {
+ int raloc = 2 * kcolA;
+ int ialoc = raloc + 1;
+ double ar0 = colA0[raloc];
+ double ai0 = colA0[ialoc];
+ double ar1 = colA1[raloc];
+ double ai1 = colA1[ialoc];
+
+ int rxloc = 2 * kcolA;
+ int ixloc = rxloc + 1;
+ double xr0 = colX0[rxloc];
+ double xi0 = colX0[ixloc];
+ double xr1 = colX1[rxloc];
+ double xi1 = colX1[ixloc];
+
+ rsum00 += ar0 * xr0 - ai0 * xi0;
+ isum00 += ar0 * xi0 + ai0 * xr0;
+ rsum01 += ar0 * xr1 - ai0 * xi1;
+ isum01 += ar0 * xi1 + ai0 * xr1;
+ rsum10 += ar1 * xr0 - ai1 * xi0;
+ isum10 += ar1 * xi0 + ai1 * xr0;
+ rsum11 += ar1 * xr1 - ai1 * xi1;
+ isum11 += ar1 * xi1 + ai1 * xr1;
+ }
+
+ colY0[0] -= rsum00;
+ colY0[1] -= isum00;
+ colY1[0] -= rsum01;
+ colY1[1] -= isum01;
+ colY0[2] -= rsum10;
+ colY0[3] -= isum10;
+ colY1[2] -= rsum11;
+ colY1[3] -= isum11;
+}
+
+/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "slp1" } } */
+/* { dg-final { scan-tree-dump "SLP size 19" "slp1" { target { !
vect_partial_vectors } } } } */
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 2250f6f74a1..8a776ee01f0 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -2988,6 +2988,14 @@ out:
stmt_can_swap = NULL;
if (can_swap)
{
+ gassign *first_op0
+ = dyn_cast <gassign *> (oprnds_info[0]->def_stmts[0]->stmt);
+ gassign *first_op1
+ = dyn_cast <gassign *> (oprnds_info[1]->def_stmts[0]->stmt);
+ tree_code first_op0_code
+ = first_op0 ? gimple_assign_rhs_code (first_op0) : ERROR_MARK;
+ tree_code first_op1_code
+ = first_op1 ? gimple_assign_rhs_code (first_op1) : ERROR_MARK;
stmt_can_swap = XALLOCAVEC (bool, group_size);
for (j = 0; j < group_size; ++j)
{
@@ -3010,6 +3018,31 @@ out:
&& first_commutative_argument (fn) == 0);
}
+ if (j != 0
+ && stmt_can_swap[j]
+ && first_op0
+ && first_op1
+ && first_op0_code != first_op1_code)
+ {
+ gassign *lane_op0
+ = oprnds_info[0]->def_stmts[j]
+ ? dyn_cast <gassign *>
+ (oprnds_info[0]->def_stmts[j]->stmt)
+ : nullptr;
+ gassign *lane_op1
+ = oprnds_info[1]->def_stmts[j]
+ ? dyn_cast <gassign *>
+ (oprnds_info[1]->def_stmts[j]->stmt)
+ : nullptr;
+ /* Check column alignment by tree_code. */
+ if (lane_op0
+ && lane_op1
+ && gimple_assign_rhs_code (lane_op0) == first_op0_code
+ && gimple_assign_rhs_code (lane_op1) == first_op1_code)
+ /* Swap would create a mixed child shape. */
+ stmt_can_swap[j] = false;
+ }
+
if (j != 0 && !stmt_can_swap[j])
can_swap_nonmatching = false;
}
--
2.43.0