Whenever we create a (root) requirement source, associate it with the
potential archetype on which the requirement is written. This lets us
follow a requirement source from the (stated or implied) requirement on
the root potential archetype to the effective requirement on the
resulting potential archetype.
Introduce FloatingRequirementSource for the cases where we need to
state what the root source is, but don't yet have a potential
archetype to attach it to. These get internally resolved to
RequirementSources as soon as possible.
Reimplement the RequirementSource class, which captures how
a particular requirement is satisfied by a generic signature. The
primary goal of this rework is to keep the complete path one follows
in a generic signature to get from some explicit requirement in the
generic signature to some derived requirement or type, e.g.,
1) Start at an explicit requirement "C: Collection"
2) Go to the inherited protocol Sequence,
3) Get the "Iterator" associated type
4) Get its conformance to "IteratorProtocol"
5) Get the "Element" associated type
We don't currently capture all of the information we want in the path,
but the basic structure is there, and should also allow us to capture
more source-location information, find the "optimal" path, etc. There are
are a number of potential uses:
* IRGen could eventually use this to dig out the witness tables and
type metadata it needs, instead of using its own fulfillment
strategy
* SubstitutionMap could use this to lookup conformances, rather than
it's egregious hacks
* The canonical generic signature builder could use this to lookup
conformances as needed, e.g., for the recursive-conformances case.
... and probably more simplifications, once we get this right.
This reverts commit 1b3d29a163, reversing
changes made to b32424953e.
We're seeing a handful of issues from turning on inlining of generics,
so I'm reverting to unblock the bots.
In addition to supporting the creation of full specializations, the EagerSpecializer changes contain some code for generating the layout-constrained partial specializations as well.
SubstitutionList is going to be a more compact representation of
a SubstitutionMap, suitable for inline allocation inside another
object.
For now, it's just a typedef for ArrayRef<Substitution>.
Formal types are defined by the language's type system. SIL types are
lowered. They are no longer part of that type system.
The important distinction here is between the SIL storage type and the SIL value
type. To make this distinction clear, I refer to the SILFunctionTypes "formal"
conventions. These conventions dictate the SIL storage type but *not* the SIL
value type. I call them "formal" conventions because they are an immutable
characteristic of the function's type and made explicit via qualifiers on the
function type's parameters and results. This is in contrast to to SIL
conventions which depend on the SIL stage, and in the short term whether the
opaque values flag is enabled.
Separate formal lowered types from SIL types.
The SIL type of an argument will depend on the SIL module's conventions.
The module conventions are determined by the SIL stage and LangOpts.
Almost NFC, but specialized manglings are broken incidentally as a result of
fixes to the way passes handle book-keeping of aruments. The mangler is fixed in
the subsequent commit.
Otherwise, NFC is intended, but quite possible do to rewriting the logic in many
places.
Most of this involved sprinkling ValueOwnershipKind::Owned in many places. In
some of these places, I am sure I was too cavalier and I expect some of them to
be trivial. The verifier will help me to track those down.
On the other hand, I do expect there to be some places where we are willing to
accept guaranteed+trivial or owned+trivial. In those cases, I am going to
provide an aggregate ValueOwnershipKind that will then tell SILArgument that it
should disambiguate using the type. This will eliminate the ackwardness from
such code.
I am going to use a verifier to fix such cases.
This commit also begins the serialization of ValueOwnershipKind of arguments,
but does not implement parsing of value ownership kinds. That and undef are the
last places that we still use ValueOwnershipKind::Any.
rdar://29791263
In response to [SR-3334], which pointed out a large cost to iteration over
ReversedRandomAccessCollections at optimization level -Onone. By adding
iteration through a.reversed() in the _Prespecialize struct, we can get to
about the same performance as forward iteration.
We preserve the current behavior of assuming Any ownership always and use
default arguments to hide this change most of the time. There are asserts now in
the SILBasicBlock::{create,replace,insert}{PHI,Function}Argument to ensure that
the people can only create SILFunctionArguments in entry blocks and
SILPHIArguments in non-entry blocks. This will ensure that the code in tree
maintains the API distinction even if we are not using the full distinction in
between the two.
Once the verifier is finished being upstreamed, I am going to audit the
createPHIArgument cases for the proper ownership. This is b/c I will be able to
use the verifier to properly debug the code. At that point, I will also start
serializing/printing/parsing the ownershipkind of SILPHIArguments, but lets take
things one step at a time and move incrementally.
In the process, I also discovered a CSE bug. I am not sure how it ever worked.
Basically we replace an argument with a new argument type but return the uses of
the old argument to refer to the old argument instead of a new argument.
rdar://29671437
This simplifies the SILType substitution APIs and brings them in line with Doug and Slava's refactorings to improve AST-level type substitution. NFC intended.
The purpose of this change is to test if the new mangling is equivalent to the old mangling.
Both mangling strings are created, de-mangled and checked if the de-mangle trees are equivalent.
This was already done for getSuccessorBlocks() to distinguish getting successor
blocks from getting the full list of SILSuccessors via getSuccessors(). This
commit just makes all of the successor/predecessor code follow that naming
convention.
Some examples:
getSingleSuccessor() => getSingleSuccessorBlock().
isSuccessor() => isSuccessorBlock().
getPreds() => getPredecessorBlocks().
Really, IMO, we should consider renaming SILSuccessor to a more verbose name so
that it is clear that it is more of an internal detail of SILBasicBlock's
implementation rather than something that one should consider as apart of one's
mental model of the IR when one really wants to be thinking about predecessor
and successor blocks. But that is not what this commit is trying to change, it
is just trying to eliminate a bit of technical debt by making the naming
conventions here consistent.
Before this commit all code relating to handling arguments in SILBasicBlock had
somewhere in the name BB. This is redundant given that the class's name is
already SILBasicBlock. This commit drops those names.
Some examples:
getBBArg() => getArgument()
BBArgList => ArgumentList
bbarg_begin() => args_begin()
This eliminates all inline creation of SILBasicBlock via placement new.
There are a few reasons to do this:
1. A SILBasicBlock is always created with a parent function. This commit
formalizes this into the SILBasicBlock API by only allowing for SILFunctions to
create SILBasicBlocks. This is implemented via the type system by making all
SILBasicBlock constructors private. Since SILFunction is a friend of
SILBasicBlock, SILFunction can still create a SILBasicBlock without issue.
2. Since all SILBasicBlocks will be created in only a few functions, it becomes
very easy to determine using instruments the amount of memory being allocated
for SILBasicBlocks by simply inverting the call tree in Allocations.
With LTO+PGO, normal inlining can occur if profitable so there shouldn't be
overhead that we care about in shipping compilers.
Today, loads and stores are treated as having @unowned(unsafe) ownership
semantics. This leaves the user to specify ownership changes on the loaded or
stored value independently of the load/store by inserting ARC operations. With
the change to Semantic SIL, this will no longer be true. Instead loads, stores
have ownership semantics that one must reason about such as copy, take, and
trivial.
This change moves us closer to that world by eliminating the default
OwnershipQualification argument from create{Load,Store}. This means that the
compiler developer cannot ignore reasoning about the ownership semantics of the
memory operation that they are creating.
Operationally, this is a NFC change since I have just gone through the compiler
and updated all places where we create loads, stores to pass in the former
default argument ({Load,Store}OwnershipQualifier::Unqualified), to
SILBuilder::create{Load,Store}(...). For now, one can just do that in situations
where one needs to create loads/stores, but over time, I am going to tighten the
semantics up via the verifier.
rdar://28685236
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 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.
The generic specialized would get out of control in certain cases and would not stop generating specializations of generic functions until it runs out of memory after a while.
rdar://21260480
Applying this patch triggered an assert while building libswiftOnoneSupport:
--- a/lib/SILOptimizer/PassManager/Passes.cpp
+++ b/lib/SILOptimizer/PassManager/Passes.cpp
@@ -283,6 +283,9 @@ void swift::runSILOptimizationPasses(SILModule &Module) {
PM.setStageName("HighLevel+EarlyLoopOpt");
// FIXME: update this to be a function pass.
PM.addEagerSpecializer();
+
+ AddSimplifyCFGSILCombine(PM);
+
AddSSAPasses(PM, OptimizationLevelKind::HighLevel);
AddHighLevelLoopOptPasses(PM);
PM.runOneIteration();
I don't have a reduced testcase, but presumably Erik will commit the above
change soon.
Fixes <rdar://problem/25646947>.