Commit Graph

11224 Commits

Author SHA1 Message Date
nate-chandler
3e35fa423d Merge pull request #81015 from nate-chandler/rdar141279635
[MoveOnly] Fix consumption of opened existentials.
2025-04-23 13:26:47 -07:00
Nate Chandler
4786bede68 [MoveOnly] Fix consumption of opened existentials.
Enable walking into `TypeOffsetSizePair`s from an existential into an
archetype.  And set the access kind on `open_existential_addr`
instructions which are the sources of rewritten `copy_addr`s to mutable.

rdar://141279635
2025-04-22 17:59:37 -07:00
Nate Chandler
6669b2497d [NFC] MoveOnly: Add parameter to function.
For now, it is unused.
2025-04-22 17:59:37 -07:00
Nate Chandler
3fbf10913c [NFC] MoveOnly: Delete some dead code.
Before adding a new parameter to the function being called.
2025-04-22 17:59:36 -07:00
nate-chandler
f424639fee Merge pull request #80990 from nate-chandler/rdar147586673
[OSSACanOwned] Don't dead-end extend if consumed.
2025-04-22 17:56:24 -07:00
Meghana Gupta
3547ba5e48 Merge pull request #80961 from meg-gupta/fixoslogcrash
Fix crash in OSLogOptimization
2025-04-21 21:21:56 -07:00
Nate Chandler
40bcc74b47 [OSSACanOwned] Don't dead-end extend if consumed.
When the utility is used by the ConsumeOperatorCopyableValuesChecker,
the checker guarantees that the lifetime can end at the consumes, that
there are no uses after those consumes.  In that circumstance, the
utility maintains liveness to those consumes and as far as possible
without introducing a copy everywhere else.

The lack of complete lifetimes has forced the utility to extend liveness
of values to dead-ends.  That extension, however, is in tension with the
use that the checker is putting the utility to.  If there is a dead-end
after a consume, liveness must not be maintained to that dead-end.

rdar://147586673
2025-04-21 18:09:30 -07:00
Nate Chandler
6ff0c07fe6 [NFC] OSSACanOwned: Extracted predicate. 2025-04-21 18:09:30 -07:00
Nate Chandler
02618f562d [NFC] OSSACanOwned: Renamed field. 2025-04-21 18:09:30 -07:00
Evan Wilde
bca1378fdb SILOptimizer: Disable invalid passes in C++-only compiler
The SimplifyCFG and LoopRotate passes result in verification failures
when built in a compiler that is not built with Swift sources enabled.

Fixes: rdar://146357242
2025-04-21 12:46:01 -07:00
Meghana Gupta
71bb088b80 Fix crash in OSLogOptimization
A metatype need not always come from a metatype instruction. It can come from
a SILArgument. Fix the invalid cast operation in OSLogOptimization.

Fixes rdar://146160325
2025-04-21 11:49:31 -07:00
Meghana Gupta
b76047a846 Merge pull request #80930 from meg-gupta/relandpr
Reland #79707
2025-04-21 11:19:33 -07:00
Meghana Gupta
d81b5f7e27 Reland #79707
Revert "Merge pull request #80767 from meg-gupta/reverttransparent"

This reverts commit 198a802719, reversing
changes made to 8eb43af590.
2025-04-19 09:55:06 -07:00
Matt Seaman
02dd40f61e Merge pull request #80873 from swiftlang/mseaman/const-expr-bb-args
Fix assertion failure when performing constant-evaluation through basic blocks with non-constant arguments
2025-04-18 16:06:35 -07:00
eeckstein
ad82261cbd Merge pull request #80884 from eeckstein/embedded-error-message2
embedded: support default methods in existentials and improve embedded error reporting
2025-04-18 22:12:18 +02:00
Kuba Mracek
9878da9046 [SILOptimizer] Expose SIL inliner heuristics/constants as -Xllvm configurable knobs 2025-04-18 10:03:26 -07:00
Erik Eckstein
6c31eb0c43 embedded: rewrite the diagnostic pass for embedded swift
1. move embedded diagnostics out of the PerformanceDiagnostics pass. It was completely separated from the other logic in this pass, anyway.
2. rewrite it in swift
3. fix several bugs, that means: missed diagnostics, which led to IRGen crashes
  * look at all methods in witness tables, including base protocols and associated conformances
  * visit all functions in the call tree, including generic functions with class bound generic arguments
  * handle all instructions, e.g. concurrency builtins
4. improve error messages by adding meaningful call-site information. For example:
  * if the error is in a specialized function, report where the generic function is originally specialized with concrete types
  * if the error is in a protocol witness method, report where the existential is created
2025-04-18 06:58:40 +02:00
Erik Eckstein
43d793ba96 GenericSpecializer: fix a bug which prevented specialization for typealiases in some cases
Need to canonicalize the replacement type. Otherwise it could be generic if it is a typealias inside a generic type, e.g.
```
  struct S<T> {
    typealias I = Int
  }
```
2025-04-18 06:58:37 +02:00
Michael Gottesman
0ece31e4f6 [sil-isolation-info] When determining isolation of a function arg, use its VarDecl.
Otherwise, we can be inconsistent with isolations returned by other parts of the
code. Previously we were just treating it always as self + nom decl, which is
clearly wrong if a type is not self (e.x.: if it is an isolated parameter).

rdar://135459885
2025-04-17 18:12:30 -07:00
Michael Gottesman
5c4ff42d77 Merge pull request #80863 from gottesmm/pr-83b58369a3d1ab17d10b9f0f2792801d804d6f81
[rbi] When checking for partial apply reachability of a value at a user, include the user itself in case the user is the actual partial apply
2025-04-17 16:54:55 -07:00
Michael Gottesman
456a26e156 Merge pull request #80860 from gottesmm/pr-08a1e121e4bb7f821e73dcc3bd65e6f1e4cedffe
[rbi] Two small fixes
2025-04-17 15:54:38 -07:00
Michael Gottesman
6eee52fb01 [rbi] When checking for partial apply reachability of a value at a user, include the user itself in case the user is the actual partial apply
The specific issue was when we were walking instructions looking to see if there
was a partial apply escaping instruction, we were not including the user
itself. That means that if the user was the partial apply escaping instruction,
we would return that no escape occured.

rdar://149414471
2025-04-17 12:26:34 -07:00
Joe Groff
3860023081 Merge pull request #80839 from jckarter/moveonly-trivial-field-as-reinitialize
MoveOnlyChecker: Treat trivial stores as reinitializations rather than initializations.
2025-04-16 17:38:55 -07:00
Matt Seaman
14d9b05cc7 Fix assertion failure when performing constant-evaluation through basic blocks with non-constant arguments 2025-04-16 17:30:01 -07:00
Michael Gottesman
d5e89723b8 [rbi] Remove some unnecessary copying when constructing partition ops.
Just a small efficiency win that @rjmccall and I noticed when I was bringing him
up on rbi.
2025-04-16 11:46:40 -07:00
Michael Gottesman
cda4ebaca0 [rbi] Rename functionArgPartition -> initialEntryBlockPartition.
While bringing up @rjmccall on rbi, our discussions showed that the name
functionArgPartition was misleading to someone who hadn't worked on the pass
before. It became clear that initialEntryBlockPartition would be a better name
that would make it clearer/easy to understand.
2025-04-16 11:46:40 -07:00
Meghana Gupta
198a802719 Merge pull request #80767 from meg-gupta/reverttransparent
Revert #79707
2025-04-15 15:45:15 -07:00
Joe Groff
a1ff2e38dc MoveOnlyChecker: Treat trivial stores as reinitializations rather than initializations.
A trivial store is allowed to occur on an existing live value, and should not
trigger an attempt to destroy the original value completely. Fixes rdar://147791932.
2025-04-15 13:40:22 -07:00
eeckstein
a9c6da6c70 Merge pull request #80819 from eeckstein/copy-block-optimization
Optimizer: remove redundant `copy_block` instructions
2025-04-15 20:17:02 +02:00
Daniil Kovalev
5d0bfed9e8 [AutoDiff] Fix adjoints for loop-local active values (#78374)
Fixes #78264
2025-04-15 06:49:15 -07:00
Erik Eckstein
199eb1d6e7 Optimizer: remove redundant copy_block instructions
Removes a `copy_block` if its only uses, beside ownership instructions, are callees of function calls
```
  %2 = copy_block %0
  %3 = begin_borrow [lexical] %2
  %4 = apply %3() : $@convention(block) @noescape () -> ()
  end_borrow %3
  destroy_value %2
```
->
```
  %4 = apply %0() : $@convention(block) @noescape () -> ()
```

rdar://118521396
2025-04-15 11:02:39 +02:00
nate-chandler
9cc1947527 Merge pull request #80766 from nate-chandler/rdar149007151
[DCE] Don't delete instructions which consume escaping values.
2025-04-12 08:31:12 -07:00
Nate Chandler
3ec9b269f5 [DCE] Verify liveness of completed lifetimes. 2025-04-11 14:58:34 -07:00
Nate Chandler
b405c8b23c [DCE] Keep insts which consume escaping values.
When DCE deletes instructions as dead, if the instruction ends one of
its operands lifetimes, it must insert a compensating lifetime end.
When the def block of the value and the parent block of the instruction
are different, it uses lifetime completion.  Lifetime completion relies
on complete liveness, which doesn't and can't exist for values with
pointer escapes.  The result is ending lifetimes too early.

Avoid this scenario by marking such instructions live.

In the fullness of time, it may be possible to track the deleted
instruction's "location" even in the face of deletions of adjacent
instructions and parent blocks and to insert the lifetime end at that
location.

rdar://149007151
2025-04-11 14:58:33 -07:00
Meghana Gupta
f462bc5d93 Revert "Merge pull request #79707 from DougGregor/transparent-integer-conversions"
This reverts commit 9c2c4ea07f, reversing
changes made to 829e03c104.
2025-04-11 10:42:17 -07:00
Michael Gottesman
ecb745ea18 Merge pull request #80745 from gottesmm/rdar149019222
[rbi] Teach RBI how to handle non-Sendable bases of Sendable values
2025-04-10 19:57:01 -07:00
Michael Gottesman
23b6937cbc [rbi] Make it so that we correctly do not error on uses of Sendable values that are projected from non-Sendable bases.
Specifically, we only do this if the base is a let or if it is a var but not
captured by reference.

rdar://149019222
2025-04-10 14:53:56 -07:00
Michael Gottesman
a045c9880a [rbi] Add the ability to add flags to PartitionOp.
I am doing this so I can mark requires as being on a mutable non-Sendable base
from a Sendable value.

I also took this as an opportunity to compress the size of PartitionOp to be 24
bytes instead of 40 bytes.
2025-04-10 14:53:56 -07:00
Michael Gottesman
6d8b9b048a [rbi] Implement support for non-Sendable base values.
There are a few major changes here:

1. We now return a TrackableValue from getTrackableValue() if we have either a
non-Sendable value or a non-Sendable base. This means that we /will/ return
TrackableValues that may have a Sendable value or a Sendable base. To make it
easier to work with this, I moved the isSendable check and the do I have a base
check into PartitionOpBuilder. So, most of the actual code around emitting
values does not need to reason about this. They can just call addRequire or
addSend and pass in either TrackableValue::value or TrackableValue::base without
needing to check if the former is non-Sendable or if the latter is non-Sendable
and non-nil.

2. I searched all of the places where we were grabbing trackable values and
inserted require checks for the base value as appropriate.

Both of these together have prevented the code from becoming too heavy.

This fixes https://forums.swift.org/t/lets-debug-missing-rbi-data-race-diagnostics/78910

rdar://149019222
2025-04-10 14:53:40 -07:00
Michael Gottesman
c846c2279e [rbi] Refactor getUnderlyingTrackedValue so that for addresses we return both a value and a base in certain situations.
Previously, when we saw any Sendable type and attempted to look up an underlying
tracked value, we just bailed. This caused an issue in situations like the
following where we need to emit an error:

```swift
func test() {
  var x = 5
  Task.detached { x += 1 }
  print(x)
}
```

The problem with the above example is that despite value in x being Sendable,
'x' is actually in a non-Sendable box. We are passing that non-Sendable box into
the detached task by reference causing a race against the read from the
non-Sendable box later in the function. In SE-0414, this is explicitly banned in
the section called "Accessing Sendable fields of non-Sendable types after weak
transferring". In this example, the box is the non-Sendable type and the value
stored in the box is the Sendable field.

To properly represent this, we need to change how the underlying object part of
our layering returns underlying objects and vends TrackableValues to the actual
analysis for addresses. NOTE: We leave the current behavior alone for SIL
objects.

By doing this, in situations like the above, despite have a Sendable value (the
integer), we are able to ensure that we require that the non-Sendable box
containing the integer is not used after we have sent it into the other Task
despite us not actually using the box directly.

Below I describe the representation change in more detail and describe the
various cases here. In this commit, I only change the representation and do not
actually use the new base information. I do that in the next commit to make this
change easier for others to read and review. I made sure that change was NFC by
leaving RegionAnalysis.cpp:727 returning an optional.none if the value found was
a Sendable value.

----

The way we modify the representation is that we instead of just returning a
single TrackedValue return a pair of tracked values, one for the base and one
for the "value". We return this pair in what is labeled a
"TrackableValueLookupResult":

```c++
struct TrackableValueLookupResult {
  TrackableValue value;

  std::optional<TrackableValue> base;

  TrackableValueLookupResult(TrackableValue value)
    : value(value), base() {}
  TrackableValueLookupResult(TrackableValue value, TrackableValue base)
    : value(value), base(base) {}
};
```

In the case where we are accessing a projection path out of a non-Sendable type
that contains all non-Sendable fields, we do not do anything different than we
did previously. We just walk up from use->def until we find the access path base
which we use as the representative of the leaf of the chain and return
TrackableValueLookupResult(access path base).

In the case where we are accessing a Sendable leaf type projected from a
non-Sendable base, we store the leaf type as our value and return the actual
non-Sendable base in TrackableValueLookupResult. Importantly this ensures that
even though our Sendable value will be ignored by the rest of the analysis, the
rest of the analysis will ensure that our base is required if our base is a var
that had been escaped into a closure by reference.

In the case where we are accessing a non-Sendable leaf type projected from a
Sendable type (which we may have continued to be projected subsequently out of
additional Sendable types or a non-Sendable type), we make the last type on the
projection path before the Sendable type, the value of the leaf type. We return
the eventual access path base as our underlying value base. The logic here is
that since we are dealing with access paths, our access path can only consist of
projections into a recursive value type (e.x.: struct/tuple/enum... never a
class). The minute that we hit a pointer or a class, we will no longer be along
the access path since we will be traversing a non-contiguous piece of
memory (consider a class vs the class's storage) and the traversal from use->def
will stop. Thus, we know that there are only two ways we can get a field in that
value type to be Sendable and have a non-Sendable field:

1. The struct can be @unchecked Sendable. In such a case, we want to treat the
leaf field as part of its own disconnected region.

2. The struct can be global actor isolated. In such a case, we want to treat the
leaf field as part of the global actor's region rather than whatever actor.

The reason why we return the eventual access path base as our tracked value base
is that we want to ensure that if the var value had been escaped by reference,
we can require that the var not be sent since we are going to attempt to access
state from the var in order to get the global actor guarded struct that we are
going to attempt to extract our non-Sendable leaf value out of.
2025-04-10 10:01:18 -07:00
Andrew Trick
a1fc2bc4d4 Merge pull request #80577 from atrick/addressable-escape
Fix GenericSpecializer for addressable parameters.
2025-04-08 12:44:28 -07:00
Slava Pestov
be5d03faa3 SILOptimizer: Remove witness table marking from DeadFunctionElimination
This logic was unconditionally disabled and incorrect.
2025-04-07 22:13:05 -04:00
Slava Pestov
b94a0448f2 SIL: Remove SILWitnessTable::ConditionalConformance 2025-04-07 21:36:05 -04:00
Andrew Trick
935b5e7ea2 Fix GenericSpecializer for addressable parameters.
Addressable parameters must remain indirect.

Incidentally also fixes an obvious latent bug in which all specialization was
disabled if any metatypes could not be specialized.

Fixes rdar://145687827 (Crash of inline-stored Span properties with optimizations)
2025-04-07 14:42:10 -07:00
Andrew Trick
6898e33edd [NFC] fix a dropUnusedArguments parameter name 2025-04-07 14:42:10 -07:00
Michael Gottesman
77a86a525b Merge pull request #79891 from gottesmm/pr-9df6772bb44656cbd85cad72ee5c3637caab8956
Make Feature a struct enum so we can put methods on it.
2025-04-07 10:32:23 -07:00
eeckstein
98739a412a Merge pull request #80543 from eeckstein/isolated-conformance-opt
CastOptimizer: handle isolated conformances
2025-04-06 10:59:51 +02:00
Anthony Latsis
5c190b9613 AST: Cut down on DescriptiveDeclKind usage in DiagnosticsSIL.def 2025-04-05 12:31:20 +01:00
Michael Gottesman
3ff9463957 Make Feature a struct enum so we can put methods on it.
Just noticed this as I was looking at making other changes.
2025-04-05 10:08:29 +01:00
Erik Eckstein
75a0cc031b CastOptimizer: handle isolated conformances
Check the isolation of conformances to avoid wrong folding of dynamic casts
rdar://147417762
2025-04-05 09:00:30 +02:00