Commit Graph

38 Commits

Author SHA1 Message Date
Andrew Trick
a9070cf6d4 Add AccessEnforcementOpts fast paths.
1. During identifyAccess, determine if there are either any
identical accesses or an accesses that aren't already marked
no_nested_storage. If there are neither, then skip the subsequent
data flow analysis.

2. In the new StorageSet, indicate whether identical storage was
seen elsewhere in the function. During dataflow, only add an access
to the out-of-scope access set if was marked as having identical
storage with another access.

3. During data flow, don't track in scope conflicts for
instructions already marked [no_nested_conflict].
2019-05-14 15:09:40 -07:00
Andrew Trick
c08e4396ab In AccessEnforcementOpts, skip SCC analysis.
When there is nothing that can be merged, there's no point doing an
extra CFG analysis.
2019-05-14 14:44:21 -07:00
Andrew Trick
cd88cedd86 Slightly reword a comment in AccessEnforcementOpts. 2019-05-14 14:44:20 -07:00
Andrew Trick
219fbe9f15 Fix a comment in AccessEnforcementOpts.
This was supposed to land in the previous commit but was dropped.
2019-03-21 15:07:58 -07:00
Andrew Trick
462df6cef3 Cleanup/fix the loop access summary in AccessEnforcementOpts.
Reuse AccessStorageAnalysis to summarize accesses.

Don't ignore call sites in loops.

Don't consider a read access in a loop to conflict with a read
outside.

Use the unidentified access flag from the analysis.

Remove extraneous code, some of which was unreachable.

General cleanup.
2019-03-19 15:29:59 -07:00
Andrew Trick
dfc2d47f3b Redo the data flow part of AccessEnforcementOpts.
Directly implement the data flow. Eliminate the extraneous work.
Remove cubic behavior. Do a single iteration of the data flow state at
each program point only performing the necessary set operations. At
unidentified access, clear the sets for simplicity and efficiency.

This cleanup results in significant functional changes:

- Allowing scopes to merge even if they are enclosed.

- Handling unidentified access conservatively.

Note that most of the added lines of code are comments.

Somehow this cleanup incidentally fixes:
<rdar://problem/48514339> swift compiler hangs building project

(I expected the subsequent loop summary cleanup to fix that problem.)
2019-03-18 12:42:53 -07:00
Andrew Trick
c516a1ca0e Retain the [no_nested_conflict] flag when merging.
The optimization already proves that there are no potential conflicts
between the two merged scopes, so merging them can't introduce a new
nested conflict.
2019-03-18 12:42:53 -07:00
Andrew Trick
4887d17dbd Remove RegionState::AccessSummary and rewrite mergePredAccesses.
AccessSummary was storing unnecessary state in every per-block entry in the
global map. It was also making most of the code in this pass very hard to read.

Rewriting mergePredAccesses allows AccessSummary to be removed. The
new implementation also avoids unnecessary DenseMap lookups.

There is also a functional change. mergePredAccesses was clearing the
state of predecessor blocks. This isn't logical and had no explanation.
2019-03-18 12:42:53 -07:00
Andrew Trick
d882b09c88 Avoid unnecessarily copying the worklist for the entire CFG. 2019-03-18 12:42:53 -07:00
Andrew Trick
25f24da779 Cleanup the recordConflict API.
And remove cubic behavior.
2019-03-18 12:42:53 -07:00
Andrew Trick
5183929d35 Cleanup the mergeAccessSummary API. 2019-03-18 12:42:53 -07:00
Andrew Trick
c2d4642bcb Rename RegionInfo to RegionState.
Most of the API's operate on the data flow state (RegionState) with
respect to the information for a given access (AccessInfo). Calling
them both "info" made the code completely indecipherable.
2019-03-18 12:42:53 -07:00
Andrew Trick
ac846cb146 Clarify AccessEnforcementOptsInfo comments. 2019-03-18 12:42:53 -07:00
Andrew Trick
f4c7d4611f Change the algorithm for the AccessEnforcementDom pass.
This adds a mostly flow-insensitive analysis that runs before the
dominator-based transformations. The analysis is simple and efficient
because it only needs to track data flow of currently in-scope
accesses. The original dominator tree walk remains simple, but it now
checks the flow insensitive analysis information to determine general
correctness. This is now correct in the presence of all kinds of nested
static and dynamic nested accesses, call sites, coroutines, etc.

This is a better compromise than:

(a) disabling the pass and taking a major performance loss.

(b) converting the pass itself to full-fledged data flow driven
optimization, which would be more optimal because it could remove
accesses when nesting is involved, but would be much more expensive
and complicated, and there's no indication that it's useful.

The new approach is also simpler than adding more complexity to
independently handle to each of many issues:

- Nested reads followed by a modify without a false conflict.
- Reads nested within a function call without a false conflict.
- Conflicts nested within a function call without dropping enforcement.
- Accesses within a generalized accessor.
- Conservative treatment of invalid storage locations.
- Conservative treatment of unknown apply callee.
- General analysis invalidation.

Some of these issues also needed to be considered in the
LoopDominatingAccess sub-pass. Rather than fix that sub-pass, I just
integrated it into the main pass. This is a simplification, is more
efficient, and also handles nested loops without creating more
redundant accesses. It is also generalized to:
- hoist non-uniquely identified accesses.
- Avoid unnecessarily promoting accesses inside the loop.

With this approach we can remove the scary warnings and caveats in the
comments.

While doing this I also took the opportunity to eliminate quadratic
behavior, make the domtree walk non-recursive, and eliminate cutoff
thresholds.

Note that simple nested dynamic reads to identical storage could very
easily be removed via separate logic, but it does not fit with the
dominator-based algorithm. For example, during the analysis phase, we
could simply mark the "fully nested" read scopes, then convert them to
[static] right after the analysis, removing them from the result
map. I didn't do this because I don't know if it happens in practice.
2019-03-07 12:39:53 -08:00
Joe Shajrawi
a4f7d01c38 AccessEnforcementOpts: Fix a bug that caused a compiler assert when dealing with nested scopes
radar rdar://problem/48318054
2019-02-22 17:29:32 -08:00
Andrew Trick
30994389f2 Disable merging of read/modify exclusivity access markers.
When two access scopes have different access types, it is not safe to
merge them into one access. Doing so will introduce false conflicts
which manifest as crashes in user code.

To do this optimization, we would need additional data flow information
about *potential* read conflicts before converting a read to a modify
access.

Fixes rdar://48239213: Fatal access conflict detected.
2019-02-21 13:05:20 -08:00
Michael Gottesman
d78e83c010 [ownership] Do some preliminary work for moving OME out of the diagnostics pipeline.
This disables a bunch of passes when ownership is enabled. This will allow me to
keep transparent functions in ossa and skip most of the performance pipeline without
being touched by passes that have not been updated for ownership.

This is important so that we can in -Onone code import transparent functions and
inline them into other ossa functions (you can't inline from ossa => non-ossa).
2019-01-31 13:38:05 -08:00
Joe Shajrawi
93dcb9bddd [Exclusivity] Support exclusivity checks originating from block arguments
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
2018-11-13 11:25:11 -08:00
Joe Shajrawi
be9d290ef9 [Exclusivity] Fix a bug wherein we miss detected a non conflicting in-scope access as conflicting 2018-11-09 14:57:25 -08:00
Joe Shajrawi
43efed3337 [Exclusivity] Merge scopes with nested conflicts
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
2018-09-20 17:01:28 -07:00
Joe Shajrawi
e7eb78e2a7 AccessEnforcementOpts continued refactoring 2018-09-05 11:04:38 -07:00
Joe Shajrawi
7297b81108 AccessEnforcementOpts: Refactoring
1) use vectors instead of MapVector for in/out of scope local maps
2) record nested conflict without creating a temporary copy
2018-09-04 13:58:37 -07:00
Joe Shajrawi
c6a4e2cdd2 [Exclusivity] Handle mayRelease instructions conservatively in AccessEnforcementOpts and LICM 2018-09-04 13:23:22 -07:00
Joe Shajrawi
19e5256baf [AccessEnforcementOpts] Fix an iterator invalidation issue
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
2018-08-21 23:26:57 -07:00
Ben Cohen
428c580158 Fix unused variable warnings in release builds. (#18755) 2018-08-16 11:46:45 -06:00
Joe Shajrawi
7281a76deb [AccessEnforcementOpts] Add mergeAccesses optimization 2018-08-09 16:15:25 -07:00
Joe Shajrawi
62e43a13d7 [AccessEnforcementOpts] Add merge accesses analysis to conflict analysis 2018-08-09 14:09:24 -07:00
Bob Wilson
8e330ee344 NFC: Fix indentation around the newly renamed LLVM_DEBUG macro.
Jordan used a sed command to rename DEBUG to LLVM_DEBUG. That caused some
lines to wrap and messed up indentiation for multi-line arguments.
2018-07-21 00:56:18 -07:00
Jordan Rose
cefb0b62ba Replace old DEBUG macro with new LLVM_DEBUG
...using a sed command provided by Vedant:

$ find . -name \*.cpp -print -exec sed -i "" -E "s/ DEBUG\(/ LLVM_DEBUG(/g" {} \;
2018-07-20 14:37:26 -07:00
Andrew Trick
4f13dedc93 Add and enable an AccessEnforcementWMO pass.
Remove dynamic access checks for global variables and and class properties that
have been proven by earlier analysis never to conflict with nested access.

This only applies "-O -enforce-exclusivity=checked" builds. By default, it is
currently NFC.

These are the most important improvements:

RecursiveOwnedParameter                           -93.7%   **15.75x**
ReversedArray                                     -89.1%   **9.17x**
ReversedDictionary                                -81.0%   **5.28x**
ArrayInClass                                      -74.3%   **3.89x**
Ary3                                              -71.7%   **3.54x**
Random                                            -66.2%   **2.96x**
StringWalk                                        -63.5%   **2.74x**
LevenshteinDistance                               -55.4%   **2.24x**
Voronoi                                           -50.0%   **2.00x**
HashTest                                          -47.7%   **1.91x**
Richards                                          -46.7%   **1.88x**
NopDeinit                                         -44.8%   **1.81x**
Rectangles                                        -41.3%   **1.70x**
MultiFileTogether                                 -33.1%   **1.50x**
MultiFileSeparate                                 -32.8%   **1.49x**
SetIntersect_OfObjects                            -26.5%   **1.36x**
Ary2                                              -22.7%   **1.29x**
Prims                                             -21.9%   **1.28x**
PrimsSplit                                        -21.8%   **1.28x**
SetExclusiveOr_OfObjects                          -19.4%   **1.24x**
ObjectAllocation                                  -18.6%   **1.23x**
DropFirstAnySeqCRangeIterLazy                     -17.2%   **1.21x**
DropFirstAnySeqCRangeIter                         -17.2%   **1.21x**
Dictionary4OfObjects                              -16.5%   **1.20x**
SetUnion_OfObjects                                -15.3%   **1.18x**
DropWhileCountableRangeLazy                       -15.3%   **1.18x**
CharIndexing_[*]_Backwards                        -14.6%   **1.17x**
(all 17 variants of CharIndexing are -14%, 1.17x)
CharIteration_[*]_Backwards                       -14.3%   **1.17x**
(all 17 variants of CharIteration take 14%, 1.17x)
RGBHistogramOfObjects                             -14.2%   **1.17x**
DeltaBlue                                         -13.5%   **1.16x**
CharacterPropertiesPrecomputed                    -12.4%   **1.14x**
DictionarySwapOfObjects                           -9.9%    **1.11x**
ClassArrayGetter                                  -9.8%    **1.11x**
DictionaryGroupOfObjects                          -7.9%    **1.09x**
DictionaryRemoveOfObjects                         -7.2%    **1.08x**
Dictionary4OfObjectsLegacy                        -6.8%    **1.07x**
Havlak                                            -6.4%    **1.07x**
COWTree                                           -6.2%    **1.07x**
Radix2CooleyTukeyf                                -5.6%    **1.06x**
2018-06-29 17:56:56 -07:00
Andrew Trick
628052810e Simplify AccessEnforcementOpts by leaving access markers in place.
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.
2018-05-24 22:18:24 -07:00
Andrew Trick
0aa2eae2e7 AccessEnforcementOpts high-level comments. 2018-05-24 22:18:24 -07:00
Andrew Trick
0d3cf75c71 Fix AccessEnforcementOpts in debug builds. 2018-05-24 14:36:19 -07:00
Andrew Trick
c5475c9442 AccessEnforcementOpts test cases. 2018-05-24 00:27:00 -07:00
Andrew Trick
df1b9b404e Rework AccessEnforcementOpts SparseSet.
This makes the intention more clear and sets up
a new optimization to merge access scopes.
2018-05-23 09:23:39 -07:00
Andrew Trick
8d67ce18d0 Teach AccessEnforcementOpts to eliminate checks.
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.
2018-05-23 09:23:39 -07:00
Andrew Trick
7fc2d6267b Rename findAccessedStorageOrigin() to findAccessedStorageNonNested(). 2018-05-15 12:29:19 -07:00
Andrew Trick
495d5aecf6 [exclusivity] Add an access marker folding pass.
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.
2018-05-15 12:29:19 -07:00