Commit Graph

167 Commits

Author SHA1 Message Date
Emil Pedersen b563de2da4 [DebugInfo] Rename debug basic blocks to reconstruction blocks 2026-05-15 16:42:53 +01:00
Joe Groff 097b0d3400 SIL: Split unchecked_*_enum_data_addr according to ownership and effects.
We cannot use spare bits or other overlapping storage layout tricks with fundamentally
address-only enums, and we can take advantage of this to do borrowing switches or other
in-place projections without copying the value. However, for resilient enums, the
implementation may use spare bit packing, but the type must be handled address-only
outside of its defining module, and we didn't have a way to express that with
borrowing switch. Optimization passes have also been running into problems with the
complexity that we were using `unchecked_take_enum_data_addr` sometimes as a pure
operation. This patch splits the instruction into three:

- `unchecked_inplace_enum_data_addr` represents a nondestructive in-place enum
  projection. It is only allowed for enums whose projection operation is
  nondestructive.
- `unchecked_take_enum_data_addr` represents a destructive enum projection,
  invalidating the enum and leaving the payload to be further consumed.
  This matches the current instruction's semantics.
- `unchecked_borrow_enum_data_addr` represents a borrowing enum projection.
  The instruction takes a second operand for "scratch" space, which the
  enum representation may be copied into in order to avoid invalidating the
  enum value, so the result is dependent on the lifetime of both the
  original enum and the scratch buffer. This allows for borrowing switches
  over resilient enums.

`unchecked_borrow_enum_data_addr` is implemented by taking advantage of the
"address-only enums can't do spare bit optimization" property at runtime.
We inspect the operand type's bitwise-borrowability from its metadata. If
the type is bitwise-borrowable, then we are allowed to bitwise-copy the
enum to the scratch space and apply the projection to the scratch space,
preserving the original value. If the type is not bitwise-borrowable, then
we cannot use spare bit optimization in its layout, so we apply the
projection in-place.

Fixes rdar://174952822.
2026-04-27 15:40:37 -07:00
John McCall 9b6777ff59 Allow alloc_pack_metadata to be marked as [non_nested].
This is inserted by SIL passes and so may not always be properly nested
with respect to non-unreorderable allocations such as async lets.
2026-04-08 17:56:47 -04:00
Meghana Gupta 78e8178675 Fix infinite recursion in the presence of phi cycles in PartialApplyInst::visitOnStackLifetimeEnds
Use a visited set to avoid infinite recursion when there are phi cycles in the SSA.

rdar://173953876
2026-04-06 10:40:18 -07:00
John McCall bf851fa4dd Model the stack allocation effects of {add,remove}TaskLocalValue.
The biggest complexity here is dealing with the improper nesting of the
allocation for the argument, and I'm not very proud of the solution I found,
but for a one-off builtin, I think it'll work.
2026-03-20 00:21:40 -04:00
John McCall d45af1c021 Allow alloc_ref and alloc_ref_dynamic to be marked [non_nested]
This hopefully unblocks fixing the stack nesting of the
concellation and priority escalation handler builtins.
2026-03-13 19:40:21 -04:00
John McCall aa2cabf718 Make this assertion fail reliably and with more useful information. 2026-03-13 19:40:21 -04:00
John McCall 9aa0cb4e4f Make the cancellation and priority-ecscalation builtins respect stack nesting.
You can see in the patch that I obviously wrote this to include the
task-local builtins, but unfortunately they don't work for this because
they don't actually have a use/def relationship. That will need to be
follow-up work.

Includes a test that the defer special case applies to the priority
escalation builtin.
2026-03-13 19:40:20 -04:00
John McCall 374e3d37f0 Allow partial_apply [on_stack] to be flagged [non_nested]. 2026-03-06 03:15:28 -05:00
John McCall baaefaff98 Model the async let builtins as participating in the stack discipline.
This interacts with my previous commits to ensure that we mark other
allocation operations as non-nested when we would otherwise need to move
the finishAsyncLet operation.
2026-03-06 03:14:46 -05:00
John McCall a3c4f35c02 Add some abstractions for working with stack alloc/dealloc instructions.
NFC. Should make it easier to be exhaustive about these things.
2026-03-06 03:14:46 -05:00
Michael Gottesman d2ae104892 [sil] Add support for ApplySite::getCalleeDeclRef.
This can be used to get the SILDeclRef for all of the various apply site
kinds. It is a composition of getCalleeOrigin + special code for handling
FunctionRefs and MethodInst. It essentially lets one abstract over the function
ref/method inst code.
2026-02-17 22:53:09 -08:00
Michael Gottesman 29229a9410 [sil] Add basic SIL support for alloc_stack [non_nested].
This means I just added the flag and added support for
cloning/printing/serializing the bit on alloc_stack.
2025-11-21 11:21:14 -08:00
John McCall a7d7970e29 Turn finishAsyncLet into a builtin.
This is necessary because we need to model its stack-allocation
behavior, although I'm not yet doing that in this patch because
StackNesting first needs to be taught to not try to move the
deallocation.

I'm not convinced that `async let` *should* be doing a stack allocation,
but it undoubtedly *is* doing a stack allocation, and until we have an
alternative to that, we will need to model it properly.
2025-11-03 16:33:40 -08:00
John McCall 7a6ee1134c [NFC] Add a utility function for testing for a specific BuiltinInst 2025-11-03 13:44:18 -08:00
swift-ci 4838c6e954 Merge remote-tracking branch 'origin/main' into rebranch 2025-08-01 23:15:28 -07:00
John McCall 46be95847b Extract TypeLowering's recursive type properties into a header, add
functions to compute them directly without a TypeLowering object, and
change a lot of getTypeLowering call sites to just use that.

There is one subtle change here that I think is okay: SILBuilder used to
use different TypeExpansionContexts when inserting into a global:
- getTypeLowering() always used a minimal context when inserting into
  a global
- getTypeExpansionContext() always returned a maximal context for the
  module scope
The latter seems more correct, as AFAIK global initializers are never
inlinable. If they are, we probably need to configure the builder with
an actual context properly rather than making global assumptions.

This is incremental progress towards computing this for most types
without a TypeLowering, and hopefully eventually removing TL entirely.
2025-08-01 15:00:57 -04:00
Anthony Latsis 5b5f50ebdc IntrinsicInfo: Adjust call to llvm::Intrinsic::getAttributes after LLVM change
See https://github.com/llvm/llvm-project/pull/135642
2025-06-25 14:54:15 +01:00
eeckstein 021bd4a2c4 Merge pull request #81684 from eeckstein/fix-mark-dependence-addr
SIL: define `mark_dependence_addr` to read and write to its address operand
2025-05-22 07:10:24 +02:00
nate-chandler 393465262b Merge pull request #81581 from nate-chandler/rdar147207926
[TypeLowering] Record packs used in signatures.
2025-05-21 13:37:10 -07:00
Erik Eckstein e0f5888a8d SIL: define mark_dependence_addr to read and write to its address operand
This prevents simplification and SILCombine passes to remove (alive) `mark_dependence_addr`.
The instruction is conceptually equivalent to
```
  %v = load %addr
  %d = mark_dependence %v on %base
  store %d to %addr
```

Therefore the address operand has to be defined as writing to the address.
2025-05-21 20:03:53 +02:00
Nate Chandler aa49b8540d [TypeLowering] Record packs used in signatures.
To determine whether an instruction may require pack metadata, the types
of its operands are examined.

Previously, the top level type was checked for having a pack in its
signature, and the whole type was checked for having a type anywhere in
its layout (via TypeLowering).  This didn't account for the case where
the metadata was required for a resilient type which uses a pack in its
signature.

Here, during type lowering, a type having a pack in its signature is
counted towards the type having a pack.

Fixes a compiler crash.

rdar://147207926
2025-05-20 16:53:28 -07:00
Erik Eckstein 9052652651 add the prepareInitialization builtin.
It is like `zeroInitializer`, but does not actually initialize the memory.
It only indicates to mandatory passes that the memory is going to be initialized.
2025-05-20 20:46:33 +02:00
Andrew Trick e7000e4668 SIL: Add mark_dependence_addr 2025-03-25 23:02:42 -07:00
Meghana Gupta 2b072a56c1 Allow duplicating mark_dependence [nonescaping] on addresses 2025-02-28 17:11:59 -08:00
Andrew Trick 1cb4d50877 Fix BorrowingOperand::visitScopeEndingUses() invariants.
This API only makes sense for a scoped borrow-introducer such as:
- reborrow
- owned mark_dependence

Borrowing operands that forward guaranteed values do not have scope-ending uses.
2025-02-25 23:08:54 -08:00
Andrew Trick 6fa0b2ec98 Add BorrowedFromInst::isReborrow.
borrowed-from instructions have different ownership semantics if the are
attached to reborrows vs. guaranteed forwarding phis.
2025-02-25 23:08:54 -08:00
Meghana Gupta a31a603e49 Handle type_value instruction in CSE 2025-02-13 10:30:25 -08:00
Erik Eckstein e0b4f71af6 SIL: remove the alloc_vector instruction
It's not needed anymore, because the "FixedArray" experimental feature is replaced by inline-arrays.
2025-02-12 10:51:14 +01: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
Andrew Trick 01c3343b05 Fix mark_dependence ownership: compatibility with owned values
This fixes an OSSA verification bug introduced here:

    commit 79b649854b
    Author: Meghana Gupta <meghanavgupta@gmail.com>
    Date:   Wed Jan 22 01:24:49 2025

        Fix operand ownership of mark_dependence [nonescaping] of address values

The bug only showed up with mark_dependence [nonescaping], which means mainly
affects `~Escapable` types. Adddressors happened to work because SILGen was
emitting a borrow scope around them.

Rather than reverting the change above, this fix migrates mark_dependence
[nonescaping] to an implicit borrow scope.

Fixes rdar://144199759 (Assert: mark_dependence [nonescaping]:
ownership incompatible with an owned value)
2025-02-05 16:23:14 -08:00
Nate Chandler 41bee47169 [Gardening] Sunk static function to use.
Now that the other caller of the function has been removed, it's more
convenient to have it adjacent to the only remaining caller.
2025-01-28 10:44:30 -08:00
Nate Chandler ad9e090243 [SIL] Only visit final on-stack pai lifetime ends.
In OSSA, the `partial_apply [on_stack]` instruction produces a value
with odd characteristics that correspond to the fact that it is lowered
to a stack-allocating instruction.  Among these characteristics is the
fact that copies of such values aren't load bearing.

When visiting the lifetime-ending uses of a `partial_apply [on_stack]`
the lifetime ending uses of (transitive) copies of the partial_apply
must be considered as well.  Otherwise, the borrow scope it defins may be
incorrectly short:

```
%closure = partial_apply %fn(%value) // borrows %value
%closure2 = copy_value %closure
destroy_value %closure // does _not_ end borrow of %value!
...
destroy_value %closure2 // ends borrow of %value
...
destroy_value %value
```

Furthermore, _only_ the final such destroys actually count as the real
lifetime ends.  At least one client (OME) relies on
`visitOnStackLifetimeEnds` visiting at most a single lifetime end on any
path.

Rewrite the utility to use PrunedLiveness, tracking only destroys of
copies and forwards.  The final destroys are the destroys on the
boundary.

rdar://142636711
2025-01-28 10:44:30 -08:00
Nate Chandler f9ddf8d4d7 [Test] Add for PAI::visitOnStackLifetimeEnds. 2025-01-28 10:44:29 -08:00
nate-chandler 8c63134570 Merge pull request #78682 from nate-chandler/rdar142636711_2
[TempRValueOpt] Invalidate insts when completing.
2025-01-27 12:53:57 -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
Nate Chandler 2eb3a86928 [NFC] SIL: Replaced a recursion with a worklist. 2025-01-16 08:18:30 -08:00
Nate Chandler 8c7f1484bb [Gardening] SIL: Move comment.
Move it to the lambda which it talks about.  The old location is in a
function which now enjoys multiple callers, and the comment applies to
only one.
2025-01-16 08:18:29 -08:00
Arnold Schwaighofer fa01d8d2f0 SIL: builtin willThrow does not modify memory or release
This enables access enforcement analysis to classify a dynamic begin_access in
access patterns (such as the one below) involving a throwing function as not
having nested conflicts.

```
struct Stack {
  var items : [UInt8]

  mutating func pop() throws -> UInt8 {
    guard let item = items.popLast() else { throw SomeErr.err }
    return item
  }
  ...
}

class Container {
  private var ref : Stack

  @inline(never)
  internal func someMethod() throws {
     try ref.pop()
  }
  ...
}
```
rdar://141182074
2024-12-10 11:27:27 -08:00
Erik Eckstein 156f1fc759 Optimizer: prevent duplicating blocks with dead-end begin-borrow instructions.
In case the control flow ends in a dead-end block there can be begin-borrow instructions which have no corresponding end-borrow uses.
After duplicating such a block, the re-borrow flags cannot be recomputed correctly for inserted phi arguments.
Therefore just disable duplicating such blocks, e.g. in jump-threading.
2024-11-12 10:04:09 +01:00
Nate Chandler c64d56c224 [NFC] SIL: Added SILInstructionContext.
It has a module or maybe a function.  In the future we may want to
change this to be either a SILFunction or a SILGlobalVariable.
2024-10-29 21:44:06 -07:00
Nate Chandler 71239d6357 [CoroutineAccessors] SIL represents callee alloc.
When its operand has coroutine kind `yield_once_2`, a `begin_apply`
instruction produces an additional value representing the storage
allocated by the callee.  This storage must be deallocated by a
`dealloc_stack` on every path out of the function.  Like any other stack
allocation, it must obey stack discipline.
2024-10-11 08:25:03 -07:00
Slava Pestov b68a78cd54 SIL: Track local environments instead of root local archetypes 2024-08-29 16:18:13 -04:00
Nate Chandler cfdbd992cd [Test] Underscored instruction_move_before.
Use underscores rather than hyphens so that text editors understand the
name as a single word.
2024-07-25 13:50:25 -07:00
Meghana Gupta 154989463b Add support for lifetime dependence in parameter position 2024-07-10 14:20:03 -07:00
Meghana Gupta 12484ff919 Merge pull request #74842 from meg-gupta/addopenpackedgecase
Fix isTriviallyDuplicatable to handle open_pack_element
2024-07-01 10:53:53 -07:00
Meghana Gupta 5282194682 Fix isTriviallyDuplicatable to handle open_pack_element
SILInstruction::clone doesn't know how to clone instructions that produce
the archetype uuid. SILCloner is equipped to handle such instructions.

Optimizations like LoopRotate use  SILInstruction::clone and will be
incorrect for such instructions.

rdar://130047619
2024-06-29 13:42:05 -07:00
Ben Barham d72f5b12c4 Update StringRef::equals references to operator==
`equals` has been deprecated upstream, use `operator==` instead.
2024-06-27 19:14:06 -07:00
Tim Kientzle 1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Emil Pedersen f6232a937d [DebugInfo] Fix wrong scope being used in AllocBoxToStack 2024-04-30 16:29:49 -07:00