And now the rest of the fix for 90036.  Two changes of note.

First, when recording temporary equivalences from the edge info cache, if the equivalence has the form:

[0/1] = A EQ/NE CST;

Go ahead and backprop that equivalence to the uses of A.

Concretely from the BZ we have this:

;;   basic block 2, loop depth 0
;;    pred:       ENTRY
  _1 = vptr_14(D) == 0;
  _2 = ownvptr_15(D) != 0;
  _3 = _1 | _2;
  if (_3 != 0)
    goto <bb 4>; [67.00%]
  else
    goto <bb 3>; [33.00%]
;;    succ:       4
;;                3
[ ... ]

;;   basic block 4, loop depth 0
;;    pred:       2
  if (vptr_14(D) != 0)
    goto <bb 5>; [25.37%]
  else
    goto <bb 10>; [74.63%]
;;    succ:       5
;;                10

;;   basic block 5, loop depth 0
;;    pred:       4
  # definition_10 = PHI <0(4)>
  # vstring_9 = PHI <0B(4)>
  if (ownvptr_15(D) != 0)
    goto <bb 7>; [80.00%]
  else
    goto <bb 6>; [20.00%]
;;    succ:       7
;;                6

;;   basic block 6, loop depth 0
;;    pred:       5
  sprintf (p_13(D), "~%%%s", vstring_9);
  goto <bb 10>; [100.00%]
;;    succ:       10

So when DOM discovers the edge equivalence for vptr_14 on the 4->5 edge DOM now back-propagates the value to the uses of vptr_14, particularly uses in bb#1.  That allows us to discover a simple equivalence for _1 which is a key nugget to unlocking this BZ.

1 = (_3 != 0) by way of traversing the 2->4 edge.
1 = (vptr_14 != 0) by way of traversing the 4->5 edge
_1 = 0 by backproping the state of vptr_14 to use point in bb1

The last step is to back-propagate the _1 = 0 equivalence to the use points of _1 in bb1.  In particular to this statement

_3 = _1 | _2;

If we know that _1 == 0, then _3 and _2 must have the same values (nonzero in this case).

_2 = ownvptr_15(D) != 0;

Since we know the state of _2, we can compute the state of ownvptr_15.  Which was the goal.  We're still on the 4->5 edge, but we've managed to compute an equivalence for ownvptr_15 which in turn allows us to know how the branch at the end of bb5 will go.

Note this is not jump threading.  It's a conditional equivalence with back propagation.

The additional lookups in the hash table trigger messages in the dump file.  The unconstrained_commons.f test scans the DOM dump file to ensure certain messages never appear.  That scan test is now bogus.  The test has other things it checks to ensure DOM hasn't done anything wrong.  So that one scan test in unconstrained_commons.f has been removed.

Bootstrapped and regression tested on x86, armv7, loongarch64, riscv64.  Regression tested on the usual crosses as well.
commit 55c6baeb86b10912e98f4cf6b0a432d7c896d81e
Author: Jeff Law <[email protected]>
Date:   Sun Feb 22 09:26:38 2026 -0700

    [1/n][PR tree-optimization/90036] All refinement of entries in DOM hash 
table
    
    This is the first of a few patches to fix pr90036.
    
    I've gone back and forth about whether or not to fix this for gcc-16 or 
queue
    for gcc-17.  Ultimately I don't think these opportunities are *that* 
common, so
    I don't expect widespread code generation changes.
    
    I'm going to drop the changes in a small series as the changes stand on 
their
    own.  This gives us better bisectability.
    
    --
    
    The first patch allows refinement of existing equivalences in a case where 
we'd
    missed it before.  In particular say we have <res> = <expr> in the 
expression
    hash table.  We later use <expr> in a way that creates a temporary 
expression
    equivalence.  We'll fail to record that temporary expression equivalence
    because of the pre-existing entry in the hash table.
    
    And just to be clear, the old equivalence will be restored when we leave the
    domwalk scope of the newer, more precise, hash table entry.
    
    This matters for pr90036 as we initially enter a simple equivalence in the
    table with the result being an SSA_NAME.  Later we have a conditional that
    allows us to refine the result to a constant.  And we're going to need that
    constant result to trigger additional simplifications and equivalence
    discovery.
    
    Bootstrapped and regression tested on x86_64, aarch64, riscv64 and probably 
a
    couple others as well.  It's also been tested across the embedded targets 
in my
    tester.  Pushing to the trunk.
    
            PR tree-optimization/90036
    gcc/
            * tree-ssa-scopedtables.cc (avail_exprs_stack::record_cond): Always
            record the new hash table entry.

diff --git a/gcc/tree-ssa-scopedtables.cc b/gcc/tree-ssa-scopedtables.cc
index 828f214c7cb..95523b23478 100644
--- a/gcc/tree-ssa-scopedtables.cc
+++ b/gcc/tree-ssa-scopedtables.cc
@@ -392,13 +392,13 @@ avail_exprs_stack::record_cond (cond_equivalence *p)
   expr_hash_elt **slot;
 
   slot = m_avail_exprs->find_slot_with_hash (element, element->hash (), 
INSERT);
-  if (*slot == NULL)
-    {
-      *slot = element;
-      record_expr (element, NULL, '1');
-    }
-  else
-    delete element;
+
+  /* We will always get back a valid slot in the hash table.  Go ahead and
+     record the new equivalence.  While it may be overwriting something older,
+     the belief is that the newer equivalence is more likely to be useful as
+     it was derived using more information/context.  */
+  record_expr (element, *slot, '1');
+  *slot = element;
 }
 
 /* Generate a hash value for a pair of expressions.  This can be used

Reply via email to