Commit Graph

67 Commits

Author SHA1 Message Date
Erik Eckstein
2b9b2d243c Optimizer: improve TempLValueOpt
* re-implement the pass in swift
* support alloc_stack liveranges which span over multiple basic blocks
* support `load`-`store` pairs, copying from the alloc_stack (in addition to `copy_addr`)

Those improvements help to reduce temporary stack allocations, especially for InlineArrays.

rdar://151606382
2025-06-05 06:45:18 +02:00
Erik Eckstein
c6b1e3e854 TempRValueElimination: re-implement the pass in swift
Beside cleaning up the source code, the motivation for the translation into Swift is to make it easier to improve the pass for some InlineArray specific optimizations (though I'm not sure, yet if we really need those).
Also, the new implementation doesn't contain the optimize-store-into-temp optimization anymore, because this is covered by redundant load elimination.
2025-05-06 13:08:09 +02:00
Erik Eckstein
63f6a2f30d Optimizer: remove the ArrayElementPropagation optimization
Propagating array element values is done by load-simplification and redundant-load-elimination.
So ArrayElementPropagation is not needed anymore.

ArrayElementPropagation also replaced `Array.append(contentsOf:)` with individual `Array.append` calls.
This optimization is removed, because the benefit is questionably, anyway.
In most cases it resulted in a code size increase.
2024-11-28 10:35:40 +01:00
Erik Eckstein
7ffd270008 embedded: move the VTableSpecializer pass into MandatoryPerformanceOptimizations
MandatoryPerformanceOptimizations already did most of the vtable specialization work.
So it makes sense to remove the VTableSpecializerPass completely and do everything in MandatoryPerformanceOptimizations.
2024-09-25 19:32:14 +02:00
Nate Chandler
5a6873b98f [SILOptimizer] Remove DestroyHoisting pass.
It's no longer used.
2024-02-19 11:41:38 -08:00
Erik Eckstein
17f246e219 Remove the old MoveOnlyDeinitDevirtualization.cpp pass 2023-11-27 09:21:34 +01:00
Kuba Mracek
d0c2a4ccf8 [embedded] Initial support for generic classes in embedded Swift
- VTableSpecializer, a new pass that synthesizes a new vtable per each observed concrete type used
- Don't use full type metadata refs in embedded Swift
- Lazily emit specialized class metadata (LazySpecializedClassMetadata) in IRGen
- Don't emit regular class metadata for a class decl if it's generic (only emit the specialized metadata)
2023-09-12 09:44:54 -07:00
Erik Eckstein
4d20423e00 Optimizer: re-implement the RedundantLoadElimination pass in Swift
The new implementation has several benefits compared to the old C++ implementation:

* It is significantly simpler. It optimizes each load separately instead of all at once with bit-field based dataflow.
* It's using alias analysis more accurately which enables more loads to be optimized
* It avoids inserting additional copies in OSSA

The algorithm is a data flow analysis which starts at the original load and searches for preceding stores or loads by following the control flow in backward direction.
The preceding stores and loads provide the "available values" with which the original load can be replaced.
2023-07-21 07:19:56 +02:00
Erik Eckstein
baaf5565b0 Optimizer: reimplement DeadStoreElimination in swift
The old C++ pass didn't catch a few cases.
Also:
* The new pass is significantly simpler: it doesn't perform dataflow for _all_ memory locations at once using bitfields, but handles each store separately. (In both implementations there is a complexity limit in place to avoid quadratic complexity)
* The new pass works with OSSA
2023-07-05 21:33:25 +02:00
Andrew Trick
0bbd92a446 [move-only] Rename MoveOnlyDeinitInsertion
to MoveOnlyDeinitDevirtualization
2023-06-06 09:17:53 -07:00
Erik Eckstein
4284dc10d0 Optimizer: implement the ObjectOutliner pass in Swift 2023-05-22 15:34:26 +02:00
Nate Chandler
1a7c4a4d12 [NFC] Renamed DestroyAddrHoisting.
It was previously named SSADestroyHoisting which is rather misleading
considering that it deals with addresses and hoists destroy_addrs.
2023-03-27 14:15:03 -07:00
Erik Eckstein
ed54253d29 SIL Optimizer: remove legacy C++ passes
They were used as a backup during the transition to Swift passes. Now they are not needed anymore.
2022-10-20 18:31:06 +02:00
Michael Gottesman
3e52007562 [builtin] Remove "unsafeGuaranteed" and related code since Unmanaged now has an Ownership SSA based implementation that works completely in SILGen.
This isn't used in the stdlib anymore as well.
2022-08-21 01:22:36 -07:00
Joe Groff
d2fad71328 Merge pull request #42589 from jckarter/begin-partial-apply-simplification-pass
[SIL] Initial work on PartialApplySimplification pass
2022-05-02 10:20:39 -07:00
Erik Eckstein
cad646b283 re-implement the StackPromotion pass in swift
It uses the new EscapeInfo.
2022-05-02 14:22:27 +02:00
Joe Groff
85760d5348 SIL: Add a PartialApplySimplification pass.
This will turn `partial_apply` instructions into explicit box construction and
extraction code sequences. To begin with, recognize when a private function
is only used in partial applications and directly modify the function to be
usable as a closure invocation function. This simplifies the lowering in IRGen
and avoids generating a "partial application forwarder" thunk.
2022-04-21 12:47:44 -07:00
Andrew Trick
c8a2130554 Add a SSADestroyHoisting utility and pass
Extract and rewrite the destroy hoisting algorithm originally from
CopyForwarding (in 2014).

This is now a light-weight utility for hoisting destroy_addr
instructions. Shrinking an object's memory lifetime can allow removal
of copy_addr and other optimization.

This is extremely low-overhead and can run at any optimization level
without dependency on any analysis.

This algorithm is:
- Incremental
- SSA-based
- Canonical
- Free from alias analysis

See file-level comments.

The immediate purpose is to specify and test the constraints
introduced by adding lexical variable lifetimes to SIL semantics. It
can be used as a template for end_borrow hoisting.

Ultimately, this utility can be invoked within any pass that needs to
optimize a particular uniquely identified address. It will be used to
remove much of the complexity from CopyForwarding.
2021-12-22 11:32:57 -08:00
Michael Gottesman
18670fc389 [assembly-vision] Rename opt remark generator to assembly vision remark generator.
TLDR: The reason why I am doing this is that often times people confuse assembly
vision remarks for normal opt remarks. I want to accentuate that this is
actually trying to do something different than a traditional opt remark. To that
end I renamed things in the compiler and added a true attribute
`@_assemblyVision` to trigger the compiler to emit these remarks to help
everyone remember what this is in their ontology. I explain below the
difference.

----

Normal opt remarks work by the optimizer telling you if it succeeded or failed
to perform an optimization. Another way of putting this is that opt remarks is
trying to give back feedback to the user from an expert system about why it did
or not do something. There is inherently an act of interpretation in the
optimizer about whether or not to report an 'action' that it perpetrated to the
user.

Assembly Vision Remarks is instead trying to be an expert tool that acts like an
xray. Instead of telling the user about what the optimizer did, it is instead a
simple visitor that visits the IR and emits SourceLocations for where specific
hazards ending up in the program. In this sense it is just telling the user
where certain instructions ended up and using heuristics to relate this to
information at the IR level. To a get a sense of this difference, consider the
following Swift Code:

```
public class Klass {
    func doSomething() {}
}

var global: Klass = Klass()

@inline(__always)
func bar() -> Klass { global }

@_assemblyVision
@inline(never)
func foo() {
  bar().doSomething()
}
```

In this case, we will emit the following remarks:

```
test.swift:16:5: remark: begin exclusive access to value of type 'Klass'
    bar().doSomething()
    ^
test.swift:7:5: note: of 'global'
var global: Klass = Klass()
    ^
test.swift:16:9: remark: end exclusive access to value of type 'Klass'
    bar().doSomething()
        ^
test.swift:7:5: note: of 'global'
var global: Klass = Klass()
    ^
test.swift:16:11: remark: retain of type 'Klass'
    bar().doSomething()
          ^
test.swift:7:5: note: of 'global'
var global: Klass = Klass()
    ^
test.swift:16:23: remark: release of type 'Klass'
    bar().doSomething()
                      ^
test.swift:7:5: note: of 'global'
var global: Klass = Klass()
    ^
```

Notice how the begin/end exclusive access are marked as actually being before
the retain, release of global. That seems weird since exclusive access to memory
seems like something that should not escape an exclusivity scope... but in fact
this corresponds directly to what we eventually see in the SIL:

```
// test.sil
sil hidden [noinline] [_semantics "optremark"] @$ss3fooyyF : $@convention(thin) () -> () {
bb0:
  %0 = global_addr @$ss6globals5KlassCvp : $*Klass
  %1 = begin_access [read] [dynamic] [no_nested_conflict] %0 : $*Klass
  %2 = load %1 : $*Klass
  end_access %1 : $*Klass
  %4 = class_method %2 : $Klass, #Klass.doSomething : (Klass) -> () -> (), $@convention(method) (@guaranteed Klass) -> ()
  strong_retain %2 : $Klass
  %6 = apply %4(%2) : $@convention(method) (@guaranteed Klass) -> ()
  strong_release %2 : $Klass
  %8 = tuple ()
  return %8 : $()
} // end sil function '$ss3fooyyF'
```

and assembly,

```
// test.S
_$ss3fooyyF:
	pushq	%rbp
	movq	%rsp, %rbp
	pushq	%r13
	pushq	%rbx
	subq	$32, %rsp
	leaq	_$ss6globals5KlassCvp(%rip), %rdi
	leaq	-40(%rbp), %rsi
	xorl	%edx, %edx
	xorl	%ecx, %ecx
	callq	_swift_beginAccess
	movq	_$ss6globals5KlassCvp(%rip), %r13
	movq	(%r13), %rax
	movq	80(%rax), %rbx
	movq	%r13, %rdi
	callq	_swift_retain
	callq	*%rbx
	movq	%r13, %rdi
	callq	_swift_release
	addq	$32, %rsp
	popq	%rbx
	popq	%r13
	popq	%rbp
	retq
```

so as one can see what we are trying to do is inform the user of hazards in the
code without trying to reason about it, automated a task that users often have
to perform by hand: inspection of assembly to determine where runtime calls and
other hazards ended up.
2021-06-12 15:09:46 -07:00
Michael Gottesman
1132cda811 [ownership] Move SemanticARCOpts into a separate folder in preparation for splitting into multiple small pseudo-passes.
SemanticARCOpts keeps on growing with various optimizations attached to a single
"optimization" manager. Move it to its own folder in prepation for splitting it
into multiple different optimizations and utility files.
2020-08-27 23:58:14 -07:00
Arnold Schwaighofer
997fc5d070 Merge pull request #33140 from aschwaighofer/eager_specializer_function_pass
Convert the EagerSpecializer pass to a function pass
2020-07-28 15:27:46 -07:00
Arnold Schwaighofer
ecf9fbd5f1 Move the EagerSpecializer pass to the Transforms directory
It is no longer a module transform.
2020-07-28 10:25:36 -07: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
Michael Gottesman
4559db01cb [opt-remark] Add a pass called Opt Remark Generator that implements small opt remarks that do not result from large dataflow checks.
We do allow for limited def-use traversal to do things like find debug_value.
But nothing like a full data flow pass. As a proof of concept I just emit
opt-remarks when we see retains, releases. Eventually I would like to also print
out which lvalue the retain is from but that is more than I want to do with this
proof of concept.
2020-07-14 19:32:46 -07: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
Joe Groff
e3ce94d97d Introduce a PruneVTables pass to mark non-overridden entries.
Start with some high-level checks of whether a declaration is formally final, or has no visible overrides
in the domain of the program visible to the SIL module.

We can eventually adopt more of the logic from the Devirtualizer pass to tell whether call sites are
"effectively final", and maybe make the Devirtualizer consume that information applied by this pass.
2020-06-05 11:03:04 -07:00
Erik Eckstein
9722578df6 SILOptimizer: a new optimization for copy-on-write
Constant folds the uniqueness result of begin_cow_mutation instructions, if it can be proved that the buffer argument is uniquely referenced.
For example:

     %buffer = end_cow_mutation %mutable_buffer
     // ...
     // %buffer does not escape here
     // ...
     (%is_unique, %mutable_buffer2) = begin_cow_mutation %buffer
     cond_br %is_unique, ...

is replaced with

     %buffer = end_cow_mutation [keep_unique] %mutable_buffer
     // ...
     (%not_used, %mutable_buffer2) = begin_cow_mutation %buffer
     %true = integer_literal 1
     cond_br %true, ...

Note that the keep_unique flag is set on the end_cow_mutation because the code now relies on that the buffer is really uniquely referenced.

The optimization can also handle def-use chains between end_cow_mutation and begin_cow_mutation which involve phi-arguments.

An additional peephole optimization is performed: if the begin_cow_mutation is the only use of the end_cow_mutation, the whole pair of instructions is eliminated.
2020-05-26 18:01:17 +02:00
Erik Eckstein
ad99b9d4f8 SILOptimizer: a new phi-argument expansion optimization.
If only a single field of a struct phi-argument is used, replace the argument by the field value.

     br bb(%str)
   bb(%phi):
     %f = struct_extract %phi, #Field // the only use of %phi
     use %f

is replaced with

     %f = struct_extract %str, #Field
     br bb(%f)
   bb(%phi):
     use %phi

This also works if the phi-argument is in a def-use cycle.

The new PhiExpansionPass is in the same file as the RedundantPhiEliminationPass. Therefore I renamed the source file to PhiArgumentOptimizations.cpp
2020-05-25 09:36:09 +02:00
Saleem Abdulrasool
cebe79d482 SIL: use object libraries instead of globbing
This simplifies the handling of the subdirectories in the SIL and
SILOptimizer paths.  Create individual libraries as object libraries
which allows the analysis of the source changes to be limited in scope.
Because these are object libraries, this has 0 overhead compared to the
previous implementation.  However, string operations over the filenames
are avoided.  The cost for this is that any new sub-library needs to be
added into the list rather than added with the special local function.
2020-05-18 18:56:34 +00:00
ematejska
4cd68edf8c [Autodiff upstream] Add DifferentiabilityWitnessDevirtualizer SILOptimizer pass (#30984)
Add DifferentiabilityWitnessDevirtualizer: an optimization pass that
devirtualizes `differentiability_witness_function` instructions into
`function_ref` instructions.

Co-authored-by: Dan Zheng <danielzheng@google.com>
2020-04-23 02:13:05 -07:00
Erik Eckstein
93a0dfc578 SILOptimizer: a new small optimization pass to remove redundant basic block arguments.
RedundantPhiElimination eliminates block phi-arguments which have the same value as other arguments of the same block.
This also works with cycles, like two equivalent loop induction variables. Such patterns are generated e.g. when using stdlib's enumerated() on Array.

   preheader:
     br bb1(%initval, %initval)
   header(%phi1, %phi2):
     %next1 = builtin "add" (%phi1, %one)
     %next2 = builtin "add" (%phi2, %one)
     cond_br %loopcond, header(%next1, %next2), exit
   exit:

is replaced with

   preheader:
     br bb1(%initval)
   header(%phi1):
     %next1 = builtin "add" (%phi1, %one)
     %next2 = builtin "add" (%phi1, %one) // dead: will be cleaned-up later
     cond_br %loopcond, header(%next1), exit
   exit:

Any remaining dead or "trivially" equivalent instructions will then be cleaned-up by DCE and CSE, respectively.

rdar://problem/33438123
2020-03-26 19:30:01 +01:00
Michael Gottesman
5e9d720a28 Move TempRValueOpt from CopyForwarding.cpp -> TempRValueElimination.cpp.
The pass is standalone from CopyForwarding and is big enough to stand on its
own.

This changes is NFC beyond clang-format + xcode rename.
2020-02-25 21:12:16 -08:00
Michael Gottesman
15bd35017d [ownership] Move semantic arc opts from Mandatory -> Transforms. 2020-02-25 14:16:43 -08:00
Arnold Schwaighofer
8aaa7b4dc1 SILOptimizer: Pipe through TypeExpansionContext 2019-11-11 14:21:52 -08:00
Michael Gottesman
386568c7e9 [gardening] Move ome from Transform -> Mandatory as per @atrick's request. 2019-10-28 16:26:13 -07:00
Erik Eckstein
0e08976600 SILOptimizer: a new optimization to hoist destroys of memory locations
DestroyHoisting moves destroys of memory locations up the control flow as far as possible.
Beside destroy_addr, also "store [assign]" is considered a destroy, because is is equivalent to an destroy_addr + a "store [init]".
The main purpose of this optimization is to minimize copy-on-write operations for arrays, etc. Especially if such COW containers  are used as enum payloads and modified in-place. E.g.

switch e {
  case .A(var arr):
    arr.append(x)
    self = .A(arr)
...

In such a case DestroyHoisting can move the destroy of the self-assignment up before the switch and thus let the array buffer only be single-referenced at the time of the append.

When we have ownership SIL throughout the pass pipeline this optimization will replace the current destroy hoisting optimization in CopyForwarding.
For now, this optimization only runs in the mandatory pipeline (but not for -Onone) where we already have ownership SIL.

SR-10605
rdar://problem/50463362
2019-08-28 15:40:05 +02:00
Michael Gottesman
1980d57cdc Move MarkUninitializedFixup to ./lib/SILOptimizer/Mandatory since it is only used in the mandatory pipeline. 2019-06-20 13:16:07 -07:00
Arnold Schwaighofer
fbf09031e4 Add a pass to specialize opaque type archetypes.
Clones functions containing opaque type archetypes replacing the opaque
type by a concrete type.

rdar://46140751
2019-05-01 09:31:07 -07:00
Joe Shajrawi
32da4f9f45 [Exclusivity] Sink may release release instructions out of access scopes
General case:
begin_access A
...
strong_release / release_value / destroy
end_access

The release instruction can be sunk below the end_access instruction,
This extends the lifetime of the released value, but, might allow us to
Mark the access scope as no nested conflict.
2018-10-31 15:48:08 -07:00
Joe Shajrawi
63b50f65a4 [Exclusivity] Remove dominated access checks with no nested conflict.
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)
2018-10-25 15:21:06 -07:00
Andrew Trick
098759f070 CopyPropagation for SILValues with ownership.
This is a simple "utility" pass that canonicalizes SSA SILValues with
respect to copies and destroys. It is a self-contained, provably
complete pass that eliminates spurious copy_value instructions from
scalar SSA SILValues. It fundamentally depends on ownership SIL, but
otherwise can be run efficiently after any other pass. It separates
the pure problem of handling scalar SSA values from the more important
and complex problems:

- Promoting variables to SSA form (PredictableMemOps and Mem2Reg
  partially do this).

- Optimizing copies within "SIL borrow" scopes (another mandatory pass
  will be introduced to do this).

- Composing and decomposing aggregates (SROA handles some of this).

- Coalescing phis (A BlockArgumentOptimizer will be introduced as part
  of AddressLowering).

- Removing unnecessary retain/release when nothing within its scope
  may release the same object (ARC Code Motion does some of this).

Note that removing SSA copies was more obviously necessary before the
migration to +0 argument convention.
2018-09-04 13:12:36 -07:00
Erik Eckstein
192431b830 SIL optimizer: remove the RemovePin optimization.
Not useful anymore after removing the pinning adressors
2018-08-23 12:47:56 -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
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
30d4f45468 [func-sig-opts] Move FunctionSignatureOpts into the directory FunctionSignatureTransform in preparation for splitting it. 2018-06-04 00:49:14 -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
5baa90ca4c [irgen-prepare] Move SILCleanup to ./lib/SILOptimizer/Mandatory and rename it to IRGenPrepare.
I am going to be adding logic here to enable apple/swift#1550 to be completed.
The rename makes sense due to precedent from LLVM's codegen prepare and also
since I am going to be expanding what the pass is doing beyond just "cleaning
up". It is really a grab bag pass for performing simple transformations that we
do not want to pollute IRGen's logic with.

https://github.com/apple/swift/pull/15502

rdar://39335800
2018-04-17 00:07:16 -07:00
Erik Eckstein
bf87035a36 GlobalOpt: Move the object outlining from GlobalOpt into a separate pass "ObjectOutliner"
We run GlobalOpt multiple times in the pass pipeline but in some cases object outlining shouldn't be done too early.
Having it done in a separate pass enables to run it independently from GlobalOpt.
2018-01-19 11:32:36 -08:00
eeckstein
b126b62256 Revert "Optimization changes to completely fold OptionSet literals" 2018-01-18 22:05:07 -08:00
Erik Eckstein
1f511ab846 GlobalOpt: Move the object outlining from GlobalOpt into a separate pass "ObjectOutliner"
We run GlobalOpt multiple times in the pass pipeline but in some cases object outlining shouldn't be done too early.
Having it done in a separate pass enables to run it independently from GlobalOpt.
2018-01-18 18:27:17 -08:00