On Wed, 19 Nov 2025, [email protected] wrote:

> From: Dhruv Chawla <[email protected]>
> 
> These patterns should not be in match.pd as they require range
> information checks that ideally belong in VRP. They were also causing
> breakages as the checks weren't tight enough.
> 
> Bootstrapped and regtested on aarch64-linux-gnu.

OK.

> Signed-off-by: Dhruv Chawla <[email protected]>
> 
>       PR tree-optimization/122733
> 
> gcc/ChangeLog:
> 
>       * match.pd: Remove patterns. Also call constant_boolean_node instead of
>       build_one_cst and build_zero_cst.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.dg/match-shift-cmp-1.c: Update test to only check
>       equality.
>       * gcc.dg/match-shift-cmp-2.c: Likewise.
>       * gcc.dg/match-shift-cmp-3.c: Likewise.
>       * gcc.dg/match-shift-cmp-4.c: Removed.
> ---
>  gcc/match.pd                             | 26 ++----------
>  gcc/testsuite/gcc.dg/match-shift-cmp-1.c | 11 +----
>  gcc/testsuite/gcc.dg/match-shift-cmp-2.c | 23 ++---------
>  gcc/testsuite/gcc.dg/match-shift-cmp-3.c | 27 ++++++-------
>  gcc/testsuite/gcc.dg/match-shift-cmp-4.c | 51 ------------------------
>  5 files changed, 22 insertions(+), 116 deletions(-)
>  delete mode 100644 gcc/testsuite/gcc.dg/match-shift-cmp-4.c
> 
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 63d56b08192..9b42c4e3c59 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -1339,37 +1339,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>      (if (INTEGRAL_TYPE_P (type))
>        (rshift (op @0 @2) @1))))
>  
> -/* (y << x) == x -> 0 when y != 0.  */
> +/* (y << x) == x -> false when y != 0.  */
>  (simplify
>    (eq:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
>    (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
>         && tree_expr_nonzero_p (@0))
> -   { build_zero_cst (type); }))
> -
> -/* (y << x) {<,<=} x -> 0 when y > 0.  */
> -(for cmp (lt le)
> -  (simplify
> -    (cmp:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
> -    (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
> -      && tree_expr_nonzero_p (@0)
> -      && tree_expr_nonnegative_p (@0))
> -     { build_zero_cst (type); })))
> +   { constant_boolean_node (false, type); }))
>  
> -/* (y << x) != x -> 1 when y != 0.  */
> +/* (y << x) != x -> true when y != 0.  */
>  (simplify
>    (ne:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
>    (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
>         && tree_expr_nonzero_p (@0))
> -   { build_one_cst (type); }))
> -
> -/* (y << x) {>,>=} x -> 1 when y > 0.  */
> -(for cmp (gt ge)
> -  (simplify
> -    (cmp:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
> -    (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
> -      && tree_expr_nonzero_p (@0)
> -      && tree_expr_nonnegative_p (@0))
> -     { build_one_cst (type); })))
> +   { constant_boolean_node (true, type); }))
>  
>  /* Fold (1 << (C - x)) where C = precision(type) - 1
>     into ((1 << C) >> x). */
> diff --git a/gcc/testsuite/gcc.dg/match-shift-cmp-1.c 
> b/gcc/testsuite/gcc.dg/match-shift-cmp-1.c
> index b22d57d370f..7a69cd19437 100644
> --- a/gcc/testsuite/gcc.dg/match-shift-cmp-1.c
> +++ b/gcc/testsuite/gcc.dg/match-shift-cmp-1.c
> @@ -34,17 +34,8 @@ typedef enum
>  
>  TEST_OP_CST (eq, ==, 1)
>  TEST_OP_CST (ne, !=, 2)
> -TEST_OP_CST (lt, <, 3)
> -TEST_OP_CST (gt, >, 4)
> -TEST_OP_CST (le, <=, 5)
> -TEST_OP_CST (ge, >=, 6)
>  
>  TEST_OP (eq, ==)
>  TEST_OP (ne, !=)
> -TEST_OP (lt, <)
> -TEST_OP (gt, >)
> -TEST_OP (le, <=)
> -TEST_OP (ge, >=)
>  
> -/* FIXME: The lt, le, gt and ge cases for int and enum don't get optimized.  
> */
> -/* { dg-final { scan-tree-dump-times "<<" 8 optimized } } */
> +/* { dg-final { scan-tree-dump-not "<<" optimized } } */
> diff --git a/gcc/testsuite/gcc.dg/match-shift-cmp-2.c 
> b/gcc/testsuite/gcc.dg/match-shift-cmp-2.c
> index 96a2fd954f6..3d514ba1ee1 100644
> --- a/gcc/testsuite/gcc.dg/match-shift-cmp-2.c
> +++ b/gcc/testsuite/gcc.dg/match-shift-cmp-2.c
> @@ -36,27 +36,12 @@ typedef enum
>  
>  TEST_OP_CST (eq, ==, 0)
>  TEST_OP_CST (ne, !=, 0)
> -TEST_OP_CST (lt, <, 0)
> -TEST_OP_CST (gt, >, 0)
> -TEST_OP_CST (le, <=, 0)
> -TEST_OP_CST (ge, >=, 0)
>  
>  TEST_OP (eq, ==)
>  TEST_OP (ne, !=)
> -TEST_OP (lt, <)
> -TEST_OP (gt, >)
> -TEST_OP (le, <=)
> -TEST_OP (ge, >=)
>  
>  /* These end up getting folded by other patterns.  */
> -/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) == 0" 8 optimized } } */
> -/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) != 0" 8 optimized } } */
> -/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) > 0" 4 optimized } } */
> -/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) < 0" 4 optimized } } */
> -/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) >= 0" 4 optimized } } */
> -/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) <= 0" 4 optimized } } */
> -/* { dg-final { scan-tree-dump-times "~x_\\d\\(D\\)" 4 optimized } } */
> -/* { dg-final { scan-tree-dump-times "return x_\\d\\(D\\);" 4 optimized } } 
> */
> -/* { dg-final { scan-tree-dump-times "return 0;" 4 optimized } } */
> -/* { dg-final { scan-tree-dump-times "return 1;" 4 optimized } } */
> -/* Total: 48.  */
> +/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) == 0" 6 optimized } } */
> +/* { dg-final { scan-tree-dump-times "x_\\d\\(D\\) != 0" 6 optimized } } */
> +/* { dg-final { scan-tree-dump-times "~x_\\d\\(D\\)" 2 optimized } } */
> +/* { dg-final { scan-tree-dump-times "return x_\\d\\(D\\);" 2 optimized } } 
> */
> diff --git a/gcc/testsuite/gcc.dg/match-shift-cmp-3.c 
> b/gcc/testsuite/gcc.dg/match-shift-cmp-3.c
> index 34380cfeb96..e46ac30b905 100644
> --- a/gcc/testsuite/gcc.dg/match-shift-cmp-3.c
> +++ b/gcc/testsuite/gcc.dg/match-shift-cmp-3.c
> @@ -1,25 +1,27 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O2 -fdump-tree-optimized" } */
>  
> -/* The fold (y << x) <op> x -> 0|1 shouldn't trigger when y is negative or
> -   zero unsigned (except for == and !=).  */
> +/* The fold (y << x) <op> x -> 0|1 should trigger when y is negative
> +   unsigned.  */
>  
>  #define TEST_ONE_CST(n, op, type, cst)                                       
>   \
> -  bool lshift_cst_##type##_##n (type x) { return ((cst << x) op x); }
> +  bool lshift_cst_##type##_##n (type x) { return ((unsigned) (cst) << x) op 
> x; }
>  
>  #define TEST_OP_CST(n, op, cst)                                              
>   \
> +  TEST_ONE_CST (n, op, unsigned, cst)                                        
>   \
>    TEST_ONE_CST (n, op, int, cst)                                             
>   \
>    TEST_ONE_CST (n, op, test_enum, cst)
>  
>  #define TEST_ONE(n, op, type)                                                
>   \
>    bool lshift_##type##_##n (type x, type y)                                  
>   \
>    {                                                                          
>   \
> -    if (y > 0)                                                               
>   \
> +    if ((int) y <= 0)                                                        
>   \
>        __builtin_unreachable ();                                              
>   \
> -    return ((y << x) op x);                                                  
>   \
> +    return ((unsigned) (y) << x) op x;                                       
>   \
>    }
>  
>  #define TEST_OP(n, op)                                                       
>   \
> +  TEST_ONE (n, op, unsigned)                                                 
>   \
>    TEST_ONE (n, op, int)                                                      
>   \
>    TEST_ONE (n, op, test_enum)
>  
> @@ -31,14 +33,11 @@ typedef enum
>    TWO = 2
>  } test_enum;
>  
> -TEST_OP_CST (lt, <, -1)
> -TEST_OP_CST (gt, >, -2)
> -TEST_OP_CST (le, <=, -3)
> -TEST_OP_CST (ge, >=, -4)
> +TEST_OP_CST (eq, ==, -1)
> +TEST_OP_CST (ne, !=, -2)
>  
> -TEST_OP (lt, <)
> -TEST_OP (gt, >)
> -TEST_OP (le, <=)
> -TEST_OP (ge, >=)
> +TEST_OP (eq, ==)
> +TEST_OP (ne, !=)
>  
> -/* { dg-final { scan-tree-dump-times "<<" 16 optimized } } */
> +/* { dg-final { scan-tree-dump-times "return 0;" 6 optimized } } */
> +/* { dg-final { scan-tree-dump-times "return 1;" 6 optimized } } */
> diff --git a/gcc/testsuite/gcc.dg/match-shift-cmp-4.c 
> b/gcc/testsuite/gcc.dg/match-shift-cmp-4.c
> deleted file mode 100644
> index 629e2a376d1..00000000000
> --- a/gcc/testsuite/gcc.dg/match-shift-cmp-4.c
> +++ /dev/null
> @@ -1,51 +0,0 @@
> -/* { dg-do compile } */
> -/* { dg-options "-O2 -fdump-tree-optimized" } */
> -
> -/* The fold (y << x) <op> x -> 0|1 should trigger when y is negative
> -   unsigned.  */
> -
> -#define TEST_ONE_CST(n, op, type, cst)                                       
>   \
> -  bool lshift_cst_##type##_##n (type x) { return ((unsigned) (cst) << x) op 
> x; }
> -
> -#define TEST_OP_CST(n, op, cst)                                              
>   \
> -  TEST_ONE_CST (n, op, unsigned, cst)                                        
>   \
> -  TEST_ONE_CST (n, op, int, cst)                                             
>   \
> -  TEST_ONE_CST (n, op, test_enum, cst)
> -
> -#define TEST_ONE(n, op, type)                                                
>   \
> -  bool lshift_##type##_##n (type x, type y)                                  
>   \
> -  {                                                                          
>   \
> -    if ((int) y <= 0)                                                        
>   \
> -      __builtin_unreachable ();                                              
>   \
> -    return ((unsigned) (y) << x) op x;                                       
>   \
> -  }
> -
> -#define TEST_OP(n, op)                                                       
>   \
> -  TEST_ONE (n, op, unsigned)                                                 
>   \
> -  TEST_ONE (n, op, int)                                                      
>   \
> -  TEST_ONE (n, op, test_enum)
> -
> -typedef enum
> -{
> -  MONE = -1,
> -  ZERO = 0,
> -  ONE = 1,
> -  TWO = 2
> -} test_enum;
> -
> -TEST_OP_CST (eq, ==, -1)
> -TEST_OP_CST (ne, !=, -2)
> -TEST_OP_CST (lt, <, -3)
> -TEST_OP_CST (gt, >, -4)
> -TEST_OP_CST (le, <=, -5)
> -TEST_OP_CST (ge, >=, -6)
> -
> -TEST_OP (eq, ==)
> -TEST_OP (ne, !=)
> -TEST_OP (lt, <)
> -TEST_OP (gt, >)
> -TEST_OP (le, <=)
> -TEST_OP (ge, >=)
> -
> -/* { dg-final { scan-tree-dump-times "return 0;" 18 optimized } } */
> -/* { dg-final { scan-tree-dump-times "return 1;" 18 optimized } } */
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to