Commit Graph

396 Commits

Author SHA1 Message Date
Michael Gottesman
3c58cd56e1 [passmanager] Change the verifier analysis to use function names instead of SILFunction pointers for its internal state.
This enables us to have state independent of the liveness of the SILFunction's
that we are tracking.

I also changed the verifier to implement only verifyFull instead of verify to
ensure that when we run with sil-verify-all this only runs at the end of pass
manager pipelines.

rdar://42301529
2018-08-16 14:46:31 -07:00
Jordan Rose
793b335d0e [SIL] Clarify ownership in FunctionAnalysisBase w/ std::unique_ptr
I also thought I was fixing a performance issue by changing
invalidateFunction not to /insert/ new entries into the map, but
I guess those entries were present in practice. So this is just
a cleanup to make ownership easier.
2018-08-09 12:40:10 -07:00
Doug Gregor
d07fa5ab69 Switch many callers of ClassDecl::getSuperclass() to ClassDecl::getSuperclassDecl().
ClassDecl::getSuperclass() produces a complete interface type describing the
superclass of a class, including any generic arguments (for a generic type).
Most callers only need the referenced ClassDecl, which is (now) cheaper
to compute: switch those callers over to ClassDecl::getSuperclassDecl().

Fixes an existing test for SR-5993.
2018-07-31 10:14:44 -07:00
John McCall
70e2aea266 Merge pull request #18156 from rjmccall/generalized-accessors
Implement generalized accessors using yield-once coroutines
2018-07-23 22:58:25 -04:00
John McCall
7a4aeed570 Implement generalized accessors using yield-once coroutines.
For now, the accessors have been underscored as `_read` and `_modify`.
I'll prepare an evolution proposal for this feature which should allow
us to remove the underscores or, y'know, rename them to `purple` and
`lettuce`.

`_read` accessors do not make any effort yet to avoid copying the
value being yielded.  I'll work on it in follow-up patches.

Opaque accesses to properties and subscripts defined with `_modify`
accessors will use an inefficient `materializeForSet` pattern that
materializes the value to a temporary instead of accessing it in-place.
That will be fixed by migrating to `modify` over `materializeForSet`,
which is next up after the `read` optimizations.

SIL ownership verification doesn't pass yet for the test cases here
because of a general fault in SILGen where borrows can outlive their
borrowed value due to being cleaned up on the general cleanup stack
when the borrowed value is cleaned up on the formal-access stack.
Michael, Andy, and I discussed various ways to fix this, but it seems
clear to me that it's not in any way specific to coroutine accesses.

rdar://35399664
2018-07-23 18:59:58 -04: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
Michael Gottesman
4ba6a50563 [pass-manager] Add a new analysis PassManagerVerifierAnalysis that validates that the pass manager is sending new/delete messages appropriately to analyses.
The invariant is that this analysis should be able to stay in sync with the list
of functions stored in SILModule's function list. If any functions are
added/deleted then analyses can get out of sync with the state of the underlying
SILModule.

Some notes:

1. This is currently disabled by default since there are a bunch of
violations of this in the compiler. I am in the process of fixing violations.
Some examples: the linker and global opt.
2. This is a no-op in non-assert builds.
3. The full verification will only happen when -sil-verify-all is enabled.
Otherwise, we only check that when we delete a function, we had state for the
function.

rdar://42301529
2018-07-17 14:29:01 -07:00
Michael Gottesman
234fcc1771 [pass-manager] notifyDeleteFunction => notifyWillDeleteFunction.
This name makes it clear that the function has not yet been deleted and also
contrasts with the past tense used in the API notifyAddedOrModifiedFunction to
show that said function has already added/modified the function.
2018-07-16 14:11:06 -07:00
Michael Gottesman
56d100f493 [analysis] Standardize AnalysisKind by moving it out of SILAnalysis into its own "struct enum" in a non-nested scope.
Generally in the SIL/SILOptimizer libraries we have been putting kinds in the
swift namespace, not a nested scope in a type in swift (see ValueKind as an
example of this).
2018-07-15 11:00:33 -07:00
Michael Gottesman
3051cd3f60 [caller-analysis] Change the dumping format to be a yaml format and update tests to use that format.
The current dumping format consists of 1 row of information per function. This
will become unweildy to write patterns for when I add additional state to
FunctionInfo.

Instead, this commit converts the dumping format of the caller analysis into a
multi line yaml format. This yaml format looks as follows:

  ---
  calleeName:      closure1
  hasCaller:       false
  minPartialAppliedArgs: 1
  partialAppliers:
    - partial_apply_one_arg
    - partial_apply_two_args1
  fullAppliers:
  ...

This can easily expand over time as we expand the queries that caller analysis
can answer.

As an additional advantage, there are definitely yaml parsers that can handle
multiple yaml documents in sequence in a stream. This means that by running via
sil-opt the caller-analysis-printer pass, one now will get a yaml description of
the caller analysis state, perfect and ready for analysis.
2018-07-12 22:43:23 -07:00
David Zarzycki
03b7eae9ed [SILOptimizer] NFC: Adopt reference storage type meta-programming macros 2018-06-30 06:44:33 -04:00
Andrew Trick
4353e27db2 Exclusivity access marker verification. Handle Unsafe access.
Now that SILGen change adds Unsafe access markers to addressors and
materializeForSet, we can use that as a sentinel to enable strict
verification everywhere.
2018-06-28 23:25:07 -07:00
Andrew Trick
8d41d6ef5f Enable strict verification of begin_access patterns in all SIL passes. (#17534)
* Teach findAccessedStorage about global addressors.

AccessedStorage now properly represents access to global variables, even if they
haven't been fully optimized down to global_addr instructions.

This is essential for optimizing dynamic exclusivity checks. As a
verified SIL property, all access to globals and class properties
needs to be identifiable.

* Add stronger SILVerifier support for formal access.

Ensure that all formal access follows recognizable patterns
at all points in the SIL pipeline.

This is important to run acccess enforcement optimization late in the pipeline.
2018-06-27 23:40:52 -07:00
Michael Gottesman
9e70b855e4 [cmake] Use a helper macro to simplify adding sources to the SILOptimizer library.
All this does is automate the creation of the ${DIRNAME}_SOURCES variables that we already create and allows for the author to avoid having to prefix with the directory name, i.e.:

set(FOOBAR_SOURCES
  FooBar/Source.cpp
  PARENT_SCOPE)

=>

silopt_register_sources(
  Source.cpp)

Much easier and cleaner to read. I put the code that implements this in the
CMakeLists.txt file just for the SILOptimizer.
2018-06-27 17:48:59 -07:00
Michael Gottesman
97367d3dd4 [ownership] Do not lower copy_unowned_value to strong_retain_unowned.
The major important thing here is that by using copy_unowned_value we can
guarantee that the non-ownership SIL ARC optimizer will treat the release
associated with the strong_retain_unowned as on a distinc rc-identity from its
argument. As an example of this problem consider the following SILGen like
output:

----
%1 = copy_value %0 : $Builtin.NativeObject
%2 = ref_to_unowned %1
%3 = copy_unowned_value %2
destroy_value %1
...
destroy_value %3
----

In this case, we are converting a strong reference to an unowned value and then
lifetime extending the value past the original value. After eliminating
ownership this lowers to:

----
strong_retain %0 : $Builtin.NativeObject
%1 = ref_to_unowned %0
strong_retain_unowned %1
strong_release %0
...
strong_release %0
----

From an RC identity perspective, we have now blurred the lines in between %3 and
%1 in the previous example. This can then result in the following miscompile:

----
%1 = ref_to_unowned %0
strong_retain_unowned %1
...
strong_release %0
----

In this case, it is possible that we created a lifetime gap that will then cause
strong_retain_unowned to assert. By not lowering copy_unowned_value throughout
the SIL pipeline, we instead get this after lowering:

----
strong_retain %0 : $Builtin.NativeObject
%1 = ref_to_unowned %0
%2 = copy_unowned_value %1
strong_release %0
...
strong_release %2
----

And we do not miscompile since we preserved the high level rc identity
pairing.

There shouldn't be any performance impact since we do not really optimize
strong_retain_unowned at the SIL level. I went through all of the places that
strong_retain_unowned was referenced and added appropriate handling for
copy_unowned_value.

rdar://41328987

**NOTE** I am going to remove strong_retain_unowned in a forthcoming commit. I
just want something more minimal for cherry-picking purposes.
2018-06-27 13:02:58 -07:00
swift-ci
ec732b09b1 Merge pull request #17367 from gottesmm/pr-54f11c8bd266d77cf730855fefc3d2a135669272 2018-06-20 12:26:04 -07:00
Michael Gottesman
00d95425be [erel-matcher] Do not throw away the list of releases if we do not have a joint post-dominating release set. Instead, use a flag.
I am tuning a new argument explosion heuristic to reduce code-size. One part of
the heuristic I am playing with is the part of the algorithm that attempts to
figure out if we could eliminate additonal arguments after performing
owned->guaranteed an additional release when we run FSO a second time. Today we
do this unconditionally. I am trying to do it in a more conservative way where
we only do it if we know that we aren't going to increase the number of
arguments too much.

rdar://41146023
2018-06-20 11:10:30 -07:00
Slava Pestov
e53ec62536 Merge pull request #17177 from rajbarik/raj-protoconfanal
ProtocolConformanceAnalysis
2018-06-19 14:37:01 -07:00
Raj Barik
c2aef11cff ProtocolConformanceAnalysis for a non-public protocol returns all the types (classes, structs, and enums) that conform to it. It is performed in the whole-module-compilation mode. 2018-06-18 13:38:24 -07:00
Michael Gottesman
369b1f41c1 [epilogue-release-matcher] Pass DenseSet by reference instead of by value.
This is particularly egrigious since we are only /reading/ from the DenseSet. So
we are basically mallocing/copying a DenseSet just to read from it... I don't
think I need to say more.

rdar://41146023
2018-06-16 23:18:36 -07:00
Michael Gottesman
595a7dbc42 [epilogue-arc-analysis] Do not copy lists by value to read them. Use an ArrayRef instead.
I don't think I need to say more here.

rdar://41146023
2018-06-16 23:18:36 -07:00
Michael Gottesman
5dcb806694 Fix comment typo. 2018-06-13 09:28:05 -07:00
Devin Coughlin
be60d9bc10 [Exclusivity] Teach separate-stored-property relaxation about TSan instrumentation
The compile-time exclusivity diagnostics explicitly allow conflicting accesses
to a struct when it can prove that the two accesses are used to project addresses
for separate stored properties. Unfortunately, the logic that detects this special
case gets confused by Thread Sanitizer's SIL-level instrumentation. This causes
the exclusivity diagnostics to have false positives when TSan is enabled.

To fix this, teach the AccessSummaryAnalysis to ignore TSan builtins when
determining whether an access has a single projected subpath.

rdar://problem/40455335
2018-06-10 16:44:19 -07:00
Erik Little
863f3a19ff Rename @effects to @_effects
@effects is too low a level, and not meant for general usage outside
the standard library. Therefore it deserves to be underscored like
other such attributes.
2018-06-06 12:53:03 -04:00
Erik Eckstein
a471bccd6d ARC code motion: handle unowned retains/releases correctly.
This fixes an assert-crash in the ReleaseHoisting pass.

rdar://problem/40525543
2018-05-24 10:40:39 -07:00
Andrew Trick
e29c2089a4 Rework AccessStorageAnalysis design. 2018-05-23 09:23:39 -07:00
Andrew Trick
e1baf91ae1 Merge pull request #16595 from atrick/accessfold
[Exclusivity] Access Enforcement Folding Optimization
2018-05-15 13:27:52 -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
Michael Gottesman
d71d69821f [rcid] Add new method getRCUses() and reimplement getRCUsers() on top of it.
The actual algorithm used here has not changed at all so this is basically a NFC
commit. What this PR does is change the underlying algorithm to return the
operands that it computes internally rather than transforming the operand list
into the user list internally. This enables the callers of the optimization to
find the operand number related to the uses. This makes working with
instructions with multiple operands much easier since one does not need to mess
around with rederiving the operand number from the user instruction/SILValue
pair.

getRCUsers() works now by running getRCUses() internally and then maps the
operand list to the user list.

rdar://38196046
2018-05-15 10:22:23 -07:00
Andrew Trick
841fc150ee Add several AccessedStorageAnalysis unit tests, and fix iterator invalidation. 2018-05-14 10:55:21 -07:00
Doug Gregor
4b5abbddbc [SIL] Teach *ApplyInst to traffic in SubstitutionMap.
Push SubstitutionMaps through most of SILGen and the SIL optimizers
that involve the various *ApplyInsts.
2018-05-11 13:18:06 -07:00
David Zarzycki
71e793f74f [SILOptimizer] NFC: Fix implicit fallthrough warning 2018-05-06 07:44:08 -04:00
Andrew Trick
0a2c935e06 Merge pull request #16398 from atrick/access-analysis-callee-origin
Access analysis callee origin
2018-05-04 18:26:08 -07:00
Andrew Trick
c5f002969f Merge pull request #16392 from atrick/sideeffect-noescape
Fix basic callee analysis to see noescape partial_applies.
2018-05-04 16:27:24 -07:00
Andrew Trick
b975156186 Fix AccessedStorageAnalysis to use getCalleeOrigin for closures.
Added test case for closures.
2018-05-04 14:02:10 -07:00
Andrew Trick
4b70d8608a Fix basic callee analysis to see noescape partial_applies.
This in turn allows side-effect analysis to handle directly applied noescape
closures.
2018-05-04 13:16:40 -07:00
David Zarzycki
8c0c55539f [SIL] NFC: Rename misleading getSwiftRValueType() to getASTType()
Reference storage types are not RValues. Also, use more SILType helper
methods to avoid line wrap.
2018-05-04 08:14:38 -04:00
swift-ci
9d3b6be3fc Merge pull request #16003 from atrick/access-analysis 2018-05-02 10:22:26 -07:00
Arnold Schwaighofer
c4ed564a46 Fixes to AccessSummaryAnalysis
The pattern we see for noescape closure passed to objective c is different:
There is the additional without actually escaping closure sentinel.

rdar://39682865
2018-05-01 07:24:19 -07:00
Huon Wilson
978a5c89b1 [SILOptimizer] std::function -> llvm::function_ref for some non-escaping params. 2018-05-01 08:29:07 +10:00
Andrew Trick
b66fa09c29 Add AccessedStorageAnalysis.
An interprocedural analysis pass that summarizes the dynamically
enforced formal accesses within a function. These summaries will be
used by a new AccessEnforcementOpts pass to locally fold access scopes
and remove dynamic checks based on whole module analysis.
2018-04-17 17:35:39 -07:00
Andrew Trick
cdcb7c7a2c [NFC] SideEffectAnalysis refactoring and cleanup.
Make this a generic analysis so that it can be used to analyze any
kind of function effect.

FunctionSideEffect becomes a trivial specialization of the analysis.

The immediate need for this is to introduce an new
AccessedStorageAnalysis, although I foresee it as a generally very
useful utility. This way, new kinds of function effects can be
computed without adding any complexity or compile time to
FunctionSideEffects. We have the flexibility of computing different
kinds of function effects at different points in the pipeline.

In the case of AccessedStorageAnalysis, it will compute both
FunctionSideEffects and FunctionAccessedStorage in the same pass by
implementing a simple wrapper on top of FunctionEffects.

This cleanup reflects my feeling that nested classes make the code
extremely unreadable unless they are very small and either private or
only used directly via its parent class. It's easier to see how these
classes compose with a flat type system.

In addition to enabling new kinds of function effects analyses, I
think this makes the implementation of side effect analysis easier to
understand by separating concerns.
2018-04-16 17:05:04 -07:00
Erik Eckstein
8b5198cc20 EscapeAnalysis: Convert a if to an assert.
because it should always be true
It's a NFC.
2018-04-12 12:28:47 -07:00
eeckstein
4a500008c6 Merge pull request #15874 from eeckstein/fix-membehavior
Fix wrong usage of escape analysis in MemBehavior
2018-04-11 13:38:24 -07:00
Erik Eckstein
3adf59561f Fix wrong usage of escape analysis in MemBehavior
The EscapeAnalysis:canEscapeTo function was actually broken, because it did not detect all escapes of a reference/pointer.
I completely replaced the implementation with the correct one (canObjectOrContentEscapeTo) and removed the now obsolete canObjectOrContentEscapeTo.
Fixes a miscompile.

rdar://problem/39161309
2018-04-11 10:20:36 -07:00
Andrew Trick
e13e1fbe9d Fix a latent bug in RCIdentityAnalysis.getUsers.
This bug was introduced by the migration to multi-value SILInstructions.

This fix will be tested by copy forwarding.

WARNING: To handle the potential existence of multi-value
instructions, don't simply iterate over the results. You may be
inadvertently skipping instructions with no results.

Details:

RCIdentityFunctionInfo::getRCUsers searches the def-use chain to find
all users. When visiting a use, it checks the result to determine if
it's casting or extracting the original reference operand. If, so it
continues along the def-use chain. So, it simply wasn't visiting
instructions with no results.

I inverted the logic so that the special case now requires identifying
a SingleValueInstruction, while the default case is conservative.
2018-04-10 22:08:35 -07:00
Slava Pestov
1a66c89d29 SIL: Remove CHA's unused 'protocol implementations' analysis
This was performing a walk over all parsed Decls in all
sources files, to build a data structure that was never used.
2018-04-01 02:27:26 -07:00
Erik Eckstein
5ce29cbdb5 BasicCalleeAnalysis: improve the fix for witness tables.
Although I think it is a NFC, it makes it more safe. This change is to align the fix with what I did on the 4.1 branch.
Also remove the not needed $ chars in the function names in the test case.
2018-03-21 13:24:53 -07:00