Commit Graph

2053 Commits

Author SHA1 Message Date
Michael Gottesman
e29e035ab8 [region-analysis] Add a pass that explicitly invalidates RegionAnalysis.
Over time I am going to be using RegionAnalysis for a series of passes that all
use that same information since I am worried about RegionAnalysis computation
time. With that being said, we want to make sure to eliminate the memory that
RegionAnalysis uses once this series of passes have completed. What this commit
does is create a pass that explicitly invalidates region analysis and explicitly
places it in the pass pipeline after the series of passes. This will ensure that
even if we add an additional pass, there is a strong "rattlesnake" signal to the
new code author that the code needs to be placed before the region analysis
invalidation and will prevent mistakes such as having to recompute the region
analysis in that later pass or the later pass forgeting to invalidate the
analysis.
2024-02-09 11:59:04 -08:00
Michael Gottesman
7df13b3c1f [sil] Refactor VariableNameUtils for handling more kinds of writes to temporaries. 2024-02-06 16:18:34 -08:00
Michael Gottesman
a569160f21 [sil] Refactor out the variable name inferer from MoveOnlyDiagnostics.cpp -> VariableNameUtils.
I am going to reuse this for TransferNonSendable. In the process I made a few
changes to make it more amenable to both use cases and used the current set of
tests that we have for noncopyable types to validate that I didn't break
anything.
2024-02-06 13:42:35 -08:00
Michael Gottesman
90f192abfe Merge pull request #71380 from gottesmm/pr-5c52de648d247153d66d33aad7d089d6324242ed
[region-isolation] When changing an elements region, if that element was the last element in a transferred regionl, remove that region from the transferredOpMap.
2024-02-04 16:55:59 -08:00
Michael Gottesman
434261b851 [region-isolation] When changing an elements region, if that element was the last element in a transferred regionl, remove that region from the transferredOpMap.
I also added some validation that we properly do this. It only runs when NDEBUG
is not set.

rdar://122280930
2024-02-04 14:16:24 -08:00
Michael Gottesman
12e4e8d6e8 [region-isolation] Add support for all pack instructions. 2024-02-02 14:50:10 -08:00
Erik Eckstein
7fb4fc0f36 MandatoryPerformanceOptimizations: fix the linkage of function-signature-specialized functions
We need to keep the original linkage because it would be illegal to call a shared not-serialized function from a serialized function.

Also, rename the API to create the specialized function.
2024-02-02 07:27:38 +01:00
Erik Eckstein
250e2680aa SwiftCompilerSources: add some module-level APIs
* `Context.lookupFunction`
* `ModulePassContext.loadFunction`
* `ModulePassContext.createSpecializedFunctionDeclaration`
* `ModulePassContext.moveFunctionBody`
* `ModulePassContext.mangle(withDeadArguments:)`
2024-01-31 17:16:13 +01:00
Erik Eckstein
fa0be3c10f SwiftCompilerSources: bridge some SIL APIs
* `TryApplyInst.specializationInfo`
* `BasicBlock.addFunctionArgument`
* `Function.appendNewBlock`
2024-01-31 17:16:12 +01:00
Erik Eckstein
7a62f15dae pass Context: verify that only the currently transformed function is modified 2024-01-31 17:16:12 +01:00
Andrew Trick
ddceffaf3b LifetimeDependenceDiagnostics pass
Initial diagnostic pass to enforce ~Escapable types.
2024-01-30 11:45:55 -08:00
Doug Gregor
e96dcac7b4 Make sure we always have a SILFunction for region-based isolation checking
Some values (such as `undef`) might not be associated with a function.
2024-01-25 16:04:48 -08:00
Michael Gottesman
9303c40162 [region-isolation] Teach region isolation that assigning into a transferring parameter is a transfer of the value.
The specific semantics is if we assign into a transferring parameter's field,
then we "merge" src's value into the transferring parameter, so we
conservatively leave the region of the transferring parameter alone. If we
assign over the entire transferring parameter, we perform an assign fresh since
any value that used to be in the transferring parameter cannot reference
anything in its new value since they are all gone.
2024-01-18 13:20:28 -08:00
eeckstein
6bf39cccd6 Merge pull request #70787 from eeckstein/boolean-literal-folding
Mandatory optimizations: constant fold boolean literals before the DefiniteInitialization pass
2024-01-11 11:39:44 +01:00
Michael Gottesman
053e30d46d [region-isolation] Make sure not to run RegionAnalysis on functions that we do not support.
Before this commit, this was done at the beginning of TransferNonSendable. I
thought that those checks would be sufficient to ensure that
RegionAnalysisFunctionInfo was not created for functions that we do not
support. Turns out when we perform certain forms of verification, we force all
function analyses to be created for all functions meaning that we would create a
RegionAnalysisFunctionInfo for such an unsupported function causing us to hit
asserts.

In this commit, I move the check to whether or not we support a function into
RegionAnalysisFunctionInfo itself and use that to determine if we should run
TransferNonSendable. This additionally allows me to change
RegionAnalysisFunctionInfo so that one can construct one for an unsupported
function... as long as one doesn't actually touch any of its methods. If one
does, I put in an assert so we will know that operator error has occured.
2024-01-10 13:41:12 -08:00
Michael Gottesman
a9dc4ed6cc [region-isolation] Refactor out the Region analysis from TransferNonSendable.
NFCI. This is just a pure refactor of the analysis part of TransferNonSendable
into a separate SIL level analysis so it can be reused by other passes.

The reason that I am committing this earlier is that I am working concurrently
on other patches that change TransferNonSendable itself and I want to avoid
issues when rebasing those patches. Getting this patch into tree earlier avoids
that.

This is in preparation for adding a new flow sensitive initialization pass that
combines region based analysis with the current flow sensitive isolation's
diagnostic emitter. The idea is that we want to preserve the diagnostics from
that pass rather than try to make our own as an initial step.
2024-01-10 13:41:12 -08:00
Erik Eckstein
c89df9ec98 Mandatory optimizations: constant fold boolean literals before the DefiniteInitialization pass
Add a new mandatory BooleanLiteralFolding pass which constant folds conditional branches with boolean literals as operands.

```
  %1 = integer_literal -1
  %2 = apply %bool_init(%1)   // Bool.init(_builtinBooleanLiteral:)
  %3 = struct_extract %2, #Bool._value
  cond_br %3, bb1, bb2
```
->
```
  ...
  br bb1
```

This pass is intended to run before DefiniteInitialization, where mandatory inlining and constant folding didn't run, yet (which would perform this kind of optimization).
This optimization is required to let DefiniteInitialization handle boolean literals correctly.
For example in infinite loops:

```
   init() {
     while true {           // DI need to know that there is no loop exit from this while-statement
       if some_condition {
         member_field = init_value
         break
       }
     }
   }
```
2024-01-10 16:15:57 +01:00
eeckstein
74fbae14cf Merge pull request #70684 from eeckstein/static-objects
ObjectOutliner: support outlining of classes in global let variables
2024-01-10 15:03:29 +01:00
Erik Eckstein
543fe31e8f SwiftCompilerSources: add Context.notifyDependency(onBodyOf:)
It notifies the pass manager that the optimization result of the current pass depends on the body (i.e. SIL instructions) of another function than the currently optimized one.
2024-01-10 09:34:00 +01:00
Erik Eckstein
4aa51ffeab PassManager: add the -sil-pass-count-config-file for easier bisecting pass counts in large projects
This is useful for bisecting passes in large projects:
  1. create a config file from a full build log. E.g. with
        ```
        grep -e '-module-name' build.log  | sed -e 's/.*-module-name \([^ ]*\) .*/\1:10000000/' | sort | uniq > config.txt
        ```
  2. add the `-Xllvm -sil-pass-count-config-file config.txt` option to the project settings
  3. bisect by modifying the counts in the config file
  4. clean-rebuild after each bisecting step
2024-01-09 12:12:33 +01:00
Michael Gottesman
8178eb0a6e Merge pull request #70514 from gottesmm/pr-763529d8ee9f4164b82d03087fec25439cc1d315
[region-isolation] Fix the dataflow and add support for project_block_storage
2023-12-19 10:21:59 -08:00
Meghana Gupta
890ec7d855 Merge pull request #70477 from meg-gupta/fixpredmemopt
Use OSSALifetimeCompletion in PredictableMemOpt
2023-12-15 19:18:22 -08:00
Michael Gottesman
bcb8f1b0d8 [region-isolation] Implement the dataflow correctly.
This involved fixing a few different bugs.

1. We were just performing dataflow by setting that only the initial block needs
to be updated. This means that if there isn’t anything in the initial dataflow
block, we won’t visit any successor blocks. Instead the correct thing to do here
is to visit all blocks in the initial round.

2. I also needed to fix a separate issue where we were updating our union-find
data structure incorrectly as found by an assert on transfernonsendable.swift
that was triggered once I fixed 1. Put simply, we needed to set a new max label
+ 1 when our new max element is less than or equal to the old max label + 1…
before we just did less than so if we had a new max element that is the same as
our fresh label, we wouldn’t increment the fresh label.

rdar://119584497
2023-12-15 17:14:09 -08:00
Meghana Gupta
06f0d15c45 Use OSSALifetimeCompletion in PredictableMemOpt
The current algorithm to complete lifetimes is incorrect in a few cases.
Use OSSALifetimeCompletion instead.

Fixes rdar://119204768
2023-12-15 15:16:55 -08:00
nate-chandler
680c737ddb Merge pull request #64789 from nate-chandler/more-move-values
[SILGen] Used move_value for more lexical values.
2023-12-15 07:07:54 -08:00
Nate Chandler
adbb10dddd [CanOSSALifetime] Respect lexical lifetimes attr. 2023-12-14 09:10:10 -08:00
Erik Eckstein
773d6b179d SwiftCompilerSources: remove the redundant BridgedPassContext.Feature enum
And replace it with the existing BridgedFeature
2023-12-13 13:28:17 +01:00
Erik Eckstein
ae278058e6 Add an experimental pass to lower allocateVector builtins
By default it lowers the builtin to an `alloc_vector` with a paired `dealloc_stack`.
If the builtin appears in the initializer of a global variable and the vector elements are initialized,
a statically initialized global is created where the initializer is a `vector` instruction.
2023-12-09 18:49:58 +01:00
Erik Eckstein
ca20ebc158 SwiftCompilerSources: add bridging to hasFeature 2023-12-09 18:49:57 +01:00
Erik Eckstein
cc83a7d414 add the "array.copy_into_vector" array-semantic 2023-12-09 18:49:57 +01:00
Erik Eckstein
9514b3450c SwiftCompilerSources: add some context APIs
* `Context.moduleIsSerialized`
* `Context.getBuiltinIntegerType`
* `Instruction.move(before:)`
2023-12-09 18:48:50 +01:00
Dario Rexin
406fe3eed2 [SILOpt] Allow pre-specializations for _Trivial of known size (#70256)
* [SILOpt] Allow pre-specializations for _Trivial of known size

rdar://119224542

This allows pre-specializations to be generated and applied for trivial types of a shared size.
2023-12-08 19:42:49 -08:00
Michael Gottesman
398fa8b10f [region-isolation] Make PartitionOpEvaluator use CRTP instead of std::function callbacks.
Just a fixup requested by reviewers of incoming code that I wanted to do in a
follow on commit.
2023-12-04 13:03:15 -06:00
Michael Gottesman
df03cb40ef [region-isolation] Make PartitionOpEvaluator no longer a friend of Partition.
I left them as friends since that was in the original code. There isn't a reason
to do this and break the encapsulation of Partition. I just added reasonable
helpers that give PartitionOpEvaluator all of the functionality it needs.
2023-12-04 13:03:15 -06:00
eeckstein
10ff55b2b3 Merge pull request #70155 from eeckstein/refactoring
MemoryLifetimeVerifier: use CalleeCache instead of AliasAnalysis
2023-12-04 08:53:59 +01:00
Michael Gottesman
12573d6b52 [region-isolation] Instead of just tracking a single transferring instruction, track all of them.
Previously I avoided doing this since the only problem would be that in a case
where we had two transfer instructions that were in an if-else block, we would
just emit an error for one:

```swift
if boolValue {
  transfer(x)
} else {
  transfer(x) // Only emit error for this transfer!
}

useValue(x)
```

Now that we are tracking at the transfer point if any element in the transfer
was captured in a closure, this becomes an actual semantic issue since if we
track the transfer instruction that isn't reachable from the closure capture, we
will not become more pessimistic:

```swift
if boolValue {
  closure = { useInOut(&x) }
  transfer(x)
} else {
  transfer(x)
}

// Since we grab from the else block, sendableField is allowed to be accessed
// since we do not track that x was captured by reference in a closure.
x.sendableField
useValue(x)
```

To be truly safe, we need to emit both errors.

rdar://119048779
2023-12-01 13:53:57 -08:00
Michael Gottesman
a2604dcafa [region-isolation] Ensure that we error if we access a Sendable field of a non-Sendable typed var and the var is captured in a closure
If the var is captured in a closure before it is transferred, it is not safe to
access the Sendable field since we may race on accessing the field with an
assignment to the field in another concurrency domain.

rdar://115124361
2023-12-01 13:53:56 -08:00
Erik Eckstein
0897d8a720 MemoryLifetimeVerifier: use CalleeCache instead of AliasAnalysis
To verify if a function may read from an indirect argument, don't use AliasAnalysis.
Instead use the CalleeCache to get the list of callees of an apply instruction.
Then use a simple call-back into the swift Function to check if a callee has any relevant memory effect set.

This avoids a dependency from SIL to the Optimizer.
It fixes a linker error when building some unit tests in debug.
2023-12-01 19:20:18 +01:00
Erik Eckstein
e80fedc52a move CalleeCache from SILOptimizer to SIL
Extract the CalleeCache from BasicCalleeAnalysis so that it can be used in SIL without BasicCalleeAnalysis
2023-12-01 19:20:18 +01:00
Michael Gottesman
ccefdebb26 Merge pull request #70031 from gottesmm/region-isolation-async-let
[region-isolation] Add support for async let
2023-11-28 20:30:47 -08:00
Michael Gottesman
d1870c1ae3 [region-isolation] Fix return vs break logic error in the evaluator.
I am not sure if this would ever actually ever cause a bug... but we should be
consistent. The issue here is that in the evaluator switch when processing
transfers in certain cases when we emitted an early error due to an actor
derived value we were performing a transfer and other times we weren't. With
this patch:

1. We now consistently do not actually transfer the value if it is actor
derived. It is always illegal to transfer an actor derived value... so we know
that if we always just error on transferring it, we have a safe model.

2. The switch we breaking so that we could do an assert that we canonicalized
the modified PartitionOp. Rather than do that and allow for people to
potentially return, I moved the assert into a SWIFT_DEFER and added an assert in
the continuation of the switch. This means that if an author ever breaks out of
the switch, they will hit the assert implying that the author in all cases must
explicitly return within the case statement guaranteeing this mistake does not
happen again.
2023-11-28 09:48:44 -08:00
Michael Gottesman
18f91c0acd [region-isolation] Add support for async let.
Specifically:

1. If the value is transferred such that it becomes part of an actor region, the
value is permanently part of the actor region as one would normally have.

2. If the value is just used in an async let or is used by a nonisolated async
function within the async let then while the async let is alive it cannot be
used. But once the async let has been awaited upon, we allow for it to be used
again.

rdar://117506395
2023-11-28 09:39:04 -08:00
Erik Eckstein
8681131c58 add some comments in the bridging headers 2023-11-28 09:02:10 +01:00
Kshitij
97a5a83ae6 [sil-optimizer] Add FP comparison support in constant folder 2023-11-27 11:32:28 -08:00
eeckstein
67ebbee39e Merge pull request #69955 from eeckstein/deinit-devirtualizer
Optimizer: de-virtualize deinits of non-copyable types
2023-11-27 12:41:49 +01:00
Erik Eckstein
17f246e219 Remove the old MoveOnlyDeinitDevirtualization.cpp pass 2023-11-27 09:21:34 +01:00
Erik Eckstein
96e57d62f6 Optimizer: de-virtualize deinits of non-copyable types
In regular swift this is a nice optimization. In embedded swift it's a requirement, because the compiler needs to be able to specialize generic deinits of non-copyable types.
The new de-virtualization utilities are called from two places:

* from the new DeinitDevirtualizer pass. It replaces the old MoveOnlyDeinitDevirtualization, which is very basic and does not fulfill the needs for embedded swift.

* from MandatoryPerformanceOptimizations for embedded swift
2023-11-27 09:21:34 +01:00
Erik Eckstein
b948ccf1ae SwiftCompilerSources: add more APIs to create new basic blocks
* rename `Context.splitBlock(at:)` -> `Context.splitBlock(before:)`
* add `Context.splitBlock(after:)`
* add `Context.createBlock(after:)`
2023-11-27 09:21:33 +01:00
Erik Eckstein
8458481f0e GenericSpecializer: support specializing typed throws
This means to support specializing functions with indirect error results.
Also, when specializing (and the concrete error type is loadable), convert the indirect error to a direct error.

rdar://118532113
2023-11-27 08:51:13 +01:00
Erik Eckstein
d4c1638f7f GenericCloner: remove FunctionExits
It's not used
2023-11-27 08:51:12 +01:00