Skip to content

[Exclusivity] Handle mayRelease instructions conservatively in AccessnforcementOpts and LICM #19119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 5, 2018

Conversation

shajrawi
Copy link

@shajrawi shajrawi commented Sep 4, 2018

radar rdar://problem/42841839

@shajrawi shajrawi requested a review from atrick September 4, 2018 17:20
@shajrawi
Copy link
Author

shajrawi commented Sep 4, 2018

@atrick Can you please review?

@shajrawi
Copy link
Author

shajrawi commented Sep 4, 2018

@swift-ci Please test

@@ -534,9 +534,21 @@ static bool handledEndAccesses(BeginAccessInst *BI, SILLoop *Loop) {
return true;
}

static bool isCoveredByScop(BeginAccessInst *BI, DominanceInfo *DT,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "scop" a typo or a term I don't know?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops! typo :) should be scope of course - thanks!

@shajrawi
Copy link
Author

shajrawi commented Sep 4, 2018

@swift-ci Please test

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your mayRelease changes look good.

Two somewhat separate areas for improvement in the existing code:

  1. Use MapVector::remove_if instead of erase. Then remove all extra while (changed) loops, which are quadratic and complicate the code. They are in visitSetForConflicts, detectApplyConflicts, and visitBeginAccess. Also, remove the temporary map and extra loop in mergeAccessStruct.

  2. Remove the temporary map and extra loop in recordConflict.

@@ -534,9 +534,21 @@ static bool handledEndAccesses(BeginAccessInst *BI, SILLoop *Loop) {
return true;
}

static bool isCoveredByScop(BeginAccessInst *BI, DominanceInfo *DT,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Scop/Scope/

// We can then make use of alias information for instr's operands
// If they don't alias - we might get away with not recording a conflict
for (auto mayWrite : MayWrites) {
if (!mayWrite->mayRelease()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me a while to convince myself this is correct. You've added an assumption at this point in the code that all possibly releasing instructions are included in MayWrites. We should add a corresponding comment where we actually compute MayWrites (in analyzeCurrentLoop). Also, note that even though we are only concerned with class or global access, we need to consider local deinitializers because they can refer to globals.

Joe Shajrawi added 2 commits September 4, 2018 13:23
1) use vectors instead of MapVector for in/out of scope local maps
2) record nested conflict without creating a temporary copy
@shajrawi
Copy link
Author

shajrawi commented Sep 4, 2018

@swift-ci Please test

@swiftlang swiftlang deleted a comment from swift-ci Sep 4, 2018
@shajrawi
Copy link
Author

shajrawi commented Sep 5, 2018

I changed the code per our offline discussion - we no longer use MapVector - added the changes as a separate commit in this PR

@shajrawi shajrawi merged commit a9df586 into swiftlang:master Sep 5, 2018
@shajrawi shajrawi deleted the mayrelease branch September 5, 2018 00:41
@@ -142,13 +142,13 @@ namespace {
/// Reachability results are stored here because very few accesses are
/// typically in-progress at a particular program point,
/// particularly at block boundaries.
using DenseAccessMap = llvm::SmallMapVector<unsigned, BeginAccessInst *, 4>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make more sense to call this DenseAccessSet (the vector part is an implementation detail of the Set).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in new PR

auto index = it->first;
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.erase(index);
auto *otherBegin = *it;
auto rmIt = std::find(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this now using find instead of conflictFreeAccesses.erase(otherBegin)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't use erase on a non-iterator type. it is a reverse iterator.

accessStruct.conflictFreeAccesses.erase(index);
}
auto pred = [&](BeginAccessInst *it) {
auto rhsIt = std::find(RHSAccessStruct.conflictFreeAccesses.begin(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking Set membership is done with count.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed - forgot to change that

info.inScopeConflictFreeAccesses.conflictFreeAccesses.insert(
std::make_pair(index, beginAccess));
assert(
std::find(info.inScopeConflictFreeAccesses.conflictFreeAccesses.begin(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set membership is done with count.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed - forgot to change that

if (isInScope) {
auto &ai = result.getAccessInfo(*it);
ai.setSeenNestedConflict();
}
accessStruct.conflictFreeAccesses.erase(it);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still invalidates the iterator.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm yes: it might invalidate the iterator in recordConflict's caller. not it in this function of course. I reverted to the old behavior in the caller

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look correct.

@shajrawi
Copy link
Author

shajrawi commented Sep 5, 2018

Fixed #19140

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants