On Sun, Oct 25, 2026 at 6:55 PM Andrea Pinski
<[email protected]> 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;
> --
> 2.43.0
>

Reply via email to