The specific problem here is that we are setting the insertion point of a
SILBuilder and not unsetting it. I fixed the problem by creating a separate
builder so the original builder stays put.
I originally came across this in my work on moving ownership stripping after the
diagnostic passes. This patch fixes it without my other changes to ease
cherry-picking to 5.1.
I also added more test coverage by expanding the test case to also handle
copy_on_success and take_always.
rdar://51093557
This is needed now that const expr handles string operations/etc. There aren't
tests for this now since I would need to stub out the stdlib. But these are
pretty simple changes overall, I do not expect any problems, and I plan on
enabling this relatively soon.
The specific case where this happened here is:
```
// Worklist = [
%0 = struct $Int (...)
%1 = $Klass
%2 = tuple (%0, %1)
(%3, %4) = destructure_tuple %2
store %3 to [trivial] %3stack
store %4 to [init] %4stack
```
What would happen is we would visit the destructure_tuple, replace %3 with %0
but fail to propagate %4:
```
%0 = struct $Int (...)
%1 = $Klass
%2 = tuple (%0, %1)
(%3, %4) = destructure_tuple %2
store %0 to [trivial] %3stack
store %4 to [init] %4stack
```
This then causes the tuple to be added to the worklist. When we visit the tuple,
we see that we have a destructure_tuple that is a user of the tuple, we see that
it still has that Struct as a user despite us having constant propagated that
component of the tuple. This then causes us to add the struct back to the
worklist despite that tuple component having no uses. Then when we visit the
struct. Which causes us to visit the tuple, etc.
rdar://49947112
This is the complement to load canonicalization. Although store
canonicalization is not required before diagnostics, it should be
defined in the same utility.
The recursivelyDeleteTriviallyDeadInstructions utility takes a
callBack to be called for every deleted instruction. However, it
wasn't passing this callBack to eraseFromParentWithdebugInsts. The
callback was used to update an iterator in some cases, so not calling
it resulted in iterator invalidation.
Doing this also cleans up the both APIs:
recursivelyDeleteTriviallyDeadInstructions and eraseFromParentWithdebugInsts.
This adds support to the load->struct_extract canonicalization for
nontrivial element types which look like:
load [copy]
borrow
struct_extract
...uses...
end_borrow
destroy
CanonicalizeInstruction will be a superset of
simplifyInstruction (once all the transforms are fixed for ownership
SIL). Additionally, it will also include simple SSA-based
canonicalization that requires new instruction creation. It may not
perform any optimization that interferes with diagnostics or increases
compile time.
Canonicalization replaces simplifyInstruction in SILCombine so we can
easily factor some existing SILCombine transforms into canonicalization.
`String.+=` function to `String.append` function, and use a new
semantics attribute for String.+=.
Teach the constant evaluator about `String.Append` instead of `String.+=`.
This is a large patch; I couldn't split it up further while still
keeping things working. There are four things being changed at
once here:
- Places that call SILType::isAddressOnly()/isLoadable() now call
the SILFunction overload and not the SILModule one.
- SILFunction's overloads of getTypeLowering() and getLoweredType()
now pass the function's resilience expansion down, instead of
hardcoding ResilienceExpansion::Minimal.
- Various other places with '// FIXME: Expansion' now use a better
resilience expansion.
- A few tests were updated to reflect SILGen's improved code
generation, and some new tests are added to cover more code paths
that previously were uncovered and only manifested themselves as
standard library build failures while I was working on this change.
unknown symbolic values by renaming some diagnostics and
creating new unknown reasons for each type of failure that
can happen during constant evaluation.
(also referred to as flow-sensitive mode) so that the evaluator
can be used by clients to constant evaluate instructions in a
SILFunction body one by one following the flow of control.
A prespecialized function may reference a non-public stdlib
symbols. Force link the function body when it is
specialized. Normally, the SILLinker does this, but it cannot see
through the prespecialize proxy function.
All symbols that must be prespecialized are now explicitly
requested. There's no accidental prespecialization, so there's no need
for special logic to adjust the specialized function linkage. Remove
all of that.