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

Reply via email to