This plugs the remaining hole in the previous fix, now with
test coverage.  The assert needs to become a scheduling failure.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/126995
        * tree-vect-slp.cc (vect_schedule_slp_node): When we cannot
        place according to constraints for possibly trapping stmts,
        fail.

        * gcc.dg/vect/bb-slp-pr126995-2.c: New testcase.
---
 gcc/testsuite/gcc.dg/vect/bb-slp-pr126995-2.c | 75 +++++++++++++++++++
 gcc/tree-vect-slp.cc                          | 12 ++-
 2 files changed, 83 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-pr126995-2.c

diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr126995-2.c 
b/gcc/testsuite/gcc.dg/vect/bb-slp-pr126995-2.c
new file mode 100644
index 00000000000..118e8bc12c4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr126995-2.c
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+/* { dg-additional-options "-mavx2" { target avx2 } } */
+
+typedef enum
+{
+  CAIRO_STATUS_LAST_STATUS
+} cairo_status_t;
+typedef struct
+{
+  int x;
+  int y;
+} cairo_point_t;
+
+typedef struct
+{
+  cairo_point_t a, b, c, d;
+} cairo_spline_knots_t;
+
+double _cairo_spline_decompose_into_tolerance_squared;
+
+static void
+_lerp_half (cairo_point_t *a, cairo_point_t *b, cairo_point_t *result)
+{
+  result->x = a->x + (b->x - a->x >> 1);
+  result->y = a->y + (b->y - a->y >> 1);
+}
+
+static void
+_de_casteljau (cairo_spline_knots_t *s1, cairo_spline_knots_t *s2)
+{
+  cairo_point_t ab, bc, cd, abbc, bccd, final;
+  _lerp_half (&s1->a, &s1->b, &ab);
+  _lerp_half (&s1->b, &s1->c, &bc);
+  _lerp_half (&ab, &bc, &abbc);
+  _lerp_half (&bc, &cd, &bccd);
+  _lerp_half (&abbc, &bccd, &final);
+  s2->a = final;
+  s2->b = s2->c = cd;
+  s1->c = abbc;
+  s1->d = final;
+}
+
+static double
+_cairo_spline_error_squared (cairo_spline_knots_t *knots)
+{
+  double cdy = knots->a.y;
+  cdy = 0;
+  if (knots->a.x != knots->d.x || knots->d.y)
+    {
+      double dx, dy, u, v;
+      dx = (double)(knots->d.x - knots->a.x);
+      dy = (double)(knots->d.y - knots->a.y);
+      v = dx * dx + dy * dy;
+      u = 0 * dx * dy;
+      if (u <= 0)
+        cdy -= v * dy;
+    }
+  if (knots->a.y > cdy)
+    return knots->a.y;
+  return 0;
+}
+
+cairo_status_t
+_cairo_spline_decompose_into (cairo_spline_knots_t *s1)
+{
+  cairo_spline_knots_t s2;
+  if (_cairo_spline_error_squared (s1)
+      < _cairo_spline_decompose_into_tolerance_squared)
+    return 0;
+  _de_casteljau (s1, &s2);
+  _cairo_spline_decompose_into (s1);
+  _cairo_spline_decompose_into (&s2);
+  return 0;
+}
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 0e74ac00075..18fb1168a3b 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -12200,10 +12200,14 @@ vect_schedule_slp_node (vec_info *vinfo,
             This is only necessary for BB vectorization since for loop vect
             all operations are in a single BB and scalar stmt based
             placement doesn't play well with epilogue vectorization.  */
-         gcc_assert (!last_stmt
-                     || dominated_by_p (CDI_DOMINATORS,
-                                        gimple_bb (stmt_info->stmt),
-                                        gimple_bb (last_stmt)));
+         if (last_stmt
+             && !dominated_by_p (CDI_DOMINATORS,
+                                 gimple_bb (stmt_info->stmt),
+                                 gimple_bb (last_stmt)))
+           {
+             gcc_assert (place_only);
+             return false;
+           }
          si = gsi_after_labels (gimple_bb (stmt_info->stmt));
          last_stmt = gsi_stmt (si);
        }
-- 
2.51.0

Reply via email to