https://gcc.gnu.org/g:d5db22c890df83f84d186916348d16b79f278b33

commit r16-5622-gd5db22c890df83f84d186916348d16b79f278b33
Author: Jakub Jelinek <[email protected]>
Date:   Wed Nov 26 10:57:37 2025 +0100

    match.pd: Use get_range_query (cfun) in more simplifications and pass 
current stmt to range_of_expr [PR119683]
    
    The following testcase regressed with r13-3596 which switched over
    vrp1 to ranger vrp.  Before that, I believe vrp1 was registering
    SSA_NAMEs with ASSERT_EXPRs at the start of bbs and so even when
    querying the global ranges from match.pd patterns during the vrp1
    pass, they saw the local ranges for a particular bb rather than global
    ranges.  In ranger vrp that doesn't happen anymore, so we need to
    pass a stmt to range_of_expr if we want the local ranges rather
    than global ones, plus should be using get_range_query (cfun)
    instead of get_global_range_query () (most patterns actually use
    the former already).  Now, for stmt the following patch attempts
    to pass the innermost stmt on which that particular capture appears
    as operand, but because some passes use match.pd folding on expressions
    not yet in the IL, I've added a helper function which tries to find out
    from a capture of the LHS operation whether it is a SSA_NAME with
    SSA_NAME_DEF_STMT which is in the IL right now and only query
    the ranger with that in that case, otherwise NULL (i.e. what it has
    been using before).
    
    2025-11-26  Jakub Jelinek  <[email protected]>
    
            PR tree-optimization/119683
            * gimple-match.h (gimple_match_ctx): New inline function.
            * match.pd ((mult (plus:s (mult:s @0 @1) @2) @3)): Capture
            PLUS, use get_range_query (cfun) instead of
            get_global_range_query () and pass gimple_match_ctx (@5)
            as 3rd argument to range_of_expr.
            ((plus (mult:s (plus:s @0 @1) @2) @3)): Similarly for MULT,
            with @4 instead of @5.
            ((t * u) / u -> t): Similarly with @2 instead of @4.
            ((t * u) / v -> t * (u / v)): Capture MULT, pass gimple_match_ctx 
(@3)
            as 3rd argument to range_of_expr.
            ((X + M*N) / N -> X / N + M): Pass gimple_match_ctx (@3) or
            gimple_match_ctx (@4) as 3rd arg to some range_of_expr calls.
            ((X - M*N) / N -> X / N - M): Likewise.
            ((X + C) / N -> X / N + C / N): Similarly.
            (((T)(A)) + CST -> (T)(A + CST)): Capture CONVERT, use
            get_range_query (cfun) instead of get_global_range_query ()
            and pass gimple_match_ctx (@2) as 3rd argument to range_of_expr.
            (x_5 == cstN ? cst4 : cst3): Capture EQNE and pass
            gimple_match_ctx (@4) as 3rd argument to range_of_expr.
    
            * gcc.dg/tree-ssa/pr119683.c: New test.

Diff:
---
 gcc/gimple-match.h                       | 13 +++++++
 gcc/match.pd                             | 64 ++++++++++++++++++++------------
 gcc/testsuite/gcc.dg/tree-ssa/pr119683.c | 19 ++++++++++
 3 files changed, 72 insertions(+), 24 deletions(-)

diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h
index 70f2f68827b4..a2c931fa60c7 100644
--- a/gcc/gimple-match.h
+++ b/gcc/gimple-match.h
@@ -427,4 +427,17 @@ bool directly_supported_p (code_helper, tree, tree,
 
 internal_fn get_conditional_internal_fn (code_helper, tree);
 
+/* If OP is a SSA_NAME with SSA_NAME_DEF_STMT in the IL, return that
+   stmt, otherwise NULL.  For use in range_of_expr calls.  */
+
+inline gimple *
+gimple_match_ctx (tree op)
+{
+  if (TREE_CODE (op) == SSA_NAME
+      && SSA_NAME_DEF_STMT (op)
+      && gimple_bb (SSA_NAME_DEF_STMT (op)))
+    return SSA_NAME_DEF_STMT (op);
+  return NULL;
+}
+
 #endif  /* GCC_GIMPLE_MATCH_H */
diff --git a/gcc/match.pd b/gcc/match.pd
index 2877f81e7a51..05c8b59eb9e8 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -648,7 +648,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* Similar to above, but there could be an extra add/sub between
    successive multuiplications.  */
 (simplify
- (mult (plus:s (mult:s@4 @0 INTEGER_CST@1) INTEGER_CST@2) INTEGER_CST@3)
+ (mult (plus:s@5 (mult:s@4 @0 INTEGER_CST@1) INTEGER_CST@2) INTEGER_CST@3)
  (with {
    bool overflowed = true;
    wi::overflow_type ovf1, ovf2;
@@ -661,7 +661,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 #if GIMPLE
       int_range_max vr0;
       if (ovf1 == wi::OVF_NONE && ovf2 == wi::OVF_NONE
-         && get_global_range_query ()->range_of_expr (vr0, @4)
+         && get_range_query (cfun)->range_of_expr (vr0, @4,
+                                                   gimple_match_ctx (@5))
          && !vr0.varying_p () && !vr0.undefined_p ())
        {
          wide_int wmin0 = vr0.lower_bound ();
@@ -688,7 +689,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
 /* Similar to above, but a multiplication between successive additions.  */
 (simplify
- (plus (mult:s (plus:s @0 INTEGER_CST@1) INTEGER_CST@2) INTEGER_CST@3)
+ (plus (mult:s (plus:s@4 @0 INTEGER_CST@1) INTEGER_CST@2) INTEGER_CST@3)
  (with {
    bool overflowed = true;
    wi::overflow_type ovf1;
@@ -702,7 +703,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 #if GIMPLE
       int_range_max vr0;
       if (ovf1 == wi::OVF_NONE && ovf2 == wi::OVF_NONE
-         && get_global_range_query ()->range_of_expr (vr0, @0)
+         && get_range_query (cfun)->range_of_expr (vr0, @0,
+                                                   gimple_match_ctx (@4))
          && !vr0.varying_p () && !vr0.undefined_p ())
        {
          wide_int wmin0 = vr0.lower_bound ();
@@ -1016,15 +1018,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (for div (trunc_div ceil_div floor_div round_div exact_div)
  /* Simplify (t * u) / u -> t.  */
  (simplify
-  (div (mult:c @0 @1) @1)
+  (div (mult:c@2 @0 @1) @1)
   (if (ANY_INTEGRAL_TYPE_P (type))
    (if (TYPE_OVERFLOW_UNDEFINED (type) && !TYPE_OVERFLOW_SANITIZED (type))
     @0
 #if GIMPLE
     (with {int_range_max vr0, vr1;}
      (if (INTEGRAL_TYPE_P (type)
-         && get_range_query (cfun)->range_of_expr (vr0, @0)
-         && get_range_query (cfun)->range_of_expr (vr1, @1)
+         && get_range_query (cfun)->range_of_expr (vr0, @0,
+                                                   gimple_match_ctx (@2))
+         && get_range_query (cfun)->range_of_expr (vr1, @1,
+                                                   gimple_match_ctx (@2))
          && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1))
       @0))
 #endif
@@ -1032,13 +1036,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 #if GIMPLE
  /* Simplify (t * u) / v -> t * (u / v) if u is multiple of v.  */
  (simplify
-  (div (mult @0 INTEGER_CST@1) INTEGER_CST@2)
+  (div (mult@3 @0 INTEGER_CST@1) INTEGER_CST@2)
   (if (INTEGRAL_TYPE_P (type)
        && wi::multiple_of_p (wi::to_widest (@1), wi::to_widest (@2), SIGNED))
    (if (TYPE_OVERFLOW_UNDEFINED (type) && !TYPE_OVERFLOW_SANITIZED (type))
     (mult @0 (div! @1 @2))
     (with {int_range_max vr0, vr1;}
-     (if (get_range_query (cfun)->range_of_expr (vr0, @0)
+     (if (get_range_query (cfun)->range_of_expr (vr0, @0,
+                                                gimple_match_ctx (@3))
          && get_range_query (cfun)->range_of_expr (vr1, @1)
          && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1))
       (mult @0 (div! @1 @2))))
@@ -1046,14 +1051,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 #endif
  /* Simplify (t * u) / (t * v) -> (u / v) if u is multiple of v.  */
  (simplify
-  (div (mult @0 INTEGER_CST@1) (mult @0 INTEGER_CST@2))
+  (div (mult@3 @0 INTEGER_CST@1) (mult @0 INTEGER_CST@2))
   (if (INTEGRAL_TYPE_P (type)
        && wi::multiple_of_p (wi::to_widest (@1), wi::to_widest (@2), SIGNED))
    (if (TYPE_OVERFLOW_UNDEFINED (type) && !TYPE_OVERFLOW_SANITIZED (type))
     (div @1 @2)
 #if GIMPLE
     (with {int_range_max vr0, vr1, vr2;}
-     (if (get_range_query (cfun)->range_of_expr (vr0, @0)
+     (if (get_range_query (cfun)->range_of_expr (vr0, @0,
+                                                gimple_match_ctx (@3))
          && get_range_query (cfun)->range_of_expr (vr1, @1)
          && get_range_query (cfun)->range_of_expr (vr2, @2)
          && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1)
@@ -1069,12 +1075,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (div (plus:c@4 @0 (mult:c@3 @1 @2)) @2)
   (with {int_range_max vr0, vr1, vr2, vr3, vr4;}
   (if (INTEGRAL_TYPE_P (type)
-       && get_range_query (cfun)->range_of_expr (vr1, @1)
-       && get_range_query (cfun)->range_of_expr (vr2, @2)
+       && get_range_query (cfun)->range_of_expr (vr1, @1,
+                                                gimple_match_ctx (@3))
+       && get_range_query (cfun)->range_of_expr (vr2, @2,
+                                                gimple_match_ctx (@3))
        /* "N*M" doesn't overflow.  */
        && range_op_handler (MULT_EXPR).overflow_free_p (vr1, vr2)
-       && get_range_query (cfun)->range_of_expr (vr0, @0)
-       && get_range_query (cfun)->range_of_expr (vr3, @3)
+       && get_range_query (cfun)->range_of_expr (vr0, @0,
+                                                gimple_match_ctx (@4))
+       && get_range_query (cfun)->range_of_expr (vr3, @3,
+                                                gimple_match_ctx (@4))
        /* "X+(N*M)" doesn't overflow.  */
        && range_op_handler (PLUS_EXPR).overflow_free_p (vr0, vr3)
        && get_range_query (cfun)->range_of_expr (vr4, @4)
@@ -1090,12 +1100,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (div (minus@4 @0 (mult:c@3 @1 @2)) @2)
   (with {int_range_max vr0, vr1, vr2, vr3, vr4;}
   (if (INTEGRAL_TYPE_P (type)
-       && get_range_query (cfun)->range_of_expr (vr1, @1)
-       && get_range_query (cfun)->range_of_expr (vr2, @2)
+       && get_range_query (cfun)->range_of_expr (vr1, @1,
+                                                gimple_match_ctx (@3))
+       && get_range_query (cfun)->range_of_expr (vr2, @2,
+                                                gimple_match_ctx (@3))
        /* "N * M" doesn't overflow.  */
        && range_op_handler (MULT_EXPR).overflow_free_p (vr1, vr2)
-       && get_range_query (cfun)->range_of_expr (vr0, @0)
-       && get_range_query (cfun)->range_of_expr (vr3, @3)
+       && get_range_query (cfun)->range_of_expr (vr0, @0,
+                                                gimple_match_ctx (@4))
+       && get_range_query (cfun)->range_of_expr (vr3, @3,
+                                                gimple_match_ctx (@4))
        /* "X - (N*M)" doesn't overflow.  */
        && range_op_handler (MINUS_EXPR).overflow_free_p (vr0, vr3)
        && get_range_query (cfun)->range_of_expr (vr4, @4)
@@ -1124,7 +1138,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       int_range_max vr0, vr1, vr3;
     }
     (if (INTEGRAL_TYPE_P (type)
-        && get_range_query (cfun)->range_of_expr (vr0, @0))
+        && get_range_query (cfun)->range_of_expr (vr0, @0,
+                                                  gimple_match_ctx (@3)))
      (if (exact_mod (c)
          && get_range_query (cfun)->range_of_expr (vr1, @1)
          /* "X+C" doesn't overflow.  */
@@ -4451,7 +4466,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* ((T)(A)) + CST -> (T)(A + CST)  */
 #if GIMPLE
   (simplify
-   (plus (convert:s SSA_NAME@0) INTEGER_CST@1)
+   (plus (convert:s@2 SSA_NAME@0) INTEGER_CST@1)
     (if (TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
          && TREE_CODE (type) == INTEGER_TYPE
          && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0))
@@ -4469,7 +4484,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
                            TYPE_SIGN (inner_type));
 
        int_range_max vr;
-       if (get_global_range_query ()->range_of_expr (vr, @0)
+       if (get_range_query (cfun)->range_of_expr (vr, @0,
+                                                  gimple_match_ctx (@2))
            && !vr.varying_p () && !vr.undefined_p ())
           {
            wide_int wmin0 = vr.lower_bound ();
@@ -6540,14 +6556,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    This was originally done by two_value_replacement in phiopt (PR 88676).  */
 (for eqne (ne eq)
  (simplify
-  (cond (eqne SSA_NAME@0 INTEGER_CST@1) INTEGER_CST@2 INTEGER_CST@3)
+  (cond (eqne@4 SSA_NAME@0 INTEGER_CST@1) INTEGER_CST@2 INTEGER_CST@3)
   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
        && INTEGRAL_TYPE_P (type)
        && (wi::to_widest (@2) + 1 == wi::to_widest (@3)
            || wi::to_widest (@2) == wi::to_widest (@3) + 1))
    (with {
      int_range_max r;
-     get_range_query (cfun)->range_of_expr (r, @0);
+     get_range_query (cfun)->range_of_expr (r, @0, gimple_match_ctx (@4));
      if (r.undefined_p ())
        r.set_varying (TREE_TYPE (@0));
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr119683.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr119683.c
new file mode 100644
index 000000000000..631ab43b7a7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr119683.c
@@ -0,0 +1,19 @@
+/* PR tree-optimization/119683 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times " = c_\[0-9]*\\\(D\\\) \\\+ 
\(?:\[0-9-]\)+;" 3 "optimized" } } */
+
+unsigned
+foo (signed char c)
+{
+  if (c >= '0' && c <= '9')
+    return c - '0';
+
+  if (c >= 'a' && c <= 'z')
+    return c - 'a' + 10;
+
+  if (c >= 'A' && c <= 'Z')
+    return c - 'A' + 10;
+
+  return -1;
+}

Reply via email to