Changes:
* Allow optimizing partial_apply capturing opened existential: we didn't do this originally because it was complicated to insert the required alloc/dealloc_stack instructions at the right places. Now we have the StackNesting utility, which makes this easier.
* Support indirect-in parameters. Not super important, but why not? It's also easy to do with the StackNesting utility.
* Share code between dead closure elimination and the apply(partial_apply) optimization. It's a bit of refactoring and allowed to eliminate some code which is not used anymore.
* Fix an ownership problem: We inserted copies of partial_apply arguments _after_ the partial_apply (which consumes the arguments).
* When replacing an apply(partial_apply) -> apply and the partial_apply becomes dead, avoid inserting copies of the arguments twice.
These changes don't have any immediate effect on our current benchmarks, but will allow eliminating curry thunks for existentials.
Otherwise the code as written miscompiles code like:
```
@inline(never)
func consumeSelf<T>(_ t : __owned T) {
print("Consuming self!")
print(t)
}
class Klass {}
struct S<T> {
let t: T? = (Klass() as! T)
@inline(__always)
__consuming func foo(_ t: T) {
consumeSelf(self)
}
}
public func test<T>(_ t: __owned T) {
let k = S<T>()
let f = k.foo
for _ in 0..<1024 {
f(t)
}
}
test(Klass())
```
As one can tell, without annotations it is hard to create an example like the
above, but there is no reason why we couldn't emit more code like this from the
frontend.
If the parameter is guaranteed though, the current impl is fine for
@in_guaranteed since in the loop, we do not need to retain or release the
value.
rdar://58885352
We generally do not use a for loop for worklist iteration since one runs into
weird issues around always needing to recompute the worklist size since it may
change per iteration. In contrast, using the while loop approach that just pops
off the back avoids such implicit weirdness.
Specifically:
1. I converted a bunch of cases where we were emitting releases/unqualified
loads to use instead the *Operation commands that work in both modes.
2. I renamed some methods/variables that referred to releases to instead refer
to destroys.