On Tue, 25 Nov 2025, Jakub Jelinek wrote:

> Hi!
> 
> 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).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

LGTM.  I wonder if it makes sense to wrap

get_range_query (cfun)->range_of_expr (r, @0, gimple_match_ctx (@4))

into sth like gimple_match_range_of_expr (r, @0, @4)?

Thanks,
Richard.

> 2025-11-25  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.
> 
> --- gcc/gimple-match.h.jj     2025-04-08 14:08:51.645276381 +0200
> +++ gcc/gimple-match.h        2025-11-25 16:08:41.399015100 +0100
> @@ -427,4 +427,17 @@ bool directly_supported_p (code_helper,
>  
>  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 */
> --- gcc/match.pd.jj   2025-11-25 10:03:25.201911338 +0100
> +++ gcc/match.pd      2025-11-25 16:22:57.214067092 +0100
> @@ -648,7 +648,7 @@ (define_operator_list SYNC_FETCH_AND_AND
>  /* 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_operator_list SYNC_FETCH_AND_AND
>  #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_operator_list SYNC_FETCH_AND_AND
>  
>  /* 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_operator_list SYNC_FETCH_AND_AND
>  #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_operator_list SYNC_FETCH_AND_AND
>  (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_operator_list SYNC_FETCH_AND_AND
>  #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_operator_list SYNC_FETCH_AND_AND
>  #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_operator_list SYNC_FETCH_AND_AND
>    (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_operator_list SYNC_FETCH_AND_AND
>    (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_operator_list SYNC_FETCH_AND_AND
>        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.  */
> @@ -4432,7 +4447,7 @@ (define_operator_list SYNC_FETCH_AND_AND
>  /* ((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))
> @@ -4450,7 +4465,8 @@ (define_operator_list SYNC_FETCH_AND_AND
>                           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 ();
> @@ -6521,14 +6537,14 @@ (define_operator_list SYNC_FETCH_AND_AND
>     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));
>  
> --- gcc/testsuite/gcc.dg/tree-ssa/pr119683.c.jj       2025-11-25 
> 16:29:51.980762609 +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/pr119683.c  2025-11-25 16:30:52.982673205 
> +0100
> @@ -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;
> +}
> 
>       Jakub
> 
> 

-- 
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