On 2026-11-01 09:52, Andrea Pinski wrote:
On Sun, Nov 1, 2026 at 1:48 AM Torbjorn SVENSSON
<[email protected]> wrote:

Hi,

The new test is failing for MVE enabled targets on arm-none-eabi.

These are the errors produced for 
thumb/arch=armv8.1-m.main+mve.fp+fp.dp/cpu=cortex-m55/float-abi=hard/fpu=auto:

/build/gcc_src/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c: In function 'a':
/build/gcc_src/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c:10:14: error: 
incompatible types when initializing type 'v4sib' {aka '__vector(4) signed 
char:4'} using type '__vector(4) int'
/build/gcc_src/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c:11:14: error: 
incompatible types when initializing type 'v4sib' {aka '__vector(4) signed 
char:4'} using type '__vector(4) int'
/build/gcc_src/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c:12:3: error: 
cannot convert a value of type '__vector(4) signed char' to vector type 
'__vector(4) int' which has different size
/build/gcc_src/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c: In function 'b':
/build/gcc_src/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c:17:14: error: 
incompatible types when initializing type 'v4sib' {aka '__vector(4) signed 
char:4'} using type '__vector(4) int'
/build/gcc_src/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c:18:14: error: 
incompatible types when initializing type 'v4sib' {aka '__vector(4) signed 
char:4'} using type '__vector(4) int'
/build/gcc_src/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c:19:3: error: 
cannot convert a value of type '__vector(4) signed char' to vector type 
'__vector(4) int' which has different size

Any idea how to fix?

Yes, the best option is just to have it tested for x86_64/i386 and
aarch64.  vector_mask is not very portable.

Can you send a patch for that?

Kind regards,
Torbjörn



Kind regards,
Torbjörn

On 2026-10-25 18:54, Andrea Pinski wrote:
r17-4001-gbbc2517fe41 added support to combine_comparisons for LT/LE/GT/GE
but it assumed unsigned boolean types ([0,1]) which is wrong for signed
boolean types ([0,-1]). For an example, for signed boolean types,
LT is the same as GT for unsigned boolean types.  So this was combining
incorrectly and getting the incorrect answer.
This fixes the problem by adding support for signed boolean. Since we
need to pass in a new argument to combine_comparisons, this updates
all of the uses of combine_comparisons which makes the patch
look bigger than it really is.

Bootstrapped and tested on x86_64-linux-gnu with no regressions.

       PR tree-optimization/128123

gcc/ChangeLog:

       * fold-const.cc (combine_comparisons): Take new argument,
       inner_truth_type and look to see if it is signed boolean
       and support that for LT/LE/GT/GE.
       (fold_truth_andor_1): Update call to combine_comparisons.
       * fold-const.h (combine_comparisons): Add new argument.
       * gimple-fold.cc (and_comparisons_1): Update call to
       combine_comparisons.
       (or_comparisons_1): Likewise.
       * tree-ssa-ifcombine.cc (ifcombine_ifandif): Likewise.
       * tree-ssa-phiopt.cc (comparison_combine): Likewise.
       * match.pd (`(CMP) OP (CMP)`): Update call to
       combine_comparisons.

gcc/testsuite/ChangeLog:

       * gcc.dg/tree-ssa/vect-cmp-cmp-1.c: New test.

Signed-off-by: Andrea Pinski <[email protected]>
---
   gcc/fold-const.cc                             | 54 ++++++++++++++-----
   gcc/fold-const.h                              |  4 +-
   gcc/gimple-fold.cc                            |  8 +--
   gcc/match.pd                                  |  5 +-
   .../gcc.dg/tree-ssa/vect-cmp-cmp-1.c          | 34 ++++++++++++
   gcc/tree-ssa-ifcombine.cc                     | 15 ++++--
   gcc/tree-ssa-phiopt.cc                        |  2 +-
   7 files changed, 95 insertions(+), 27 deletions(-)
   create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 1fc4941b481..047c7dcada4 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -3010,13 +3010,21 @@ inverse_conditions_p (const_tree cond1, const_tree 
cond2)

   enum tree_code
   combine_comparisons (enum tree_code code, enum tree_code lcode,
-                    enum tree_code rcode, tree truth_type,
-                    bool honor_nans, tree *res)
+                  enum tree_code rcode, tree truth_type,
+                  tree inner_truth_type,
+                  bool honor_nans, tree *res)
   {
     enum comparison_code lcompcode = comparison_to_compcode (lcode);
     enum comparison_code rcompcode = comparison_to_compcode (rcode);
     int compcode;
     *res = NULL_TREE;
+  if (TREE_CODE (inner_truth_type) == VECTOR_TYPE)
+    inner_truth_type = TREE_TYPE (inner_truth_type);
+  bool signed_bool = false;
+  if (TYPE_SIGN (inner_truth_type) == SIGNED
+      && (TREE_CODE (inner_truth_type) == BOOLEAN_TYPE
+          || TYPE_PRECISION (inner_truth_type) == 1))
+    signed_bool = true;

     switch (code)
       {
@@ -3039,24 +3047,40 @@ combine_comparisons (enum tree_code code, enum 
tree_code lcode,
         compcode = ~(lcompcode ^ rcompcode);
         break;

-    //`bool0 < bool1` is `!bool0 & bool1`
+    //`bool0 < bool1` is `!bool0 & bool1` for unsigned
+    //`bool0 < bool1` is `bool0 & !bool1` for signed
       case LT_EXPR:
-      compcode = ~lcompcode & rcompcode;
+      if (signed_bool)
+        compcode = lcompcode & ~rcompcode;
+      else
+        compcode = ~lcompcode & rcompcode;
         break;

-    //`bool0 > bool1` is `bool0 & !bool1`
+    //`bool0 > bool1` is `bool0 & !bool1` for unsigned
+    //`bool0 > bool1` is `!bool0 & bool1` for signed
       case GT_EXPR:
-      compcode = lcompcode & ~rcompcode;
+      if (signed_bool)
+        compcode = ~lcompcode & rcompcode;
+      else
+        compcode = lcompcode & ~rcompcode;
         break;

-    // `bool0 <= bool1` as !bool0 | bool1
+    // `bool0 <= bool1` as !bool0 | bool1 for unsigned
+    // `bool0 <= bool1` as bool0 | !bool1 for signed
       case LE_EXPR:
-      compcode = ~lcompcode | rcompcode;
+      if (signed_bool)
+        compcode = lcompcode | ~rcompcode;
+      else
+        compcode = ~lcompcode | rcompcode;
         break;

-    //`bool0 >= bool1` is `bool0 | !bool1`
+    //`bool0 >= bool1` is `bool0 | !bool1` for unsigned
+    //`bool0 >= bool1` is `bool0 | !bool1` for signed
       case GE_EXPR:
-      compcode = lcompcode | ~rcompcode;
+      if (signed_bool)
+        compcode = ~lcompcode | rcompcode;
+      else
+        compcode = lcompcode | ~rcompcode;
         break;

       default:
@@ -3136,12 +3160,14 @@ tree
   combine_comparisons (location_t loc,
                    enum tree_code code, enum tree_code lcode,
                    enum tree_code rcode, tree truth_type,
+                  tree inner_truth_type,
                    tree ll_arg, tree lr_arg)
   {
     bool honor_nans = HONOR_NANS (ll_arg);
     tree_code rescode;
     tree res;
-  rescode = combine_comparisons (code, lcode, rcode, truth_type,
+  rescode = combine_comparisons (code, lcode, rcode,
+                              truth_type, inner_truth_type,
                                honor_nans, &res);
     if (rescode == ERROR_MARK)
       return NULL_TREE;
@@ -6504,7 +6530,8 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, 
tree truth_type,
             && operand_equal_p (lr_arg, rr_arg, 0))
       {
             result = combine_comparisons (loc, code, lcode, rcode,
-                                     truth_type, ll_arg, lr_arg);
+                                     truth_type, TREE_TYPE (lhs),
+                                     ll_arg, lr_arg);
         if (result)
           return result;
       }
@@ -6513,7 +6540,8 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, 
tree truth_type,
       {
             result = combine_comparisons (loc, code, lcode,
                                       swap_tree_comparison (rcode),
-                                     truth_type, ll_arg, lr_arg);
+                                     truth_type,  TREE_TYPE (lhs),
+                                     ll_arg, lr_arg);
         if (result)
           return result;
       }
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 437d8ece021..4e640de725f 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -180,9 +180,9 @@ extern bool fold_cmp_float_cst_p (const wide_int &lo, const 
wide_int &hi,
                                 const wide_int &i, signop isign);

   extern tree combine_comparisons (location_t, enum tree_code, enum tree_code,
-                              enum tree_code, tree, tree, tree);
+                              enum tree_code, tree, tree, tree, tree);
   extern tree_code combine_comparisons (enum tree_code, enum tree_code,
-                                   enum tree_code, tree, bool, tree*);
+                                   enum tree_code, tree, tree, bool, tree*);
   extern void debug_fold_checksum (const_tree);
   extern bool may_negate_without_overflow_p (const_tree);
   #define round_up(T,N) round_up_loc (UNKNOWN_LOCATION, T, N)
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index e0197edece6..ed84dab7f37 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -7602,7 +7602,7 @@ and_comparisons_1 (tree type, enum tree_code code1, tree 
op1a, tree op1b,
         /* Result will be either NULL_TREE, or a combined comparison.  */
         tree t = combine_comparisons (UNKNOWN_LOCATION,
                                   TRUTH_ANDIF_EXPR, code1, code2,
-                                 truth_type, op1a, op1b);
+                                 truth_type, truth_type, op1a, op1b);
         if (t)
       return t;
       }
@@ -7615,7 +7615,7 @@ and_comparisons_1 (tree type, enum tree_code code1, tree 
op1a, tree op1b,
         tree t = combine_comparisons (UNKNOWN_LOCATION,
                                   TRUTH_ANDIF_EXPR, code1,
                                   swap_tree_comparison (code2),
-                                 truth_type, op1a, op1b);
+                                 truth_type, truth_type, op1a, op1b);
         if (t)
       return t;
       }
@@ -9574,7 +9574,7 @@ or_comparisons_1 (tree type, enum tree_code code1, tree 
op1a, tree op1b,
         /* Result will be either NULL_TREE, or a combined comparison.  */
         tree t = combine_comparisons (UNKNOWN_LOCATION,
                                   TRUTH_ORIF_EXPR, code1, code2,
-                                 truth_type, op1a, op1b);
+                                 truth_type, truth_type, op1a, op1b);
         if (t)
       return t;
       }
@@ -9587,7 +9587,7 @@ or_comparisons_1 (tree type, enum tree_code code1, tree 
op1a, tree op1b,
         tree t = combine_comparisons (UNKNOWN_LOCATION,
                                   TRUTH_ORIF_EXPR, code1,
                                   swap_tree_comparison (code2),
-                                 truth_type, op1a, op1b);
+                                 truth_type, truth_type, op1a, op1b);
         if (t)
       return t;
       }
diff --git a/gcc/match.pd b/gcc/match.pd
index 696e69fd980..02941a7dacf 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3771,14 +3771,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (for cmp1 (tcc_comparison)
     (for cmp2 (tcc_comparison)
      (simplify
-    (bitop (cmp1 @0 @1) (cmp2 @0 @1))
+    (bitop (cmp1@2 @0 @1) (cmp2 @0 @1))
       (with rescmpcode (tcc_comparison)
         {
           tree_code rescmpcode;
           tree res;
           bool honor_nans = HONOR_NANS (@0);
           rescmpcode = combine_comparisons (bitop, cmp1, cmp2,
-                                       type, honor_nans, &res);
+                                       type, TREE_TYPE (@2),
+                                       honor_nans, &res);
         }
        (if (rescmpcode == INTEGER_CST)
         { res; }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c
new file mode 100644
index 00000000000..8ccf94df274
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vect-cmp-cmp-1.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-O -fgimple" } */
+/* PR tree-optimization/128123 */
+
+typedef int v4si __attribute__((vector_size (4*sizeof(int))));
+typedef v4si v4sib __attribute__((vector_mask));
+
+__attribute__((noipa)) void a(v4si *x, v4si *y, v4si *res)
+{
+  v4sib m1 = *x < *y;
+  v4sib m2 = *x > *y;
+  *res = (v4si) (m1 < m2);
+}
+
+__attribute__((noipa)) void b(v4si *x, v4si *y, v4si *res)
+{
+  v4sib m1 = *x < *y;
+  v4sib m2 = *x > *y;
+  *res = (v4si) (m1 <= m2);
+}
+
+int main (void)
+{
+  v4si x = { 1, 2, 3, 4 }, y = { 2, 2, 2, 5 };
+  v4si r;
+  a(&x, &y, &r);
+  v4si s;
+  b(&x, &y, &s);
+  for (int i = 0; i < 4; i++)
+    if (r[i] != -(x[i] < y[i]) || s[i] != -(x[i] <= y[i]))
+      __builtin_abort();
+  return 0;
+}
+
diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
index 28bb5bf0998..0d663f4130b 100644
--- a/gcc/tree-ssa-ifcombine.cc
+++ b/gcc/tree-ssa-ifcombine.cc
@@ -865,14 +865,16 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
        if (!inner_inv && !outer_inv)
       res = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ANDIF_EXPR,
                                  outer_cond_code, inner_cond_code,
-                                boolean_type_node, larg, rarg);
+                                boolean_type_node, boolean_type_node,
+                                larg, rarg);
         // If both are inverse, `!a && !b`, then handle it as `!(a || b)`
         // As that !a or !b are most likely not producing a comparison code.
         else if (inner_inv && outer_inv)
       {
         res = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ORIF_EXPR,
                                    outer_cond_code, inner_cond_code,
-                                  boolean_type_node, larg, rarg);
+                                  boolean_type_node, boolean_type_node,
+                                  larg, rarg);
         if (res)
           res = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (res), res);
       }
@@ -891,7 +893,8 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
         if (inner_cond_code1 != ERROR_MARK && outer_cond_code1 != ERROR_MARK)
           res = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ANDIF_EXPR,
                                      outer_cond_code1, inner_cond_code1,
-                                    boolean_type_node, larg, rarg);
+                                    boolean_type_node, boolean_type_node,
+                                    larg, rarg);
         // Otherwise, we need to try `!(!a || b)
         else if (inner_cond_code1 == ERROR_MARK)
           {
@@ -901,7 +904,8 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
             if (outer_cond_code1 != ERROR_MARK)
               res = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ORIF_EXPR,
                                          outer_cond_code1, inner_cond_code,
-                                        boolean_type_node, larg, rarg);
+                                        boolean_type_node, boolean_type_node,
+                                        larg, rarg);
             if (res)
               res = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (res), res);
           }
@@ -914,7 +918,8 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
             if (inner_cond_code1 != ERROR_MARK)
               res = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ORIF_EXPR,
                                          outer_cond_code, inner_cond_code1,
-                                        boolean_type_node, larg, rarg);
+                                        boolean_type_node, boolean_type_node,
+                                        larg, rarg);
             if (res)
               res = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (res), res);
           }
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 08b40897a60..51553484226 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -1651,7 +1651,7 @@ comparison_combine (basic_block cond_bb, basic_block 
middle_bb,
     tree result;
     tree_code newcmp_code;
     newcmp_code = combine_comparisons (logical, outer_code, inner_code,
-                                  boolean_type_node,
+                                  boolean_type_node, boolean_type_node,
                                    HONOR_NANS (larg), &result);
     if (newcmp_code == ERROR_MARK)
       return false;


Reply via email to