> On Oct 20, 2016, at 10:45 AM, John McCall <rjmcc...@apple.com> wrote:
> 
>> On Oct 19, 2016, at 8:42 PM, Joe Groff via swift-dev <swift-dev@swift.org> 
>> wrote:
>> I had a discussion with Steve this morning about the potential for enum 
>> layout optimization with floating-point payloads. One great thing about 
>> floating-point is that it has NaNs, and lots of them. For the most part, the 
>> only significant semantic difference among these NaNs is whether they're 
>> signaling or not, so it's tempting to reclaim some of these representations 
>> for other purposes. Javascript engines are of course famous for 
>> "NaN-encoding" values, representing JS numbers as native Doubles and packing 
>> pointers to non-number object instances into the same representation by 
>> using NaN bit patterns. In Swift, we could do similar things for enums with 
>> floating-point payloads, making 'Float?' and 'Double?' take the same amount 
>> of space as non-optionals, and automatically applying Javascript-style 
>> layout optimizations when defining enums with mixed float and object 
>> payloads. IEEE 754 is ambivalent about the role of NaN payloads, and there 
>> are libraries that use payloads for interesting diagnostic purposes, but the 
>> standard declares up front that it "does not interpret the sign of a NaN" 
>> (section 6.3). Reserving "negative" NaNs with the sign bit set as extra 
>> inhabitants could let us do enum layout optimization without interfering 
>> with the ability for libraries to freely use NaN payloads.
>> 
>> However, the way we usually handle enum optimization with extra inhabitants 
>> is problematic for floats. We normally say that it is undefined behavior for 
>> a value to have an extra inhabitant representation—a class reference cannot 
>> be null, a Bool can only be 0 or 1, and so on. With floats, we need to 
>> interoperate with numerics code not written in Swift, and we want to be able 
>> to read floating-point data out of memory that may use arbitrary bit 
>> patterns. We don't want every double-returning C function or load from 
>> memory to require a check for reserved values afterward. Making it undefined 
>> behavior for floats to have "extra inhabitant" representations is thus 
>> probably not practical.
>> 
>> Instead of saying that extra inhabitants are undefined behavior, we could 
>> instead continue to allow Floats and Doubles to have arbitrary bit patterns, 
>> and only check for reserved values at the point we construct an enum that 
>> wants to use reserved values for layout. If we reserve negative NaNs, then 
>> for example, constructing a Float? or Double? from a nonoptional value would 
>> check whether the payload value is NaN and if so, clear the sign bit at that 
>> point. That way, we don't have any ABI problems with Floats and Doubles from 
>> foreign sources, but still get the benefits of layout optimization for Swift 
>> types. On the other hand, this would mean that supposedly-idempotent 
>> operations like '.some(x)!' lose the sign information for NaNs. Since we 
>> wouldn't want to prevent the optimizer from folding those kinds of 
>> operations away, we could define Swift's semantics to say that querying the 
>> sign of a NaN value produces an unspecified value. This matches the intent 
>> of IEEE 754, and shouldn't impact most numerics code in practice. If we were 
>> interested in pursuing enum layout optimization with float payloads, I think 
>> this would be the best approach.
> 
> As an implementation matter, is this going to significantly complicate the 
> "make a T? from an unknown T" path?  Currently, I think that logic just asks 
> whether a type has extra inhabitants; it doesn't have any notion of having to 
> rewrite actual values to avoid colliding with the "extra" inhabitants.

It's true that it would no longer be a guaranteed identity operation, but we 
already have the notion of "inject tag" in the abstract access pattern for 
enums, which occurs after the payload has been stored, which normally sets the 
extra tag bits. It seems to me we could also use it to collapse NaN 
representations when the "some" tag is injected over a float (though we would 
need a "evacuateExtraInhabitantRepresentations" value witness to do this 
generically).

-Joe
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to