https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109564
--- Comment #14 from Richard Biener <rguenth at gcc dot gnu.org> ---
I think the issue is a bit more involved - when
_1 = PHI <_2, _3>
and _2 is UNDEFINED _on the edge!_, the equivalence _1 == _3 only holds
when the condition making _2 UNDEFINED holds. Trivially that's for
all blocks dominated by that edge but that's exactly zero blocks
(unless it's a backedge but that would likely have other issues).
Now, when the edge was proven to be not executable the story is different
I think - still the equivalence then only holds for blocks dominated by
the PHI. So we can replace _1 with _3 but not _3 with _1 outside of such
region.
The bottom line is equivalences derived from PHIs are conditional (not global),
much like equivalences derived from if (_1 == _2) are. But somehow
they end up being used differently:
Optimizing block #12
1>>> STMT 1 = _3 le_expr -65536
1>>> STMT 1 = _3 ge_expr -65536
1>>> STMT 1 = _3 eq_expr -65536
1>>> STMT 0 = _3 ne_expr -65536
0>>> COPY _3 = -65536
Optimizing statement if (_1 != -65536)
226 range_of_expr(_1) at stmt if (_1 != -65536)
227 range_on_entry (_1) to BB 12
228 range_of_stmt (_1) at stmt _1 = *spec_16(D).state_size;
TRUE : (228) cached (_1) [irange] long int VARYING
_1 : CACHE: BB 12 DOM query for _1, found [irange] long int [-65536, -65536][1,
1600] at BB5
CACHE: Range for DOM returns : [irange] long int [-65536, -65536][1, 1600]
Filled from dominator! : [irange] long int [-65536, -65536][1, 1600]
good sofar, but then:
Checking Equivalence ( == ) state_size_8
CACHE: BB 12 DOM query for state_size_8, found [irange] long int [1, 1600]
NONZERO 0x7ff at BB5
CACHE: Range for DOM returns : [irange] long int [1, 1600] NONZERO 0x7ff
Equivalence update! : state_size_8 has range : [irange] long int [1, 1600]
NONZERO 0x7ff refining range to :[irange] long int [1, 1600] NONZERO 0x7ff
oops.