[SR-12222] No safe way to performantly zero-extend an Array #54648
Labels
bug
A deviation from expected or documented behavior. Also: expected but undesirable behavior.
standard library
Area: Standard library umbrella
Environment
Apple Swift version 5.2 (swiftlang-1103.0.24.3 clang-1103.0.30.1)
Target: x86_64-apple-darwin19.4.0
Additional Detail from JIRA
md5: dd5e30591fa50bc140e23288fa911137
Issue Description:
Related to SR-12221.
Sometimes I have situations where I want to zero-extend an Array. This is usually done to bring a whole bunch of indices into existence and make them valid at once. One case where I might do that is when I want to express a safe memmove (hence the relationship to SR-12221), which requires that all indices used be valid.
I am happy enough to pay the price of initialising this memory in this case, as it's usually not too much memory I have to initialise. Right now, there are three obvious ways to do this on Array (using
Array<UInt8>
for clarity), shown below and in a compiler explorer page:All three of these generate suboptimal code.
The first two generate monstrously large chunks of code.
repeatElement
is the baseline: it generates an enormous amount of code, which would be acceptable if it was vectorised, but it degrades to a byte-by-byte copy: the compiler is not able to constant-propagate the zero byte through and observe that there is no need to do this byte wise. The Array based one avoids the byte wise operation, but has to initialise each byte twice: once withbzero
to create the new array, and then again when those bytes are {{memcpy}}d into the target.Option 3 is in most ways the best. It generates much smaller code, and the compiler would almost be able vectorise it, except that the quadratic growth of
Array
stymies it. Each byte must be checked to confirm that theArray
has space, otherwise a resizing operation occurs. This also slows this down, and in cases where the array started out empty we'll get a fairly large number of resizing operations.It's very unfortunate that there is no good way to rapidly extend a collection with a single element. We can construct new ones this way: just not extend old ones. It would be very helpful to have some way for a type to express that it can safely be rapidly extended like this.
The text was updated successfully, but these errors were encountered: