Commit Graph

2864 Commits

Author SHA1 Message Date
Michael Gottesman
5e31124054 [pmo] Update the memory use collector for ownership.
This is technically a NFC commit. The changes are:

1. When we scalarize loads/stores, we need to not just use unqualified
loads/stores. Instead we need to use the createTrivial{Load,Store}Or APIs. In
OSSA mode, this will propagate through the original ownership qualifier if the
sub-type is non-trivial, but if the sub-type is non-trivial will change the
qualifier to trivial. Today when the pass runs without ownership nothing is
changed since I am passing in the "supports unqualified" flag to the
createTrivial{Load,Store}Or API so that we just create an unqualified memop if
we are passed in an unqualified memop. Once we fully move pmo to ownership, this
flag will be removed and we will assert.

2. The container walker is taught about copy_value, destroy_value. Specifically,
we teach the walker how to recursively look through copy_values during the walk
and to treat a destroy_value of the box like a strong_release,
release_value. Since destroy_value, copy_value only exist in [ossa] today, this
is also NFC.
2019-01-15 09:34:45 -08:00
Jordan Rose
425c190086 Restore initializing entry points for @objc convenience initializers (#21815)
This undoes some of Joe's work in 8665342 to add a guarantee: if an
@objc convenience initializer only calls other @objc initializers that
eventually call a designated initializer, it won't result in an extra
allocation. While Objective-C /allows/ returning a different object
from an initializer than the allocation you were given, doing so
doesn't play well with some very hairy implementation details of
compiled nib files (or NSCoding archives with cyclic references in
general).

This guarantee only applies to
(1) calling `self.init`
(2) where the delegated-to initializer is @objc
because convenience initializers must do dynamic dispatch when they
delegate, and Swift only stores allocating entry points for
initializers in a class's vtable. To dynamically find an initializing
entry point, ObjC dispatch must be used instead.

(It's worth noting that this patch does NOT check that the calling
initializer is a convenience initializer when deciding whether to use
ObjC dispatch for `self.init`. If we ever add peer delegation to
designated initializers, which is totally a valid feature, that should
use static dispatch and therefore should not go through objc_msgSend.)

This change doesn't /always/ result in fewer allocations; if the
delegated-to initializer ends up returning a different object after
all, the original allocation was wasted. Objective-C has the same
problem (one of the reasons why factory methods exist for things like
NSNumber and NSArray).

We do still get most of the benefits of Joe's original change. In
particular, vtables only ever contain allocating initializer entry
points, never the initializing ones, and never /both/ (which was a
thing that could happen with 'required' before).

rdar://problem/46823518
2019-01-14 13:06:50 -08:00
Slava Pestov
84ed245f2f DI: Fix transformation of value_metatype inside convenience init in Swift 5 mode
In Swift 5 mode, 'self' in a convenience init has a DynamicSelfType, so
the value_metatype instruction returns a DynamicSelfType metatype.

However, the metatype argument to the constructor is a plain class metatype
because it's an interface type, so we have to "open" it by bitcasting it
to a DynamicSelfType.

Fixes <https://bugs.swift.org/browse/SR-9430>, <rdar://problem/46982573>.
2019-01-11 15:53:37 -05:00
Arnold Schwaighofer
82c941ed11 Delete dead code 2019-01-10 10:22:06 -08:00
Michael Gottesman
be475827db [pmo] Move handling of releases: ElementUseCollector::{collectFrom,collectContainerUses}()
Since:

1. We only handle alloc_stack, alloc_box in predictable memopts.
2. alloc_stack can not be released.

We know that the release collecting in collectFrom can just be done in
collectContainerUses() [which only processes alloc_box].

This also let me simplify some code as well and add a defensive check in case
for some reason we are passed a release_value on the box. NOTE: I verified that
previously this did not result in a bug since we would consider the
release_value to be an escape of the underlying value even though we didn't
handle it in collectFrom. But the proper way to handle release_value is like
strong_release, so I added code to do that as well.
2019-01-05 23:47:07 -08:00
Michael Gottesman
ecacc7541f [pmo] Now that we are doing far less in these methods, inline them.
These increased the amount of code to read in the file and are really not
necessary.
2019-01-04 14:30:16 -08:00
Michael Gottesman
7b7ccdcca0 [pmo] Eliminate more dead code. 2019-01-04 13:19:43 -08:00
Michael Gottesman
7175e1790a [pmo] Eliminate dead flat namespace tuple numbering from PMOMemoryUseCollector.
TLDR: This does not eliminate the struct/tuple flat namespace from Predictable
Mem Opts. Just the tuple specific flat namespace code from PMOMemoryUseCollector
that we were computing and then throwing away. I explain below in more detail.

First note that this is cruft from when def-init and pmo were one pass. What we
were doing here was maintaing a flattened tuple namespace while we were
collecting uses in PMOMemoryUseCollector. We never actually used them for
anything since we recomputed this information including information about
structs in PMO itself! So this information was truly completely dead.

This commit removes that and related logic and from a maintenance standpoint
makes PMOMemoryUseCollector a simple visitor that doesn't have any real special
logic in it beyond the tuple scalarization.
2019-01-04 13:19:43 -08:00
swift-ci
480b433ba4 Merge pull request #21641 from gottesmm/pr-a9ae83f3b19ca0f52f9d16140b57859e2dd77a71 2019-01-04 12:30:50 -08:00
swift-ci
9fdf850ee5 Merge pull request #21640 from gottesmm/pr-02a5ad432c647ea45ba14d73742ac44ca22abc0f 2019-01-04 12:13:41 -08:00
Michael Gottesman
ef99325427 [pmo] Debride more code that is still in PMO but was only used by DI. 2019-01-04 11:29:43 -08:00
Michael Gottesman
f4b1ae07e8 [pmo] Simplify code by inverting an if check. 2019-01-04 11:20:22 -08:00
Arnold Schwaighofer
cb0c53abee SIL: Remove isEscapedByUser flag on convert_escape_to_noescape instruction
It was only used for materializeForSet and is now dead code.
2019-01-04 09:21:38 -08:00
Michael Gottesman
b70f6f8171 [pmo] Eliminate dynamically dead code paths.
Specifically, we are putting dealloc_stack, destroy_box into the Releases array
in PMOMemoryUseCollector only to ignore them in the only place that we use the
Releases array in PredictableMemOpts.
2019-01-03 08:58:20 -08:00
swift-ci
22f6a2d382 Merge pull request #21591 from gottesmm/pr-e660d1b5bce380646191167f914c88477253a5dd 2019-01-02 11:58:59 -08:00
Michael Gottesman
0d962b237f [pmo] Change MemoryInst to be an AllocationInst since it will always be so.
Just a part of a series of small cleanups I found over the break in PMO that I
am landing in preparation for landing patches that fix PMO for ownership.
2019-01-02 11:07:13 -08:00
Michael Gottesman
c6f5995254 [definite-init] Convert always true bool return value to void.
Just a small cleanup.
2019-01-02 09:45:11 -08:00
Saleem Abdulrasool
cde0862468 Merge pull request #21537 from compnerd/optimize-incorrectly
SILOptimizer: fix a few instances of use-after-free
2019-01-02 08:28:44 -08:00
Michael Gottesman
d414648236 Merge pull request #21463 from gottesmm/pr-89ba7f1c9c5ad900f1217f32305fc79028e07eff
[predictable-mem-opts] Eliminate unused PMOUseKind.
2019-01-02 08:25:54 -08:00
Michael Gottesman
9620bedf7a [di] Rename: DIMemoryUseCollector{Ownership,}.{cpp,h}
This was done early on during the split of predictable mem opts from DI. This
has been done for a long time, so eliminate the "Ownership" basename suffix.
2018-12-30 16:11:56 -08:00
Saleem Abdulrasool
bd93229428 SILOptimizer: fix a few instances of use-after-free
When building on Windows, the std::string being passed will on the
stack, where the destructor will be invoked before the return, nil'ing
out reference.  This causes incorrect behaviour when building the
diagnostic or FIXITs.  Explicitly create the StringRef to prevent the
std::string from being invalidated.
2018-12-23 16:24:04 -08:00
Michael Gottesman
c67b80e7a5 [predictable-mem-opts] Eliminate unused PMOUseKind.
These are vestigal remnants of the code when it needed to support DI and
PredMemOpts. Since both of the passes have been split, these are now dead in
PMO. So eliminate them.
2018-12-20 10:00:51 -08:00
Michael Gottesman
69f6ae54f9 Merge pull request #20923 from gottesmm/pr-f63866d54df4db5291264283fe900d1af78ac87b
[semantic-arc-opts] Convert exclusive accessed load [copy] that are n…
2018-12-16 13:51:09 -08:00
Michael Gottesman
8f7620f627 [semantic-arc-opts] Implement a simple load [copy] -> load_borrow optimization for arguments to create optimization scaffolding.
This is the first in a sequence of patches that implement various optimizations
to transform load [copy] into load_borrow.

The optimization works by looking for a load [copy] that:

1. Only has destroy_value as consuming users. This implies that we do not need
to pass off the in memory value at +1 and that we can use a +0 value.

2. Is loading from a memory location that is never written to or only written to
after all uses of the load [copy].

and then RAUW the load [copy] with a load_borrow and convertes the destroy_value
to end_borrow.

NOTE: I also a .def file for AccessedStorage so we can do visitors over the
kinds. The reason I want to do this is to ensure that people update these
optimizations if we add new storage kinds.
2018-12-16 12:32:46 -08:00
Michael Gottesman
d85012f9aa [semantic-arc-opts] Improve comment on isConsumed. 2018-12-16 11:32:20 -08:00
Slava Pestov
047c55c0bb Merge pull request #21160 from slavapestov/di-untangle-analysis-from-mutation
DI: Lower AssignInst in a post-processing pass
2018-12-10 16:34:04 -05:00
Michael Gottesman
4212142745 [semantic-arc-opts] Abstract out the check if a value is consumed into a utility called isConsumed().
I am doing this for two reasons:

1. I want to use this in a different optimization where we optimize load [copy]
=> load_borrow.
2. This will ensure that if/when the ownership APIs change to use isConsume/etc
instead of the current operand ownership map, the optimization will be easy to
update.
2018-12-09 23:45:24 -08:00
Slava Pestov
a5f9619062 DI: Lower AssignInst in a post-processing pass
Compiler passes that intermingle analysis with mutation of the CFG
are fraught with danger. The bug here was that a single AssignInst
could appear twice in DI's Uses list, once as a store use and once
as a load use.

When processing Uses, we would lower AssignInsts on the fly. We would
take care to erase the instruction pointer from the current Use, but
if a subsequent Use *also* referenced the now-deleted AssignInst, we
would crash.

Handle this in the standard way: instead of lowering assignments
right away, just build a list of assignments that we're planning on
lowering and process them all at the very end.

This has the added benefit of simplifying the code, because we no
longer have to work as hard to keep the state of the Uses list
consistent while lowering AssignInsts. The rest of DI should not
care that the lowering got postponed either, since it was already
expected to handle any ordering of elements in the Uses list, so
it could not assume that any particular AssignInst has been lowered.

Fixes <https://bugs.swift.org/browse/SR-9451>.
2018-12-10 00:03:08 -05:00
Slava Pestov
38263ca000 DI: Small cleanups
- Handle DIMemoryUse::Kind::IndirectIn just like Load
- Consolidate duplicated 'only touches trivial elements' check
2018-12-10 00:03:08 -05:00
Slava Pestov
6c012b2aec AST: Remove some unnecessary LazyResolver * parameters from ASTContext methods 2018-12-07 20:39:27 -05:00
swift-ci
3a445ec64b Merge pull request #21064 from gottesmm/pr-05a3d471333a422857df5a8499dd12c99aac0bae 2018-12-05 17:01:39 -08:00
Michael Gottesman
0f319dda67 [semantic-arc-opts] Eliminate all dead live ranges.
Previously, we only did single copy/destroys. Now we handle a copy + any number
of destroy_values.
2018-12-05 15:22:23 -08:00
Michael Gottesman
33e5aba554 Merge pull request #20855 from gottesmm/pr-94ee6e6c6e2d268f47f17dead77e4feb169c24e6
[ownership] Replace ValueOwnershipKind::Trivial with ValueOwnershipKi…
2018-12-05 14:47:04 -08:00
Michael Gottesman
4a5af03ec9 [semantic-arc-opts] Add a large comment to the guaranteed copy value optimization describing it in more depth. 2018-12-05 14:15:41 -08:00
Michael Gottesman
0af0d5fddc [ownership] Replace ValueOwnershipKind::Trivial with ValueOwnershipKind::Any.
In a previous commit, I banned in the verifier any SILValue from producing
ValueOwnershipKind::Any in preparation for this.

This change arises out of discussions in between John, Andy, and I around
ValueOwnershipKind::Trivial. The specific realization was that this ownership
kind was an unnecessary conflation of the a type system idea (triviality) with
an ownership idea (@any, an ownership kind that is compatible with any other
ownership kind at value merge points and can only create). This caused the
ownership model to have to contort to handle the non-payloaded or trivial cases
of non-trivial enums. This is unnecessary if we just eliminate the any case and
in the verifier separately verify that trivial => @any (notice that we do not
verify that @any => trivial).

NOTE: This is technically an NFC intended change since I am just replacing
Trivial with Any. That is why if you look at the tests you will see that I
actually did not need to update anything except removing some @trivial ownership
since @any ownership is represented without writing @any in the parsed sil.

rdar://46294760
2018-12-04 23:01:43 -08:00
Adrian Prantl
ff63eaea6f Remove \brief commands from doxygen comments.
We've been running doxygen with the autobrief option for a couple of
years now. This makes the \brief markers into our comments
redundant. Since they are a visual distraction and we don't want to
encourage more \brief markers in new code either, this patch removes
them all.

Patch produced by

      for i in $(git grep -l '\\brief'); do perl -pi -e 's/\\brief //g' $i & done
2018-12-04 15:45:04 -08:00
swift-ci
2ef35ac80e Merge pull request #19655 from apple/marcrasi-const-evaluator-part-1 2018-11-29 19:25:14 -08:00
Michael Gottesman
c65c540d71 Merge pull request #20819 from gottesmm/pr-f46c6ad2fee1ea70f7b25a8f6a89ab7af28c1404
[ownership] Ban ValueOwnershipKind::Any in preparation for eliminated ValueOwnershipKind::Trivial
2018-11-28 13:55:10 -08:00
Michael Gottesman
c9bb5161a1 [ownership] Change SILUndef to return Any ownership for trivial values and owned for non-trivial values.
This is in preparation for verifying that when ownership verification is enabled
that only enums and trivial values can have any ownership. I am doing this in
preparation for eliminating ValueOwnershipKind::Trivial.

rdar://46294760
2018-11-27 17:31:08 -08:00
Andrew Trick
ff132a711f Merge pull request #20630 from atrick/fix-quadratic-block-merge
Fix block merging after inlining to be linear, not quadratic.
2018-11-27 11:08:59 -08:00
Marc Rasi
44d7cdd4e6 constant interpreter: basic integer operations
Implements a constant interpreter that can deal with basic integer operations.

Summary of the features that it includes:
* builtin integer values, and builtin integer insts
* struct and tuple values, and insts that construct and extract them (necessary to use stdlib integers)
* function referencing and application (necessary to call stdlib integer functions)
* error handling data structures and logic, for telling you why your value is not evaluatable
* metatype values (not necessary for integers, but it's only a few extra lines, so I thought it would be more trouble than it's worth to put them in a separate PR)
* conditional branches (ditto)
2018-11-26 14:27:10 -08:00
Saleem Abdulrasool
15d3bf15db SILOptimizer: avoid use-after-free with the name
On Windows at least, the std::string associated with the name of the
property would be copy constructed before being passed to the diagnostic
engine.  The resultant DiagnosticArgument in the InFlightDiagnostic
would hold a StringRef to the copy-constructed std::string.  However,
because the arguments are inalloca'ed on Windows, the copy constructed
string would be destructed before the return of the argument.
Fortunately, this would result in the standard library overwriting the
string and the use-after-free would fail to print the argument.
Explicitly construct the StringRef before passing the name to the
diagnostic to avoid the use-after-free.
2018-11-26 13:04:06 -08:00
Andrew Trick
702981f775 Fix MandatoryInlining to not be quadratic.
Inlining has always been quadratic for no good reason. There was a
special hack for single-block callees that allowed linear inlining.

Instead, the now iterates over blocks and instructions in reverse,
splitting blocks as it inlines. There no longer needs to be special
case for single block callees, and the inliner is linear for all kinds
of callees.

This further simplifies and cleans up the code. There are just a few
basic invariants that the common inliner needs to provide about how
blocks are split and laid out. We can do this if we don't add hacks
for special cases within the inliner. Those invariants allow the
inliner clients to be much simpler and more efficient.

PerformanceInliner still needs to be fixed.

Fixes SR-9223: Inliner exhibits slow compilation time with a large
static array.
2018-11-26 09:41:28 -08:00
Andrew Trick
9c46b2a053 Fix block merging after inlining to help avoid quadratic inlining.
A recent SILCloner rewrite removed a special case hack for single
basic block callee functions:

commit c6865c0dff
Merge: 76e6c4157e 9e440d13a6
Author: Andrew Trick <atrick@apple.com>
Date:   Thu Oct 11 14:23:32 2018

    Merge pull request #19786 from atrick/silcloner-cleanup

    SILCloner and SILInliner rewrite.

Instead, the new inliner simply merges trivial unconditional branches
after inlining the return block. This way, the CFG is always in
canonical state after inlining. This is more robust, and avoids
interfering with subsequent SIL passes when non-single-block callees
are inlined.

The problem is that inlining a series of calls within a large block
could result in interleaved block splitting and merging operations,
which is quadratic in the block size. This showed up when inlining the
tens of thousands of array subscript calls emitted for a large array
initialization.

The first half of the fix is to simply defer block merging until all
calls are inlined. We can't expect SimplifyCFG to run immediately
after inlining, nor would we want to do that, *especially* for
mandatory inlining. This fix instead exposes block merging as a
trivial utility.

Note: by eliminating some unconditional branches, this change could
reduce the number of debug locations emitted. This does not
fundamentally change any debug information guarantee, and I was unable
to observe any behavior difference in the debugger.
2018-11-26 09:41:28 -08:00
Michael Gottesman
caa86c424e [gardening] Change a function with 4 space indent => 2 space indent and standardize variable names.
NFC.
2018-11-18 14:58:01 -08:00
Michael Gottesman
e2d7f77557 [semantic-sil] Enable the mandatory sil ownership optimization on all stdlib overlays.
We can do this b/c all overlays pass the ownership verifier, so it is safe.
2018-11-13 16:08:14 -08:00
Michael Gottesman
099cae5692 [semantic-arc-opts] Handle arg extract + copy + borrow + use.
Specifically, now the optimizer can take the following code:

sil @foo: $@convention(thin) (@guaranteed NativeObjectPair) -> () {
bb0(%0 : @guaranteed $NativeObjectPair):
  %1 = struct_extract %0 : $NativeObjectPair, #NativeObjectPair.obj1
  %2 = copy_value %1 : $Builtin.NativeObject
  %3 = begin_borrow %2 : $Builtin.NativeObject
  %foo = function_ref ...
  apply %foo(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
  end_borrow %3 : $Builtin.NativeObject
  destroy_value %2 : $Builtin.NativeObject
  ...
}

and eliminate all ownership instructions. I.e.:

sil @foo: $@convention(thin) (@guaranteed NativeObjectPair) -> () {
bb0(%0 : @guaranteed $NativeObjectPair):
  %1 = struct_extract %0 : $NativeObjectPair, #NativeObjectPair.obj1
  %foo = function_ref ....
  apply %foo(%1)
  ...
}

Before this the optimizer could only eliminate 200 insts in the stdlib. With
this change, we now can eliminate ~7000.
2018-11-13 12:07:48 -08:00
Michael Gottesman
5a73063e37 [semantic-arc-opts] Eliminate all copy_value from guaranteed arguments that have all uses that can accept values with guaranteed ownership.
This takes advantage of my restricting Semantic ARC Opts to run only on the
stdlib since we know it passes the ownership verifier. Using that I
reimplemented this optimization in a more robust, elegant, general
way. Specifically, we now will eliminate any SILGen copy_value on a guaranteed
argument all of whose uses are either destroy_values or instructions that can
accept guaranteed parameters. To be clear: This means that the value must be
consumed in the same function only be destroy_value.

Since we know that the lifetime of the guaranteed parameter will be larger than
any owned value created/destroyed in the body, we do not need to check that the
copy_value's destroy_value set is joint post-dominated by the set of end_borrows.

That will have to be added to turn this into a general optimization.
2018-11-13 12:07:48 -08:00
Marc Rasi
bf18697b4f parsing, typechecking, and SILGen for #assert
`#assert` is a new static assertion statement that will let us write
tests for the new constant evaluation infrastructure that we are working
on. `#assert` works by lowering to a `Builtin.poundAssert` SIL
instruction. The constant evaluation infrastructure will look for these
SIL instructions, const-evaluate their conditions, and emit errors if
the conditions are non-constant or false.

This commit implements parsing, typechecking and SILGen for `#assert`.
2018-11-07 16:34:17 -08:00
Arnold Schwaighofer
7e32c68e1d Add new SIL instruction for calling dynamically_replaceable funtions
%0 = dynamic_function_ref @dynamically_replaceable_function
  apply %0()
  Calls a [dynamically_replaceable] function.

  %0 = prev_dynamic_function_ref @dynamic_replacement_function
  apply %0
  Calls the previous implementation that dynamic_replacement_function
  replaced.
2018-11-06 09:53:22 -08:00