I’ve had this idea floating around my head for a little while, and I’m not sure
if it’s either really interesting or totally absurd.
Sorry if it’s not time for ideas like this yet. It’s not really a “proposal”,
but it would be ABI-related I think.
So, the idea: The compiler can generate variations of functions where it
statically substitutes a type for a placeholder name. Would it also be possible
to statically generate a variation of a function if a parameter is a certain
value?
I have some code which scans a sequence of bytes. The bytes may be in UTF-8,
UTF-16 or UTF-32, and any endianness flavour thereof. Fortunately, the scanner
is looking for a ASCII-compatible characters which have the same value (albeit
a different size) in each encoding, so this can be implemented as a generic
function based on the type of the CodeUnit (UInt8/16/32 respectively).
Something roughly like this:
> @_specialize(UInt8)
> @_specialize(UInt16)
> @_specialize(UInt32)
> func scanCharacters<U:UnsignedInteger>(from bytes: [UInt8],
> hasMismatchedEndianness: Bool) -> ... {
>
> var byteIterator = bytes.makeIterator()
> while let nextByte = byteIterator.next() {
>
> var codeUnit : U
> // The compiler will statically optimise this branching away
> because generics.
> if size(of: U.self) == 1 {
> codeUnit = numericCast(nextByte)
> }
> else {
> codeUnit = consumeCodeUnit(withInitialByte: nextByte,
> source: byteIterator)
> // Even when marking this _slowPath(), there is a
> significant overhead.
> if hasMismatchedEndianness {
> codeUnit = codeUnit.byteSwapped
> }
> }
>
> // Process the code-unit
> }
> }
However, we still have a problem with this endianness flag. All it requires is
that after we consume an entire CodeUnit from the buffer, that we byte-swap it
before checking its value. I don’t want to duplicate the entire function code
to deal with this one variation in parameter value, but this is a very hot
code-path and the branching overhead is significant.
So I would like to tell the compiler that we branch a lot on
`hasMismatchedEndianness`, so it can generate and optimise variations of the
function while keeping the abstraction level high and the maintenance burden
low. There are lots of contexts where this could be useful - not just your
typical Boolean switches, but Optionals, too. Even general value-types with
specific values that are heavily branched against could benefit from these
kinds of optimisations.
Thoughts? Would something like this be possible/valuable?
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution