Add a new mandatory BooleanLiteralFolding pass which constant folds conditional branches with boolean literals as operands.
```
%1 = integer_literal -1
%2 = apply %bool_init(%1) // Bool.init(_builtinBooleanLiteral:)
%3 = struct_extract %2, #Bool._value
cond_br %3, bb1, bb2
```
->
```
...
br bb1
```
This pass is intended to run before DefiniteInitialization, where mandatory inlining and constant folding didn't run, yet (which would perform this kind of optimization).
This optimization is required to let DefiniteInitialization handle boolean literals correctly.
For example in infinite loops:
```
init() {
while true { // DI need to know that there is no loop exit from this while-statement
if some_condition {
member_field = init_value
break
}
}
}
```
```
let c = SomeClass()
```
is turned into
```
private let outlinedVariable = SomeClass() // statically initialized and allocated in the data section
let c = outlinedVariable
```
rdar://111021230
rdar://115502043
Also, make the ObjectOutliner work for OSSA. Though, it currently doesn't run in the OSSA pipeline.
It notifies the pass manager that the optimization result of the current pass depends on the body (i.e. SIL instructions) of another function than the currently optimized one.
Optionally, the dependency to the initialization of the global can be specified with a dependency token `depends_on <token>`.
This is usually a `builtin "once"` which calls the initializer for the global variable.
An instruction is a deinit barrier whenever one of three component
predicates is true for it. In the case of applies, it is true whenever
one of those three predicates is true for any of the instructions in any
of its callees; that fact is cached in the side-effect analysis of every
function.
If side-effect analysis or callee analysis is unavailable, in order to
define each of those three component predicates on a
`FullApplySite`/`EndApplyInst`/`AbortApplyInst`, it would be necessary
to define them to conservatively return true: it isn't known whether any
of the instructions in any of the callees were deinit barriers.
Refactored the two versions of the deinit barrier predicate (namely
`Instruction.isDeinitBarrier(_:) and
`swift::mayBeDeinitBarrierNotConsideringSideEffects`) to handle
`FullApplySite`/`EndApplyInst`/`AbortApplyInst`s specially first (to
look up the callees' side-effect and to conservatively bail,
respectively). Asserted that the three component predicates are not
called with `FullApplySite`/`EndApplyInst`/`AbortApplyInst`s. Callers
should instead use the `isDeinitBarrier` APIs.
An alternative would be to conservatively return true from the three
components. That seems more likely to result in direct calls to these
member predicates, however, and at the moment at least there is no
reason for such calls to exist. If some other caller besides the
deinit-barrier predicates needs to call this function, side-effect
analysis should be updated to cache these three properties separately at
that point.
Layers:
- FunctionConvention: AST FunctionType: results, parameters
- ArgumentConventions: SIL function arguments
- ApplyOperandConventions: applied operands
The meaning of an integer index is determined by the collection
type. All the mapping between the various indices (results,
parameters, SIL argument, applied arguments) is restricted to the
collection type that owns that mapping. Remove the concept of a
"caller argument index".
The previous implementation just checked that a value's only uses besides the begin_borrow were destroys. That's insufficient to say the value is destroyed after the borrow (i.e. that all its destroys are dominated by the borrow). Add the relevant dominance check.
Fixes a compiler crash
rdar://119873930
Even if the destroyed value doesn't have a deinit.
This fixes a false alarm when a non-copyable value ends its lifetime in a function with performance annotations.
rdar://117002721
By default it lowers the builtin to an `alloc_vector` with a paired `dealloc_stack`.
If the builtin appears in the initializer of a global variable and the vector elements are initialized,
a statically initialized global is created where the initializer is a `vector` instruction.
This flag is important for following optimizations. Therefore such `end_cow_mutation` instructions must not be removed.
Also, keep the flag in a SILCombine transformation.
rdar://119178823
Make it clear that drop_deinit cannot be used to prevent a deinit called from a destroy_addr.
This is more a refactoring and clarification than a bug fix, because a destroy_addr cannot have a drop_deinit as operand, anyway.
In regular swift this is a nice optimization. In embedded swift it's a requirement, because the compiler needs to be able to specialize generic deinits of non-copyable types.
The new de-virtualization utilities are called from two places:
* from the new DeinitDevirtualizer pass. It replaces the old MoveOnlyDeinitDevirtualization, which is very basic and does not fulfill the needs for embedded swift.
* from MandatoryPerformanceOptimizations for embedded swift
* add `NominalTypeDecl.isResilient`
* make the return type of `Type.getNominalFields` optional and return nil in case the nominal type is resilient.
This forces users of this API to think about what to do in case the nominal type is resilient.
A transformation must not create a `struct` instruction with a non-copyable type because this would apply that a (potential) deinit would be called for that struct.
ASTGen always builds with the host Swift compiler, without requiring
bootstrapping, and is enabled in more places. Move the regex literal
parsing logic there so it is enabled in more host environments, and
makes use of CMake's Swift support. Enable all of the regex literal
tests when ASTGen is built, to ensure everything is working.
Remove the "AST" and "Parse" Swift modules from SwiftCompilerSources,
because they are no longer needed.
Try to replace a begin_borrow with its owned operand.
This is either possible if the borrowed value (or a forwarded value if it) is copied:
```
%1 = begin_borrow %0
%2 = struct_extract %1 // a chain of forwarding instructions
%3 = copy_value %1
// ... uses of %3
end_borrow %1
```
->
```
%1 = copy_value %0
%3 = destructure_struct %0 // owned version of the forwarding instructions
// ... uses of %3
```
Or if the borrowed value is destroyed immediately after the borrow scope:
```
%1 = begin_borrow %0
%2 = struct_extract %1 // a chain of forwarding instructions
// ... uses of %2
end_borrow %1
destroy_value %1 // the only other use of %0 beside begin_borrow
```
->
```
%2 = destructure_struct %0 // owned version of the forwarding instructions
// ... uses of %2
destroy_value %2
```