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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to