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)
