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