fp-contract=fast and pragmas

Hi everyone,

I’ve been exploring clang’s fp-contract behavior recently, and I see that when ‘-ffp-contract=fast’ is used it can’t be overridden with a pragma. I would have regarded this as a bug (and in fact, a bug has been filed https://bugs.llvm.org/show_bug.cgi?id=39679). However, I’ve found some discussions on the mailing lists that described this as expected behavior.

Last October, Sam Liu added support for a new setting (‘fp-contract=fast-honor-pragmas’) and updated the clang documentation to reflect the behavior of fp-contract=fast. See https://reviews.llvm.org/D90174. I feel very strongly that this should have been done the other way around – fp-contract=fast should honor pragmas and if we need an option that doesn’t that could be added.

In the above review, John McCall asked what “other compilers” do. Steve Canon showed that GCC doesn’t honor the pragma. If I may humbly offer another “other compiler”, ICC (which doesn’t distinguish between ‘on’ and ‘fast’ for fp-contract) does respect the pragma (https://godbolt.org/z/x5r9WdYb4). I’m not saying that ICC should be treated as a reference implementation over GCC or anything like that, but I am saying that its behavior strikes me as more correct than what GCC or clang currently do.

Thoughts and opinions?

Thanks,

Andy

I don’t disagree with you in the abstract, but we consider this a GCC-designed feature. ICC’s value as contrary precedent appears especially weak because, as you point out, they don’t really implement -ffp-contract=fast.

There are plenty of other GCC-designed things that I don’t particularly like the design of, but where we nonetheless consider ourselves bound by their behavior.

John.

Hi John,

Let me be clarify that ICC-compatibility isn’t my goal here. We can do that out-of-tree for Intel compilers based on LLVM.

My motivation is a problem I’m working on with the LLVM test suite. The Polybench benchmarks in the test are currently attempting to use ‘#pragma STDC FP_CONTRACT OFF’ to create a value-safe kernel whose results can be compared against an otherwise identical kernel that is compiled with whatever options the test suite is configured to use. This strategy fails if the test suite is configured to compile with ‘-ffp-contract=fast’. That’s the problem I’m trying to solve by having clang respect the pragma.

See https://reviews.llvm.org/D25346, https://reviews.llvm.org/D102861, and https://reviews.llvm.org/D104935.

Thanks,

Andy

It sounds to me like this test is simply incompatible with fp-contract=fast and should not be used in that mode.

– Steve

It seems awkward to me that we have a command-line switch that overrides source code to this extent. Typically our command-line arguments cause us to change ‘defaults’, rarely do they cause us to ignore the source code. IMO, there is a bit of a natural ‘order’ to where how an option like this should be specified, that is, code overrides command line overrides default.

At bare minimum, having a pragma like this that is supported, but just ignored in this case needs to have some level of diagnostic. Silently ignoring a developer’s preference is the worst thing we can do.

Aren’t you all (Intel) the ones promoting -f(no-)protect-parens, which is a command line flag that overrides source code semantics in _exactly_ the same manner?

– Steve

I personally am not/have nothing to do with it, but I don’t doubt Intel is doing something like that.

The difference is that the flag alters the ‘default’ semantics. Here, the #pragma ALSO attempts to alter the ‘default’ semantics explicitly, but is ignored.

Note that I’m actually pretty sympathetic to this line of argument; compilation-unit scoped flags are too heavy-handed, and pragma and attribute scoping is much nicer. I just think that it’s a much broader change than this one flag and requires a correspondingly broader discussion. E.g. I would expect fast-math to behave identically. It would also, as John noted, introduce a subtle incompatibility with GCC, which would be pretty dangerous.

– Steve

I would also expect/hope fast-math to work the same way.

As far as GCC compat, I know we play a little fast/loose with it in other cases, but I can definitely see the danger here. To me, this feels like “GCC made a bad choice, so we are sticking ourselves with it”.

The behavior of -fprotect-parens goes in the opposite direction. It provides a way for the user to indicate specific areas of the code where fast-math (specifically reassociation) should not be allowed. Conversely, -fno-protect-parens simply allows the default behavior. I can’t think of a case where the -fprotect-parens flag overrides the explicit behavior of the source code.

We have support in clang for a pragma (‘clang fp <>’) which can enable and disable individual fast-math flags (including contract).

I wouldn’t consider the deviation from GCC to be dangerous in this case since the deviation is just disabling an optimization which isn’t guaranteed to happen anyway.

I personally am not/have nothing to do with it, but I don’t doubt Intel is doing something like that.

The difference is that the flag alters the ‘default’ semantics. Here, the #pragma ALSO attempts to alter the ‘default’ semantics explicitly, but is ignored.

Yes, deliberately, because that’s the apparently-intended interaction by the compiler that introduced those two features. Go convince the GCC developers that they’re wrong about their feature, and then I’ll happily sign off on changing Clang’s behavior to match. Otherwise you might as well be arguing that the “pure” and “const” attributes are backwards.

John.

Jumping in here, AFAIK gcc doesn't support anything along the lines of #pragma float_control -- is that right?

I thought there is general agreement that source > command-line > default. Surprised to find this isn't universal.

Also a reply about fprotect-parens below

From: John McCall <rjmccall@apple.com>
Sent: Wednesday, June 30, 2021 2:02 PM
To: Keane, Erich <erich.keane@intel.com>
Cc: Steve (Numerics) Canon <scanon@apple.com>; Kaylor, Andrew
<andrew.kaylor@intel.com>; llvm-dev@lists.llvm.org; cfe-dev@lists.llvm.org;
Yaxun Liu <yaxun.liu@amd.com>; Blower, Melanie I
<melanie.blower@intel.com>; Sanjay Patel <spatel@rotateright.com>;
Renato Golin <rengolin@gmail.com>; Hal Finkel
<hal.finkel.llvm@gmail.com>; guille@berkeley.edu;
ueno.masakazu@jp.fujitsu.com; Matthew.Arsenault@amd.com
Subject: Re: fp-contract=fast and pragmas

> I personally am not/have nothing to do with it, but I don’t doubt
> Intel is doing something like that.

[Blower, Melanie] Yes I committed those changes for fprotect-parens today

Yes, deliberately, because that’s the apparently-intended interaction by the compiler that introduced those two features.

Given GCC's history with fp-contract (for example, the fact that it treats fp-contract=on as an alias for fp-contract=off) I think it's difficult to make any confident statements about what is intended. The fact that clang will generate FMA with '-ffp-contract=on' is a bigger (and arguably more "dangerous") deviation from GCC than having clang respect the STDC pragma would be.

I don’t believe GCC implements the "STDC FP_CONTRACT" pragma. Their documentation (https://gcc.gnu.org/onlinedocs/gcc/Floating-point-implementation.html) says they do not. See also, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=20785

I'll admit there is a bit of ambiguity here. The ISO standard says that "#pragma STDC FP_CONTRACT OFF" should disable FMA, but -ffp-contract=fast allows contraction when the language standard doesn't. Here's the thing though -- putting aside the question of how the contraction mode is set, it is a bug to generate FMA when contraction is disabled, but it is not a bug to not generate FMA instructions when contraction is enabled. So, depending on your expectations, the current behavior may or may not be a bug with respect to the generated code, but the behavior I'm proposing would be conservatively correct.