On Wed, Aug 12, 2026 at 2:25 AM Daniel Barboza
<[email protected]> wrote:
>
> Given a bit_ior in the format A | B, if we know for certain that
> A != B then we can infer that A | B will always be nonzero.
>
> Bootstrapped and regression tested in x86_64, aarch64 and riscv64.

Ok.

>
>         PR tree-optimization/126743
>
> gcc/ChangeLog:
>
>         * range-op-mixed.h: declare.
>         * range-op.cc (operator_bitwise_or::op1_op2_relation_effect):
>         add op1 NE op2 relation range for op1 | op2 as nonzero.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/tree-ssa/pr126743.c: New test.
> ---
>  gcc/range-op-mixed.h                     |  6 ++++++
>  gcc/range-op.cc                          | 25 ++++++++++++++++++++++++
>  gcc/testsuite/gcc.dg/tree-ssa/pr126743.c | 23 ++++++++++++++++++++++
>  3 files changed, 54 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126743.c
>
> diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
> index a870a0c1211..0e97fb11688 100644
> --- a/gcc/range-op-mixed.h
> +++ b/gcc/range-op-mixed.h
> @@ -849,6 +849,7 @@ public:
>    using range_operator::fold_range;
>    using range_operator::op1_range;
>    using range_operator::op2_range;
> +  using range_operator::op1_op2_relation_effect;
>    using range_operator::update_bitmask;
>
>    bool fold_range (prange &r, tree type,
> @@ -861,6 +862,11 @@ public:
>    bool op2_range (irange &r, tree type,
>                   const irange &lhs, const irange &op1,
>                   relation_trio rel = TRIO_VARYING) const override;
> +  bool op1_op2_relation_effect (irange &lhs_range,
> +                               tree type,
> +                               const irange &op1_range,
> +                               const irange &op2_range,
> +                               relation_kind rel) const final override;
>    void update_bitmask (irange &r, const irange &lh,
>                        const irange &rh) const override;
>    // Check compatibility of all operands.
> diff --git a/gcc/range-op.cc b/gcc/range-op.cc
> index 07413ef7054..b878a6052c6 100644
> --- a/gcc/range-op.cc
> +++ b/gcc/range-op.cc
> @@ -4060,6 +4060,31 @@ operator_bitwise_or::wi_fold (irange &r, tree type,
>    value_range_with_overflow (r, type, new_lb, new_ub);
>  }
>
> +bool
> +operator_bitwise_or::op1_op2_relation_effect (irange &lhs_range,
> +                                             tree type,
> +                                             const irange &,
> +                                             const irange &,
> +                                             relation_kind rel) const
> +{
> +  if (rel == VREL_VARYING)
> +    return false;
> +
> +  int_range<2> rel_range;
> +
> +  switch (rel)
> +    {
> +    case VREL_NE:
> +      rel_range.set_nonzero (type);
> +      break;
> +    default:
> +      return false;
> +    }
> +
> +  lhs_range.intersect (rel_range);
> +  return true;
> +}
> +
>  bool
>  operator_bitwise_or::op1_range (irange &r, tree type,
>                                 const irange &lhs,
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126743.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr126743.c
> new file mode 100644
> index 00000000000..a99e6efbff9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126743.c
> @@ -0,0 +1,23 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-evrp" } */
> +
> +unsigned int
> +or_eq_zero (int a, int b)
> +{
> +  if (a == b)
> +    __builtin_unreachable ();
> +  // return 0;
> +  return (a | b) == 0;
> +}
> +
> +unsigned int
> +or_ne_zero (int a, int b)
> +{
> +  if (a == b)
> +    __builtin_unreachable ();
> +  // return 1;
> +  return (a | b) != 0;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "return 0;" 1 "evrp" } } */
> +/* { dg-final { scan-tree-dump-times "return 1;" 1 "evrp" } } */
> --
> 2.43.0
>

Reply via email to