[llvm-dev] [RFC] Eliminating non-IR floating-point controls in the selection DAG

Renato Golin via llvm-dev llvm-dev at lists.llvm.org
Sat Oct 30 06:29:59 PDT 2021

On Fri, 29 Oct 2021 at 21:51, Kaylor, Andrew <andrew.kaylor at intel.com>

> > Finally, I think we need to separate the IR from DAG/MIR behaviour. It
> seems to me that the target option is what overrides the behaviour, not
> function/module options, so we should worry about the targets' behaviour,
> not at which level the flag is
I don’t know what you’re saying here. What do you mean by “we should worry
> about the targets' behaviour”? If the IR says fp-contract is not allowed
> for a given instruction, why should the target options be allowed to
> overrule that?

They shouldn't. Unless it's a hardware-specific design issue (ex. there is
no fused op, or there is no un-fused op), but that should be done at the
DAG level, I think, not IR level.

Two notes, however:
>    1. resetTargetOptions doesn’t handle the AllowFPOpFusion setting (as
>    far as I can tell, there is no corresponding function attribute)
>    2. There is a comment for resetTargetOptions which says this:
> // FIXME: This function needs to go away for a number of reasons:
> // a) global state on the TargetMachine is terrible in general,
> // b) these target options should be passed only on the function
> //    and not on the TargetMachine (via TargetOptions) at all.
> As you may guess, I completely agree with the comment. FWIW, this comment
> was added by Eric Christopher in 2015 (
> https://github.com/llvm/llvm-project/commit/35a8a62125ccfa0ef804584738a295ed5c17750f
> ).

I think the biggest problem there is that this is a target flag not an IR
flag and that's not a good design. I completely agree with the comment also.

I also agree the dance of inst/func/mod level flags isn't trivial and it a
source of at least confusion, but potentially bugs.

I also want to clarify what I meant for "perfectly valid", and that was "it
solves the problem and is technically doable". I didn't want to imply it
was good or there wasn't a better way of doing it.

The core of my complaint about the current state of things is that the
> backend is treating the fast-math flags as if they are “on or undecided”
> rather than “on or off.” IMO, the absence of a fast-math flag in the IR
> means that the behavior controlled by that flag is not permitted. That’s
> the way the IR is treated in IR-level optimization passes, but the backend
> codegen (at least in places) behaves as though the absence of a fast-math
> flag means “not permitted unless enabled by TargetOptions.” That’s bad as a
> starting point, but it’s particularly bad when you start linking together
> IR from multiple modules that may have been created from different
> compilation units with different options.

I absolutely agree with you. That's why I've added Sebastian, who worked on
a very similar problem not long ago. I myself have fixed similar problems
in the Arm backend a long time ago.

I think we really should treat the lack of fast-math-like flags to mean
their behaviour is *forbidden*, and force front-ends and middle-end passes
to add them if the user requested / allowed.

I’d also like to make one thing explicit. While the change I’m proposing
> would change the behavior of the backend for all front ends, it wouldn’t
> “break” them in the sense of producing incorrect results. When
> TargetOptions::AllowFPOpFusion==FPOpFusionMode::Fast the backend is *
> *allowed** to fuse operations, but it isn’t required or guaranteed to
> fuse them. With the change I am proposing, the backend wouldn’t form fuse
> FP options unless the ‘contract’ flag were set, but that wouldn’t lead to
> incorrect results. It would lead to lost performance in some cases, but I
> think that can be recovered by generating IR with the semantics that were
> intended. Similarly, for the other fast-math flags. However, I will admit
> that it could be an uncomfortable transition for some front ends.

It's not that simple. We want to keep the performance for existing code
with existing compilation infrastructure as much as possible.

When an existing project with its existing compilation flags use a new
version of clang and suddenly the performance is considerably lower, they
may start to look for things to change or may just blame on "new compiler"
and try other compilers, or worse, get stuck with an old version of clang.

But this is also not a huge deal, and we can fix that with more clear

Regarding bloating the IR, I’m not sure if this is a theoretical problem or
> real one. The bitcode writer will emit a byte for the fast-math flags if
> any are set for each call or FP operation, and if none are set it will not
> emit that byte. For clang, this is a non-issue because clang always sets
> the fast-math flags on the individual operations. It’s at least
> theoretically possible that there is some front end that never sets the
> fast-math flags and relies on the global setting. In that case, adding the
> fast-math flags would bloat the IR considerably. For most of the FMF,
> omitting the flags would cause considerable missed optimization
> opportunities in the middle end, but the ‘contract’ flag is a bit of a
> special case because it isn’t typically used at all before codegen.

My comment on the increase in size was meant as a check, not as a blocker.
It could be well within noise levels and totally worth the change.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20211030/93fd8839/attachment.html>

More information about the llvm-dev mailing list