This is an archive of the discontinued LLVM Phabricator instance.

[Clang][DOC] Add documentation in for __builtin_flt_rounds and __builtin_set_flt_rounds
ClosedPublic

Authored by xiongji90 on Mar 15 2023, 8:08 PM.

Details

Summary

This patch aims to add necessary description for builtin_flt_rounds and builtins_set_flt_rounds in LanguageExtensions.rst

Diff Detail

Event Timeline

xiongji90 created this revision.Mar 15 2023, 8:08 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 15 2023, 8:08 PM
xiongji90 requested review of this revision.Mar 15 2023, 8:08 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 15 2023, 8:09 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
sepavloff added inline comments.Mar 15 2023, 9:09 PM
clang/docs/LanguageExtensions.rst
3293

If some other target start supporting llvm.set_rounding this statement becomes wrong. Maybe just 'some targets'?

3295

Not necessary. Options -ffp-model=strict or -frounding-math also can be used. I would remove this statement.

rjmccall added inline comments.Mar 16 2023, 12:28 AM
clang/docs/LanguageExtensions.rst
3283

"Sets the current floating-point rounding mode. The parameter uses the same values specified for `FLT_ROUNDS` by the C standard:
...
The effect of passing some other value to this builtin is implementation-defined."

3293

The manual should document when a specific builtin is restricted to specific targets. If someone adds support for the builtin on new targets, they should update the manual. Think about it from a user's perspective: they should be able to check what targets support this builtin without having to figure out that the builtin turns into a specific intrinsic and then crawl around in the LLVM source code to figure out which targets implement that intrinsic.

With that said, please do not refer to LLVM-level details in the Clang documentation. Users shouldn't have to care that the builtin is lowered to such-and-such LLVM intrinsic. Even if they did, that's not a hard guarantee we want to make anyway — we document high-level semantics, not the fine details of the intermediate representation coming out of the frontend.

Also, please do not cross-reference the LLVM documentation. The Clang documentation is user-facing and has a much, much wider potential audience than the LLVM documentation, which is focused on implementors. People should be able to use the compiler without worrying about backend details. If we have to repeat some information between the two places, that's fine.

3295

It is appropriate to at least say that not all modes permit changing the default floating-point environment and cross-reference the appropriate place in the Clang documentation where we talk about that in more detail. If we don't have such a place already, this is the time to add it.

xiongji90 updated this revision to Diff 506460.Mar 19 2023, 8:51 PM
xiongji90 marked 2 inline comments as done.
xiongji90 added inline comments.Mar 19 2023, 8:56 PM
clang/docs/LanguageExtensions.rst
3295

Hi, @rjmccall and @sepavloff
I removed the statement that requiring to add "#pragma stdc fenv access", I checked the doc that there has not been any description about default fp environment, do you mean we need to add such description first and cross-reference it here?
Thanks very much.

rjmccall added inline comments.Mar 19 2023, 9:30 PM
clang/docs/LanguageExtensions.rst
3271

This comment belongs with the other builtin. I would suggest just combining these two into one section, though, like:

``__builtin_flt_rounds`` and ``__builtin_set_flt_rounds``
---------------------------------------------------------

That way you don't have to describe the options twice.

Make sure you clarify that the target restrictions only applies to __builtin_set_flt_rounds.

3280
3287
rjmccall added inline comments.Mar 19 2023, 10:20 PM
clang/docs/LanguageExtensions.rst
3288

This meta-commentary about when to update the manual should not go into the manual.

I'm going to insist that we talk about `#pragma STDC FENV_ACCESS` here. It would be inappropriate not to, given that it's undefined behavior to use this without also using the pragma or one of those flags. We should not be documenting features with non-obvious UB without warning.

How about:

By default, these builtins may not be used.  The floating point rounding mode is part of the floating point environment, and it is undefined behavior to read or modify the floating point environment, or to run code under a non-default floating point environment, unless that code is compiled under a special mode.  Clang supports three well-defined ways to control the rounding mode of floating point operations:

- The standard pragma ``#pragma STDC FENV_ROUND <mode>`` can change the rounding mode to a specific value for the operations covered by the pragma.  This does not permit dynamic access to the rounding mode, but in many cases it is sufficient to achieve the desired effect, and it is more optimizable than the alternatives below.

- The standard pragma ``#pragma STDC FENV_ROUND FE_DYNAMIC`` allows dynamic access to the floating point rounding mode (including by these builtins) in code covered by the pragma.  The command line option ``-frounding-math`` behaves as if the translation unit began with this pragma.  This pragma does not allow changes to the floating point exceptions mode and so may be more optimizable than the next alternative.

- The standard pragma ``#pragma STDC FENV_ACCESS ON`` allows dynamic access to the entire floating point environment (including by these builtins) in code covered by the pragma.  The command line option ``-ffp-model=strict`` behaves as if the translation unit began with this pragma.

Code that modifies the floating point rounding mode dynamically must take care to reset it to the default mode before returning control to code that is not compiled under one of these last two pragmas.  See the C standard for more information about these pragmas.

Serge, please fact-check all that.

Combine description of builtin_flt_rounds and builtin_set_flt_rounds

xiongji90 marked 4 inline comments as done.Mar 19 2023, 11:37 PM
xiongji90 added inline comments.Mar 20 2023, 11:47 PM
clang/docs/LanguageExtensions.rst
3288

This meta-commentary about when to update the manual should not go into the manual.

I'm going to insist that we talk about `#pragma STDC FENV_ACCESS` here. It would be inappropriate not to, given that it's undefined behavior to use this without also using the pragma or one of those flags. We should not be documenting features with non-obvious UB without warning.

How about:

By default, these builtins may not be used.  The floating point rounding mode is part of the floating point environment, and it is undefined behavior to read or modify the floating point environment, or to run code under a non-default floating point environment, unless that code is compiled under a special mode.  Clang supports three well-defined ways to control the rounding mode of floating point operations:

- The standard pragma ``#pragma STDC FENV_ROUND <mode>`` can change the rounding mode to a specific value for the operations covered by the pragma.  This does not permit dynamic access to the rounding mode, but in many cases it is sufficient to achieve the desired effect, and it is more optimizable than the alternatives below.

- The standard pragma ``#pragma STDC FENV_ROUND FE_DYNAMIC`` allows dynamic access to the floating point rounding mode (including by these builtins) in code covered by the pragma.  The command line option ``-frounding-math`` behaves as if the translation unit began with this pragma.  This pragma does not allow changes to the floating point exceptions mode and so may be more optimizable than the next alternative.

- The standard pragma ``#pragma STDC FENV_ACCESS ON`` allows dynamic access to the entire floating point environment (including by these builtins) in code covered by the pragma.  The command line option ``-ffp-model=strict`` behaves as if the translation unit began with this pragma.

Code that modifies the floating point rounding mode dynamically must take care to reset it to the default mode before returning control to code that is not compiled under one of these last two pragmas.  See the C standard for more information about these pragmas.

Serge, please fact-check all that.

Hi, @sepavloff
Could you provide your insight here?
Thanks very much.

sepavloff added inline comments.Mar 21 2023, 5:00 AM
clang/docs/LanguageExtensions.rst
3288

Such note is useful for any function that operates floating-point environment. It makes sense to put such functions to a separate section, like Floating-point environment access or something similar. Now only __builtin_flt_rounds and __builtin_set_flt_rounds are here but other builtins like fesetmode, fesetenv and similar can appear later on. At the beginning of this section the explanation about FP environment is quite useful.

By default, these builtins may not be used.  The floating point rounding mode is part of the floating point environment, and it is undefined behavior to read or modify the floating point environment, or to run code under a non-default floating point environment, unless that code is compiled under a special mode.  Clang supports three well-defined ways to control the rounding mode of floating point operations:

The latest standard draft (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3088.pdf) says (7.6.1p2):

The FENV_ACCESS pragma provides a means to inform the implementation when a program might
access the floating-point environment to test floating-point status flags or run under non-default
floating-point control modes.

So, reading FP environment (made by __builtin_flt_rounds) does not require special arrangements. It however is worth mentioning that in this case the compiler may assume default values instead of reading them from hardware.

- The standard pragma ``#pragma STDC FENV_ROUND <mode>`` can change the rounding mode to a specific value for the operations covered by the pragma.  This does not permit dynamic access to the rounding mode, but in many cases it is sufficient to achieve the desired effect, and it is more optimizable than the alternatives below.

Here dynamic access may be confusing. Maybe describe it more verbose, like:

This does not permit changing rounding mode by other means, including call of `__builtin_set_flt_rounds` or `fesetround`.
- The standard pragma ``#pragma STDC FENV_ROUND FE_DYNAMIC`` allows dynamic access to the floating point rounding mode (including by these builtins) in code covered by the pragma.  The command line option ``-frounding-math`` behaves as if the translation unit began with this pragma.  This pragma does not allow changes to the floating point exceptions mode and so may be more optimizable than the next alternative.

According to the standard draft (7.6.2p4):

...If no FENV_ROUND pragma is in effect, or the specified constant rounding mode is FE_DYNAMIC,
rounding is according to the mode specified by the dynamic floating-point environment, which is the
dynamic rounding mode that was established either at thread creation or by a call to fesetround,
fesetmode, fesetenv, or feupdateenv. If the FE_DYNAMIC mode is specified and FENV_ACCESS is
“off”, the translator may assume that the default rounding mode is in effect.

This pragma does not set rounding mode (in contrast to the first variant), it must be set by other means, and __builtin_set_flt_rounds may be used for that.

- The standard pragma ``#pragma STDC FENV_ACCESS ON`` allows dynamic access to the entire floating point environment (including by these builtins) in code covered by the pragma.  The command line option ``-ffp-model=strict`` behaves as if the translation unit began with this pragma.

Again, dynamic access may be unclear here, maybe we can use any access?

Okay. I was looking at a version of the standard that makes reading the environment UB. If that's been relaxed, then I agree that it would be much more natural to talk about *changing* the environment than just *accessing* it.

And yeah, I agree it would make sense to break this out into a separate section under "Controlling floating-point behavior". We can cross-reference to that section from the Language Extensions document with something like:

These builtins read and modify the floating-point environment, which is not always allowed and may have unexpected behavior.  Please see the section on `accessing the floating point environment <UsersManual.html#floating-point-environment>`_.

And then you just need to set up the corresponding anchor in the user's manual:

.. _floating-point-environment:

Accessing the floating point environment
----------------------

Many targets allow floating point operations to be configured to control things such as how inexact results should be rounded and how exceptional conditions should be handled.  This configuration is called the floating point environment.  C and C++ restrict access to the floating point environment by default, and the compiler is allowed to assume that all operations are performed in the default environment.  When code is compiled in this default mode, operations that depend on the environment (such as floating-point arithmetic and `FLT_ROUNDS`) may have undefined behavior if the dynamic environment is not the default environment; for example, `FLT_ROUNDS` may or may not simply return its default value for the target instead of reading the dynamic environment, and floating-point operations may be optimized as if the dynamic environment were the default.  Similarly, it is undefined behavior to change the floating point environment in this default mode, for example by calling the `fesetround` function.

Clang supports three ways to change how floating point operations behave:
...

Hi, @rjmccall and @sepavloff
In UserManual, we include a section Controlling Floating Point Behavior: https://github.com/llvm/llvm-project/blob/main/clang/docs/UsersManual.rst#controlling-floating-point-behavior , now we need to add a new section for floating-point environment, do we need to add the new section in parallel with Controlling Floating Point Behavior section or just put the section under Controlling Floating Point Behavior? And current Controlling Floating Point Behavior includes following description:
Clang provides a number of ways to control floating point behavior, including with command line options and source pragmas.
So, we need to update it to Clang provides a number of ways to control floating point behavior, including with command line options, source pragmas and builtins. and mention builtin_flt_rounds, builtin_set_flt_rounds in this section. Does this meet your expectation?
Thanks very much.

Hi, @rjmccall and @sepavloff
In UserManual, we include a section Controlling Floating Point Behavior: https://github.com/llvm/llvm-project/blob/main/clang/docs/UsersManual.rst#controlling-floating-point-behavior , now we need to add a new section for floating-point environment, do we need to add the new section in parallel with Controlling Floating Point Behavior section or just put the section under Controlling Floating Point Behavior? And current Controlling Floating Point Behavior includes following description:
Clang provides a number of ways to control floating point behavior, including with command line options and source pragmas.
So, we need to update it to Clang provides a number of ways to control floating point behavior, including with command line options, source pragmas and builtins. and mention builtin_flt_rounds, builtin_set_flt_rounds in this section. Does this meet your expectation?

I think you should add a subsection to Controlling Floating Point Behavior about the floating-point environment. You should not mention these builtins there specifically — if you want an example function that reads or modifies the environment, you should use one of the standard APIs like the FLT_ROUNDS macro or the fesetround function. You should also add the documentation for these builtins where you've currently got it, and that documentation can cross-reference to Controlling Floating Point Behavior. Does that make sense?

xiongji90 updated this revision to Diff 508925.Mar 28 2023, 1:18 AM

Add floating point environment section in UserManual.rst

Hi, @rjmccall and @sepavloff
In UserManual, we include a section Controlling Floating Point Behavior: https://github.com/llvm/llvm-project/blob/main/clang/docs/UsersManual.rst#controlling-floating-point-behavior , now we need to add a new section for floating-point environment, do we need to add the new section in parallel with Controlling Floating Point Behavior section or just put the section under Controlling Floating Point Behavior? And current Controlling Floating Point Behavior includes following description:
Clang provides a number of ways to control floating point behavior, including with command line options and source pragmas.
So, we need to update it to Clang provides a number of ways to control floating point behavior, including with command line options, source pragmas and builtins. and mention builtin_flt_rounds, builtin_set_flt_rounds in this section. Does this meet your expectation?

I think you should add a subsection to Controlling Floating Point Behavior about the floating-point environment. You should not mention these builtins there specifically — if you want an example function that reads or modifies the environment, you should use one of the standard APIs like the FLT_ROUNDS macro or the fesetround function. You should also add the documentation for these builtins where you've currently got it, and that documentation can cross-reference to Controlling Floating Point Behavior. Does that make sense?

Hi, @rjmccall
I created floating point environment section, does it meet your expectation?
Thanks very much.

rjmccall added inline comments.Mar 28 2023, 12:57 PM
clang/docs/LanguageExtensions.rst
3272

I suspect this won't end up being formatted as a list; you should do something like:

- ``0`` - toward zero
- ``1`` - to nearest, ties to even
...
clang/docs/UsersManual.rst
1388 ↗(On Diff #508925)

This isn't quite the right place for this. Please put this new subsection after the described flags but before the "A note about..." subsections.

This file is RST, so you need to use double-backticks to format text in monospace.

This paragraph is just talking about the default mode which restricts access to the floating-point environment; let's add some text after it on how to get out of that default mode:

C provides two pragmas to allow code to dynamically modify the floating point environment:

- ``#pragma STDC FENV_ACCESS ON`` allows dynamic changes to the entire floating point environment.

- ``#pragma STDC FENV_ROUND FE_DYNAMIC`` allows dynamic changes to just the floating point rounding mode.  This may be more optimizable than ``FENV_ACCESS ON`` because the compiler can still ignore the possibility of floating-point exceptions by default.

Both of these can be used either at the start of a block scope, in which case they cover all code in that scope (unless they're turned off in a child scope), or at the top level in a file, in which case they cover all subsequent function bodies until they're turned off.  Note that it is undefined behavior to enter code that is *not* covered by one of these pragmas from code that *is* covered by one of these pragmas unless the floating point environment has been restored to its default state.  See the C standard for more information about these pragmas.

The command line option ``-frounding-math`` behaves as if the translation unit began with ``#pragma STDC FENV_ROUND FE_DYNAMIC``.  The command line option ``-ffp-model=strict`` behaves as if the translation unit began with ``#pragma STDC FENV_ACCESS ON``.

Code that just wants to use a specific rounding mode for specific floating point operations can avoid most of the hazards of the dynamic floating point environment by using ``#pragma STDC FENV_ROUND`` with a value other than ``FE_DYNAMIC``.
xiongji90 updated this revision to Diff 520288.May 8 2023, 12:50 AM

Address previous comments

xiongji90 marked an inline comment as done.May 8 2023, 12:54 AM

Hi, @rjmccall
I updated the patch to address your previous comments, could you help review again?
Thanks very much.

clang/docs/LanguageExtensions.rst
3272

Done.
Thanks very much.

rjmccall accepted this revision.May 8 2023, 8:02 AM

Thanks!

This revision is now accepted and ready to land.May 8 2023, 8:02 AM
This revision was automatically updated to reflect the committed changes.
xiongji90 marked an inline comment as done.