This function is used by passes and salvages to facilitate adding
instructions to reconstruction blocks, even if no block exists on the
debug value yet.
Instead of using an op_constu/consts in the DIExpr, the integer literal
salvage now uses a debug basic block using a typed integer_literal.
This also has the effect of supporting integer literals bigger than
64 bits (such as an Int128 being salvaged) correctly.
Assisted-by: Claude
The salvage for this instruction was wrong as it didn't multiply the
index by the element stride.
As this salvage is rare, only was correct for byte sized elements, and
will be rewritten in the future, remove it rather than fix it.
The VarInfo for an alloc_stack will always have an op_deref, so that they can
get copied along when the VarInfo is moved to a debug_value. This op_deref is
not printed by the SILPrinter.
This commit also updates uses of AllocStackInst's getVarInfo to strip this
op_deref at places where it is not needed, and uses of createDebugValueAddr
where the extra op_deref is no longer needed.
The only change at the IR level is for undef values that now have a DW_OP_deref
for move-only values.
This fixes most of the inconsitencies with op_deref at the SIL level. All
debug_values with addresses should always have an op_deref.
Assisted-by: Claude Opus 4.6 (Updated tests)
usePoints is an artifact of the time when we didn't have guaranteed forwarding phis.
It is no longer used and triggered an unnecessary assert for borrow accessors.
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.
There is some logic to figure out if a type is unreferencable but that
did not handle tuple fields. C arrays are imported as Swift tuples, so
in case a C array had unreferenceable element type we can end up taking
the wrong path in the optimizer and trigger a crash.
rdar://175037688
A dead forwarding operation (e.g. `unchecked_enum_data`,
`unchecked_value_cast`, `destructure_struct`) with an owned move-only operand
must not be deleted because it ends the lifetime of its operand.
Previously, only `destructure_struct` was guarded against deletion. This
change uses `ForwardingOperation` and `getSingleForwardingOperand()` to
cover all single-operand forwarding instructions uniformly.
Resolves rdar://175150849
Mainly:
* look through ownership instructions in more places
* support `load_borrow` and `store_borrow` where `load` and `store`s are expected
* support `destructure_struct` where `struct_extract` is expected
* enable inout-keypath optimization for OSSA
* OSSA support in StringOptimization
Inserts an unreachable after an unconditional fail:
```
%0 = integer_literal 1
cond_fail %0, "message"
// following instructions
```
->
```
%0 = integer_literal 1
cond_fail %0, "message"
unreachable
deadblock:
// following instructions
```
Remove the old SILCombine implementation because it's not working well with OSSA lifetime completion.
This also required to move the `shouldRemoveCondFail` utility function from SILCombine to InstOptUtils.
We may see undef closure captures in ClosureLifetimeFixup since
it is a mandatory pass that runs on invalid code as well.
This could sometimes hang the compiler while running `insertDeallocOfCapturedArguments`
in release builds.
This change adds a bailout when we see an undef closure capture to avoid running into this issue.
This peephole optimization didn't consider that an alloc_stack of an enum can be overridden by another value.
The fix is to remove this peephole optimization at all because it is already covered by `optimizeEnum` in alloc_stack simplification.
Fixes a miscompile
https://github.com/swiftlang/swift/issues/85687
rdar://165374568
A dead `destructure_struct` with an owned argument can appear for a non-copyable or non-escapable struct which has only trivial elements.
The instruction is not trivially dead because it ends the lifetime of its operand.
Fixes an ownership verification error.
executing unknown code
This means we have to claw back some performance by recognizing harmless
releases.
Such as releases on types we known don't call a deinit with unknown
side-effects.
rdar://143497196
rdar://143141695
Make sure that an enum is only initialized once before it is taken. This implies that the initialization must dominate the take.
Fixes a verifier crash: rdar://139381701
Remove `deque` from files it isn't actually used in. Add it and `stack`
to files that it is - presumably they were previously transitively found
through other includes.
When devirtualizing witness method calls, it can happen that we need a cast between ABI compatible return types.
We were missing supporting type casts between nominal types which are ABI compatible.
This comes from whole-module reasoning of protocol conformances.
If a protocol only has a single conformance where the associated type (`ID`) is some concrete type (e.g. `Int`), then the devirtualizer knows that `p.get()` can only return an `Int`:
```
public struct X2<ID> {
let p: any P2<ID>
public func testit(i: ID, x: ID) -> S2<ID> {
return p.get(x: x)
}
}
```
and after devirtualizing the `get` function, its result must be cast from `Int` to `ID`.
The `layoutIsTypeDependent` utility is basically only used here to assert that this cast can only happen between layout compatible types.
rdar://129004015
This is usually the case. Some examples, where they layout is _not_ dependent:
```
struct S<T> {
var x: Int // no members which depend on T
}
struct S<T> {
var c: SomeClass<T> // a class reference does not depend on the layout of the class
}
```
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)
inlining, generic/closure specialization, and devirtualization optimization passes.
SILFunction::canBeInlinedIntoCaller now exlicitly requires a caller's SerializedKind_t arg.
isAnySerialized() is added as a convenience function that checks if [serialized] or [serialized_for_pkg].
Resolves rdar://128704752
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
[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
getVarInfo() now always returns a variable with a location and scope.
To opt out of this change, getVarInfo(false) returns an incomplete variable.
This can be used to work around bugs, but should only really be used for
printing.
The complete var info will also contain the type, except for debug_values,
as its type depends on another instruction, which may be inconsistent if
called mid-pass.
All locations in debug variables are now also stripped of flags, to avoid
issues when comparing or hashing debug variables.