On Tue, 17 Feb 2015, Richard Earnshaw wrote:
So the problem we have today is the compiler has no way to distinguish
between, say, < and __builtin_isless. According to Annex F (c99) the
former should be signalling while the latter quiet.
We do have a way: < is LT and __builtin_isless is !UNGE.
__builtin_islessgreater is !UNEQ. The question is whether it's also LTGT
or whether LTGT means LT || GT. And the existing documentation of
LTGT_EXPR leaves this unspecified, which seems clearly unhelpful. Either
way, you have existing code in GCC that's incorrect (i.e. that does not
correspond to the set of transformations that are actually valid for the
chosen semantics).
I suspect there are two ways we could deal with that: add new comparison
RTL codes to distinguish the cases; or use something like the RTL /v bit
on a comparison to indicate that it should be signalling.
Of the two, the latter would probably be easiest to implement in a
backwards compatible manner (backends not understanding /v would
continue to use their existing code paths), but it would still take a
fair amount of rejigging in the mid end to fully preserve the signalling
nature of comparisons: there are many places where just RTX_CODE is
available and a new pattern is generated from that. The first method
would require all back-ends to be updated pretty much simultaneously to
handle the new RTL codes.
I don't know the optimal way of representing these variants in GENERIC,
GIMPLE and RTL (the existing representation can cover everything, and is
unambiguous apart from LTGT, but may not be optimal).
I think the main difficulty in proper Annex F support would be making
optimizers (on each IR) understand the side-effects operations have in
terms of raising exceptions, and how operations may take the rounding mode
or existing exceptions raised as inputs - with an associated issue of
defining the existing default floating-point rules well enough to keep a
default mode that doesn't unduly inhibit optimization.