This is an archive of the discontinued LLVM Phabricator instance.

[SCEV] Do not erase LoopUsers. PR53969
ClosedPublic

Authored by mkazantsev on Feb 21 2022, 10:59 PM.

Details

Summary

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:

  1. We have a loop L and an AddRec AR that depends on it;
  2. We modify something in the loop, but don't destroy it. We still call forgetLoop on it;
  3. AR is no longer dependent on L according to LoopUsers. It is erased from ValueExprMap` and `ExprValue map, but still exists in UniqueSCEVs;
  4. We can later request the very same AddRec for the very same loop again, and get existing SCEV AR.
  5. Now, AR exists and is used again, but its notion that it depends on L is lost;
  6. Then we decide to delete L. AR will not be forgotten because we have lost it;
  7. 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.

Diff Detail

Event Timeline

mkazantsev created this revision.Feb 21 2022, 10:59 PM
mkazantsev requested review of this revision.Feb 21 2022, 10:59 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 21 2022, 10:59 PM
mkazantsev edited the summary of this revision. (Show Details)Feb 21 2022, 11:14 PM
nikic accepted this revision.Feb 22 2022, 12:11 AM

LGTM. It's a bit unfortunate that we conflate the notion of "forget this loop because we're about to delete it" and "forget this loop because we made a significant change to it", but as things are right now, I agree that dropping from LoopUsers is not correct here.

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 can't happen, because Loop addresses are not reused.

This revision is now accepted and ready to land.Feb 22 2022, 12:11 AM

JFYI: I ran it through 4k fuzzed Java tests and it didn't fail, so it should be ok.

This revision was landed with ongoing or failed builds.Feb 22 2022, 2:24 AM
This revision was automatically updated to reflect the committed changes.