Skip to content

[Exclusivity] Remove dominated access checks with no nested conflict. #20053

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
Oct 26, 2018

Conversation

shajrawi
Copy link

Radar rdar://problem/42789656

General case:


begin_access A (may or may not have no_nested_conflict)
load/store
end_access

apply // may have a scoped access that conflicts with A

begin_access A [no_nested_conflict]
load/store
end_access A

The second access scope does not need to be emitted.

NOTE: KeyPath access must be identified at the top-level, non-inlinable stdlib entry point.
As such, The sodlib entry pointed is annotated by a new @_semantics that is equivalent to inline(never)

General case:

—
begin_access A (may or may not have no_nested_conflict)
load/store
end_access

apply // may have a scoped access that conflicts with A

begin_access A [no_nested_conflict]
load/store
end_access A
—

The second access scope does not need to be emitted.

NOTE: KeyPath access must be identified at the top-level, non-inlinable stdlib entry point.
As such, The sodlib entry pointed is annotated by a new @_semantics that is equivalent to inline(never)
@shajrawi
Copy link
Author

@swift-ci Please test

@shajrawi shajrawi requested a review from atrick October 25, 2018 22:22
@shajrawi
Copy link
Author

@atrick Can you please review?

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 63b50f6

@shajrawi
Copy link
Author

This build failed because of a Jenkins Error; typically a Java exception.

@shajrawi
Copy link
Author

@swift-ci Please test OS X

@shajrawi
Copy link
Author

@swift-ci Please test

@shajrawi shajrawi requested a review from eeckstein October 26, 2018 02:49
@shajrawi
Copy link
Author

@eeckstein I have added a new commit that makes the changes we discussed offline - mainly bailing out when encountering unpaired accesses and the new recursive walk that avoids explicitly checking for proper dominance:

I went with a small vector of (begin_access, storage location) that only keeps track of distinct storage locations that can be optimized (which should be a tiny set no matter the size of the function or number of begin_access instructions in it)

This vector keeps track of the first (begin_access, storage location) seen in the dominator (sub)tree.

When encountering a begin_access instruction we just have to see if its storage location is in said vector or not - iterating over a handful of unique storage locations at the most

When we are done with a sub-tree, we just have to remove the new elements in the small vector, which are the last entries we pushed back, this is efficiently implemented of course.

@swiftlang swiftlang deleted a comment from swift-ci Oct 26, 2018
@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - c70ff9b747673d3f36b27747604893b78cb8ff98

@shajrawi
Copy link
Author

@swift-ci Please test OS X

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - c70ff9b747673d3f36b27747604893b78cb8ff98

@shajrawi
Copy link
Author

@swift-ci Please smoke test OS X

Copy link
Contributor

@eeckstein eeckstein left a comment

Choose a reason for hiding this comment

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

the basic algorithm looks good.


// Finds domPairs for which we can change the dominated instruction to static
// NOTE: We might not be able to optimize some the pairs due to other
// restrictions Such as key-path or unpaired begin access We only traverse the
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: missing "." after "access"

// function once, if we find a pattern that *might* prevent optimization, we
// just add it to appropriate data structures which will be analyzed later.
// If we should bail on this function we return false - else true
// we bail to Simplify the code instead of handling unpaired accesses
Copy link
Contributor

Choose a reason for hiding this comment

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

typo "simplify"


// Restore the sets to their previous state as described above,
// removing all "new" elements
auto newNumOfElems = visitedDomAccessesToStorageInfo.size();
Copy link
Contributor

Choose a reason for hiding this comment

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

please inline this expression into the assert. Otherwise you'll get a warning in the release build

return false;
}

bool DominatedAccessRemoval::visitInstruction(
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a comment what the boolean return value means

// we can turn the dominated to static during the optimize() phase
DomPairSet domPairs;
// All stdlib entry points that we've found in this function
KeyPathEntryPointsSet keypathEntries;
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason you are not handling the key path calls like unpaired accesses?

SILFunction *callee = fullApply.getReferencedFunction();
if (!callee)
return true;
if (!callee->hasSemanticsAttr("_keyPathEntryPoint"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the right check? Isn't it a decl attribute and not a semantic attribute?

return true;
// we can't eliminate dominated checks even when we can prove that
// the dominated scope has no internal nested conflicts.
keypathEntries.insert(fullApply.getInstruction());
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just return false here (and treat it like unpaired accesses)?

// checks if the current storage has never been seen before
auto predNewStorageLoc = [&](AccessedStoragePair it) {
auto currStorage = it.second;
return !currStorage.isDistinctFrom(storage);
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 is is the wrong check. AFAIK, !isDistinct is not the inverse of locations being equal. And the equal-check is needed to be able to optimize the access.

dealloc_stack %buffer : $*Builtin.UnsafeValueBuffer
%10 = tuple ()
return %10 : $()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a test with a key path


bool DominatedAccessRemoval::analyzeDomSubTree(
SILBasicBlock *block,
AccessedStorageInfo &visitedDomAccessesToStorageInfo) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It's okay that AccessedStorageInfo is a vector - assuming that it's small in the common case.
But you have to add a bail-out check if it gets larger than a certain limit, to avoid quadratic compile time in corner cases.

Also, you have to add a maximum-recursion-depth check because for very large functions, with lot of control flow, you can run into a stack overflow here.

@shajrawi
Copy link
Author

@eeckstein I’ve done all the changes in the review, including adding recursion and quadratic compile time bail-outs, new key path test and bug-fix for the equal-check of accesses. I also changed the new attribute from a decl attribute to a semantic attribute

Simplification of the code (bail on unpaired accesses) + change the implementation so we can avoid quadratic behavior
@shajrawi
Copy link
Author

@swift-ci Please smoke test

Copy link
Contributor

@eeckstein eeckstein left a comment

Choose a reason for hiding this comment

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

LGTM!

@shajrawi shajrawi merged commit 22d411c into swiftlang:master Oct 26, 2018
@shajrawi shajrawi deleted the enforce_dom branch October 26, 2018 20:22
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