Commit Graph

830 Commits

Author SHA1 Message Date
Andrew Trick
8b39b6d16a LocalVariableUtils: record mark_dependence bad address operands
Avoid bailing out when something depends on the local variable.
2025-02-10 09:11:22 -08:00
Erik Eckstein
a88cb49ee8 SIL: define a memory-read effect on the mark_dependence base value
If the base value of a mark_dependence is an address, that memory location must be initialized at the mark_dependence.
This requires that the mark_dependence is considered to read from the base address.
2025-02-10 17:57:47 +01:00
Erik Eckstein
33761454b7 MandatoryPerformanceOptimizations: use eliminateRedundantLoads instead of optimizeMemoryAccesses to optimize redundant loads 2025-02-07 11:30:35 +01:00
Erik Eckstein
ce73deebc4 RedundantLoadElimination: add a "mandatory" redundant load elimination pass
And make `eliminateRedundantLoads` callable from other optimizations
2025-02-07 11:30:35 +01:00
Erik Eckstein
2af24703ab RedundantLoadElimination: insert mark_dependence instructions for a removed load
If the memory location depends on something, insert a dependency for the loaded value:
```
  %2 = mark_dependence %1 on %0
  %3 = load %2
```
->
```
  %2 = mark_dependence %1 on %0 // not needed anymore, can be removed eventually
  %3 = load %2
  %4 = mark_dependence %3 on %0
  // replace %3 with %4
```
2025-02-07 11:30:35 +01:00
Erik Eckstein
5acccf1802 RedundantLoadElimination: ignore memory effects of begin_access
Memory effects of begin_access are only defined to prevent the optimizer moving loads and stores across a begin_access.
But those memory effects are not relevant for RedundantLoadElimination
2025-02-07 11:30:35 +01:00
Erik Eckstein
ad2462f7f2 RedundantLoadElimination: optimize a load from a memory location which was written by copy_addr
For example:
```
  %1 = alloc_stack $B
  copy_addr %0 to [init] %1
  %3 = load [take] %1
  dealloc_stack %1
```
->
```
  %3 = load [copy] %0
```
2025-02-07 11:30:34 +01:00
Andrew Trick
e705a6d7c3 Temporarily introduce AnyInteriorPointer operand ownership.
This is necessary to fix a recent OSSA bug that breaks common occurrences on
mark_dependence [nonescaping]. Rather than reverting that change above, we make
forward progress toward implicit borrows scopes, as was the original intention.

In the near future, all InteriorPointer instructions will create an implicit
borrow scope. This means we have the option of not emitting extraneous
begin/end_borrow instructions around intructions like ref_element_addr,
open_existential, and project_box. After that, we can also migrate
GuaranteedForwarding instructions like tuple_extract and struct_extract.
2025-02-05 16:23:02 -08:00
Erik Eckstein
9b2dfbb741 DestroyHoisting: visit begin_borrows which don't have an end_borrow in dead-end blocks.
This makes sure that incomplete lifetimes are handled correctly.

Fixes an ownership violation.
rdar://144065326
2025-02-04 12:59:40 +01:00
Arnold Schwaighofer
c95c45201e Merge pull request #78996 from aschwaighofer/checked_cast_br_nightmares
SIL: Update formal source type in SimplifyRefCasts when possible
2025-02-02 08:27:01 -08:00
Arnold Schwaighofer
0fe3cf0096 SIL: Update formal source type in SimplifyRefCasts when possible
We use the formal source type do decide whether a checked_cast_br is
known to succeed/fail. If we don't update it we loose that optimization

That is:

```
  checked_cast_br AnyObject in %2 : X to X, bb1, bb2
```

Will not be simplified even though the operand and the destintation type
matches.
2025-01-29 09:07:21 -08:00
Kuba (Brecka) Mracek
7c685ba36b Merge pull request #78915 from kubamracek/embedded-string-switch-with-cache
[embedded] Support _findStringSwitchCaseWithCache in Embedded Swift
2025-01-28 15:56:22 -08:00
Kuba Mracek
e1d22b5076 [embedded] Avoid changing lookupStdlibFunction, load findStringSwitchCaseWithCache in MPO instead 2025-01-28 10:03:14 -08:00
Erik Eckstein
1f534e1c6f DeinitDevirtualizer: bail out for C++ move-only types.
We cannot de-virtualize C++ destructor calls of C++ move-only types because we cannot get its destructor in SIL.
Fixes a miscompile.
2025-01-27 09:59:48 +01:00
Kuba Mracek
92b0c5f5d0 [embedded] Support _findStringSwitchCaseWithCache in Embedded Swift 2025-01-25 09:09:47 -08:00
Erik Eckstein
3ec5d7de24 SIL: replace the is_escaping_closure instruction with destroy_not_escaped_closure
The problem with `is_escaping_closure` was that it didn't consume its operand and therefore reference count checks were unreliable.
For example, copy-propagation could break it.
As this instruction was always used together with an immediately following `destroy_value` of the closure, it makes sense to combine both into a `destroy_not_escaped_closure`.
It
1. checks the reference count and returns true if it is 1
2. consumes and destroys the operand
2025-01-24 19:23:27 +01:00
Erik Eckstein
09f6f4f9b6 AutodiffClosureSpecialization: workaround a problem with OSSA.
Disable the closure specializer optimization for closures in OSSA until the underlying problem is fixed.
https://github.com/swiftlang/swift/issues/78847

Part of rdar://140229560
2025-01-23 16:10:32 +01:00
eeckstein
2af03dd177 Merge pull request #78768 from eeckstein/fix-borrowed-from-updater
SIL: when updating borrowed-from instructions, remove the old enclosing values first
2025-01-22 18:40:26 +01:00
Andrew Trick
5066dd9f90 Merge pull request #78716 from atrick/fix-lifedep-out
Fix LifetimeDependenceDiagnostics for @out dependencies
2025-01-22 00:17:50 -08:00
Erik Eckstein
5dc67fab3f SIL Verifier: check that the enclosing values of a borrowed-from instructions are valid 2025-01-21 08:21:26 +01:00
Erik Eckstein
012aa6227d SIL: when updating borrowed-from instructions, remove the old enclosing values first
When an optimization updates borrowed-from instruction it might be necessary to remove the old enclosing values from the borrowed-from instructions.
An optimization might transform the SIL in a way that an existing enclosing value is not valid anymore.
Fixes a compiler crash:
rdar://142991910
2025-01-21 08:21:26 +01:00
Erik Eckstein
97db5d8a80 AliasAnalysis: handle global let-variables in ImmutableScope
Global let-variables are immutable, except in functions which initialize them.
This brings back handling of global let-variables in alias analysis, which was removed in the previous commit.
2025-01-20 08:50:56 +01:00
Erik Eckstein
a312732f84 AliasAnalysis: consider memory effects of a consume/destroy of a class on it's let-fields
Although a let-field can never be mutated, a release or consume of the class must be considered as writing to such a field.

This change removes the special handling of let-fields in two places, where they don't belong.
Class fields are handled by ImmutableScope anyway.
Handling of global let-variable is temporarily removed by this commit.

Fixes a miscompile.
rdar://142996449
2025-01-20 08:50:56 +01:00
Andrew Trick
cc07b4ba11 Fix LifetimeDependenceDiagnostics for @out dependencies.
Record a forwarding mark_dependence as a local access. This is necessary because
we now emit a mark_dependence for @out arguments, which will be the starting
point for diagnostics:

  %out = alloc_stack
  apply %f(%owned, %out) : $(Owner) -> @lifetime(borrow 0) @out View
  %unused = mark_dependence [unresolved] %out on %owner
  %dependentValue = load %out

This mark_dependence has no uses. Instead, it simply records the dependency of
the in-memory value on the owner. Consequently, simply walking the uses of
LifetimeDependence.dependentValue does fails to diagnose any escapes. Instead,
if the dependentValue is an address-type mark_dependence, treat it as a local
access to the address that it forwards. Then we find any reachable uses of that
local variable as a potential escape.

Fixes rdar://143040479
(Borrow diagnostics not triggered for @out return values)
2025-01-17 11:19:04 -08:00
Andrew Trick
afda6453a5 Improve LocalVariableAccessInfo: recognize more full-assignments.
Ignore marker instructions for the purpose of determining whether a store is a
full assignment:

  %a = alloc_stack
  %m = moveonlywrapper_to_copyable_addr %a
  store %0 to [init] %m // <=== full assignemt
2025-01-17 11:19:04 -08:00
Andrew Trick
c839e265df [NFC] Update an incomplete comment. 2025-01-15 16:53:03 -08:00
Andrew Trick
c8bec28e6a LifetimeDependence.Scope: recognize @in_guaranteed dependencies.
Unlike @in, treat @in_guaranteed like a caller-side dependence
scope because there is not need to look for the end of the lifetime in the
current function.

Completely fixes rdar://142847915 (Crash during lifetime checking
while building new swift standard library `Span`-related features)
2025-01-14 15:38:54 -08:00
Andrew Trick
a8caedfbec LifetimeDependenceInsertion: fix dependence on store_borrow.
For a lifetime dependent call that depends on a temporary store_borrow, the
generated mark_dependendence should be on the stored value, not the stack
location.

  %temp = alloc_stack $AnyObject
  %sb = store_borrow %arg to %temp
  apply %10(%out, %sb)
  mark_dependence [unresolved] %out on %arg
  end_borrow %sb

Fixes rdar://142847915 (Crash during lifetime checking while
building new swift standard library `Span`-related features)
2025-01-14 00:11:17 -08:00
Andrew Trick
6849b66bb3 LifetimeDependenceDiagnostics; remove a bootstrapping hack.
This temporary hack was preventing diagnostics from kicking in. This could even
result in invalid SIL after the diagnostic failed to trigger.
2025-01-13 08:30:41 -08:00
Andrew Trick
0326c98f72 LifetimeDependenceScopeFixup: handle unsafe addressors
Handle unsafe addressors just like projections of stored properties rather than
as separate variable accesses.
2025-01-11 15:40:22 -08:00
Andrew Trick
b0f2ca03a7 AccessUtils: allow mark_deps to be tracked by the EnclosingScope.
This encourages AccessPathWalker clients to handle enclosing mark_deps. In
some cases, it is necessary. The accessBaseWithScopes API now provides both
nested begin_access and mark_dependence.
2025-01-11 15:40:22 -08:00
eeckstein
8ec8a1229a Merge pull request #78543 from eeckstein/fix-copy-to-borrow-optimization
Fix two problems in the copy-to-borrow optimization
2025-01-10 19:44:00 +01:00
Erik Eckstein
e215ae990b CopyToBorrowOptimization: correctly handle unchecked_enum_data
A `unchecked_enum_data` which extracts a trivial payload out of a non-trivial enum ends the lifetime of its owned operand.

Fixes an ownership verification error
rdar://142644731
2025-01-10 09:08:31 +01:00
Erik Eckstein
a4c675ec88 CopyToBorrowOptimization: fix insertion order of end_borrows
In liferange exit blocks the end_borrows were inserted in the wrong order.

Fixes an ownership verification error
rdar://142632741
2025-01-10 08:56:42 +01:00
Erik Eckstein
df62235fe6 SIL Verifier: avoid crashing for a missing borrowed-from - instead report an error 2025-01-09 19:56:25 +01:00
Andrew Trick
195ca7ceae Improve LifetimeDependence.Scope for mutable trivial variables.
Recognize dependence on the address of a trivial 'var' as an "access" dependence
instead of an "unknown" dependence. This allows the mark_dependence to be
resolved as "[nonescaping]".
2025-01-07 22:21:15 -08:00
Andrew Trick
49136f237f Fix LifetimeDependenceScopeFixup to avoid rewriting mark_dependence.
This pass rewrites mark_depenendence to ignore "useless" borrow scopes. It was
also accidentally rewriting a dependence on a loaded value, which may redirect the
dependence to the access scope used to load that value. That access scope may be
narrower than the lifetime of the loaded value which could result in invalid
SIL. Do not rewrite this mark_dependence:

  %access = begin_access [read] [unknown] %base
  %load = load [trivial] %access
  end_access %access
  %adr = pointer_to_address
  %md = mark_dependence [unresolved] %adr on %load

Fixes rdar://142424000 (Swift compiler crashes with Assertion failed
(isa<UnreachableInst>(block->getTerminator())))
2025-01-07 15:36:52 -08:00
eeckstein
f096787871 Merge pull request #78384 from eeckstein/enable-code-motion-in-ossa
Optimizer: enable SILCodeMotion in OSSA, but only for trivial values.
2025-01-02 20:36:29 +01:00
Erik Eckstein
c58f04f165 PhiUpdater: fix a problem when incrementally updating borrowed-from instructions
When replacing all uses, ignore existing borrowed-from instructions.

Fixes a SIL verifier error.
2025-01-02 10:42:00 +01:00
Erik Eckstein
9aff288be4 Optimizer: re-implement the pointer_to_address SILCombine peephole optimizations in swift
Which consists of
* removing redundant `address_to_pointer`-`pointer_to_address` pairs
* optimize `index_raw_pointer` of a manually computed stride to `index_addr`
* remove or increase the alignment based on a "assumeAlignment" builtin

This is a big code cleanup but also has some functional differences for the `address_to_pointer`-`pointer_to_address` pair removal:

* It's not done if the resulting SIL would result in a (detectable) use-after-dealloc_stack memory lifetime failure.
* It's not done if `copy_value`s must be inserted or borrow-scopes must be extended to comply with ownership rules (this was the task of the OwnershipRAUWHelper).

Inserting copies is bad anyway.
Extending borrow-scopes would only be required if the original lifetime of the pointer extends a borrow scope - which shouldn't happen in save code. Therefore this is a very rare case which is not worth handling.
2024-12-21 08:28:22 +01:00
Erik Eckstein
51c6a60d9d SIL Verifier: check that an instruction with a guaranteed result is either a BeginBorrowValue or a ForwardingInstruction 2024-12-21 08:28:21 +01:00
Erik Eckstein
c5b14c2b93 BorrowUtils: make unchecked_ownership_conversion to guaranteed ownership a BeginBorrowValue
BeginBorrowValue needs to handle all cases where a guaranteed value is produced.
Fixes a compiler crash.
2024-12-21 08:28:21 +01:00
Erik Eckstein
1856d4e94c SIL: add APIs to set and get the alignment of a pointer_to_address instruction.
Also add a getter for the `isInvariant` property.
2024-12-21 08:28:21 +01:00
Ben Barham
8111fe9343 Merge pull request #78262 from bnbarham/skip-non-wmo-diag
[Embedded] Do not produce `cannot_specialize_class` for live issues
2024-12-20 10:40:07 -08:00
Ben Barham
a2fda1d9f3 [Embedded] Do not produce cannot_specialize_class for live issues
SourceKit explicitly disables WMO, silence the diagnostic in this case
(but leave it enabled for explicit non-WMO builds otherwise).
2024-12-19 15:31:41 -08:00
Erik Eckstein
89353506f5 SimplifyBuiltin: support metatype and function types when optimizing Builtin.sizeof/alignof/strideof/destroyArray
Get the maximally abstracted lowered type instead of bailing if the ast type isn't equal to the lowered SIL type.
2024-12-19 20:53:46 +01:00
Erik Eckstein
4fdf16de1b SIL: add CanonicalType.canBeClass
And move the implementation of `SIL.Type.canBeClass` to the AST Type. The SIL Type just calls the AST Type implementation.
Also rename `SIL.Type.canonicalASTType` -> `SIL.Type.astType`.
2024-12-19 20:53:46 +01:00
Erik Eckstein
cd7c533d42 Optimizer: add SingleValueInstruction.replace(with:) and use it throughout the optimizer
It replaces all uses and then erases the instruction.
2024-12-19 20:53:45 +01:00
Erik Eckstein
ca7facde35 SIL: add some use-list APIs
* `users`: maps from a sequence of operands to a sequence of instructions
* `users(ofType:)` : as `users`, but filters users of a certain instruction type
* `Value.users`: = `Value.uses.users`
2024-12-19 20:53:45 +01:00
Erik Eckstein
1545e01ab5 SIL: Let SubstitutionMap.replacementTypes return AST types rather than optional SIL types.
This is what the C++ SubstitutionMap does. One has to use `Type.loweredType` to get from the AST type to the SIL type.
2024-12-19 20:53:45 +01:00