Commit Graph

8 Commits

Author SHA1 Message Date
Erik Eckstein
85789367a3 SILOptimizer: restructure the apply(partial_apply) peephole and the dead partial_apply elimination optimizations
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.
2020-02-11 12:48:39 +01:00
Michael Gottesman
e5aaa68b52 [sil] Do not eliminate (apply (partial_apply)) if the partial_apply captures an @in parameter and handle @in_guaranteed appropriately.
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
2020-02-04 14:20:58 -08:00
Michael Gottesman
f30b2c9b9f [pa-combiner] Change worklist iteration to use a more canonical worklist form.
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.
2019-12-13 13:31:15 -08:00
Michael Gottesman
89ff110c0d [pa-combiner] Use llvm::any_of instead of a for loop. 2019-12-13 13:31:15 -08:00
Michael Gottesman
5acb59aea4 [pa-combiner] Simplify some cleanup code by using FullApplySite::insertAfterFullInvocation. 2019-12-13 12:51:04 -08:00
Michael Gottesman
e4e48e81f1 [pa-combiner] Modernize some appending code to use a range instead of iterators. NFC. 2019-12-12 09:52:28 -08:00
Michael Gottesman
0d88ff1432 [pa-combiner] Some further updates for supporting ossa.
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.
2019-12-12 09:52:28 -08:00
Michael Gottesman
113c22a680 [sil] Move partial apply combiner code from SILCombiner into InstOptUtils.h/SILCombinerApplyVisitor.cpp.
This is in preparation for moving this into the mandatory combiner.
2019-12-11 14:48:19 -08:00