[llvm-dev] Calling function from non-default floating-point environment

Kevin Neal via llvm-dev llvm-dev at lists.llvm.org
Tue Jan 7 11:00:30 PST 2020

From: Serge Pavlov <sepavloff at gmail.com>
Sent: Tuesday, January 07, 2020 1:02 PM
To: LLVM Developers <llvm-dev at lists.llvm.org>; Clang Dev <cfe-dev at lists.llvm.org>
Cc: Kevin Neal <Kevin.Neal at sas.com>
Subject: Calling function from non-default floating-point environment

Hi all,

Implementation of #pragma STDC FENV_ACCESS raises a problem: what to do if a function is called inside a region where FP environment differs from the default? If the function expects default FP mode it may work incorrectly in such case.

The C2x standard draft (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2454.pdf<https://nam02.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg14%2Fwww%2Fdocs%2Fn2454.pdf&data=02%7C01%7Ckevin.neal%40sas.com%7Ca580fda4e7484c2bfbe908d7939bbfd8%7Cb1c14d5c362545b3a4309552373a0c2f%7C0%7C0%7C637140170280825183&sdata=v5ZXB4G0YpXBdzFvgsJhc1vIHa6cCO2vvasaM%2B3xkvQ%3D&reserved=0>) states (7.6p4):
Certain programming conventions support the intended model of use for the dynamic floating-point environment:*)
— a function call does not alter its caller’s floating-point control modes, clear its caller’s floating point status flags, nor depend on the state of its caller’s floating-point status flags unless the function is so documented;
— a function call is assumed to require default floating-point control modes, unless its documentation promises otherwise;
— a function call is assumed to have the potential for raising floating-point exceptions, unless its documentation promises otherwise.
*) With these conventions, a programmer can safely assume default floating-point control modes (or be unaware of them). The responsibilities associated with accessing the floating-point environment fall on the programmer or program that does so explicitly.

Right here it says that dealing with non-default modes is the job of the program or programmer: “The responsibilities associated with accessing the floating-point environment fall on the programmer or program that does so explicitly.” It doesn’t say compiler. It also hedges with words like “certain ... conventions”. If only some conventions then that implies that there are other conventions that do things differently and that’s OK.

It explicitly calls out the programmer to solve these issues when opting in to non-default FP behavior.

And I say this from a company that always runs with traps enabled and therefore has to deal with these FP issues. Sometimes we work around traps in third party, default FP environment software. Sometimes we _want_ that trap from default FP environment software because it indicates a bug somewhere. We have to examine these cases individually and determine what we need. It’s not the compiler’s job to protect us from ourselves.

Can we get a language lawyer to settle this once and for all?

It looks like that the standard requires to call functions in default FP mode, so inside a block where #pragma STDC FENV_ACCESS acts, each function call should be converted into sequence:
 - store FP state,
 - set default FP state,
 - call the function,
 - restore FP state.
These save/restore instructions could be inserted by compiler. This could be the safest solution but it complicates implementation and may impact performance. There is also another viewpoint: it is user responsibility to provide necessary environment and save/restore operations must be inserted manually.

Choosing the proper way we need to take into account:
- generally it is hard for a user to be sure that a function do not depend on FP environment. Functions that apparently do not use FP numbers (like addition to hash table) may actually involve FP operations internally.
- function inlining occurs in IR level and the chosen solution may potentially affect semantics of other languages (maybe Fortran?).

So the first question is: should the compiler set default FP state prior to function calls?


The next question is: should the compiler support some frontend attribute to mark functions that do not require default FP mode? These are functions that:
- do not involve FP operations,
- work correctly in any FP mode,
- expects particular FP mode,
- modifies FP mode,
- probably something else.
For such functions compiler would not generate save/restore operations. We also could have several attributes if we need to distinguish between these cases.

No, the compiler should not be inserting save/restore operations. If this was intended then attributes or keywords would have been introduced a long time ago I bet.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200107/66105db6/attachment-0001.html>

More information about the llvm-dev mailing list