This patch implements collection and dumping of statistics about SILModules, SILFunctions and memory consumption during the execution of SIL optimization pipelines.
The following statistics can be collected:
* For SILFunctions: the number of SIL basic blocks, the number of SIL instructions, the number of SIL instructions of a specific kind, duration of a pass
* For SILModules: the number of SIL basic blocks, the number of SIL instructions, the number of SIL instructions of a specific kind, the number of SILFunctions, the amount of memory used by the compiler, duration of a pass
By default, any collection of statistics is disabled to avoid affecting compile times.
One can enable the collection of statistics and dumping of these statistics for the whole SILModule and/or for SILFunctions.
To reduce the amount of produced data, one can set thresholds in such a way that changes in the statistics are only reported if the delta between the old and the new values are at least X%. The deltas are computed as using the following formula:
Delta = (NewValue - OldValue) / OldValue
Thresholds provide a simple way to perform a simple filtering of the collected statistics during the compilation. But if there is a need for a more complex analysis of collected data (e.g. aggregation by a pipeline stage or by the type of a transformation), it is often better to dump as much data as possible into a file using e.g. -sil-stats-dump-all -sil-stats-modules -sil-stats-functions and then e.g. use the helper scripts to store the collected data into a database and then perform complex queries on it. Many kinds of analysis can be then formulated pretty easily as SQL queries.
This commit contains:
-) adding the new instructions + infrastructure, like parsing, printing, etc.
-) support in IRGen to generate global object-variables (i.e. "heap" objects) which are statically initialized in the data section.
-) IRGen for global_value which lazily initializes the object header and returns a reference to the object.
For details see the documentation of the new instructions in SIL.rst.
Static initializers are now represented by a list of literal and aggregate instructions in a SILGlobalVariable.
For details see SIL.rst.
This representation is cleaner than what we did so far (point to the initializer function and do some pattern matching).
One implication of that change is that now (a subset of) instructions not necessarily have a parent function.
Regarding the generated code it's a NFC.
Also the swift module format didn't change because so far we don't serializer global variables.
Remove the cast consumption kind from all unconditional casts. It
doesn't make sense for unconditional casts, complicates SIL ownership,
and wasn't fully supported for all variants. Copies should be
explicit.
GenericSpecializationInformation contains information regarding how a given specialized function was created, e.g. which caller function triggered this specialization, which substitutions were used, etc. Provide some debugging flags to dump the collected specialization information.
The information about generic specializations is referenced by the specialized functions and by call-sites originating from specialized functions.
This information can be created/used by the generic specializer to detect generic call-sites whose specialization would result in non-terminating sequence of subsequent generic specializations.
This has the same semantics as open_existential_box, but returns an object value
instead of an address.
This is used in SIL opaque values mode. Attempting to reuse open_existential_box
in this mode causes SIL type inconsistencies that are too difficult to work
around. Adding this instruction allows for consistent handling of opaque values.
The original versions of several of these currently redundant instructions will
be removed once the SIL representation stabilizes.
These instructions have the same semantics as the *ExistentialAddr instructions
but operate directly on the existential value, not its address.
This is in preparation for adding ExistentialBoxValue instructions.
The previous name would cause impossible confusion with "opaque existentials"
and "opaque existential boxes".
Use the KeyPath implementation's new support for instantiating and dealing with captures to lower the generic context required to dispatch computed accessors with dependent generics.
This is a very easily misused API since it allows for users to leak instructions
if they are not careful. This commit removes this API and replaces the small
number of uses of this API with higher level APIs that accomplish the same task
without using removeFromParent(). There were no API users that specifically
required removeFromParent.
An example of one way we were using removeFromParent is to move a SILInstruction
to the front of a block. That does not require exposing an API like
removeFromParent()... we can just create a higher level API like the one added
in this commit: SILInstruction::moveFront(SILBasicBlock *).
rdar://31276565
Till now createApply, createTryApply, createPartialApply were taking some arguments like SubstCalleeType or ResultType. But these arguments are redundant and can be easily derived from other arguments of these functions. There is no need to put the burden of their computation on the clients of these APIs.
The removal of these redundant parameters simplifies the APIs and reduces the possibility of providing mismatched types by clients, which often happened in the past.
The following instructions were enhanced with type dependent operands:
- convert_function
- pointer_to_thin_function
- upcast_inst
- thin_to_thick_function
Fixes rdar://31879356
I put in a simple fixup pass (MarkUninitializedFixup) for staging purposes. I
don't expect it to be in tree long. I just did not feel comfortable fixing up in
1 commit all of the passes up to DI.
rdar://31521023
A computed component needs:
- A stable identifier for equality checking. This can be either a static function reference for concrete property implementations, or a reference into a vtable or witness table for a dynamically dispatched property. This should correspond to a public ABI interface for public things.
- Getter and setter (TODO: and materializeForSet) references. These might be thunks to reach the necessary abstraction level for the keypath implementation, so they can't be used as stable identifiers directly.
- Separate out a uniquable KeyPathPattern that describes the context-free shape of the key path, with generic parameters and (eventually) subscript index slots factored out.
- Add component kinds for gettable and settable properties.