FENV_ACCESS status

Richard Biener richard.guenther@gmail.com
Fri Aug 7 09:19:08 GMT 2020


On Wed, Aug 5, 2020 at 8:02 PM Marc Glisse <marc.glisse@inria.fr> wrote:
>
> Hello,
>
> I updated the patch discussed in
> https://patchwork.ozlabs.org/project/gcc/patch/alpine.DEB.2.02.1906221743430.16432@grove.saclay.inria.fr/
> and pushed it as something like refs/users/glisse/heads/fenv (first user
> branch in gcc's git, I hope it worked). I am also attaching the diff here.
>
> I managed to compile and run real-world code with it, which is a good sign
> :-)
>
> As should be obvious looking at the diff, there is a lot of work left.
> Experts may also find much better ways to rewrite several parts of the
> patch.
>
> The option is called -ffenv-access so it doesn't interfere with
> -frounding-math, at least until we have something good enough to replace
> -frounding-math without too much performance regression.
>
> I switched to hex float constants for DBL_MAX and others for C99+, I don't
> care about making fenv_access work in prehistoric modes. On the other
> hand, since I haven't started on fenv_round, this is probably useless for
> now.
>
> Several changes, in particular the constexpr stuff, was needed to parse
> standard headers, otherwise I would have delayed the implementation.
>
> Currently the floating point environment is represented by "memory" in
> general. Refining it so the compiler knows that storing a float does not
> change the rounding mode (for instance) should wait, in my opinion.
>
> Conversions look like
> .FENV_CONVERT (arg, (target_type*)0, 0)
> the pointer is there so we know the target type, even if the lhs
> disappears at some point. The last 0 is the same as for all the others, a
> place to store options about the operation (do we care about rounding,
> about exceptions, etc), it is just a placeholder for now. I could rename
> it to .FENV_NOP since we seem to generate NOP usually, but it looked
> strange to me.

You could carry the info in the existing flags operand if you make that a
pointer ...

> I did not do anything for templates in C++. As long as we have a constant
> global flag, it doesn't matter, but as soon as we will have a pragma,
> things will get messy, we will need to remember what the mode was when
> parsing, so we can use it at instantiation time... (or just declare that
> the pragma doesn't work with templates in a first version)
>
> I am trying to have enough infrastructure in place so that the
> functionality is useful, and also so that implementing other pieces
> (parsing the pragma, C front-end, gimple optimizations, target hook for
> the asm string, opcode and target optimization, simd, etc) become
> independent and can be done by different people. It is unlikely that I can
> find the time to do everything. If other people want to contribute or even
> take over (assuming the branch does not look hopelessly bad to them), that
> would be great! That's also why I pushed it as a branch.
>
> Apart from the obvious (making sure it bootstraps, running the testsuite,
> adding a few tests), what missing pieces do you consider a strict
> requirement for this to have a chance to reach master one day as an
> experimental option?

Adding some info missing above from reading the patch.

The idea seems to be to turn FP operations like PLUS_EXPR, FLOAT_EXPR
but also (only?) calls to BUILT_IN_SQRT to internal functions named
IFN_FENV_* where the internal function presumably has some extra
information.

You have

+/* float operations with rounding / exception flags.  */
+DEF_INTERNAL_FN (FENV_PLUS, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (FENV_MINUS, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (FENV_MULT, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (FENV_RDIV, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (FENV_FLOAT, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (FENV_CONVERT, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (FENV_SQRT, ECF_LEAF | ECF_NOTHROW, NULL)

so with -fnon-call-exceptions they will not be throwing (but regular
FP PLUS_EXPR
would).  They will appear to alter memory state - that's probably to have the
extra dependence on FENV changing/querying operations but then why do you
still need to emit asm()s?

I suppose the (currently unused) flags parameter could be populated with
some known FP ENV state and then limited optimization across stmts
with the same non-zero state could be done?

Using internal function calls paints us a bit into a corner since they are still
subject to the single-SSA def restriction in case we'd want to make FENV
dataflow more explicit.  What's the advantage of internal functions compared
to using asms for the operations themselves if we wrap this class into
a set of "nicer" helpers?

One complication with tracking data-flow is "unknown" stuff, I'd suggest
to invent a mediator between memory state and FP state which would
semantically be load and store operations of the FP state from/to memory.

That said, you're the one doing the work and going with internal functions
is reasonable - I'm not sure to what extent optimization for FENV acccess
code will ever be possible (or wanted/expected).  So going more precise
might not have any advantage.

You needed to guard SQRT - will you need to guard other math functions?
(round, etc.)

If we need to keep the IFNs use memory state they will count towards
walk limits of the alias oracle even if they can be disambiguated against.
This will affect both compile-time and optimizations.

+  /* Careful not to end up with something like X - X, which could get
+     simplified.  */
+  if (!skip0 && already_protected (op1))

we're already relying on RTL not optimizing (x + 0.5) - 0.5 but since
that would involve association the simple X - X case might indeed
be optimized (but wouldn't that be a bug if it is not correct?)

Thanks,
Richard.

> --
> Marc Glisse


More information about the Gcc-patches mailing list