Type annotations for instruction operands are omitted, e.g.
```
%3 = struct $S(%1, %2)
```
Operand types are redundant anyway and were only used for sanity checking in the SIL parser.
But: operand types _are_ printed if the definition of the operand value was not printed yet.
This happens:
* if the block with the definition appears after the block where the operand's instruction is located
* if a block or instruction is printed in isolation, e.g. in a debugger
The old behavior can be restored with `-Xllvm -sil-print-types`.
This option is added to many existing test files which check for operand types in their check-lines.
If there is no read from an indirect argument, this argument has to be dropped.
At the call site the store to the argument's memory location could have been removed (based on the callee's memory effects).
Therefore, converting such an unused indirect argument to a direct argument, would load an uninitialized value at the call site.
This would lead to verifier errors and in worst case to a miscompile because IRGen can implicitly use dead arguments, e.g. for getting the type of a class reference.
And replace them with explicit `metatype` instruction in the entry block.
This allows such metatype instructions to be deleted if they are dead.
This was already done for performance-annotated functions. But now do this for all functions.
It is essential that performance-annotated functions are specialized in the same way as other functions.
Because otherwise it can happen that the same specialization has different performance characteristics in different modules.
And it's up to the linker to select one of those ODR functions when linking.
Also, dropping metatype arguments is good for performance and code size in general.
This change also contains a few bug fixes for dropping metatype arguments.
rdar://110509780
`int_trap` doesn't provide a failure message, which makes crash reports hard to understand.
This is mostly the case for optimized casts which fail.
rdar://97681511
The ComputeEffects pass derives escape information for function arguments and adds those effects in the function.
This needs a lot of changes in check-lines in the tests, because the effects are printed in SIL
The ComputeEffects pass derives escape information for function arguments and adds those effects in the function.
This needs a lot of changes in check-lines in the tests, because the effects are printed in SIL
SROA and Mem2Reg now can leverage DIExpression -- op_fragment, more
specifically -- to generate correct debug info for optimized SIL. Some
important highlights:
- The new swift::salvageDebugInfo, similar to llvm::salvageDebugInfo,
tries to restore / transfer debug info from a deleted instruction.
Currently I only implemented this for store instruction whose
destination is an alloc_stack value.
- Since we now have source-variable-specific SIL location inside a
`debug_value` instruction (and its friends), this patch teaches
SILCloner and SILInliner to remap the debug scope there in addition
to debug scope of the instruction.
- DCE now does not remove `debug_value` instruction whose associating
with a function argument SSA value that is not used elsewhere. Since
that SSA value will not disappear so we should keep the debug info.
While tightening the requirements of the debug info generator in
IRGenSIL I noticed that SILCloner didn't correctly transfer variable
debug info on alloc_box and alloc_stack instructions. In order to make
these mistakes easier to find I added an assertion to SILBuilder and
fixed all issues uncovered by that assertion, too.
The result is a moderate increase in debug info coverage in optimized code.
On stdlib/public/core/OSX/x86_64/Swift.o "variables with location"
increases from 60134 to 60299.
Replacing an alloc_stack of a struct/tuple with multiple alloc_stacks of the struct/tuple elements should only be done if the elements are somehow accessed individually.
If not, e.g. if the whole struct/tuple is just copied, there is no benefit of doing SROA.
Although this change has little impact by its own (some small code size wins), it is important for the improvement of let-property optimization.
We did this for @in => @owned for all parameters before enabling +0. We decided
to defer this work to after +0 was turned back on.
This also fixes the array_contentof_opt test without making append(contentOf: )
take the container at +1.
rdar://38152291
I am going to leave in the infrastructure around this just in case. But there is
no reason to keep this in the tests themselves. I can always just revert this
and I don't think merge conflicts are likely due to previous work I did around
the tooling for this.
* rename "Name" to "Description" in the pass definition, because it's not really the pass name, but the description of a pass
* remove the getName() from Transforms (which actually returned the description of a pass)
* in debug printing, print the pass ID and not the pass description. It makes it easier to correlate the debug output to the actual pass implementation.
* remove the iteration numbering in the pass manager, because we only run a single iteration anyway.
This is important in case the inline restarts the pass pipeline.
In a sub-sequent invocation of the inlined it should receive a cleaned-up function so that it can make better estimations for further inlining.
As a compensation, reduce the caller-block limit of the inliner.
And add an overall block limit which is also taken into account for always-inline functions.
Extend NSNumber bridging to cover not only `Int`, `UInt`, `Double`, and `Bool`, but all of the standard types as well. Extend the `TypePreservingNSNumber` subclass to accommodate all of these types, so that we preserve type identity for `AnyHashable` and dynamic casting of Swift-bridged NSNumbers. If a pure Cocoa NSNumber is cast, just trust that the user knows what they're doing.
This XFAILs a couple of serialization tests that attempt to build the Foundation overlay, but which don't properly handle `gyb` files.
With this re-abstraction a specialized function has the same calling convention as if it would have been written with the specialized types in the first place.
In general this results in less alloc_stacks and load/stores.
It also can eliminate some re-abstraction thunks, e.g. if a generic closure is used in a non-generic context.
It some (hopefully rare) cases it may require to add re-abstraction thunks.
In case a function has multiple indirect results, only the first is converted to a direct result. This is an open TODO.
Similarly to how we've always handled parameter types, we
now recursively expand tuples in result types and separately
determine a result convention for each result.
The most important code-generation change here is that
indirect results are now returned separately from each
other and from any direct results. It is generally far
better, when receiving an indirect result, to receive it
as an independent result; the caller is much more likely
to be able to directly receive the result in the address
they want to initialize, rather than having to receive it
in temporary memory and then copy parts of it into the
target.
The most important conceptual change here that clients and
producers of SIL must be aware of is the new distinction
between a SILFunctionType's *parameters* and its *argument
list*. The former is just the formal parameters, derived
purely from the parameter types of the original function;
indirect results are no longer in this list. The latter
includes the indirect result arguments; as always, all
the indirect results strictly precede the parameters.
Apply instructions and entry block arguments follow the
argument list, not the parameter list.
A relatively minor change is that there can now be multiple
direct results, each with its own result convention.
This is a minor change because I've chosen to leave
return instructions as taking a single operand and
apply instructions as producing a single result; when
the type describes multiple results, they are implicitly
bound up in a tuple. It might make sense to split these
up and allow e.g. return instructions to take a list
of operands; however, it's not clear what to do on the
caller side, and this would be a major change that can
be separated out from this already over-large patch.
Unsurprisingly, the most invasive changes here are in
SILGen; this requires substantial reworking of both call
emission and reabstraction. It also proved important
to switch several SILGen operations over to work with
RValue instead of ManagedValue, since otherwise they
would be forced to spuriously "implode" buffers.
On the whole it looks like this currently benefits performance.
As with the devirtualization pass, once the updated inliner is
committed, the position of this pass in the pipeline will change.
They aren't needed at the moment, and running the specialization pass
early might have resulted in some performance regressions.
We can add these back in (and in the appropriate place in the pipeline)
when the changes to unbundle this functionality from the inliner goes in.
Begin unbundling devirtualization, specialization, and inlining by
recreating the stand-alone generic specializer pass.
I've added a use of the pass to the pipeline, but this is almost
certainly not going to be the final location of where it runs. It's
primarily there to ensure this code gets exercised.
Since this is running prior to inlining, it changes the order that some
functions are specialized in, which means differences in the order of
output of one of the tests (one which similarly changed when
devirtualization, specialization, and inlining were bundled together).