On Mon, Aug 30, 2021 at 11:13 AM Roger Sayle <ro...@nextmovesoftware.com> wrote: > > > Hi Richard, > > > I hoped the one jumping on the "traps" bandwagon would have tackled -ftrapv > > first. > > I did, back in 2003 I introduced (or helped introduce) the flag "-fwrapv" 😊 > https://gcc.gnu.org/legacy-ml/gcc-patches/2003-03/msg02126.html > > Prior to that, signed overflow was undefined in the middle-end, and it was > useful to > have some way to specify the sensible behaviour of having signed and unsigned > arithmetic > behave the same way. I'm delighted that those semantics have become the > default.
Actually -fno-wrapv is the default nowadays. That still is a hassle whenever the compiler itself tries to emit twos-complement arithmetic - while there's the possibility to use unsigned arithmetic for most cases there's no substitute for signed division (albeit the possibly overflowing case is rare). What's most annoying is IMHO that we have a bunch of flags controlling overflow behavior - flag_wrapv, flag_trapv plus flag_sanitize & SANITIZE_SI_OVERFLOW (and we've had a separate flag_strict_overflow and we do have a separate flag_wrapv_pointer now) but not all possible states have well-defined behavior, like flag_trapv && flag_wrapv (we disallow this specific combination of course). > Doh! Sorry for the ENOPATCH. I'll wait to hear how your experiments with > -fnon-call-execeptions > go before trying again, but an interesting additional usage is in match.pd: > > diff --git a/gcc/match.pd b/gcc/match.pd > index f421c74..1eeb5eb 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -348,7 +348,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > /* X / bool_range_Y is X. */ > (simplify > (div @0 SSA_NAME@1) > - (if (INTEGRAL_TYPE_P (type) && ssa_name_has_boolean_range (@1)) > + (if (INTEGRAL_TYPE_P (type) > + && ssa_name_has_boolean_range (@1) > + && !flag_preserve_traps) > @0)) > /* X / X is one. */ > (simplify > > This is the transformation that leads to the counter-intuitive "quantum" > behaviour in PR 77980. > It's difficult to believe that all the language front-ends supported by GCC > consider this transformation > as "safe". Perhaps 20 years from now, preserving traps will be the sensible > default. Yes, but there's interplay with what GCC considers undefined behavior. So wouldn't it better to have flag_divde_by_zero_traps which says divide by zero is _not_ undefined behavior? I think that -fpreserve-traps applying to -ftrapv is not what people would expect (they'd expect dead code to be elided). Richard. > Cheers, > Roger > -- > > -----Original Message----- > From: Richard Biener <richard.guent...@gmail.com> > Sent: 30 August 2021 08:13 > To: Roger Sayle <ro...@nextmovesoftware.com> > Cc: GCC Patches <gcc-patches@gcc.gnu.org>; Eric Botcazou > <botca...@adacore.com> > Subject: Re: [PATCH take 3] Experimental -fpreserve-traps option > > 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. > > > > >