[Pitch] Modernize imported C arrays

Couldn't we document this guarantee, with a note that it currently does not hold because of a bug?

By the same token, I don't think there is any need to change the 4096-element limit.

Separately, an array of 4096 elements at 1024 bytes each could overflow a small stack, while an array of 16K one-byte elements might be perfectly fine. Perhaps the limit should be based on the array's total size rather than its element count.

I did some poking around and I think the deal is this:

Small InlineArrays (maybe like four elements; I suspect this is specific to the calling convention and element type) are passed with each element in a separate register, while larger InlineArrays are passed as a single pointer. If you want to dynamically index into a small InlineArray, it’s necessary to copy the elements onto the stack so the compiler can index into them by adding the index to a base pointer. However, Swift also copies large InlineArrays to the stack in this situation, even though it could just use the pointer it already has as the base pointer.

In the large array scenario, the copy is totally unnecessary and eliminating it should probably be a minor bug fix. The copy is necessary for small arrays, but by definition that only happens with arrays where the copy is cheap to create and probably won’t be a significant factor in the time complexity of the operation.

9 Likes

Doesn't this violate the documented guarantees of InlineArray? Under Memory Layout, it states:

An InlineArray stores its elements contiguously. If an InlineArray is a stored property of a class, then it’s allocated on the heap along with the other stored properties of the class. Otherwise, in general, an InlineArray is allocated on the stack.

"[I]n general" is doing some heavy lifting here. I suppose there's an argument that could be made here about how the contiguity of the elements isn't materialized until it can actually be observed, but even for small arrays this behavior feels like an unnecessary performance concern.

1 Like

Not to speak for Becca, but register promotion occurs for all (small) value types in Swift, and is not observable by Swift code in practice, so it ought to be allowed under the Swift version of the "as if" rule.

7 Likes

Yeah, happens in C too: Compiler Explorer.

(An example showing that a C struct containing an "inline array" of two floats struct ofTwoFloats { float a[2]; } is passed in register on x86_64).

4 Likes

I have been waiting for that, thank you and please carry on!

1 Like

Yes, that is sometimes true in 6.4. The optimizer folks are working to resolve that.

3 Likes