On Fri, May 15, 2026 at 6:21 AM Richard Biener <[email protected]> wrote: > > On Thu, May 14, 2026 at 4:11 AM Pengxuan Zheng > <[email protected]> wrote: > > > > The patch adds the following simplification pattern. > > > > (a == b) & (a == c) & (b != c) -> false > > > > Bootstrapped and tested on x86_64-linux-gnu and aarch64-linux-gnu. > > This feels like sth for reassoc instead (my hunch as soon as when > I see two or more &|^)?
So this is the transitive property being used here. So reassociation is not the right place. VRP is the place which should handle this but currently the transitive property usage is only across blocks and not associated with ssa names. I wonder if it is important to enhance VRP to handle this. so we have: _1 = a == b _2 = a == c _3 = _1 & _2 ;; // when true Implies a == b, a == c and b == c _4 = _b != c _r = _4 & _3 ;; _3 and _4 are opposites so they can never be true at the same time so false (note this I think is only true for integers or maybe !HONOR_NANS) This is definitely VRPish but I have not looked to see if there are any papers written on doing this in a reasonable way. I tried looking for one but I didn't see one. I am also not a fan of adding these transitive property/VRP match patterns either because where do we stop. We already have some patterns which are VRP-like already (though not using the transitive property): (a != b) & ((a|b) != 0) ((a ^ b) & c) cmp d || a != b a * ((a || b) != 0) x > y && x != XXX_MIN (X == CST1) && ((other)X OP2 CST2) (X == Y) && (X OP2 Y) etc. Adding these patterns definitely have been easier than enhancing VRP. But the question becomes maybe we should improve VRP in the end. Thanks, Andrea > > > PR tree-optimization/110922 > > > > gcc/ChangeLog: > > > > * match.pd ((a==b)&(a==c)&(b!=c)): New Pattern. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.dg/tree-ssa/pr110922.c: New test. > > > > Signed-off-by: Pengxuan Zheng <[email protected]> > > --- > > gcc/match.pd | 12 +++ > > gcc/testsuite/gcc.dg/tree-ssa/pr110922.c | 100 +++++++++++++++++++++++ > > 2 files changed, 112 insertions(+) > > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr110922.c > > > > diff --git a/gcc/match.pd b/gcc/match.pd > > index b037b1a2876..e6552c4e868 100644 > > --- a/gcc/match.pd > > +++ b/gcc/match.pd > > @@ -6643,6 +6643,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > (simplify > > (bitop (neeql @0 @1) (neeqr (bit_ior @0 @1) integer_zerop)) > > { constant_boolean_node (bitop == BIT_IOR_EXPR, type); })) > > + > > +/* (a == b) & (a == c) & (b != c) -> false */ > > +(simplify > > + (bit_and:c > > + (bit_and:c (eq:c @0 @1) (eq:c @0 @2)) > > + (ne:c @1 @2)) > > + { constant_boolean_node (false, type); }) > > +(simplify > > + (bit_and:c > > + (bit_and:c (eq:c @0 @1) (ne:c @1 @2)) > > + (eq:c @0 @2)) > > + { constant_boolean_node (false, type); }) > > #endif > > > > /* These was part of minmax phiopt. */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110922.c > > b/gcc/testsuite/gcc.dg/tree-ssa/pr110922.c > > new file mode 100644 > > index 00000000000..353c99bbc2d > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110922.c > > @@ -0,0 +1,100 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > > + > > +int f1(int a, int b, int c) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == c; > > + _Bool t2 = b != c; > > + return t&t1&t2; > > +} > > + > > +int f2(int a, int b, int c) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == c; > > + _Bool t2 = b != c; > > + return t1&t&t2; > > +} > > + > > +int f3(int a, int b, int c) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == c; > > + _Bool t2 = b != c; > > + return t2&(t&t1); > > +} > > + > > +int f4(int a, int b, int c) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == c; > > + _Bool t2 = b != c; > > + return t2&(t1&t); > > +} > > + > > +int f5(int a, int b, int c) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == c; > > + _Bool t2 = b != c; > > + return t&t2&t1; > > +} > > + > > +int f6(int a, int b, int c) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == c; > > + _Bool t2 = b != c; > > + return t2&t&t1; > > +} > > + > > +int f7(int a, int b, int c) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == c; > > + _Bool t2 = b != c; > > + return t2&(t&t1); > > +} > > + > > +int f8(int a, int b, int c) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == c; > > + _Bool t2 = b != c; > > + return t2&(t1&t); > > +} > > + > > +int f9(int a, int b) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == 0; > > + _Bool t2 = b != 0; > > + return t&(t1&t2); > > +} > > + > > +int f10(int a, int b) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == 0; > > + _Bool t2 = b != 0; > > + return t&(t2&t1); > > +} > > + > > +int f11(int a, int b) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == 0; > > + _Bool t2 = b != 0; > > + return (t1&t2)&t; > > +} > > + > > +int f12(int a, int b) > > +{ > > + _Bool t = a == b; > > + _Bool t1 = a == 0; > > + _Bool t2 = b != 0; > > + return (t2&t1)&t; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "return 0;" 12 "optimized" } } */ > > -- > > 2.34.1 > >
