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" } } */

Reply via email to