On Thu, Sep 10, 2026 at 09:46:22AM -0400, Andrew MacLeod wrote:
> 
> On 9/10/26 5:48 AM, Aldy Hernandez wrote:
> > [Andrew, are you OK with this?  It seems simple enough, but I may be
> > missing something subtle, or perhaps there is another place in the
> > compiler we should be fixing this?  Either way, it seems something
> > good to implement for completeness sake.  OK for trunk?]
> 
> 
> I'm OK with it... just check the performance... it'll probably trigger a
> bunch more edge range calculations...  At some point it might be worth
> adding some kind of indication to range-ops when a routine is "the
> default".  For instance, if op1_op2_relation is the default for handler,

I'm torn here.

VRP gets 0.8% slower, but the threader gets 3.4% slower.  All because
register_outgoing_edges is now 36% slower with the extra edge ranges.

I have some good will I've bought in the back threader, but it's
annoying.  I was hoping to use the good will with some sort of value
numbering to help us get memory stuff in the threader.

This catches real things I've run into, but honestly not
that many.  Up to you.

Aldy

> then we dont even need to check for that stmt.    Im not saying we do it
> now, but consider such a thing if performance starts to be impacted by some
> fo the checks we do. GORI might also benefit in places from it.  something
> to explore eventually.
> 
> Given that this seems OK, any reason why we would even check the type
> anymore?   could work with floating point or pointers too... I suspect its
> mostly an artifact from early days of relations...
> 
> Andrew
> 
> > 
> > A conditional such as:
> > 
> >    d_5 = a_3 - b_4;
> >    if (d_5 == 0)
> > 
> > implies a_3 == b_4 on the true edge regardless of overflow behavior,
> > but no relation was recorded because operator_minus lacks
> > op1_op2_relation and register_outgoing_edges only derives relations
> > from boolean exports.  Add the former and relax the latter.
> > 
> > match.pd already folds this:
> > 
> >    /* Transform comparisons of the form X - Y CMP 0 to X CMP Y.  */
> >    (cmp (sub@2 @0 @1) integer_zerop)
> >     (if (single_use (@2)) (cmp @0 @1))
> > 
> > but only for a single-use difference.
> > 
> > Tested on ppc64le Linux.
> > 
> > gcc/ChangeLog:
> > 
> >     * range-op-mixed.h (class operator_minus): Add op1_op2_relation.
> >     * range-op.cc (operator_minus::op1_op2_relation): New.
> >     * gimple-range-fold.cc (fur_source::register_outgoing_edges):
> >     Derive relations from any integral export, not just booleans.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * gcc.dg/tree-ssa/vrp-minus-relation-1.c: New test.
> > ---
> >   gcc/gimple-range-fold.cc                      |  5 ++++-
> >   gcc/range-op-mixed.h                          |  3 +++
> >   gcc/range-op.cc                               | 19 +++++++++++++++++++
> >   .../gcc.dg/tree-ssa/vrp-minus-relation-1.c    | 17 +++++++++++++++++
> >   4 files changed, 43 insertions(+), 1 deletion(-)
> >   create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-minus-relation-1.c
> > 
> > diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
> > index abe3ade2960..a143c19647a 100644
> > --- a/gcc/gimple-range-fold.cc
> > +++ b/gcc/gimple-range-fold.cc
> > @@ -1751,9 +1751,12 @@ fur_source::register_outgoing_edges (gcond *s, 
> > irange &lhs_range,
> >     // leading to the condition such as:
> >     // c_2 = a_4 < b_7
> >     // if (c_2)
> > +  // as well as relations implied by a known result, such as:
> > +  // c_2 = a_4 - b_7
> > +  // if (c_2 == 0)
> >     FOR_EACH_GORI_EXPORT_NAME (gori_ssa (), bb, name)
> >       {
> > -      if (TREE_CODE (TREE_TYPE (name)) != BOOLEAN_TYPE)
> > +      if (!INTEGRAL_TYPE_P (TREE_TYPE (name)))
> >     continue;
> >         gimple *stmt = SSA_NAME_DEF_STMT (name);
> >         gimple_range_op_handler handler (stmt);
> > diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
> > index 0e97fb11688..b084c3edeab 100644
> > --- a/gcc/range-op-mixed.h
> > +++ b/gcc/range-op-mixed.h
> > @@ -648,6 +648,7 @@ public:
> >     using range_operator::op1_range;
> >     using range_operator::op2_range;
> >     using range_operator::lhs_op1_relation;
> > +  using range_operator::op1_op2_relation;
> >     using range_operator::op1_op2_relation_effect;
> >     using range_operator::update_bitmask;
> >     bool op1_range (irange &r, tree type,
> > @@ -668,6 +669,8 @@ public:
> >     relation_kind lhs_op1_relation (const irange &lhs,
> >                               const irange &op1, const irange &op2,
> >                               relation_kind rel) const final override;
> > +  relation_kind op1_op2_relation (const irange &lhs, const irange &,
> > +                             const irange &) const final override;
> >     bool op1_op2_relation_effect (irange &lhs_range, tree type,
> >                             const irange &op1_range,
> >                             const irange &op2_range,
> > diff --git a/gcc/range-op.cc b/gcc/range-op.cc
> > index 350548951f4..07318bca71e 100644
> > --- a/gcc/range-op.cc
> > +++ b/gcc/range-op.cc
> > @@ -2102,6 +2102,25 @@ minus_op1_op2_relation_effect (irange &lhs_range, 
> > tree type,
> >     return true;
> >   }
> > +// Check if the LHS range indicates a relation between OP1 and OP2.
> > +// OP1 - OP2 == 0 implies OP1 == OP2 even with wrapping arithmetic.
> > +
> > +relation_kind
> > +operator_minus::op1_op2_relation (const irange &lhs, const irange &,
> > +                             const irange &) const
> > +{
> > +  if (lhs.undefined_p ())
> > +    return VREL_UNDEFINED;
> > +
> > +  if (lhs.zero_p ())
> > +    return VREL_EQ;
> > +
> > +  if (!lhs.contains_zero_p ())
> > +    return VREL_NE;
> > +
> > +  return VREL_VARYING;
> > +}
> > +
> >   bool
> >   operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
> >                                      const irange &op1_range,
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-minus-relation-1.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/vrp-minus-relation-1.c
> > new file mode 100644
> > index 00000000000..f071ffa5796
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-minus-relation-1.c
> > @@ -0,0 +1,17 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fdump-tree-vrp1" } */
> > +
> > +void dead (void);
> > +
> > +void f (int a, int b)
> > +{
> > +  int d = a - b;
> > +  if (d < 0)
> > +    return;
> > +  if (d > 0)
> > +    return;
> > +  if (a != b)
> > +    dead ();
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-not "dead" "vrp1" } } */
> 

Reply via email to