On Thu, 27 Nov 2025, Jakub Jelinek wrote:

> Hi!
> 
> The following patch is a small extension of the previous patch to pass stmt
> context to the ranger queries from match.pd where possible, so that we can
> use local ranges on a particular statement rather than global ones.
> 
> expr_not_equal_to also uses the ranger, so when possible this passes it
> the statement context.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Richard.

> 2025-11-27  Jakub Jelinek  <[email protected]>
> 
>       * fold-const.h (expr_not_equal_to): Add gimple * argument defaulted
>       to NULL.
>       * fold-const.cc (expr_not_equal_to): Likewise, pass it through to
>       range_of_expr.
>       * generic-match-head.cc (gimple_match_ctx): New static inline.
>       * match.pd (X % -Y -> X % Y): Capture NEGATE and pass
>       gimple_match_ctx (@2) as new 3rd argument to expr_not_equal_to.
>       ((A * C) +- (B * C) -> (A+-B) * C): Pass gimple_match_ctx (@3)
>       as new 3rd argument to expr_not_equal_to.
>       (a rrotate (bitsize-b) -> a lrotate b): Likewise.
> 
> --- gcc/fold-const.h.jj       2025-11-24 17:17:33.860960760 +0100
> +++ gcc/fold-const.h  2025-11-26 16:16:44.155650861 +0100
> @@ -223,7 +223,7 @@ extern bool merge_ranges (int *, tree *,
>  extern tree sign_bit_p (tree, const_tree);
>  extern bool simple_condition_p (tree);
>  extern tree exact_inverse (tree, tree);
> -extern bool expr_not_equal_to (tree t, const wide_int &);
> +extern bool expr_not_equal_to (tree t, const wide_int &, gimple * = NULL);
>  extern tree const_unop (enum tree_code, tree, tree);
>  extern tree vector_const_binop (enum tree_code, tree, tree,
>                               tree (*) (enum tree_code, tree, tree));
> --- gcc/fold-const.cc.jj      2025-11-24 17:17:33.848960971 +0100
> +++ gcc/fold-const.cc 2025-11-26 16:16:18.700091782 +0100
> @@ -10938,10 +10938,12 @@ tree_expr_nonzero_p (tree t)
>    return ret;
>  }
>  
> -/* Return true if T is known not to be equal to an integer W.  */
> +/* Return true if T is known not to be equal to an integer W.
> +   If STMT is specified, the check is if T on STMT is not equal
> +   to W.  */
>  
>  bool
> -expr_not_equal_to (tree t, const wide_int &w)
> +expr_not_equal_to (tree t, const wide_int &w, gimple *stmt /* = NULL */)
>  {
>    int_range_max vr;
>    switch (TREE_CODE (t))
> @@ -10953,7 +10955,7 @@ expr_not_equal_to (tree t, const wide_in
>        if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
>       return false;
>  
> -      get_range_query (cfun)->range_of_expr (vr, t);
> +      get_range_query (cfun)->range_of_expr (vr, t, stmt);
>        if (!vr.undefined_p () && !vr.contains_p (w))
>       return true;
>        /* If T has some known zero bits and W has any of those bits set,
> --- gcc/generic-match-head.cc.jj      2025-10-06 09:38:31.865370145 +0200
> +++ gcc/generic-match-head.cc 2025-11-26 16:22:53.872248271 +0100
> @@ -203,3 +203,9 @@ bitwise_inverted_equal_p (tree expr1, tr
>      }
>    return false;
>  }
> +
> +static inline gimple *
> +gimple_match_ctx (tree)
> +{
> +  return NULL;
> +}
> --- gcc/match.pd.jj   2025-11-26 14:55:52.453747538 +0100
> +++ gcc/match.pd      2025-11-26 16:21:13.416987904 +0100
> @@ -920,7 +920,7 @@ (define_operator_list SYNC_FETCH_AND_AND
>  
>  /* X % -Y is the same as X % Y.  */
>  (simplify
> - (trunc_mod @0 (convert? (negate @1)))
> + (trunc_mod @0 (convert? (negate@2 @1)))
>   (if (INTEGRAL_TYPE_P (type)
>        && !TYPE_UNSIGNED (type)
>        && !TYPE_OVERFLOW_TRAPS (type)
> @@ -930,7 +930,8 @@ (define_operator_list SYNC_FETCH_AND_AND
>        INT_MIN % -(-1) into invalid INT_MIN % -1.  */
>        && (expr_not_equal_to (@0, wi::to_wide (TYPE_MIN_VALUE (type)))
>         || expr_not_equal_to (@1, wi::minus_one (TYPE_PRECISION
> -                                                     (TREE_TYPE (@1))))))
> +                                                     (TREE_TYPE (@1))),
> +                             gimple_match_ctx (@2))))
>    (trunc_mod @0 (convert @1))))
>  
>  /* X - (X / Y) * Y is the same as X % Y.  */
> @@ -4711,7 +4712,8 @@ (define_operator_list SYNC_FETCH_AND_AND
>       || TYPE_OVERFLOW_WRAPS (type)
>       || (INTEGRAL_TYPE_P (type)
>           && tree_expr_nonzero_p (@0)
> -         && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
> +         && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)),
> +                               gimple_match_ctx (@3))))
>      (if (single_use (@3) || single_use (@4))
>       /* If @1 +- @2 is constant require a hard single-use on either
>       original operand (but not on both).  */
> @@ -4731,16 +4733,19 @@ (define_operator_list SYNC_FETCH_AND_AND
>         || (INTEGRAL_TYPE_P (type)
>             && ((tree_expr_nonzero_p (@0)
>                  && expr_not_equal_to (@0,
> -                             wi::minus_one (TYPE_PRECISION (type))))
> +                             wi::minus_one (TYPE_PRECISION (type)),
> +                             gimple_match_ctx (@3)))
>                 || (plusminus == PLUS_EXPR
>                     ? expr_not_equal_to (@2,
> -                         wi::max_value (TYPE_PRECISION (type), SIGNED))
> +                         wi::max_value (TYPE_PRECISION (type), SIGNED),
> +                         gimple_match_ctx (@3))
>                     /* Let's ignore the @0 -1 and @2 min case.  */
>                     : (expr_not_equal_to (@2,
> -                         wi::min_value (TYPE_PRECISION (type), SIGNED))
> +                         wi::min_value (TYPE_PRECISION (type), SIGNED),
> +                         gimple_match_ctx (@3))
>                        && expr_not_equal_to (@2,
>                               wi::min_value (TYPE_PRECISION (type), SIGNED)
> -                             + 1))))))
> +                             + 1, gimple_match_ctx (@3)))))))
>        && single_use (@3))
>       (mult (plusminus { build_one_cst (type); } @2) @0)))
>     (simplify
> @@ -4755,11 +4760,13 @@ (define_operator_list SYNC_FETCH_AND_AND
>             && ((tree_expr_nonzero_p (@0)
>                  && (plusminus == MINUS_EXPR
>                      || expr_not_equal_to (@0,
> -                             wi::minus_one (TYPE_PRECISION (type)))))
> +                             wi::minus_one (TYPE_PRECISION (type)),
> +                             gimple_match_ctx (@3))))
>                 || expr_not_equal_to (@2,
>                       (plusminus == PLUS_EXPR
>                        ? wi::max_value (TYPE_PRECISION (type), SIGNED)
> -                      : wi::min_value (TYPE_PRECISION (type), SIGNED))))))
> +                      : wi::min_value (TYPE_PRECISION (type), SIGNED)),
> +                     gimple_match_ctx (@3)))))
>        && single_use (@3))
>        (mult (plusminus @2 { build_one_cst (type); }) @0)))))
>   /* (A * B) + (-C) -> (B - C/A) * A, if C is a multiple of A.  */
> @@ -5360,7 +5367,8 @@ (define_operator_list SYNC_FETCH_AND_AND
>     (if (prec == wi::to_wide (@1))
>      (switch
>       (if (expr_not_equal_to (@2, wi::uhwi (prec,
> -                                        TYPE_PRECISION (TREE_TYPE (@2)))))
> +                                        TYPE_PRECISION (TREE_TYPE (@2))),
> +                          gimple_match_ctx (@3)))
>        (orotate @0 @2))
>       (if (single_use (@3)
>         && pow2p_hwi (prec)
> 
>       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