This includes:
1) Not crashing in AccessEnforcementOpts in case we have an Unidentified storage access - rdar://problem/45956642 and rdar://problem/45956777
2) Actually supporting finding the storage locations if we do begin_access <block argument>
3) Test case for said support
We can merge out-of-scope regardless of having a conflict within a scope
i.e.
begin_access %x
end_access %x
begin_access %x
conflict
end_access %x
can be merged (same for the same scopes in reverse order)
We can always do so unless there's a conflict between the first end_access and the second begin_access
visitSetForConflicts Had a bug wherein we might change the accessSet while iterating over it by recording a conflict. This makes our current iterator invalid.
Work-around this issue by restarting the iteration in case we made any changes to the accessSet
Similarly, we do that for anywhere where in we recorded a conflict
The extra cost of deterministically deleting instructions is unnecessary. In the
long term, we'll want to verify that access markers exist after all SIL
passes. So just change their enforcement level rather than removing them.
Previously, it only folded begin/end access into a single runtime
operation. When all accessed for a uniquely identified storage object
have been folded, then they can all be removed.
Reworked the design of the pass so this falls out naturally just by
updating AccessedStorageAnalysis.
Use AccessedStorageAnalysis to find access markers with no nested conflicts.
This optimization analyzes the scope of each access to determine
whether it contains a potentially conflicting access. If not, then it
can be demoted to an instantaneous check, which still catches
conflicts on any enclosing outer scope.
This removes up to half of the runtime calls associated with
exclusivity checking.