The following doesn't plug the hole I think there still is but
it makes sure we honor SLP scheduling constraints when we want
to schedule after a possibly trapping stmt.

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

        PR tree-optimization/126995
        * tree-vect-slp.cc (vect_schedule_slp_node): Keep
        schedule when we schedule to a point dominated by the
        trapping stmt.

        * gcc.dg/vect/bb-slp-pr126995.c: New testcase.
---
 gcc/testsuite/gcc.dg/vect/bb-slp-pr126995.c | 56 +++++++++++++++++++++
 gcc/tree-vect-slp.cc                        |  3 +-
 2 files changed, 58 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-pr126995.c

diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr126995.c 
b/gcc/testsuite/gcc.dg/vect/bb-slp-pr126995.c
new file mode 100644
index 00000000000..aa15d68cb23
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr126995.c
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+typedef struct
+{
+  int x;
+  int y;
+} cairo_point_t;
+
+typedef struct
+{
+  cairo_point_t a, b;
+} cairo_spline_knots_t;
+
+int _lerp_half_b_1, fallback;
+cairo_point_t _de_casteljau_ab, _de_casteljau_abbc;
+cairo_spline_knots_t _de_casteljau_s1;
+double sq_berr, sq_cdx, sq_cdy;
+
+void
+_lerp_half (cairo_point_t *a, cairo_point_t *result)
+{
+  result->x = a->x + (a->x >> 1);
+  result->y = a->y + (_lerp_half_b_1 >> 1);
+}
+
+void
+_de_casteljau (cairo_spline_knots_t *s2)
+{
+  cairo_point_t bc, bccd, final;
+
+  _lerp_half (&_de_casteljau_s1.b, &bc);
+  _lerp_half (&_de_casteljau_ab, &_de_casteljau_abbc);
+  _lerp_half (&bc, &bccd);
+  _lerp_half (&_de_casteljau_abbc, &final);
+
+  s2->a = final;
+  s2->b = bccd;
+}
+
+int
+_cairo_spline_decompose_into (cairo_spline_knots_t *s1)
+{
+  cairo_spline_knots_t s2, knots = *s1;
+  sq_cdx = knots.a.x;
+  sq_cdy = knots.a.y;
+  sq_berr = sq_cdx * sq_cdx + sq_cdy * sq_cdy;
+
+  if (sq_berr)
+    return fallback;
+
+  _de_casteljau (&s2);
+  _cairo_spline_decompose_into (&s2);
+
+  return 0;
+}
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index d06205e7f3e..4ef1f7b91b1 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -12190,7 +12190,8 @@ vect_schedule_slp_node (vec_info *vinfo,
       if (is_a <bb_vec_info> (vinfo)
          && !SLP_TREE_PERMUTE_P (node)
          && (!last_stmt
-             || gimple_bb (last_stmt) != gimple_bb (stmt_info->stmt))
+             || !dominated_by_p (CDI_DOMINATORS, gimple_bb (last_stmt),
+                                 gimple_bb (stmt_info->stmt)))
          && gimple_could_trap_p (stmt_info->stmt))
        {
          /* We've constrained possibly trapping operations to all come
-- 
2.51.0

Reply via email to