Renato Golin via llvm-dev
2021-Oct-30 13:29 UTC
[llvm-dev] [RFC] Eliminating non-IR floating-point controls in the selection DAG
On Fri, 29 Oct 2021 at 21:51, Kaylor, Andrew <andrew.kaylor at intel.com> wrote:> > 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 communication... 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. cheers, --renato>-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20211030/93fd8839/attachment.html>
Wang, Pengfei via llvm-dev
2021-Oct-30 15:01 UTC
[llvm-dev] [RFC] Eliminating non-IR floating-point controls in the selection DAG
I think the use of target option simply owe to the fact that DAG and other backend passes always lose the FMFs during transformation in the past. Thanks Phoebe (Pengfei) From: llvm-dev <llvm-dev-bounces at lists.llvm.org> On Behalf Of Renato Golin via llvm-dev Sent: Saturday, October 30, 2021 9:30 PM To: Kaylor, Andrew <andrew.kaylor at intel.com> Cc: Yaxun Liu <yaxun.liu at amd.com>; Sebastian Pop <sebpop at gmail.com>; llvm-dev at lists.llvm.org; Ammarguellat, Zahira <zahira.ammarguellat at intel.com>; Ulrich Weigand <Ulrich.Weigand at de.ibm.com>; Ballman, Aaron <aaron.ballman at intel.com> Subject: Re: [llvm-dev] [RFC] Eliminating non-IR floating-point controls in the selection DAG On Fri, 29 Oct 2021 at 21:51, Kaylor, Andrew <andrew.kaylor at intel.com<mailto:andrew.kaylor at intel.com>> wrote:> 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 isI 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 communication... 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. cheers, --renato -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20211030/c488859c/attachment.html>