This patch fixes a logical error in how we work with LoopUsers map.
It maps a loop onto a set of AddRecs that depend on it. The Addrecs
are added to this map only once when they are created and put to
the UniqueSCEVs` map.
The only purpose of this map is to make sure that, whenever we forget
a loop, all (directly or indirectly) dependent SCEVs get forgotten too.
Current code erases SCEVs from dependent set of a given loop whenever
we forget this loop. This is not a correct behavior due to the following scenario:
- We have a loop L and an AddRec AR that depends on it;
- We modify something in the loop, but don't destroy it. We still call forgetLoop on it;
- AR is no longer dependent on L according to LoopUsers. It is erased from ValueExprMap` and `ExprValue map, but still exists in UniqueSCEVs;
- We can later request the very same AddRec for the very same loop again, and get existing SCEV AR.
- Now, AR exists and is used again, but its notion that it depends on L is lost;
- Then we decide to delete L. AR will not be forgotten because we have lost it;
- Just you wait when you run into a dangling pointer problem, or any other kind of problem because an active SCEV is now referecing a non-existent loop.
The solution to this is to stop erasing values from LoopUsers. Yes, we will maybe forget something
that is already not used, but it's cheap. The only real problem we can run into is following: if we
delete a loop, and then create a new loop by the same address, this may cause cache confusion.
However, this still should be safe because the *only* purpose of LoopUsers is invalidation, and
invalidation never reads loops from AddRecs.
This fixes a functional bug and potentially may have negative compile time impact on methods with
huge or numerous loops.