This is one reason for the weird iteration maintainance code in
MandatoryInlining. This comment at least makes it clear what is going on (more
for historical purposes, since I am hoping to fix this soon).
rdar://31521023
I am refactoring this for two reasons:
1. This code was 60-70% of cleanupCalleeValue, yet cleanupCalleeValue also
performs other tasks. This is a classic situation where one should extract a
subroutine to make cleanupCalleeValue more readable.
2. I am going to be extracting out the cleanup of the callee to be outside the
main inlining loop. Without this refactoring, I would have to use goto to
perform a continue from the inside of an inner for loop of an outer for loop.
Instead by refactoring it this way, I can separate continuing in the inner loop
from continuing in the outer loop.
rdar://31521023
The main loop of mandatory inlining is spending a lot of time managing complex
iterator invalidation issues. This is the first in a series of commits that move
the main inlining loop to only delete the callee and to do all cleanups after we
have finished inlining.
This specific optimization (the quick retain/release peephole), I am not going
to do in MandatoryInlining, we already have guaranteed arc opts afterwards that
will be able to hit such a peephole so no perf should be lost.
*NOTE* The reason why I had to touch some of the code motion tests is that the
routine I am using to ensure that strong_retain/release_value is emitted as
appropriate is also used by codemotion. Code motion tests had cargo culted some
code from previous tests that retained Builtin.Int32. I changed the routines
though so that when a retain/release is inserted, if it is trivial, nothing is
inserted. No routine was relying on the actual usage of the inserted
retain/releases, so everything will be safe. This addition to the relevant code
caused me to need to change the tests in code motion to use actual non-trivial
values. The same code paths are being tested in terms of blocking code
motion/etc.
rdar://31521023
F{I,E} is generally used for function iterators over a module's functions.
B{I,E} are generally standard for block iterator, block end. I make the II
change just to make it clearer that the given value is an instruction iterator
like in other parts of the SIL Optimizer.
rdar://31521023
The reason to do this is:
1. The check in SILInliner if we can inline can be done without triggering
side-effects.
2. This enables us to know if inlining will succeed before attempting to inline.
This enables for arguments to be adjusted with new SILInstructions and the like
before inlining occurs. I use this in a forthcoming patch that updates mandatory
inlining for ownership.
rdar://31521023
Do not report any constant propagation issues in (generic) function specializations, because these issues are eventually not visible in the original function and thus would be very misleading and difficult to understand.
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.
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".
Update static exclusivity diagnostics to not suggest copying to a local
when a call to swapAt() should be used instead. We already emit a FixIt in
this case, so don't suggest an an helpful fix in the diagnostic.
rdar://problem/32296784
Make the static enforcement of accesses in noescape closures stored-property
sensitive. This will relax the existing enforcement so that the following is
not diagnosed:
struct MyStruct {
var x = X()
var y = Y()
mutating
func foo() {
x.mutatesAndTakesClosure() {
_ = y.read() // no-warning
}
}
}
To do this, update the access summary analysis to summarize accesses to
subpaths of a capture.
rdar://problem/32987932
Make the static enforcement of accesses in noescape closures stored-property
sensitive. This will relax the existing enforcement so that the following is
not diagnosed:
struct MyStruct {
var x = X()
var y = Y()
mutating
func foo() {
x.mutatesAndTakesClosure() {
_ = y.read()
}
}
}
To do this, update the access summary analysis to be stored-property sensitive.
rdar://problem/32987932
In raw SIL, access markers are unconditionally retained. In canonical SIL,
markers are still removed prior to optimization.
A new flag, -sil-optimized-access-markers, allows testing access markers in
optimized builds, but it is not yet fully supported.
In anticipation of future attributes, and perhaps the ability to
declare lvalues with specifiers other than 'let' and 'var', expand
the "isLet" bit into a more general "specifier" field.
Fix an unreachable when constructing the description of the accessed subpath
when diagnosing an exclusivity violation on a variable of
BoundGenericStructType.
rdar://problem/33031311
This analysis has a whitelist to ensure that we aren't missing any SIL
patterns and failing to enforce some cases.
There is a special case involving nested non-escaping closures being passed as a
block argument. Whitelist this very special case even though we don't enforce
it because the corresponding diagnostics pass also doesn't enforce it.
This uses the new ClosureScopeAnalysis to process parent functions before the
closures they reference. The analysis now tracks captured variables in addition
to immediately accessed variables. If the variable escapes before it's capture
is applied, then that closure uses dynamic enforcement for the variable.
<rdar://problem/32061282> [Exclusivity] Enforcement selection for noescape closure captures.
Use the AccessSummaryAnalysis to statically enforce exclusive access for
noescape closures passed as arguments to functions.
We will now diagnose when a function is passed a noescape closure that begins
an access on capture when that same capture already has a conflicting access
in progress at the time the function is applied.
The interprocedural analysis is not yet stored-property sensitive (unlike the
intraprocedural analysis), so this will report violations on accesses to
separate stored properties of the same struct.
rdar://problem/32020710
IndexTrie is a more light-weight representation and it works well in this case.
This requires recovering the represented sequence from an IndexTrieNode, so
also add a getParent() method.
Remove the descriptive decl kind (since with subpaths it is not correct and
cannot represent a tuple element) and change "simultaneous" to "overlapping"
in order to lower the register slightly and avoid connoting threading.
For example, for the following:
takesTwoInouts(&x.f, &x.f)
the diagnostic will change from
"simultaneous accesses to var 'x.f', but modification requires exclusive access;
consider copying to a local variable"
to
"overlapping accesses to 'x.f', but modification requires exclusive access;
consider copying to a local variable"
Relax the static enforcement of exclusive access so that we no longer diagnose
on accesses to separate stored structs of the same property:
takesInout(&s.f1, &s.f2) // no-warning
And perform the analogous relaxation for tuple elements.
To do this, track for each begin_access the projection path from that
access and record the read and write-like modifications on a per-subpath
basis.
We still warn if the there are conflicting accesses on subpaths where one is
the prefix of another.
This commit leaves the diagnostic text in a not-so-good shape since we refer
to the DescriptiveDeclKind of the access even describing a subpath.
I'll fix that up in a later commit that changes only diagnostic text.
https://bugs.swift.org/browse/SR-5119
rdar://problem/31909639
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
Adjust the definition of some diagnostics that are already called with
DeclBaseNames so that the implicit conversion from DeclBaseName to
Identifier is no longer needed.
Adjust the call side of diagnostics which don't have to deal with
special names to pass an Identifier to the diagnostic.
With the introduction of special decl names, `Identifier getName()` on
`ValueDecl` will be removed and pushed down to nominal declarations
whose name is guaranteed not to be special. Prepare for this by calling
to `DeclBaseName getBaseName()` instead where appropriate.
This fixes a too-strong assertion when suggesting a Fix-It to replace
module-qualified calls to swap():
Swift.swap(&a[i], &a[j])
Other than weakening the assert, there is no functional change here.
rdar://problem/32358872
Extend the static diagnostics for exclusivity violations to suggest replacing
swap(&collection[index1], &collection[index2]
with
collection.swapAt(index1, index2).
when 'collection' is a MutableCollection.
To do so, repurpose some vestigial code that was previously used to suppress all
exclusivity diagnostics for calls to swap() and add some additional syntactic,
semantic, and textual pattern matching.
rdar://problem/31916085