This patch aims to add necessary description for builtin_flt_rounds and builtins_set_flt_rounds in LanguageExtensions.rst
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
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: | |
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. |
clang/docs/LanguageExtensions.rst | ||
---|---|---|
3295 | Hi, @rjmccall and @sepavloff |
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 |
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. |
clang/docs/LanguageExtensions.rst | ||
---|---|---|
3288 |
Hi, @sepavloff |
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.
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.
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``. |
This comment belongs with the other builtin. I would suggest just combining these two into one section, though, like:
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.