Commit Graph

1000 Commits

Author SHA1 Message Date
nate-chandler
23915e8075 Merge pull request #74109 from nate-chandler/rdar113142446
[ConsumeObjectChecker] End lifetimes at consumes.
2024-06-04 18:17:36 -07:00
Nate Chandler
04ffbe8a6e [NFC] OwnedValueCan: Add support for end markers.
Enhance the utility with the ability to end lifetimes of lexical values
at indicated instructions, overriding the usual behavior of maintaining
such lifetimes' previous endpoints (modulo non-deinit-barrier
instructions).
2024-06-03 15:45:29 -07:00
Nate Chandler
dc9baba586 [NFC] OwnedValueCan: Extracted extension visitor.
Parameterized `extendUnconsumedLiveness` on the ends of interest and the
action to take when visiting the extended boundary and named the
resulting function `visitExtendedUnconsumedBoundary`.
2024-06-03 15:45:26 -07:00
Nate Chandler
aa3cbe0c67 [NFC] OwnedValueCan: Typed maximizeLifetime. 2024-06-03 15:45:23 -07:00
Nate Chandler
df008924da [NFC] OwnedValueCan: Typed pruneDebugMode. 2024-06-03 15:45:20 -07:00
Michael Gottesman
74ac12c9d2 [region-isolation] Make temporary alloc_stack that we form for returning values from a non-final class field take on the class method's isolation.
The reason why we are doing this is that otherwise, we have that the alloc_stack
formed for the result is disconnected and despite the fact that we merge it into
the actor region of the class method, we do not have that the alloc_stack
specifically is marked when we attempt to squelch Please.

This patch fixes that problem by detecting when an alloc_stack is being used as
a temporary for an out parameter and makes the alloc_stack initially isolated as
appropriate. It only does this in the specific cases where we can pattern match
it which in my limited testing has handled everything.
2024-05-28 17:31:08 -07:00
Michael Gottesman
2de13df909 [region-isolation] Use SILIsolationInfo::initializeTrackableValue instead of SILIsolationInfo::mergeIsolationRegionInfo to fix last issue
When merging SILIsolationInfo for regions, we want to drop
nonisolated(unsafe). This is important since nonisolated(unsafe) should only
apply to the specific "value" that it belongs to, not the entire region.

This creates a problem since in a few places in the code base we initialize a
value (producing a disconnected value) and then initialize it by merging in an
actor isolation. This no longer work since we will then always have
nonisolated(unsafe) stripped, so no values would ever be considered to be
nonisolated(unsafe). After analyzing the use case, I realized that these were
just initialization patterns and in this commit, I added a specific
initialization operation called SILIsolationInfo::initializeTrackableValue and
eliminated those calls to SILIsolationInfo::mergeIsolationRegionInfo.

Since SILIsolationInfo no longer has any merge operation on it, I then
eliminated that code in this commit. This completes the behavior split that I
put into the type system in the last commit. Specifically, I defined a
composition type called SILDynamicMergedIsolationInfo. It represents a
SILIsolationInfo that has been merged... that is why I called it the
DynamicMergedIsolationInfo. It could probably use a better name = (.

This fixes one of the last weird test case that I wrote where we were not letting through valid
nonisolated(unsafe) code.

At the same time, I discovered an additional issue (which can be seen in the
TODOs in this commit), where we are being too conservative around a non-Sendable
class var field. I am going to fix that in the next commit.

rdar://128299305
2024-05-27 21:42:15 -07:00
Michael Gottesman
1bef011e48 [region-isolation] Add the ability for the analysis to emit "unknown error" partition ops in case we detect a case we cannot pattern match.
DISCUSSION: The analysis itself is unable to emit errors. So we achieve the same
functionality by in such cases emitting a partition op that signals to our user
that when they process that partition op they should emit an "unknown pattern"
error at the partition op's instructions.

I have wanted this for a long time, but I never got around to it.
2024-05-27 21:42:04 -07:00
Michael Gottesman
741244e16b [region-isolation] Split in the type system SILIsolationInfo that has been merged and those that haven't.
Specifically, I introduced a new composition type called
SILDynamicMergedIsolationInfo that just contains a
SILIsolationInfo. Importantly, whenever one merges a SILIsolationInfo with
another SILIsolationInfo, one gets back a SILDynamicMergedIsolationInfo.

The reason why I am doing this is that we drop nonisolated(unsafe) when merging
so I want to ensure that parts of the code that use merging (where the dropping
occurs) and normal SILIsolationInfo where we do not want to merge is
distinguished.
2024-05-27 21:41:54 -07:00
Michael Gottesman
3a1f58a72a [region-isolation] Make sure that nonisolated(unsafe) works in all cases.
I made sure we match what we get without region isolation by turning off region
isolation in one of the test runs on the test for this.

There is one problem where for non-final classes with nonisolated(unsafe) var
fields, we currently do not properly squelch since I need to do more
infrastructure work. I am going to do that in the next commit.

rdar://128299305
2024-05-27 21:41:32 -07:00
Michael Gottesman
89a2cfce0b [region-isolation] Initialize TrackableValueState's regionInfo with a .none instead of a disconnected region.
The design change here is that instead of just initializing the regionInfo with
disconnected, we set it as .none and if we see .none, just return a newly
construct disconnected isolation region info when getIsolationRegionInfo() is
called.

This enables us to provide a setIsolationRegionInfo() helper for
RegionAnalysisValueMap::getTrackableValue that does not perform a merge. This is
important since for nonisolated(unsafe), we want to not have nonisolated(unsafe)
propagate through merging. So if we use merging to initialize the internal
regionInfo state of a SILIsolationInfo, we will never have a SILIsolationInfo
with that bit set since it will be lost in the merge. So we need some sort of
other assignment operator. Noting that we should only compute a value's
SILIsolationInfo once in RegionAnalysisValueMap before we cache it in the map,
it made sense to just represent it as an optional that way we can guarantee that
the regionInfo is only ever set exactly once by that routine.
2024-05-27 21:28:34 -07:00
Michael Gottesman
3f26d08ee4 [region-isolation] Add the ability in SILIsolationInfo to represent a disconnected value that is nonisolated(unsafe). 2024-05-27 21:25:44 -07:00
Michael Gottesman
4b29089f8b [region-isolation] Add a little bit of documentation to ActorInstance. 2024-05-27 21:21:52 -07:00
Michael Gottesman
3597006200 [region-isolation] Move SILIsolationInfo out of PartitionUtils into its own header/cpp file.
SILIsolationInfo is conceptually a layer that composes with PartitionUtils so it
makes sense for it to be in a different file.
2024-05-27 20:37:08 -07:00
Ellie Shin
5ccc4cd394 SIL function can be serialized with different kinds: [serialized] or
[serialized_for_package] if Package CMO is enabled. The latter kind
allows a function to be serialized even if it contains loadable types,
if Package CMO is enabled. Renamed IsSerialized_t as SerializedKind_t.

The tri-state serialization kind requires validating inlinability
depending on the serialization kinds of callee vs caller; e.g. if the
callee is [serialized_for_package], the caller must be _not_ [serialized].
Renamed `hasValidLinkageForFragileInline` as `canBeInlinedIntoCaller`
that takes in its caller's SerializedKind as an argument. Another argument
`assumeFragileCaller` is also added to ensure that the calle sites of
this function know the caller is serialized unless it's called for SIL
inlining optimization passes.

The [serialized_for_package] attribute is allowed for SIL function, global var,
v-table, and witness-table.

Resolves rdar://128406520
2024-05-23 15:53:02 -07:00
Slava Pestov
a1462ef184 SIL: Promote removeDeadBlock() from SILOptimizer to a method on SILBasicBlock 2024-05-21 13:52:58 -04:00
Michael Gottesman
fe2dc11cb9 [region-isolation] When computing isolation for isolated parameters, use getAnyActor instead of getNominalOrBoundGenericNominal().
This ensures that we can properly compute isolation for generic types that
conform to AnyActor.

I found this by playing with test cases from the previous commit. We would not
find an actor type for the actor instance isolation and would fall back along an
incorrect path.

rdar://128021548
2024-05-13 13:43:51 -07:00
Michael Gottesman
35a5a2546a [region-isolation] Fix isolation inference for init accessors.
rdar://127844737
2024-05-10 15:33:44 -07:00
Michael Gottesman
50c2d678f2 [region-isolation] When inferring isolation for an argument, handle non-self isolated parameters as well as self parameters that are actor isolated.
As part of this I went through how we handled inference and rather than using a
grab-bag getActorIsolation that was confusing to use, I created split APIs for
specific use cases (actor instance, global actor, just an apply expr crossing)
that makes it clearer inside the SILIsolationInfo::get* APIs what we are
actually trying to model. I found a few issues as a result and fixed most of
them if they were small. I also fixed one bigger one around computed property
initializers in the next commit. There is a larger change I didn't fix around allowing function
ref/partial_apply with isolated self parameters have a delayed flow sensitive
actor isolation... this will be fixed in a subsequent commit.

This also fixes a bunch of cases where we were printing actor-isolated instead
of 'self' isolated.

rdar://127295657
2024-05-10 15:33:44 -07:00
Kshitij
a7f8d6c647 [Autodiff] Adds bridging code in preparation for the Swift based Autodiff closure-spec pass 2024-05-02 09:14:05 -07:00
Emil Pedersen
a31d15c438 Merge pull request #72964 from Snowy1803/mem2reg-salvage-store
[DebugInfo] Salvage all stores
2024-04-25 16:52:37 -07:00
Emil Pedersen
523a769e34 [DebugInfo] [Mem2Reg] Move debug info promotion to salvageDebugInfo 2024-04-23 13:12:21 -07:00
Michael Gottesman
1113a61f8d [region-isolation] Stub out getIsolationInfo so the mocking unit tests succeed.
Specifically, the partition unit tests pass in bogus instructions/operands so we
cannot call /any/ methods on them. So I created stubed out helpers on the
evaluator that in the case of mocking just return a default initialized
SILIsolationInfo().
2024-04-19 15:28:48 -07:00
Michael Gottesman
0e21c58619 [region-isolation] Disconnected regions in global actor isolated function are not accessible again after call to nonisolated async function
I also fixed the nonisolated(unsafe) issue.

rdar://126667934
rdar://126174959
2024-04-19 13:52:58 -07:00
Michael Gottesman
3c29997cd1 [region-isolation] Out of an abundance of caution convert isActor -> isAnyActor(). 2024-04-17 13:07:56 -07:00
Michael Gottesman
2e5b3bc257 [region-isolation] Do not treat functions/class_methods that are isolated to a #isolated as being globally isolated to that.
Instead, we need to consider the isolation at the apply site.

rdar://126285681
rdar://125078448
2024-04-11 16:00:55 -07:00
Michael Gottesman
51ef67d7df [variable-name-utils] Refactor inferName/inferNameAndRoot helpers onto VariableNameInferrer.
I have been using these in TransferNonSendable and they are useful in terms of
reducing the amount of code that one has to type to use this API. I am going to
need to use it in SILIsolationInfo, so it makes sense to move it into
SILOptimizer/Utils.

NFCI.
2024-04-11 15:41:18 -07:00
Michael Gottesman
d8f39f70d9 [region-isolation] Begin tracking in SILIsolationInfo the actorInstance that a value is isolated to if we are dealing with an actor instance.
This will let us distinguish in between values derived from two actor instances
of the same type and to emit better errors.
2024-04-11 15:41:18 -07:00
Michael Gottesman
b407b21e9a [region-isolation] Finish moving isolation computation into SILIsolationInfo::get. 2024-04-11 15:41:18 -07:00
Michael Gottesman
513ab78602 [region-isolation] Move SILIsolationInfo determining code for ref_element_addr and global_addr onto SILIsolationInfo and call that instead. 2024-04-11 15:41:18 -07:00
Michael Gottesman
b80faee2a7 [region-isolation] Rename Partition::{fresh_label,freshLabel}. 2024-04-11 15:41:18 -07:00
Michael Gottesman
df4fb64ea1 Merge pull request #72955 from gottesmm/rdar126170014
[region-isolation] Include the region -> transferring operand map in the dataflow convergence.
2024-04-10 17:20:55 -07:00
Michael Gottesman
d2bdec2acd [region-isolation] Include the region -> transferring operand map in the dataflow convergence.
The reason why I am doing this is that really we are running two different
dataflow equations at the same time... one for propagating tracking transferring
sets and the other for propagating regions. Since at the source level the two
dataflow problems are very interrelated, I was unable to come up with an example
where we fail to iterate because of this, but I would like to be sure that we do
not hit one, so I am fixing this here.

rdar://126170014
2024-04-10 10:36:42 -07:00
Michael Gottesman
ca8179aa7c [region-isolation] Track operand info in a separate map rather than inline in a TransferringOperand data structure.
This is backing out an approach that I thought would be superior, but ended up
causing problems.

Originally, we mapped a region number to an immutable pointer set containing
Operand * where the region was tranferred. This worked great for a time... until
I began to need to propagate other information from the transferring code in the
analysis to the actual diagnostic emitter.

To be able to do that, my thought was to make a wrapper type around Operand
called TransferringOperand that contained the operand and the other information
I needed. This seemed to provide me what I wanted but I later found that since
the immutable pointer set was tracking TransferringOperands which were always
newly wrapped with an Operand *, we actually always created new pointer
sets. This is of course wasteful from a memory perspective, but also prevents me
from tracking transferring operand sets during the dataflow since we would never
converge.

In this commit, I fix that issue by again tracking just an Operand * in the
TransferringOperandSet and instead map each operand to a state structure which
we merge dataflow state into whenever we visit it. This provides us with
everything we need to in the next commit to including a region -> transferring
operand set equality check in our dataflow equations and always converge.
2024-04-10 10:30:10 -07:00
Erik Eckstein
e14c1d1f62 SIL, Optimizer: update and handle borrowed-from instructions
Compute, update and handle borrowed-from instruction in various utilities and passes.
Also, used borrowed-from to simplify `gatherBorrowIntroducers` and `gatherEnclosingValues`.
Replace those utilities by `Value.getBorrowIntroducers` and `Value.getEnclosingValues`, which return a lazily computed Sequence of borrowed/enclosing values.
2024-04-10 13:38:10 +02:00
Michael Gottesman
13d01394d4 [region-isolation] Change the region -> transferring operand map to use a MapVector instead of a DenseMap.
This ensures that we can efficiently iterate over the map which we will need to
do for equality queries.

I am going to add the equality queries in a subsequent commit. Just chopping off
a larger commit.
2024-04-09 10:56:19 -07:00
Michael Gottesman
cc1a873b9e Fix another mocking issue with PartitionUtils unittest. 2024-04-06 01:39:00 -07:00
Michael Gottesman
6844b995a4 [region-isolation] Wire up history diagnostics through the checker, but do not use it to emit diagnostics yet.
Specifically:

1. I copy the history that we have been tracking from the transferring operand
value at the transfer point. This is then available for use to emit diagnostics.

2. I added the ability for SILIsolationInfo to not only track the ActorIsolation
of an actor isolated value, but also if we have a value, we can track that as
well. Since we now track a value for task isolated and actor isolated
SILIsolationInfo, I just renamed the field to isolatedValue and moved it out of
the enum.

In a subsequent commit, I am going to wire it up to a few diagnostics.

rdar://123479934
2024-04-06 00:58:10 -07:00
Michael Gottesman
d6b4f16382 [region-isolation] Add a SILLocation to SequenceBoundary in IsolationHistory.
We package all isolation history nodes from a single instruction by placing a
sequence boundary at the bottom. When ever we pop, we actually pop a PartitionOp
at a time meaning that we pop until we see a SequenceBoundary. Thus the sequence
boundary will always be the last element visited when popping meaning that it is
a convenient place to stick the SILLocation associated with the entire
PartitionOp. As a benefit, there was some unused space in IsolationHistory::Node
for that case since we were not using the std::variant field at all.
2024-04-06 00:58:10 -07:00
Michael Gottesman
aee5a37d9d [region-isolation] Add isolation history support but do not wire it up to the checker.
This means that I added an IsolationHistory field to Partition. Just upstreaming
the beginning part of this work. I added some unittests to exercise the code as
well. NOTE: This means that I did need to begin tracking an
IsolationHistoryFactory and propagating IsolationHistory in the pass
itself... but we do not use it for anything.

A quick overview of the design.

IsolationHistory is the head of an immutable directed acyclic graph. It is
actually represented as an immutable linked list with a special node that ties
in extra children nodes. The users of the information are expected to get a
SmallVectorImpl and process those sibling nodes afterwards. The reason why we
use an immutable approach is that it fits well with the problem and saves space
since different partitions could be pointing at the same linked list
node. Operations occur on an isolation history by pushing/popping nodes. It is
assumed that the user will push nodes in batches with a sequence boundary at the
bottom of the addition which signals to stop processing nodes.

Tieing this together, each Partition within it contains an IsolationHistory. As
the PartitionOpEvaluator applies PartitionOps to Partition in
PartitionOpEvaluator::apply, the evaluator also updates the isolation history in
the partition by first pushing a SequenceBoundary node and then pushing nodes
that will undo the operation that it is performing. This information is used by
the method Partition::popHistory. This pops linked list nodes from its history,
performing the operation in reverse until it hits a SequenceBoundary node.

This allows for one to rewind Partition history. And if one stashes an isolation
history as a target, one can even unwind a partition to what its state was at a
specific transfer point or earlier. Once we are at that point, we can begin
going one node back at a time and see when two values that we are searching for
no longer are apart of the same region. That is a place where we want to emit a
diagnostic. We then process until we find for both of our values history points
where they were the immediate reason why the two regions merge.

rdar://123479934
2024-04-06 00:58:05 -07:00
Michael Gottesman
c2350dfe7e [region-isolation] Change SILIsolationInfo to only traffic in ActorIsolation instead of that or nominal type decls.
This should be NFC since the only case where I used this was with self... and I
found another way of doing that using the API I added in the previous commit.
2024-04-04 10:58:57 -07:00
Michael Gottesman
1cf4e99454 Propagate global actor-ness of functions/closures.
I fixed a bunch of small issues around here that resulted in a bunch of radars
being fixed. Specifically:

1. I made it so that we treat function_refs that are from an actor isolated
function as actor isolated instead of sendable.

2. I made it so that autoclosures which return global actor isolated functions
are treated as producing a global actor isolated function.

3. I made it so that we properly handle SILGen code patterns produced by
Sendable GlobalActor isolated things.

rdar://125452372
rdar://121954871
rdar://121955895
rdar://122692698
2024-03-29 14:39:34 -07:00
Michael Gottesman
77dccacbd3 Make ActorIsolation on SILFunction non-optional.
ActorIsolation already has a "I have no value case": unspecified. Lets just use
that.

Just a mistake I made that I am trying to fix before anything further depends on
this code.
2024-03-29 14:39:26 -07:00
Michael Gottesman
6f66849610 [region-isolation] Do not squelch errors in the unittests.
To squelch errors, we need access to functionality not available in the
unittests. The unittests do not require this functionality anyways, so just
disable squelching during the unittests.
2024-03-26 10:06:21 -07:00
Michael Gottesman
e36aab6301 [region-isolation] Squelch use after transfer if the use has effectively the same isolation as the transfer inst.
To be more specific this means that either:

1. The use is actually isolated to the same actor. This could mean that the
use is global actor isolated to the same function.

2. The use is nonisolated but is executing within a function that is globally
isolated to the same isolation domain.

rdar://123474616
2024-03-25 23:32:17 -07:00
Michael Gottesman
8243b5cb74 [region-isolation] If a value is dynamically actor isolated, do not consider it transferred if the transfer statically was to that same actor isolation.
This issue can come up when a value is initially statically disconnected, but
after we performed dataflow, we discovered that it was actually actor isolated
at the transfer point, implying that we are not actually transferring.

Example:

```swift
@MainActor func testGlobalAndGlobalIsolatedPartialApplyMatch2() {
  var ns = (NonSendableKlass(), NonSendableKlass())
  // Regions: (ns.0, ns.1), {(mainActorIsolatedGlobal), @MainActor}

  ns.0 = mainActorIsolatedGlobal
  // Regions: {(ns.0, ns.1, mainActorIsolatedGlobal), @MainActor}

  // This is not a transfer since ns is already main actor isolated.
  let _ = { @MainActor in
    print(ns)
  }

  useValue(ns)
}
```

To do this, I also added to SILFunction an actor isolation that SILGen puts on
the SILFunction during pre function visitation. We don't print it or serialize
it for now.

rdar://123474616
2024-03-25 22:58:17 -07:00
Michael Gottesman
0b13da8fa6 Merge pull request #72572 from gottesmm/pr-26c22d031b70b00c14d7990ff90f70b64f91e0f9
[region-isolation] Shrink PartitionUtils.h by moving large functions to cpp file.
2024-03-25 17:14:50 -07:00
Michael Gottesman
901c7c2b6c [region-isolation] Shrink PartitionUtils.h by moving large functions to cpp file.
Just making PartitionUtils.h a little easier to walk through by moving more of
the impl into the .cpp file. This reduces the header from ~1500 lines to ~950
lines which is more managable. This is especially important since I am going
to be adding IsolationHistory to the header file which will expand it even
further.
2024-03-25 14:15:10 -07:00
Kuba (Brecka) Mracek
89cd62604b Merge pull request #72472 from kubamracek/embedded-keypaths
[embedded] Compile-time (literal) KeyPaths for Embedded Swift
2024-03-25 10:58:51 -07:00
Michael Gottesman
357a53ab48 [region-isolation] Clean up use after transfer error to use the dynamic isolation information of the transfered operand value in its diagnostic message.
As an example of the change:

-  // expected-note @-1 {{'x' is transferred from nonisolated caller to main actor-isolated callee. Later uses in caller could race with potential uses in callee}}
+  // expected-note @-1 {{transferring disconnected 'x' to main actor-isolated callee could cause races in between callee main actor-isolated and local nonisolated uses}}

Part of the reason I am doing this is that I am going to be ensuring that we
handle a bunch more cases and I wanted to fix this diagnostic before I added
more incaranations of it to the tests.
2024-03-22 13:12:51 -07:00