Weirdness With Inout Optimizations

This article got posted to reddit the other day, and during a discussion in the comments about the semantics of inout he posted a benchmark with a really weird optimization miss.

The important part is this:

// Doesn't optimize.
func fx(_ allints: inout [Int],  _ j : inout Int) {
      for k in allints.indices {
        allints[k] = j
        j &+= 1
      }
 }

// Does optimize.
 func f(_ allints: inout [Int],  _ i : inout Int) {
      var j = i
      for k in allints.indices {
        allints[k] = j
        j &+= 1
      }
      i = j
 }

An inout variable is supposed to be semantically equivalent to copying the value of the parameter to a local when the function starts and copying the value back out when the function ends. But in this case the compiler doesn't seem to optimize the function unless the copying is done manually.

I've run the benchmark, and confirmed that this happens on Apple Swift version 5.0, but I don't have the Xcode beta installed to see if it's already been fixed in 5.1. So, I was wondering if someone could confirm that this bug still exists before I report it.

This is a performance opportunity. It is worthy of a bug report. Thanks!

1 Like

Can you add this as a benchmark to the benchmark suite?

Reported as SR-11452.

How does one go about adding a benchmark to the suite?

Adding a benchmark:

Editing in Xcode:

And let me elaborate slightly more on this:

  1. I would follow those instructions above. Create the PR as you normally would and we will run a special test that makes sure that the test is wired up correctly and also that it maintains certain invariants.
  2. The reason why I suggest strongly when we have these weird results to add benchmarks is that it ensures that the project has a nice reproducer and prioritizes it. Without the benchmark as an example there is always the possibility that engineering time will be spent on other benchmarks rather than the ones that one may care about [like this one] ; ).