This is an archive of the discontinued LLVM Phabricator instance.

[X86][FPEnv] Lowering of {get,set,reset}_fpmode
Needs ReviewPublic

Authored by sepavloff on Jul 2 2020, 4:24 AM.

Diff Detail

Event Timeline

sepavloff created this revision.Jul 2 2020, 4:24 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 2 2020, 4:24 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
sepavloff updated this revision to Diff 281830.Jul 30 2020, 1:41 AM

Rebased patch

RKSimon added inline comments.Aug 11 2020, 12:55 PM
llvm/test/CodeGen/X86/fpenv.ll
4

regenerate with the update_llc_test_checks.py script?

llvm/test/CodeGen/X86/fpenv32.ll
2

regenerate with the update_llc_test_checks.py script?

sepavloff updated this revision to Diff 285083.Aug 12 2020, 7:33 AM

Rebased and used update_llc_test_checks.py script

sepavloff updated this revision to Diff 289370.Sep 2 2020, 1:51 AM

Rebased patch

sepavloff updated this revision to Diff 327837.Mar 3 2021, 9:54 AM

Rebased patch

craig.topper added inline comments.Mar 4 2021, 3:55 PM
llvm/test/CodeGen/X86/fpenv32.ll
17

I'm still not clear who the intended user of these intrinsics are? How would they know when to use i32 and when to use i64?

sepavloff added inline comments.Mar 4 2021, 8:10 PM
llvm/test/CodeGen/X86/fpenv32.ll
17

who the intended user of these intrinsics are?

These intrinsics can be useful at least in these cases:

  • native implementation of fegetmode/fesetmode,
  • internally by compiler when it implements pragmas changing control modes. Such pragma acts only within a compound statement and control modes should be restored upon exit.

How would they know when to use i32 and when to use i64?

This is a platform-dependent choice, just as the size of pointers. We could encode them in DataLayout (see D71741).

craig.topper added inline comments.Mar 4 2021, 8:25 PM
llvm/test/CodeGen/X86/fpenv32.ll
17

who the intended user of these intrinsics are?

These intrinsics can be useful at least in these cases:

  • native implementation of fegetmode/fesetmode,
  • internally by compiler when it implements pragmas changing control modes. Such pragma acts only within a compound statement and control modes should be restored upon exit.

For the pragma case, would that mean the frontend would have to pass different values to the intrinsic for each target to match the target dependent behavior? Is the pragma also target specific? Or is there some target independent representation a frontend should be giving to llvm.

The ABI code in clang is a place where we have a ton of target specific rules in the frontend. It has come up many times on the mailing lists that this is bad design as every frontend needs to reimplement it. So I want to make sure we're being careful about the interface here and not creating work for frontends.

How would they know when to use i32 and when to use i64?

This is a platform-dependent choice, just as the size of pointers. We could encode them in DataLayout (see D71741).

Based on the tests here it appears the size to use is different on 32-bit mode depending on whether sse is enabled. DataLayout can't be dependent on subtarget features. It's derived from the target triple.

kpn added a subscriber: kpn.Mar 5 2021, 6:38 AM
kpn added inline comments.
llvm/test/CodeGen/X86/fpenv32.ll
17

What pragmas are there that change control modes or the floating point environment? I don't think we have any, or at least none are required by C standards document.

sepavloff added inline comments.Mar 5 2021, 8:14 AM
llvm/test/CodeGen/X86/fpenv32.ll
17

who the intended user of these intrinsics are?

These intrinsics can be useful at least in these cases:

  • native implementation of fegetmode/fesetmode,
  • internally by compiler when it implements pragmas changing control modes. Such pragma acts only within a compound statement and control modes should be restored upon exit.

For the pragma case, would that mean the frontend would have to pass different values to the intrinsic for each target to match the target dependent behavior?

Yes. The frontend now does the same things for long and some other types, it takes IR representation from DataLayout , and it is different for different architectures.

Is the pragma also target specific?

pragma STDC FENV_ROUND is not target specific. Target-specific pragmas are of course possible, for example it could be a pragma that sets rounding mode for a particular type, if the target supports different modes for different types.

Or is there some target independent representation a frontend should be giving to llvm.

For llvm properly generated variables are enough. It is frontend that need information, which can be supplied by DataLayout or TatgetInfo.

The ABI code in clang is a place where we have a ton of target specific rules in the frontend. It has come up many times on the mailing lists that this is bad design as every frontend needs to reimplement it. So I want to make sure we're being careful about the interface here and not creating work for frontends.

The ABI is not touched here, these are intrinsics, they are not called as regular functions.

How would they know when to use i32 and when to use i64?

This is a platform-dependent choice, just as the size of pointers. We could encode them in DataLayout (see D71741).

Based on the tests here it appears the size to use is different on 32-bit mode depending on whether sse is enabled. DataLayout can't be dependent on subtarget features. It's derived from the target triple.

We can use the widest type for the mode set.

It is possible to use i64 for all targets, it would be enough for all targets supported by glibc. There are however functions fesetenv and fegetenv and in that case we cannot do similar thing as the size of FP state on X86 is 256 bits.

craig.topper added inline comments.Mar 5 2021, 8:57 AM
llvm/test/CodeGen/X86/fpenv32.ll
17

The ABI code in clang is a place where we have a ton of target specific rules in the frontend. It has come up many times on the mailing lists that this is bad design as every frontend needs to reimplement it. So I want to make sure we're being careful about the interface here and not creating work for frontends.

The ABI is not touched here, these are intrinsics, they are not called as regular functions.

I only mentioned ABI because it is an example of a place where the interface between llvm and frontends is considered the wrong design. I wasn't trying to say that this affects ABI.

It sounds like for this intrinsic to be usable by a frontend, that any frontend that wants to use it needs to know exactly which bits represent rounding mode, what encoding they use, the fact that x86 has rounding mode bits in two places, etc. That's a lot of information to try to pack into datalayout so likely it will have to just be hardcoded into custom C++ code in the frontend. Then when another frontend wants to use it they will have to write the same code into their frontend. And they'll need to update it every time they want to add support in their frontend for a new target that llvm already supports. This doesn't seem like a clean division between frontend and backend responsibilities.

sepavloff added inline comments.Mar 5 2021, 10:17 AM
llvm/test/CodeGen/X86/fpenv32.ll
17

What pragmas are there that change control modes or the floating point environment? I don't think we have any, or at least none are required by C standards document.

#pragma STDC FENV_ROUND can change the floating point environment.

17

It sounds like for this intrinsic to be usable by a frontend, that any frontend that wants to use it needs to know exactly which bits represent rounding mode, what encoding they use, the fact that x86 has rounding mode bits in two places, etc.

There is no attempt to interpret the control modes value. The main expected use cases are:

  • Use get_fpmode to read current modes, tweak it, for example by setting new rounding mode using set_rounding, then restore the modes using set_fpmode. In this case the value returned by get_fpmode is opaque.
  • Some code can call set_fpmode (actually fesetmode) and provide it with an expression formatted in a target-specific way to set required control modes. This usage can solve the problem described in https://reviews.llvm.org/D74729#2006017. In this case the frontend does not need to know what bits of control modes value mean.

The only thing that DataLayout need to keep is the size of control modes (and floating point environment in fegetenv).

kpn added inline comments.Mar 5 2021, 12:33 PM
llvm/test/CodeGen/X86/fpenv32.ll
17

I'm not convinced that it is _required_ to change the floating point environment. The compiler inserting calls to fesetround() would have a performance cost, and we shouldn't pay that cost unless we are required to by the standard.

I've started a thread on cfe-dev named "C2x FP_ROUND pragma meaning ambiguous?"

kpn added inline comments.Mar 9 2021, 7:38 AM
llvm/test/CodeGen/X86/fpenv32.ll
17

From asking on cfe-dev, it sounds like this FENV_ROUND pragma is a perfect use case for the constrained FP intrinsics. After all, they do have that rounding mode argument, and I'm pretty sure there are issues here with instructions getting reordered and possibly moved above or below the call to change the hardware rounding mode.

It would be up to the target backend to decide when its instructions can't or won't embed a rounding mode in them and instead issue the instructions to change the rounding mode.

sepavloff updated this revision to Diff 334166.Mar 30 2021, 7:46 AM

Rebased patch. Fixed issue of getConstantPool.

Changed mode type in test fpenv32.ll from i32 to i64 to match glibc types

sepavloff updated this revision to Diff 389819.Nov 25 2021, 9:11 AM

Update patch because dependency has been updated