On Sat, 22 Jun 2019, Richard Biener wrote:
On June 22, 2019 6:10:15 PM GMT+02:00, Marc Glisse <marc.gli...@inria.fr> wrote:
Hello,
as discussed in the PR, this seems like a simple enough approach to
handle
FENV functionality safely, while keeping it possible to implement
optimizations in the future.
Some key missing things:
- handle C, not just C++ (I don't care, but some people probably do)
As you tackle C++, what does the standard say to constexpr contexts and
FENV? That is, what's the FP environment at compiler - time (I suppose
FENV modifying functions are not constexpr declared).
The C++ standard doesn't care much about fenv:
[Note: This document does not require an implementation to support the
FENV_ACCESS pragma; it is implementation-defined (15.8) whether the pragma
is supported. As a consequence, it is implementation- defined whether
these functions can be used to test floating-point status flags, set
floating-point control modes, or run under non-default mode settings. If
the pragma is used to enable control over the floating-point environment,
this document does not specify the effect on floating-point evaluation in
constant expressions. — end note]
We should care about the C standard, and do whatever makes sense for C++
without expecting the C++ standard to tell us exactly what that is. We can
check what visual studio and intel do, but we don't have to follow them.
-frounding-math is supposed to be equivalent to "#pragma stdc fenv_access
on" covering the whole program.
For constant expressions, I see a difference between
constexpr double third = 1. / 3.;
which really needs to be done at compile time, and
const double third = 1. / 3.;
which will try to evaluate the rhs as constexpr, but where the program is
still valid if that fails. The second one clearly should refuse to be
evaluated at compile time if we are specifying a dynamic rounding
direction. For the first one, I am not sure. I guess you should only write
that in "fenv_access off" regions and I wouldn't mind a compile error.
Note that C2x adds a pragma fenv_round that specifies a rounding direction
for a region of code, which seems relevant for constant expressions. That
pragma looks hard, but maybe some pieces would be nice to add.
- handle vectors (for complex, I don't know what it means)
Then flag_trapping_math should also enable this path, meaning that we
should stop making it the default, or performance will suffer.
Do we need N variants of the functions to really encode FP options into
the IL and thus allow inlining of say different signed-zero flag
functions?
Not sure what you are suggesting. I am essentially creating a new
tree_code (well, an internal function) for an addition-like function that
actually reads/writes memory, so it should be orthogonal to inlining, and
only the front-end should care about -frounding-math. I didn't think about
the interaction with signed-zero. Ah, you mean
IFN_FENV_ADD_WITH_ROUNDING_AND_SIGNED_ZEROS, etc? The ones I am starting
from are supposed to be safe-for-everything. As refinement, I was thinking
in 2 directions:
* add a third constant argument, where we can specify extra info
* add a variant for the case where the function is pure (because I expect
that's easier on the compiler than "pure if (arg3 & 8) != 0")
I am not sure more variants are needed.
Also, while rounding clearly applies to an operation, signed-zero kind of
seems to apply to a variable, and in an operation, I don't really know if
it means that I can pretend that an argument of -0. is +0. (I can return
+inf for 1/-0.) or if it means I can return 0. when the operation should
return -0.. Probably both... If we have just -fsigned-zeros but no
rounding or trapping, the penalty of using an IFN would be bad. But indeed
inlining functions with different -f(no-)signed-zeros forces to use
-fsigned-zeros for the whole merged function if we don't encode it in the
operations. Hmm
I didn't look at the patch but I suppose you rely on RTL to not do code
motion across FENV modifications and not fold Constants?
No, I rely on asm volatile to prevent that, as in your recent hack, except
that the asm only appears near expansion. I am trying to start from
something safe and refine with optimizations, no subtlety.
That is, don't we really need unspec_volatile variant patterns for the
Operations?
Yes. One future optimization (that I listed in the PR) is to let targets
expand those IFN as they like (without the asm barriers), using some
unspec_volatile. I hope we can get there, although just letting targets
replace "=g" with whatever in the asm would already get most of the
benefits.
I just thought of one issue for vector intrinsics, say _mm_add_pd, where
the fenv_access status that should matter is that of the caller, not the
one in emmintrin.h. But since I don't have the pragma or vectors, that can
wait.
--
Marc Glisse