https://gcc.gnu.org/g:4fb8fb67284acfdf224f6855d809c4a298cc044a
commit r17-5334-g4fb8fb67284acfdf224f6855d809c4a298cc044a Author: Igor Shevlyakov <[email protected]> Date: Thu Oct 15 18:41:05 2026 -0700 match.pd: Sink FLOAT_EXPR/FIX_TRUNC_EXPR into VEC_COND_EXPR constant arms match.pd sinks conversions and some unary operations into the arms of a VEC_COND_EXPR when both arms fold, but not FLOAT_EXPR or FIX_TRUNC_EXPR. For r[i] = !(a[i] >= b[i]); with float r, a and b, the vectorizer produces _1 = VEC_COND_EXPR <mask_2, { 0, 0, 0, 0 }, { 1, 1, 1, 1 }>; _3 = (vector(4) float) _1; which is then expanded as a select of integer constants followed by a vector conversion, instead of a select of the float constants. Extend the convert sink to FLOAT_EXPR and FIX_TRUNC_EXPR. Its conditions apply unchanged: the mask must be the truth type of the result, and the new VEC_COND_EXPR must be expandable if the original one is. Assisted-by: Claude Opus 5.5 gcc/ChangeLog: * match.pd (convert (vec_cond)): Also handle float and fix_trunc. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/forwprop-vec-cond-float.c: New test. * gcc.dg/vect/vect-cond-15.c: New test. Signed-off-by: Igor Shevlyakov <[email protected]> Diff: --- gcc/match.pd | 15 ++++---- .../gcc.dg/tree-ssa/forwprop-vec-cond-float.c | 40 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/vect/vect-cond-15.c | 25 ++++++++++++++ 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index 7bb9126065dc..bdd874079631 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6604,13 +6604,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* Sink unary conversions to branches, but only if we do fold both and the target's truth type is the same as we already have. */ -(simplify - (convert (vec_cond:s @0 @1 @2)) - (if (VECTOR_TYPE_P (type) - && types_match (TREE_TYPE (@0), truth_type_for (type)) - && (expand_vec_cond_expr_p (type, TREE_TYPE (@0)) - || !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0)))) - (vec_cond @0 (convert! @1) (convert! @2)))) +(for op (convert float fix_trunc) + (simplify + (op (vec_cond:s @0 @1 @2)) + (if (VECTOR_TYPE_P (type) + && types_match (TREE_TYPE (@0), truth_type_for (type)) + && (expand_vec_cond_expr_p (type, TREE_TYPE (@0)) + || !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0)))) + (vec_cond @0 (op! @1) (op! @2))))) /* Likewise for view_convert of nop_conversions. */ (simplify diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-vec-cond-float.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-vec-cond-float.c new file mode 100644 index 000000000000..b4cabcd659f7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-vec-cond-float.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fgimple -fdump-tree-forwprop1 -Wno-psabi" } */ + +typedef float v4sf __attribute__ ((vector_size (16))); +typedef int v4si __attribute__ ((vector_size (16))); +typedef v4si v4sib __attribute__ ((vector_mask)); + +v4sf __GIMPLE (ssa) +f (v4sf a, v4sf b) +{ + v4sib m; + v4si s; + v4sf r; + +__BB(2): + m_3 = a_1(D) >= b_2(D); + s_4 = m_3 ? _Literal (v4si) { 0, 0, 0, 0 } + : _Literal (v4si) { 1, 1, 1, 1 }; + r_5 = (v4sf) s_4; + return r_5; +} + +v4si __GIMPLE (ssa) +g (v4sf a, v4sf b) +{ + v4sib m; + v4sf s; + v4si r; + +__BB(2): + m_3 = a_1(D) < b_2(D); + s_4 = m_3 ? _Literal (v4sf) { 2.5f, 2.5f, 2.5f, 2.5f } + : _Literal (v4sf) { 3.75f, 3.75f, 3.75f, 3.75f }; + r_5 = (v4si) s_4; + return r_5; +} + +/* { dg-final { scan-tree-dump-not "= \\(v4s\[fi\]\\)" "forwprop1" } } */ +/* { dg-final { scan-tree-dump "<m_3, { 0\\.0, 0\\.0, 0\\.0, 0\\.0 }, { 1\\.0e\\+0, 1\\.0e\\+0, 1\\.0e\\+0, 1\\.0e\\+0 }>" "forwprop1" } } */ +/* { dg-final { scan-tree-dump "<m_3, { 2, 2, 2, 2 }, { 3, 3, 3, 3 }>" "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-15.c b/gcc/testsuite/gcc.dg/vect/vect-cond-15.c new file mode 100644 index 000000000000..d9582381413b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-cond-15.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-require-effective-target vect_condition } */ +/* { dg-require-effective-target vect_intfloat_cvt } */ +/* { dg-additional-options "-fdump-tree-optimized" } */ + +/* The negated comparison becomes a { 0, 1 } integer select; it is done + on the float constants instead of being converted. */ + +void +f (float *__restrict r, float *__restrict a, float *__restrict b, int n) +{ + for (int i = 0; i < n; i++) + r[i] = !(a[i] >= b[i]); +} + +void +g (float *__restrict r, float *__restrict a, float *__restrict b, int n) +{ + for (int i = 0; i < n; i++) + r[i] = !(a[i] < b[i]); +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */ +/* { dg-final { scan-tree-dump-not "= \\(vector\\(\[^)\]*\\) float\\)" "optimized" } } */
