On Sun, Aug 29, 2021 at 11:28 AM Roger Sayle <ro...@nextmovesoftware.com> wrote: > > > This is another attempt to add an -fpreserve-traps command line > option to GCC. Many thanks to Richard Beiner for approving the > code clean-up pieces of my earlier submission: This revision > contains just the actual functional change(s). > > My recent attempt at humour in comment #8 of PR 77980 has > reminded me that we still really need to tackle/improve the > semantics of trapping instructions. > > Firstly, I completely agree with Richard (and Eric) that the > current situation with the semantics of -fexceptions and > -fnon-call-exceptions (especially the latter without the > former) is a mess. Alas, the testsuite (and source) is full > of checks that the current status quo is preserved, so any > attempts to tweak exception handling leads to a world of pain.
I'm giving the following a try now which at least would remove the '-fno-exceptions -fnon-call-exceptions' state (it then might ask for unification of the flag_ vars to an enum, but that would be for a followup). diff --git a/gcc/common.opt b/gcc/common.opt index ed8ab5fbe13..7d69ab5ef7c 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1509,7 +1509,7 @@ Common Var(flag_emit_class_debug_always) Init(0) Do not suppress C++ class debug information. fexceptions -Common Var(flag_exceptions) Optimization +Common Var(flag_exceptions) Optimization EnabledBy(fnon-call-exceptions) Enable exception handling. fexpensive-optimizations > The most relevant thing that I would like to point out is that > this proposed option, -fpreserve-traps, and the semantics of > trapping instructions are completely orthogonal to exception > handling. As the term EH implies, exceptions are a form of flow > control (on those targets that support it). Traps, signals(?), > segmentation faults, illegal accesses and invalid instructions > are things that can't (always?) be controlled. Exceptional yes, > but not handleable. Are they really independent? Consider -fnon-call-exceptions where trapping instructions (may) raise exceptions - now with your change (ENOPATCH btw...) any such instructions would be considered having side-effects despite the 'trapping' bit now covered by EH IL. Now - individual stmts can be marked as known to not throw, what does this now mean for its trapping state? How do -fpreserve-traps and -fdelete-dead-exceptions interact here? I think that going down the -fpreserve-traps way opens a whole can of worms with respects to users doing weird things and us having to maintain sth not well thought out - so IMHO adding a user-visible option shouldn't be the first thing to do. IIRC we got -ftrapv because there were frontends requiring its semantics (Java)? But even -ftrapv is utterly broken and only "works" in very small circumstances (SImode and DImode operations). But now -ftrapv interacts with -fpreserve-traps as well given it makes some (not very well defined) operations possibly trapping. What does preserving a trap mean btw, does it require to preserve the exact trapping instruction (a trap handler might inspect the trapping instruction after all)? Or are we allowed to replace a known to be trapping instruction by sth else that also traps? I suppose traps will be non-recoverable (you have -fnon-call-exceptions and EH as the only mechanism to resume after a trap). Does -fpreserve-traps imply that a trap is now sth well-defined and that for example a division by zero is no longer considered undefined behavior (with all consequences for VRP and thus removing unused divisions)? Is any operation triggering undefined behavior now possibly trapping? In the end the main question to ask is probably what the motivation behind adding -fpreserve-traps is? Is it making a quite vaguely defined part of GCCs behavior properly defined? Is it giving users much needed control about "preserving traps"? I hoped the one jumping on the "traps" bandwagon would have tackled -ftrapv first (thankfully very few references in GCC itself remain), by nuking flag_trapv from the middle-end and reflecting -ftrapv to the IL from the two FEs it is exposed to (C and C++). We did have this situation with adding some extra option, only confusing things further, in the past - not sure if you remember -fstrict-overflow which added a third kind of overflow behavior. Thanks, Richard. > I also agree with Richard's sentiment that GCC should aim to > store semantics in the representation, not in global variables. > Interestingly, whether a tree or rtx can trap has been explicitly > represented in every allocated node for decades; it's what the > compiler should do (or is allowed to do) with that information > that has been missing. > > My proposal is to treat -fpreserve-traps as an experiment for > the time being. Allowing all the places in the compiler that > make assumptions about traps to be found/documented (by searching > for flag_perserve_traps in the source code), and their influence > on performance benchmarked. If things don't work out, there's > the option to revert these patches, or #define flag_perserve_traps 0 > with no run-time overhead. If this option proves useful, we can > figure out how to serialize it in LTO, whether it's controlled > by some language front-ends (e.g. Ada) or target backends, etc. > > I think it was Wittgenstein that explained that you need to have > a name for a concept to reason or argue about it. -fpreserve-traps > is a concept that GCC has never had, which is why it has been > conflated with exceptions and exception handling over the years. > In C++, division by zero is undefined behaviour; having a flag > brings us one step closer to implementation defined. > > This patch has been tested on x86_64-pc-linux-gnu with a "make > bootstrap" and "make -k check" with no new failures. > > Ok for mainline? > > > 2021-08-29 Roger Sayle <ro...@nextmovesoftware.com> > Eric Botcazou <ebotca...@adacore.com> > Richard Biener <rguent...@suse.de> > > gcc/ChangeLog > PR tree-optimization/38943 > * common.opt (fpreserve-traps): New code generation option. > * doc/invoke.texi (-fpreserve-traps): Document new option. > * gimple.c (gimple_has_side_effects): Consider trapping to > be a side-effect when -fpreserve-traps is specified. > * ipa-pure-const.c (check_stmt): When preserving traps, > a trapping statement should be considered a side-effect, > so the function is neither const nor pure. > > gcc/testsuite/ChangeLog > PR tree-optimization/38943 > * gcc.dg/pr38943.c: New test case. > > Roger > -- > Roger > > -----Original Message----- > From: Richard Biener <richard.guent...@gmail.com> > Sent: 12 July 2021 12:26 > To: Roger Sayle <ro...@nextmovesoftware.com> > Cc: Eric Botcazou <botca...@adacore.com>; GCC Patches > <gcc-patches@gcc.gnu.org> > Subject: Re: [PATCH take 2] PR tree-optimization/38943: Preserve trapping > instructions with -fpreserve-traps > > ... > > I've reviewed the cited PRs and most of them would have individual fixes and > are not fixed by your patch, though -fpreserve-traps would offer a workaround > in some cases. > > Now, -fpreserve-traps follows the unfortunate precedence of tieing IL > semantics to a (global) flag rather than to individual stmts. I'm not sure > -fpreserve-traps is something good to offer since on its own it looks not too > useful and for making use of it one still needs -fnon-call-exceptions > [-fexceptions]. > > There's still the open question what -fnon-call-exceptions on its own should > do - IMHO it doesn't make sense to allow unwiding from a trapping memory > reference but not from the call it resides in which means > -fnon-call-exceptions should better enable -fexceptions? > > There's also valid points made in some of the PRs (some of which look like > dups of each other) that an asm with memory operands should be trapping and > thus throwing with -fnon-call-exceptions even when it is not volatile and > that some builtin functions like memcpy should not be nothrow with > -fnon-call-exceptions. > > There's const-correctness pieces in your patch - those are OK under the > obvious rule and you might want to push them separately. > > Thanks, > Richard. > >