Commit Graph

326 Commits

Author SHA1 Message Date
Andrew Trick
b689b1dabe Rename GuaranteedARCOpts to MandatoryARCOpts.
This bleeds into the implementation where "guaranteed" is used
everywhere to talk about optimization of guaranteed values. We need to
use mandatory to indicate we're talking about the pass pipeline.
2021-03-02 22:20:13 -08:00
Andrew Trick
cb1ed89c9a [NFC] Add support for a mandatory-copy-propagation pass.
It is currently disabled so this commit is NFC.

MandatoryCopyPropagation canonicalizes all all OSSA lifetimes with
either CopyValue or DestroyValue operations. While regular
CopyPropagation only canonicalizes lifetimes with copies. This ensures
that more lifetime program bugs are found in debug builds. Eventually,
regular CopyPropagation will also canonicalize all lifetimes, but for
now, we don't want to expose optimized code to more behavior change
than necessary.

Add frontend flags for developers to easily control copy propagation:

-enable-copy-propagation: enables whatever form of copy propagation
 the current pipeline runs (mandatory-copy-propagation at -Onone,
 regular copy-propation at -O).

-disable-copy-propagation: similarly disables any form of copy
 propagation in the current pipelien.

To control a specific variant of the passes, use
   -Xllvm -disable-pass=mandatory-copy-propagation
or -Xllvm -disable-pass=copy-propagation instead.

The meaning of these flags will stay the same as we adjust the
defaults. Soon mandatory-copy-propagation will be enabled by
default. There are two reasons to do this, both related to predictable
behavior across Debug and Release builds.

1. Shortening object lifetimes can cause observable changes in program
   behavior in the presense of weak/unowned reference and
   deinitializer side effects.

2. Programmers need to know reliably whether a given code pattern will
   copy the storage for copy-on-write types (Array, Set). Eliminating
   the "unexpected" copies the same way at -Onone and -O both makes
   debugging tractable and provides assurance that the code isn't
   relying on the luck of the optimizer in a particular compiler
   release.
2021-03-02 22:19:47 -08:00
Michael Gottesman
91317c723c [ownership] Make whether or not we serialize in OSSA form based off of the flag -enable-ossa-modules.
I added a change to CMake so that the stdlib still gets the option passed in so
should be NFC.
2021-02-22 19:07:45 -08:00
Erik Eckstein
a17f8c2f3f SILOptimizer: add a diagnostics pass to warn about lifetime issues with weak references.
The DiagnoseLifetimeIssuesPass pass prints a warning if an object is stored to a weak property (or is weakly captured) and destroyed before the property (or captured reference) is ever used again.
This can happen if the programmer relies on the lexical scope to keep an object alive, but copy-propagation can shrink the object's lifetime to its last use.
For example:

  func test() {
    let k = Klass()
      // k is deallocated immediately after the closure capture (a store_weak).
      functionWithClosure({ [weak k] in
                            // crash!
                            k!.foo()
                          })
    }

Unfortunately this pass can only catch simple cases, but it's better than nothing.

rdar://73910632
2021-02-15 11:11:35 +01:00
Michael Gottesman
dd6439d31e [ownership] Change the stdlib to serialize code in ossa form on Darwin.
There is some sort of ASAN issue that this exposes on Linux, so I am going to do
this on Darwin and then debug the Linux issue using ASAN over the weekend/next
week.
2021-02-12 23:20:17 -08:00
Meghana Gupta
ff3c7ba4a9 [sil] Add another run of ARCSequenceOpts before inlining in function passes.
This eliminates some regressions by eliminating phase ordering in between
ARCSequenceOpts/inlining with read only functions whose read onlyness is lost
after inlining.
2021-02-12 23:20:17 -08:00
Erik Eckstein
9f616e5e37 DeadFunctionElimination: rename the pass and some other refactoring
The main change is to rename DeadFunctionElimination -> DeadFunctionAndGlobalElimination, because the pass is now also doing dead-global elimination.
A second change is to remove the FunctionLivenessComputation base class. It’s not used anywhere else.
2021-02-09 19:56:43 +01:00
Michael Gottesman
5ab80224fa [ownership] Move ownership lowering to right before the first inliner run.
I am doing this to separate the perf effect of moving ownership past the inliner
with this earlier stuff.
2021-02-05 18:01:15 -08:00
Michael Gottesman
20b882a14e [ownership] Move OME on the stdlib passed the existential specializer/performance constant prop.
Just trying to do this in as small chunks as possible to get better blame
lists.
2021-02-02 13:33:20 -08:00
Varun Gandhi
e00ef28024 [SILOpt] Turn off PruneVTables.
Fixes rdar://73638176.
2021-01-27 14:28:50 -08:00
Andrew Trick
47a4ad267d Merge pull request #35531 from atrick/ossa-enforcementopts
Enable AccessEnforcementOpts with OSSA
2021-01-21 11:27:12 -08:00
Andrew Trick
454a4452bd Enable AccessEnforcementOpts with OSSA 2021-01-20 19:08:36 -08:00
Slava Pestov
f641a266a8 Merge pull request #35495 from slavapestov/remove-obsolete-staging-flags
Frontend: Remove a couple of obsolete staging flags
2021-01-19 21:28:47 -05:00
Slava Pestov
c456748551 Frontend: Remove a couple of obsolete staging flags
-enable-subst-sil-function-types-for-function-values
-enable-large-loadable-types

These defaulted to on, and there were no corresponding flags for
turning them off, so the flags had no effect.
2021-01-19 17:47:53 -05:00
Meghana Gupta
e5a6de6c01 Merge pull request #34996 from meg-gupta/ossarle
Enable RLE on OSSA
2021-01-19 14:10:42 -08:00
Meghana Gupta
66ef200105 Enable RLE on OSSA 2021-01-17 23:39:03 -08:00
Andrew Trick
93a514c136 Enable the CopyPropagation pass.
For now simply run the pass before SemanticARCOpts. This will probably
be called as a utility from within SemanticARCOpts so it can be
iteratively applied after other ARC-related transformations.
2021-01-16 23:57:14 -08:00
Andrew Trick
cead6a5122 Add an OptimizedMandatoryCombine pass variant.
It's against the principles of pass design to check the driver mode
within the pass. A pass always needs to do the same thing regardless
of where it runs in the pass pipeline. It also needs to be possible to
test passes in isolation.
2021-01-01 19:22:19 -08:00
eeckstein
56928ba851 Merge pull request #34593 from eeckstein/optimize_hte
[concurrency] SILOptimizer: optimize hop_to_executor instructions.
2020-11-09 09:23:46 +01:00
Ben Barham
7cee600bcd [SILGen] Add flag to skip typechecking and SIL gen for function bodies
Adds a new flag "-experimental-skip-all-function-bodies" that skips
typechecking and SIL generation for all function bodies (where
possible).

`didSet` functions are still typechecked and have SIL generated as their
body is checked for the `oldValue` parameter, but are not serialized.
Parsing will generally be skipped as well, but this isn't necessarily
the case since other flags (eg. "-verify-syntax-tree") may force delayed
parsing off.
2020-11-06 12:08:19 +10:00
Erik Eckstein
a47ebabe54 [concurrency] SILOptimizer: optimize hop_to_executor instructions.
* Redundant hop_to_executor elimination: if a hop_to_executor is dominated by another hop_to_executor with the same operand, it is eliminated:

      hop_to_executor %a
      ... // no suspension points
      hop_to_executor %a // can be eliminated

* Dead hop_to_executor elimination: if a hop_to_executor is not followed by any code which requires to run on its actor's executor, it is eliminated:

      hop_to_executor %a
      ... // no instruction which require to run on %a
      return

rdar://problem/70304809
2020-11-05 18:48:22 +01:00
Andrew Trick
3128eae3f0 Add NestedSemanticFunctionCheck diagnostic
to check for improperly nested '@_semantic' functions.

Add a missing @_semantics("array.init") in ArraySlice found by the
diagnostic.

Distinguish between array.init and array.init.empty.

Categorize the types of semantic functions by how they affect the
inliner and pass pipeline, and centralize this logic in
PerformanceInlinerUtils. The ultimate goal is to prevent inlining of
"Fundamental" @_semantics calls and @_effects calls until the late
pipeline where we can safely discard semantics. However, that requires
significant pipeline changes.

In the meantime, this change prevents the situation from getting worse
and makes the intention clear. However, it has no significant effect
on the pass pipeline and inliner.
2020-10-26 17:02:33 -07:00
Michael Gottesman
4a52f5afa3 [ownership] Add another run of SemanticARCOpts right before eliminating ARC on the stdlib functions.
This just canonicalizes the ARC before we lower OME in the face of ARC twiddles
by other passes.
2020-10-23 13:57:50 -07:00
Meghana Gupta
0044e7dcac [ownership] Move OME past SILMem2Reg 2020-10-21 12:04:10 -07:00
Andrew Trick
b2d1ac1631 Add AccessPathVerification pass and run it in the pipeline. 2020-10-16 15:00:10 -07:00
Arnold Schwaighofer
b994bf3191 Add support for _specialize(exported: true, ...)
This attribute allows to define a pre-specialized entry point of a
generic function in a library.

The following definition provides a pre-specialized entry point for
`genericFunc(_:)` for the parameter type `Int` that clients of the
library can call.

```
@_specialize(exported: true, where T == Int)
public func genericFunc<T>(_ t: T) { ... }
```

Pre-specializations of internal `@inlinable` functions are allowed.

```
@usableFromInline
internal struct GenericThing<T> {
  @_specialize(exported: true, where T == Int)
  @inlinable
  internal func genericMethod(_ t: T) {
  }
}
```

There is syntax to pre-specialize a method from a different module.

```
import ModuleDefiningGenericFunc

@_specialize(exported: true, target: genericFunc(_:), where T == Double)
func prespecialize_genericFunc(_ t: T) { fatalError("dont call") }

```

Specially marked extensions allow for pre-specialization of internal
methods accross module boundries (respecting `@inlinable` and
`@usableFromInline`).

```
import ModuleDefiningGenericThing
public struct Something {}

@_specializeExtension
extension GenericThing {
  @_specialize(exported: true, target: genericMethod(_:), where T == Something)
  func prespecialize_genericMethod(_ t: T) { fatalError("dont call") }
}
```

rdar://64993425
2020-10-12 09:19:29 -07:00
Erik Eckstein
68f485424c SILOptimizer: add an additional TempRValueOpt pass later in the pipeline.
This can compensate the performance regression of the more conservative handling of function calls in TempRValueOpt (see previous commit).
The pass runs after the inlining passes and can therefore optimize in some cases where it's not possible before inlining.
2020-10-09 20:54:59 +02:00
Michael Gottesman
4c8d09feb3 [ownership] Move ownership lowering past SROA.
I already updated SROA for this and we already have tests/etc. We have just been
waiting on some other passes to be moved afterwards.
2020-09-30 16:08:44 -05:00
Michael Gottesman
c3bc8e8ef9 [ownership] Move ownership elimination on the stdlib passed lower aggregate instrs. 2020-09-30 11:43:34 -05:00
Michael Gottesman
d1f43032fc [ownership] Move ownership passed TempLValueOpt for the stdlib and add an ossa test case. 2020-09-29 16:36:12 -05:00
Meghana Gupta
163d47ec90 Revert "Revert #33106 and #33205" (#34106) 2020-09-28 23:08:14 -07:00
Meghana Gupta
49d93c58a7 Revert "[ownership] Move OME after CopyForwarding (#33106)"
This reverts commit ef972eb34d.
2020-09-25 11:49:07 -07:00
Meghana Gupta
ef972eb34d [ownership] Move OME after CopyForwarding (#33106)
* Move OME after CopyForwarding

* Minor fix in CopyForwarding test
2020-09-24 20:59:28 -07:00
Michael Gottesman
4cbc07c6c6 [ownership] Add a frontend option to stop optimizing right before we lower ownership.
Specifically the option: -sil-stop-optzns-before-lowering-ownership. This makes
it possible to write end-to-end tests on OSSA passes. Before one would have to
pattern match after ownership was lowered, losing the ability to do finegrained
FileCheck pattern matching on ossa itself.
2020-09-17 18:02:33 -05:00
Erik Eckstein
4d03eb4f0f SILOptimizer: Move the StringOptimization a bit earlier in the pipeline.
Needed to make sure that global initializers are not optimized in mid-level SIL while other functions are still in high-level SIL.
Having the StringOptimization not in high-level SIL was just a mistake in my earlier PR.
2020-08-03 12:01:29 +02:00
Erik Eckstein
2a035432e7 SILOptimizer: make a separate SROA pass for high-level SIL, which doesn't split String types.
The StringOptimization relies on seeing String values a a whole and not being split.
2020-08-03 12:01:29 +02:00
Erik Eckstein
7f684b62e2 SIL optimizer: Add a new string optimization.
Optimizes String operations with constant operands.

Specifically:
  * Replaces x.append(y) with x = y if x is empty.
  * Removes x.append("")
  * Replaces x.append(y) with x = x + y if x and y are constant strings.
  * Replaces _typeName(T.self) with a constant string if T is statically known.

With this optimization it's possible to constant fold string interpolations, like "the \(Int.self) type" -> "the Int type"

This new pass runs on high-level SIL, where semantic calls are still in place.

rdar://problem/65642843
2020-07-27 21:32:56 +02:00
Joe Groff
b4a0ceac71 Add PruneVTables to the performance optimizer passes. 2020-07-23 20:40:49 -07:00
Michael Gottesman
76c7c3e579 [opt-remark] Add support for emitting opt-remark-generator remarks when compiling with optimization.
In order to test this, I implemented a small source loc inference routine for
instructions without valid SILLocations. This is an optional nob that the
opt-remark writer can optionally enable on a per remark basis. The current
behaviors are just forward/backward scans in the same basic block. If we scan
forwards, if we find a valid SourceLoc, we just use ethat. If we are scanning
backwards, instead we grab the SourceRange and if it is valid use the end source
range of the given instruction. This seems to give a good result for retain
(forward scan) and release (backward scan).

The specific reason that I did that is that my test case for this are
retain/release operations. Often times these operations due to code-motion are
moved around (and rightly to prevent user confusion) given by optimizations auto
generated SIL locations. Since that is the test case I am using, to test this I
needed said engine.
2020-07-20 12:01:34 -07:00
Michael Gottesman
0dbed44ddd [ownership] Move ownership lowering past the eager specializer on the stdlib. 2020-07-10 15:31:59 -07:00
Meghana Gupta
f8d8091c98 [ownership] Move ome after GlobalOpt (#32742) 2020-07-08 14:54:59 -07:00
Michael Gottesman
ba2e04be7e [ownership] Move the stdlib ome point to before global opt.
This just moves it past the SIL linker (which since the stdlib doesn't link
anything will not change anything and past TempRValueOpt which is already
updated for OSSA.
2020-06-26 14:04:48 -07:00
Michael Gottesman
5b6918fd3f Merge pull request #32505 from gottesmm/pr-12b4fd6015e37d9a95ea6a81da117e6678369d02
[ownership] Split ownership lowering in the pass pipeline for non-transparent stdlib vs non-stdlib functions.
2020-06-23 15:02:35 -07:00
Michael Gottesman
3530f8e26d [ownership] Split ownership lowering in the pass pipeline for non-transparent stdlib vs non-stdlib functions.
I am going to be moving back ownership lowering first in the stdlib so that we
can bring up the optimizer on ownership without needing to deal with
serialization issues (the stdlib doesn't deserialize SIL from any other
modules).

This patch just begins the mechanical process with a nice commit message. Should
be NFC.
2020-06-22 18:32:17 -07:00
Erik Eckstein
a7425c16ff Improvements for cross-module-optimization
* Include small non-generic functions for serializaion
* serialize initializer of global variables: so that global let variables can be constant propagated across modules

rdar://problem/60696510
2020-06-22 16:49:26 +02:00
Erik Eckstein
9e92389fa5 SILOptimizer: a new "TempLValueOpt" optimization pass for copy_addr
Optimizes copies from a temporary (an "l-value") to a destination.

    %temp = alloc_stack $Ty
    instructions_which_store_to %temp
    copy_addr [take] %temp to %destination
    dealloc_stack %temp

is optimized to

    destroy_addr %destination
    instructions_which_store_to %destination

The name TempLValueOpt refers to the TempRValueOpt pass, which performs a related transformation, just with the temporary on the "right" side.
The TempLValueOpt is similar to CopyForwarding::backwardPropagateCopy.
It's more restricted (e.g. the copy-source must be an alloc_stack).
That enables other patterns to be optimized, which backwardPropagateCopy cannot handle.

This pass also performs a small peephole optimization which simplifies copy_addr - destroy sequences.

    copy_addr %source to %destination
    destroy_addr %source

is replace with

    copy_addr [take] %source to %destination
2020-06-22 13:47:31 +02:00
Michael Gottesman
46432404f3 [ownership] Remove dead option: enable-ownership-stripping-after-serialization.
We always lower ownership now after the diagnostic passes (what this option
actually controlled). So remove it.

NFC.
2020-06-16 10:52:02 -07:00
Michael Gottesman
702c1bc5e8 [arc] Change guaranteed arc opts to be based on SemanticARCOpts and move from Diagnostic pipeline -> Onone pipeline.
The pass is already not being run during normal compilation scenarios today
since it bails on OSSA except in certain bit-rot situations where a test wasn't
updated and so was inadvertently invoking the pass. I discovered these while
originally just trying to eliminate the pass from the diagnostic pipeline. The
reason why I am doing this in one larger change is that I found there were a
bunch of sil tests inadvertently relying on guaranteed arc opts to eliminate
copy traffic. So, if I just removed this and did this in two steps, I would
basically be unoptimizing then re-optimizing the tests.

Some notes:

1. The new guaranteed arc opts is based off of SemanticARCOpts and runs only on
   ossa. Specifically, in this new pass, we just perform simple
   canonicalizations that do not involve any significant analysis. Some
   examples: a copy_value all of whose uses are destroys. This will do what the
   original pass did and more without more compile time. I did a conservative
   first approximation, but we can probably tune this a bit.

2. the reason why I am doing this now is that I was trying to eliminate the
   enable-ownership-stripping-after-serialization flag and discovered that the
   test opaque_value_mandatory implicitly depends on this since sil-opt by
   default was the only place left in the compiler with that option set to false
   by default. So I am eliminating that dependency before I land the larger
   change.
2020-06-15 17:00:18 -07:00
Erik Eckstein
6569c98332 SIL optimizer: add an additional stack promotion pass to the late pipeline
Sometimes stack promotion can catch cases only at a late stage of the pipeline, after FunctionSignatureOpts.

https://bugs.swift.org/browse/SR-12773
rdar://problem/63068408
2020-05-28 10:23:40 +02:00
Erik Eckstein
216eec2d21 SIL optimizer: add an additional LICM pass to the pipeline.
The COWOpts optimization relies more on LICM. This additional run of the pass ensures that there is no phase ordering issue between LICM and COWOpts
2020-05-26 18:01:17 +02:00