This is an archive of the discontinued LLVM Phabricator instance.

[flang] Add -ffp-contract option processing
ClosedPublic

Authored by tblah on Oct 17 2022, 7:08 AM.

Details

Summary

Only add the option processing and store the result. No attributes are
added to FIR yet.

Only the "off" and "fast" options are supported. "fast-honor-pragmas" is not applicable because we do not implement #pragma clang fp contract() in Fortran [1]. "on" is not supported because it is unclear how to fuse only within individual statements. gfortran also does not implement "on": treating it as an "off".

Currently the default value is "off" to preserve existing behavior. gfortran uses "fast" by default and that may be the right thing for flang-new after further discussion in the future, but that can be changed separately. gfortran's documentation is available here.

[1] https://clang.llvm.org/docs/LanguageExtensions.html#extensions-to-specify-floating-point-flags

Diff Detail

Event Timeline

tblah created this revision.Oct 17 2022, 7:08 AM
Herald added a project: Restricted Project. · View Herald Transcript
Herald added a subscriber: jdoerfert. · View Herald Transcript
tblah requested review of this revision.Oct 17 2022, 7:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 17 2022, 7:09 AM
tblah updated this revision to Diff 468258.Oct 17 2022, 10:53 AM

clang-format plus cleaning up typos.

Thanks for implementing this, @tblah!

Two high level questions/requests:

-Andrzej

clang/lib/Driver/ToolChains/Flang.cpp
85–86

What's RenderFloatingPointOptions?

flang/lib/Frontend/CompilerInvocation.cpp
664

res is a very confusing name (that I used myself in various places). Basically, it's the CompilerInvocation instance ... result. Perhaps use invoc?

665

[nit] "The compiler invocation args to parse"

flang/test/Driver/driver-help.f90
108

Why not expose this flag in flang-new? (as well as flang-new -fc1?)

flang/test/Driver/flang_fp_opts.f90
2–3

Sounds like a test for frontend-forwarding.f90

7–8

Could you use more descriptive prefixes?

tblah marked 5 inline comments as done.Oct 18 2022, 3:58 AM

Thanks for taking a look. I've updated accordingly and will upload the patch soon.

are you confident that we will need LangOptions.def?

Clang places this flag (and many other floating point options) in LangOptions so I thought I would follow the same convention here. Is there somewhere more appropriate to put them?

clang/lib/Driver/ToolChains/Flang.cpp
85–86

It is a static function in clang/lib/Driver/ToolChains/Clang.cpp which does the same job as AddFloatingPointOptions, except for clang. I couldn't use it right away because not all of the options it it processes are supported in flang, but once we get there it would make sense to share code.

tblah updated this revision to Diff 468475.Oct 18 2022, 4:07 AM
tblah added a comment.Oct 18 2022, 5:36 AM

Linux CI is passing. I suspect the CI failure on windows is unrelated to my code: the test failure is for clang-scan-deps and the previous version of the patch passed CI.

The omission of the fast-honor-pragmas argument from the compiler driver is deliberate.

Where is it omitted?

I suspect the CI failure on windows is unrelated to my code

I agree.

clang/lib/Driver/ToolChains/Flang.cpp
85–86

Ah! That function is over 400 LOC and looks super complex. I doubt Flang will be able to share that logic with Clang any time soon. If ever. I would actually skip this comment. Sometimes code duplication is the right approach ;-)

167

From LLVM Coding style

Function names should be verb phrases (as they represent actions), and command-like function should be imperative. The name should be camel case, and start with a lower case letter (e.g. openFile() or isFoo()).

I know that this style is not followed here 100%. But that's what we should aim for :)

flang/include/flang/Frontend/LangOptions.h
10–12

UPDATEME

30

What are these pragmas? Perhaps you can add a test that would include them?

50–51
flang/lib/Frontend/CompilerInvocation.cpp
661–662

populates the variables options accordingly

Perhaps this would be a bit more specific/descriptive:

"and configures the input CompilerInvocation accordingly". Ultimately, this is about ... configuring the current compiler invocation, which is represented by an instance of CompilerInvocaiton.

693

In here you only configure CompilerInvocation. This configuration will be used elsewhere (i.e. where codegen happens). So, I think, as far as this method is concerned the implementation is complete.

flang/test/Driver/flang_fp_opts.f90
2–3

No longer valid ;-)

5

Can you test with flang as well?

Glad to see this flag being added to flang-new! As a note to self I've written some tests that should be updated once this lands that currently don't pass through the flang-new driver.

flang/test/Driver/driver-help.f90
108

I think @awarzynski is right here, this is an option we want to expose to end users so I think the top-level driver should have it as well.

As a general rule of thumb: if a flag is in clang as well as clang -cc1 it should be in flang as well as flang -fc1
In this case -ffp-contract is a clang flag as well as a clang -cc1 flag, and so should probably be a flang flag as well as flang -fc1

tblah marked 8 inline comments as done.Oct 19 2022, 2:28 AM

The omission of the fast-honor-pragmas argument from the compiler driver is deliberate.

Where is it omitted?

This argument is only supported in the frontend driver, not the compiler driver:

flang-new -ffp-contract=fast-honor-pragmas test.f90 
flang-new: error: unsupported argument 'fast-honor-pragmas' to option '-ffp-contract='

flang-new -fc1 -ffp-contract=fast-honor-pragmas test.f90
warning: ffp-contract= is not currently implemented
flang/include/flang/Frontend/LangOptions.h
30

I copied this comment from clang. I believe the pragma is

#pragma clang fp contract(fast)

See https://clang.llvm.org/docs/LanguageExtensions.html#extensions-to-specify-floating-point-flags

This patch only adds support for argument processing, so I can't test for the pragmas.

flang/test/Driver/flang_fp_opts.f90
5

We already test that these flags are passed to the frontend driver from the compiler driver in flang/test/Driver/frontend-forwarding.f90

tblah updated this revision to Diff 468840.Oct 19 2022, 3:13 AM
vzakhari added inline comments.Oct 19 2022, 11:53 AM
flang/include/flang/Frontend/LangOptions.h
30

I do not think we should blindly copy this from clang. I believe -ffp-contract=on is there to do the contraction complying to the language standard - but Fortran standard says nothing about contraction. I am also not aware about a Fortran compiler that supports directives related to contraction, so fast-honor-pragmas does not seem to be applicable as well. Basically, we end up with just off and fast.

Now, it may be reasonable to support the same -ffp-contract= arguments so that users can apply the same options sets for C/C++ and Fortran compilations. If we want to do this, we need to map on and fast-honor-pragmas to something, e.g. fast. A driver warning (not an error) may be useful to make the option's behavior clear when on and fast-honor-pragmas are passed.

flang/test/Driver/driver-help-hidden.f90
34

Is it easy to emit a different help message for Flang to say that there are only two modes for Fortran?

tblah added inline comments.Oct 20 2022, 3:19 AM
flang/include/flang/Frontend/LangOptions.h
30

From the clang help text:

Form fused FP ops (e.g. FMAs):
fast (fuses across statements disregarding pragmas)
| on (only fuses in the same statement unless dictated by pragmas)
| off (never fuses)
Default is 'on'

So if we removed on and set the default to off we would no longer fuse within the same statement by default.

Classic-flang seems to support on, off and fast: https://github.com/flang-compiler/flang/blob/master/test/llvm_ir_correct/fma.f90

flang/test/Driver/driver-help-hidden.f90
34

@awarzynski tells me there is no way to do this short of having separate Options.td for flang and clang. Once we have settled on which arguments to support, I will update the shared help text to mention flang.

awarzynski added inline comments.Oct 20 2022, 9:07 AM
flang/test/Driver/driver-help-hidden.f90
34

Both clang -help and flang-new -help must be 100% correct. As this help text is not valid in the case of LLVM Flang, it needs to be updated accordingly.

As @tblah points out, there's no straightforward mechanism for having a custom help texts for clang and flang-new in Clang's driver library ATM. But I think that this can be achieved even without creating a separate "Options.td" file. One would have to define a new tablegen record in "Options.td". That would be a separate patch though, probably accompanied by an RFC.

There's a different solution too. Note that currently the definition uses the HelpText field. However, you could use DocBrief instead (which we used to solve a similar issue with -I). That's what I suggest that you do. Basically, copy the contents of HelpText for -ffp-contract into a DocBrief field (we don't use this field in Flang and it should probably be renamed as DocBriefClang). HelpText should be replaced with something brief that applies both to Clang and Flang.

Btw, what's the help-text/spelling in gfortran?

vzakhari added inline comments.Oct 20 2022, 11:26 AM
flang/include/flang/Frontend/LangOptions.h
30

Not talking about defaults just yet, I think Flang cannot currently support the on mode as documented.

I do not have the latest classic flang readily availalbe, but I am curious what it will generate for this example:

function fn(x,y,z)
  real :: x,y,z
  fn = x * y
  fn = fn + z
end function

With a very old classic flang I get just fast math flags on the multiple and add instructions, which is obviously not what on is supposed to do:

$ flang -target aarch64-linux-gnu -O1 -c -S -emit-llvm -ffp-contract=on fma.f90
$ cat fma.ll
  %4 = fmul fast float %3, %1, !dbg !10
  %5 = bitcast i64* %z to float*, !dbg !11
  %6 = load float, float* %5, align 4, !dbg !11
  %7 = fadd fast float %6, %4, !dbg !11

Maybe the latest classic flang does support it properly, e.g. it only contracts operations from the same statement. But I do not see a way to support this in Flang right now, so documenting the on mode as it is in clang seems confusing.

We can still support on in the Flang option, but I think we need to issue a warning saying that it defaults to something else, e.g. to fast. If mapping on to fast is not appropriate to some users, then they will have to explicitly specify -ffp-contract=off for Fortran compilations in their build system.

I am also curious what fuses in the same statement means for Fortran. For example:

x1 = DOT_PRODUCT(x2, x3)+x4*x5+x6

If Fortran processor decides to implement DOT_PRODUCT as inline multiply+add loop, does -ffp-contract=on apply to them or it only applies to x4*x5+x6?

tblah added inline comments.Oct 21 2022, 5:00 AM
flang/include/flang/Frontend/LangOptions.h
30

Thanks for your feedback.

I've updated my patch. Now flang only supports off and fast. The other two map to fast and we default to off.

gfortran seems to default to fast:

-ffp-contract=style

    -ffp-contract=off disables floating-point expression contraction. -ffp-contract=fast enables floating-point expression contraction such as forming of fused multiply-add operations if the target has native support for them. -ffp-contract=on enables floating-point expression contraction if allowed by the language standard. This is currently not implemented and treated equal to -ffp-contract=off.

    The default is -ffp-contract=fast.

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

flang/test/Driver/driver-help-hidden.f90
34

Thanks for the feedback.

I have added a mention of flang to the old help, which has been moved to DocBrief. The new HelpText just mentions which options are supported by each frontend without explaining them.

tblah updated this revision to Diff 469556.Oct 21 2022, 5:00 AM
awarzynski added inline comments.Oct 24 2022, 1:33 AM
clang/include/clang/Driver/Options.td
1926

As far as users are concerned, flang-new is just a Fortran compiler. Once we start adding references to Clang in flang-new --help, we might be confusing users (i.e. where's the boundary between Clang and Flang?) and exposing implementation details (i.e. that flang-new is implemented using clangDriver). Ideally we should avoid that.

flang/include/flang/Frontend/LangOptions.h
30

gfortran seems to default to fast:

Thanks for checking those docs - it's now becoming clear that -ffp-contract=style should only support: on, off, fast. https://reviews.llvm.org/D90174 introduced fast-honor-pragmas to solve a particular problem for a particular backend, i.e. HIP. From the commit message for D90174:

'fast-honor-pragmas' is equivalent to 'fast' in frontend but let the backend to use 'Standard' fp fuse option.

To me this sounds like --ffp-contract=fast-honor-pragrmas should be replaced with:

  • --ffp-contract=fast --ffp-fusion=standard (i.e. add a new flag to provide extra control to the end users)
  • --ffp-control=fast -x hip --> FPM_FastHonorPragmas somewhere in Clang's CompilerInvocartion.cpp

As in, I believe that the issue in HIP can be solved without --ffp-contract=fast-honor-pragrmas. And if we avoid that approach, we can have a flag that's consistent with GCC and also make the help text much clearer.

@vzakhari

Now, it may be reasonable to support the same -ffp-contract= arguments so that users can apply the same options sets for C/C++ and Fortran compilations.

Yes, but I am not aware of anyone experimenting with mixed-source projects yet. So currently flang-new should only be used for Fortran sources and clang for C family of languages. So I would leave that for later.

tblah updated this revision to Diff 470184.Oct 24 2022, 9:29 AM
tblah marked 2 inline comments as not done.
tblah edited the summary of this revision. (Show Details)

Updated diff with a further reduced help text after discussions with @awarzynski

vzakhari added inline comments.Oct 24 2022, 8:43 PM
clang/lib/Driver/ToolChains/Flang.cpp
94

I know I suggested myself mapping on to fast, but it seems it will be more reasonable to map it to off. Both my old classic flang and gfortran (12.2.0) do not generate FMAs under on. Moreover, mapping it to off may allow us to adapt gcc's help message "if allowed by the language standard" (maybe not in this commit).

tblah updated this revision to Diff 470496.Oct 25 2022, 7:55 AM
tblah marked 8 inline comments as done.Oct 25 2022, 7:59 AM
tblah marked an inline comment as done.
vzakhari accepted this revision.Oct 25 2022, 10:52 AM

Thank you! LGTM

This revision is now accepted and ready to land.Oct 25 2022, 10:52 AM

Added Clang reviewers who touched the definition of --fp-contract most recently. Mostly for visibility, but lets give them at least a couple of days to take a look at the changes in Options.td.

Thanks for all the updates, Tom! I have a few more suggestions.

From the summary:

implement these pragmas

Could you explain what pragmas you are referring to here? (i.e. Clang pragmas for C and C++ + link)

gfortran uses "fast" by default

For our future self, could you add a link as well?

clang/include/clang/Driver/Options.td
1925–1926

I still think that we shouldn't be making references to Flang in Clang documentation. And this DocBrief is only used by Clang. Also, "flang" is problematic - what do you mean by "flang"?

clang/lib/Driver/ToolChains/Flang.cpp
91–98

Some "unsupported" options are treated as errors and some are warnings. I think that for the sake of consistency it would be better to keep them all as errors. Also, why not use Val instead of e.g. "off"?

MaskRay added inline comments.Oct 26 2022, 11:03 AM
clang/lib/Driver/ToolChains/Flang.cpp
89

We prefer == to equals

tblah updated this revision to Diff 471163.Oct 27 2022, 7:30 AM
tblah edited the summary of this revision. (Show Details)
tblah marked 4 inline comments as done.
awarzynski accepted this revision.Oct 27 2022, 12:48 PM

LGTM, thanks for implementing this!

clang/lib/Driver/ToolChains/Flang.cpp
98–99

[nit] "... and pragmas are not relevant to Fortran." Fortran has directives rather than pragmas. So it's not quite like pragmas are not supported. It's just that there's different mechanism instead.

tblah updated this revision to Diff 471958.Oct 31 2022, 4:28 AM

I've updated the patch with @awarzynski's nit and an up-to-date context.

@kiranchandramohan please could you commit for me

This revision was landed with ongoing or failed builds.Oct 31 2022, 4:37 AM
This revision was automatically updated to reflect the committed changes.