https://gcc.gnu.org/g:fea8a2b9bf26f654ec0b97d43259dad5b0275c00
commit r17-4401-gfea8a2b9bf26f654ec0b97d43259dad5b0275c00 Author: Andrew MacLeod <[email protected]> Date: Wed Sep 16 07:15:42 2026 -0400 Keep partial equivalences out of ordering relations. If a partial equivalence and a normal relation both exist, prefer the normal relation. Also, partial equivalences should not be entered into the path oracle, nor should they be combined with normal relations when recording a relation. Assisted-By: Claude Opus 5 gcc/ * value-relation.cc (dom_oracle::query): Prefer a normal relation over a partial equivalency. (path_oracle::record): Do not record partial equivalences, nor intersect one with the relation being recorded. gcc/testsuite/ * gcc.dg/tree-ssa/vrp-rel3.c: New. Diff: --- gcc/testsuite/gcc.dg/tree-ssa/vrp-rel3.c | 42 ++++++++++++++++++++++++++++++++ gcc/value-relation.cc | 28 +++++++++++++-------- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-rel3.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-rel3.c new file mode 100644 index 000000000000..6a0a32fee01c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-rel3.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +/* Masking with 0xff makes C a partial equivalence of A, and unlike the cast + case both names have the same type, so an ordinary comparison can relate + the pair as well. A partial equivalence and an ordering relation do not + combine, but the partial equivalence must not hide the ordering either. */ + +void keep (void); +void kill (void); + +void +f1 (int a, int b) +{ + int c = a & 0xff; + if (c > b) + if (b > a) + { + if (c > a) + keep (); + else + kill (); + } +} + +/* Same shape with a mask which is not a partial equivalence, as a control. */ +void +f2 (int a, int b) +{ + int c = a & 0xfe; + if (c > b) + if (b > a) + { + if (c > a) + keep (); + else + kill (); + } +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ +/* { dg-final { scan-tree-dump-times "keep" 2 "evrp" } } */ diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc index 0eb6bdec75fa..f5b286128353 100644 --- a/gcc/value-relation.cc +++ b/gcc/value-relation.cc @@ -1880,17 +1880,17 @@ dom_oracle::query (basic_block bb, tree ssa1, tree ssa2) if (bitmap_bit_p (equiv1, v2) && bitmap_bit_p (equiv2, v1)) return VREL_EQ; - kind = partial_equiv (ssa1, ssa2); - if (kind != VREL_VARYING) - return kind; - - // Initially look for a direct relationship and just return that. + // A statement such as c = a & 0xff makes a partial equivalence between + // c and a, and an ordinary comparison can then relate the same pair. + // If both exist, prefer the relation, so look for that first. kind = find_relation_dom (bb, ssa1, ssa2); - if (kind != VREL_VARYING) - return kind; + // If no direct relation exists, try the query using the equivalence sets. + if (kind == VREL_VARYING) + kind = query (bb, equiv1, equiv2); - // Query using the equivalence sets. - kind = query (bb, equiv1, equiv2); + // Finally look for partial equivalences. + if (kind == VREL_VARYING) + kind = partial_equiv (ssa1, ssa2); return kind; } @@ -2078,8 +2078,16 @@ path_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) if (ssa1 == ssa2) return false; + // Partial equivalences are tracked in the root equivalence oracle rather + // than on the path. Registering a partial equivalence in the path would + // cause normal relations to collapse to VARYING. + if (relation_partial_equiv_p (k)) + return false; + relation_kind curr = query (bb, ssa1, ssa2); - if (curr != VREL_VARYING) + // Likewise, a partial equivalency result should not be combined with K + // or the result drops to VARYING. + if (curr != VREL_VARYING && !relation_partial_equiv_p (curr)) k = relation_intersect (curr, k); // Do not register an impossible relation.
