https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103721
--- Comment #5 from Andrew Macleod <amacleod at redhat dot com> --- > How does equivalence handling in the Ranger world work once you traverse the > backedge of a loop? There are 2 aspects. Ranger itself registers equivalence sets by basic block, not by name. All lookups are done via the dominator tree. The definition of a name creates an equivalence record containing just that name in it def block. When that name is registered in an equivalence, there will be an equivalence record in that block created combining the equivalence set of each name in the block. When we check for equivalence, we look up the "current" equivalence set for BOTH names in the dominator tree. They are only considered equivalent if both queries come up with the same set. Anything else means the equivalence set for one of the names has changed, so they are no longer equivalent. So far I have not found this to be an issue with back edges. We basically defer validation of equivalences until we go to look it up, and then require the 2 searches to come back with the same result. With the Definitions acting as "equivalency" killers, we don't pick up old equivalencies from back edges. Assuming I set everything up right :-) The threader adds a path_oracle on top of that which proceeds to manage its own relations and equivalences along the path. It first tries to resolve equivalences from within the path, and if it doesn't find anything, reverts to a ranger query at the top of the path. Thus is can inherit anything ranger knows coming into the path but it is subject to getting things right within the path. There have been a few issues along the way getting this right. I think I may have found the issue with this particular case: When I try to thread the path by hand, it boils down to the following (equivalence set created in { }: <bb2> <bb9> # searchVolume_5 = PHI <world_7(D)(2)> { _5, world_7 } # currentVolume_6 = PHI <0(2)> { _6 } [1,1] = searchVolume_5 != currentVolume_6; [1,1] = searchVolume_5 != 0; [1,1] = _2 & _3; goto <bb 3>; [89.00%] <bb3> <bb4> <bb8> # searchVolume_11 = PHI <1(4), 0(3)> { _11 } # currentVolume_8 = searchVolume_5 { _5, _8 , world_7 } <bb9> # searchVolume_5 = PHI <searchVolume_11(8)> { _5, _11 } # currentVolume_6 = PHI <currentVolume_8(8)> { whoops } _2 = searchVolume_5 != currentVolume_6 _3 = searchVolume_5 != 0; _4 = _2 & _3; When it creates the equivalency set for _6, it queries the equivalence set of _8, and comes up with { _5, _8, world_7 }.. which is wrong because _5 is in a set with {_5, _11} now. In fact, the code wont come out exactly like this in the end because its SSA. so the _5 and _6 will be renamed to something new, but I think we are doing the analysis using the original names until wehave done all the threading.. Which is why we are folding the _5 != _6 comparison "thinking" they are equivalent. First, When we combine the equivalence sets for _6 and _8, we should be confirming the equivalence set matches for each element.. so a check for _5, _8 and world_7 would eliminate _5 from the equivalency set for _8.... and we would then generate an equivalency set of {_6, _8, world_7 }... which would then be correct. What its missing is we aren't suppose to register the equivalency set without confirming each member at that location. Even fixing this, I think there is still an issue as this does not fix pr104067.. so I think there is still an underlying issue within the path oracle. I dont know precisely how it all works together but I believe the threader queues up all its changes, and then does all the work at the end? I think there is something going on with different generations of name from one thread to another. I'll try to work thru it and discuss it with aldy tomorrow when he returns.