The old code was changing the fragility of some pre-specialized symbols which made them invisible outside of their own object files, which resulted in linking errors.
Fixes radr://problem/28615847
When applying substitutions to substitution lists in SIL, we would
unpack the ArrayRef<Substitution> into a SubstitutionMap on each
iteration over the original ArrayRef<Substitution>. Discourage
this sort of thing by removing the API in question and refactoring
surrounding code.
This patch is rather large, since it was hard to make this change
incrementally, but most of the changes are mechanical.
Now that we have a lighter-weight data structure in the AST for mapping
interface types to archetypes and vice versa, use that in SIL instead of
a GenericParamList.
This means that when serializing a SILFunction body, we no longer need to
serialize references to archetypes from other modules.
Several methods used for forming substitutions can now be moved from
GenericParamList to GenericEnvironment.
Also, GenericParamList::cloneWithOuterParameters() and
GenericParamList::getEmpty() can now go away, since they were only used
when SILGen-ing witness thunks.
Finally, when printing generic parameters with identical names, the
SIL printer used to number them from highest depth to lowest, by
walking generic parameter lists starting with the innermost one.
Now, ambiguous generic parameters are numbered from lowest depth
to highest, by walking the generic signature, which means test
output in one of the SILGen tests has changed.
This consists of 3 parts:
1) Extend CallerAnalysis to also provide information if a function is partially applied
2) A new DeadArgSignatureOpt pass, similar to FunctionSignatureOpts, which just specializes for dead arguments of partially applied functions.
3) Let CapturePropagation eliminate such partial_apply instructions and replace them with a thin_to_thick conversion of the specialized functions.
This optimzation improves benchmarks where static struct or class functions are passed as a closure (e.g. -20% for SortStrings).
Such functions have a additional metatype parameter. We used to create a partial_apply in this case, which allocates a context, etc.
But this is not necessary as the metatype parameter is not used in most cases.
rdar://problem/27513085
This function takes a substitution array and produces a
contextual type substitution map, so it is the contextual
type equivalent of GenericSignature::getSubstitutionMap(),
which produces an interface type substitution map.
The new version takes a GenericSignature, just like the new
getForwardingSubstitutions(), so that it can walk the
requirements of the signature rather than walking the
AllArchetypes list.
Also, this new version now produces a mapping from
archetypes to conformances in addition to the type mapping,
which will allow it to be used in a few places that had
hand-coded logic.
This re-instates commit de9622654d
The problem of the infinite loop should be fixed by the previous fix in FunctionSignatureOpts.
In addition this new commit implements a safety check to void such cases, even if buggy optimizations try to keep pushing new functions onto the work list.
This establishes a real def-use relation from the self-parameter to any instruction which uses the dynamic-self type.
This is an addition to what was already done for opened archetypes.
The biggest part of this commit is to rename "OpenedArchetypeOperands" to "TypeDependentOperands" as this name is now more appropriate.
Other than that the change includes:
*) type-dependent operands are now printed after a SIL instruction in a comment as "type-defs:" (for debugging)
*) FuncationSignatureOpts doesn't need to explicitly check if a function doesn't bind dynamic self to remove a dead self metadata argument
*) the check if a function binds dynamic self (used in the inliner) is much simpler now
*) also collect type-dependent operands for ApplyInstBase::SubstCalleeType and not only in the substitution list
*) with this SILInstruction::mayHaveOpenedArchetypeOperands (used in CSE) is not needed anymore and removed
*) add type dependent operands to dynamic_method instruction
Regarding the generated code it should be a NFC.
One minor revision: this lifts the proposed restriction against
overriding a non-open method with an open one. On reflection,
that was inconsistent with the existing rule permitting non-public
methods to be overridden with public ones. The restriction on
subclassing a non-open class with an open class remains, and is
in fact consistent with the existing access rule.
'fileprivate' is considered a broader level of access than 'private',
but for now both of them are still available to the entire file. This
is intended as a migration aid.
One interesting fallout of the "access scope" model described in
758cf64 is that something declared 'private' at file scope is actually
treated as 'fileprivate' for diagnostic purposes. This is something
we can fix later, once the full model is in place. (It's not really
/wrong/ in that they have identical behavior, but diagnostics still
shouldn't refer to a type explicitly declared 'private' as
'fileprivate'.)
As a note, ValueDecl::getEffectiveAccess will always return 'FilePrivate'
rather than 'Private'; for purposes of optimization and code generation,
we should never try to distinguish these two cases.
This should have essentially no effect on code that's /not/ using
'fileprivate' other than altered diagnostics.
Progress on SE-0025 ('fileprivate' and 'private')
Since this code has an isAvailableExternally check, this probably makes
no difference, but it's still more correct: SIL-level code should
always use a declaration's effective access.
Till now there was no way in SIL to explicitly express a dependency of an instruction on any opened archetypes used by it. This was a cause of many errors and correctness issues. In many cases the code was moved around without taking into account these dependencies, which resulted in breaking the invariant that any uses of an opened archetype should be dominated by the definition of this archetype.
This patch does the following:
- Map opened archetypes to the instructions defining them, i.e. to open_existential instructions.
- Introduce a helper class SILOpenedArchetypesTracker for creating and maintaining such mappings.
- Introduce a helper class SILOpenedArchetypesState for providing a read-only API for looking up available opened archetypes.
- Each SIL instruction which uses an opened archetype as a type gets an additional opened archetype operand representing a dependency of the instruction on this archetype. These opened archetypes operands are an in-memory representation. They are not serialized. Instead, they are re-constructed when reading binary or textual SIL files.
- SILVerifier was extended to conduct more thorough checks related to the usage of opened archetypes.
Till now there was no way in SIL to explicitly express a dependency of an instruction on any opened archetypes used by it. This was a cause of many errors and correctness issues. In many cases the code was moved around without taking into account these dependencies, which resulted in breaking the invariant that any uses of an opened archetype should be dominated by the definition of this archetype.
This patch does the following:
- Map opened archetypes to the instructions defining them, i.e. to open_existential instructions.
- Introduce a helper class SILOpenedArchetypesTracker for creating and maintaining such mappings.
- Introduce a helper class SILOpenedArchetypesState for providing a read-only API for looking up available opened archetypes.
- Each SIL instruction which uses an opened archetype as a type gets an additional opened archetype operand representing a dependency of the instruction on this archetype. These opened archetypes operands are an in-memory representation. They are not serialized. Instead, they are re-constructed when reading binary or textual SIL files.
- SILVerifier was extended to conduct more thorough checks related to the usage of opened archetypes.
Till now there was no way in SIL to explicitly express a dependency of an instruction on any opened archetypes used by it. This was a cause of many errors and correctness issues. In many cases the code was moved around without taking into account these dependencies, which resulted in breaking the invariant that any uses of an opened archetype should be dominated by the definition of this archetype.
This patch does the following:
- Map opened archetypes to the instructions defining them, i.e. to open_existential instructions.
- Introduce a helper class SILOpenedArchetypesTracker for creating and maintaining such mappings.
- Introduce a helper class SILOpenedArchetypesState for providing a read-only API for looking up available opened archetypes.
- Each SIL instruction which uses an opened archetype as a type gets an additional opened archetype operand representing a dependency of the instruction on this archetype. These opened archetypes operands are an in-memory representation. They are not serialized. Instead, they are re-constructed when reading binary or textual SIL files.
- SILVerifier was extended to conduct more thorough checks related to the usage of opened archetypes.
They are mandatory inlined anyway. Therefore the binary code of transparent functions is not used in most cases.
In case the address of a transparent function is taken, the main program (which deserialized the transparent function) generates code for it and treats it as shared function.
This reduces the stdlib code size by 2.8%.
...in code that I wrote. The integrated REPL, deprecated though it may
be, does not have an associated DeclContext because its SourceFile is
not considered complete. (The proper LLDB REPL does not suffer from
this problem because they use a new SourceFile for every block of
input.)
Elsewhere, tighten up code that may have hit similar bugs, though we
haven't seen anything hit these yet.
rdar://problem/26476281
This made call sites confusing to read because it doesn't actually
check if the function already exists.
Also fix some minor formatting issues. This came up while I was working
on a fix for a bug that turned out to not be a bug.
If we find a specialization within the current module, it's okay if it
has a body. This can come up if we compile something with optimizations
and then compile the resulting SIL (or SIB) without optimizations.
Change the optimizer to only make specializations [fragile] if both the
original callee is [fragile] *and* the caller is [fragile].
Otherwise, the specialized callee might be [fragile] even if it is never
called from a [fragile] function, which inhibits the optimizer from
devirtualizing calls inside the specialization.
This opens up some missed optimization opportunities in the performance
inliner and devirtualization, which currently reject fragile->non-fragile
references:
TEST | OLD_MIN | NEW_MIN | DELTA (%) | SPEEDUP
--- | --- | --- | --- | ---
DictionaryRemoveOfObjects | 38391 | 35859 | -6.6% | **1.07x**
Hanoi | 5853 | 5288 | -9.7% | **1.11x**
Phonebook | 18287 | 14988 | -18.0% | **1.22x**
SetExclusiveOr_OfObjects | 20001 | 15906 | -20.5% | **1.26x**
SetUnion_OfObjects | 16490 | 12370 | -25.0% | **1.33x**
Right now, passes other than performance inlining and devirtualization
of class methods are not checking invariants on [fragile] functions
at all, which was incorrect; as part of the work on building the
standard library with -enable-resilience, I added these checks, which
regressed performance with resilience disabled. This patch makes up for
these regressions.
Furthermore, once SIL type lowering is aware of resilience, this will
allow the stack promotion pass to make further optimizations after
specializing [fragile] callees.
Based on the review of my previous commit, I did some re-factorings.
The code is now simpler and handles more cases. More tests were added.
The overall idea of this rewrite is that the pass basically tries to check if it can
see all possible writes (i.e. initializations) into a given let property. Only if it can be proven
that the pass sees all possible writes and all those initializations are producing
the same constant, statically known value, the pass propagates this constant value
into uses of a property.
SR-1026 and rdar://25303106