public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH take 3] Experimental -fpreserve-traps option
@ 2021-08-29  9:27 Roger Sayle
  2021-08-30  7:13 ` Richard Biener
  0 siblings, 1 reply; 4+ messages in thread
From: Roger Sayle @ 2021-08-29  9:27 UTC (permalink / raw)
  To: 'GCC Patches', 'Richard Biener'; +Cc: 'Eric Botcazou'

[-- Attachment #1: Type: text/plain, Size: 5072 bytes --]


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.

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.

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  <roger@nextmovesoftware.com>
            Eric Botcazou  <ebotcazou@adacore.com>
            Richard Biener  <rguenther@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.guenther@gmail.com> 
Sent: 12 July 2021 12:26
To: Roger Sayle <roger@nextmovesoftware.com>
Cc: Eric Botcazou <botcazou@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.



[-- Attachment #2: patche.log --]
[-- Type: application/octet-stream, Size: 3452 bytes --]

[PATCH take 3] Experimental -fpreserve-traps option

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.

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.

I also agree with Richard's sentiment that GCC should aim to
store semantics in the representation, not in global variables.
Interesting, 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  <roger@nextmovesoftware.com>
	    Eric Botcazou  <ebotcazou@adacore.com>
	    Richard Biener  <rguenther@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
--

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH take 3] Experimental -fpreserve-traps option
  2021-08-29  9:27 [PATCH take 3] Experimental -fpreserve-traps option Roger Sayle
@ 2021-08-30  7:13 ` Richard Biener
  2021-08-30  9:12   ` Roger Sayle
  0 siblings, 1 reply; 4+ messages in thread
From: Richard Biener @ 2021-08-30  7:13 UTC (permalink / raw)
  To: Roger Sayle; +Cc: GCC Patches, Eric Botcazou

On Sun, Aug 29, 2021 at 11:28 AM Roger Sayle <roger@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  <roger@nextmovesoftware.com>
>             Eric Botcazou  <ebotcazou@adacore.com>
>             Richard Biener  <rguenther@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.guenther@gmail.com>
> Sent: 12 July 2021 12:26
> To: Roger Sayle <roger@nextmovesoftware.com>
> Cc: Eric Botcazou <botcazou@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.
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [PATCH take 3] Experimental -fpreserve-traps option
  2021-08-30  7:13 ` Richard Biener
@ 2021-08-30  9:12   ` Roger Sayle
  2021-08-30  9:41     ` Richard Biener
  0 siblings, 1 reply; 4+ messages in thread
From: Roger Sayle @ 2021-08-30  9:12 UTC (permalink / raw)
  To: 'Richard Biener'; +Cc: 'GCC Patches', 'Eric Botcazou'


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.

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.

Cheers,
Roger
--

-----Original Message-----
From: Richard Biener <richard.guenther@gmail.com> 
Sent: 30 August 2021 08:13
To: Roger Sayle <roger@nextmovesoftware.com>
Cc: GCC Patches <gcc-patches@gcc.gnu.org>; Eric Botcazou <botcazou@adacore.com>
Subject: Re: [PATCH take 3] Experimental -fpreserve-traps option

On Sun, Aug 29, 2021 at 11:28 AM Roger Sayle <roger@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  <roger@nextmovesoftware.com>
>             Eric Botcazou  <ebotcazou@adacore.com>
>             Richard Biener  <rguenther@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.guenther@gmail.com>
> Sent: 12 July 2021 12:26
> To: Roger Sayle <roger@nextmovesoftware.com>
> Cc: Eric Botcazou <botcazou@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.
>
>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH take 3] Experimental -fpreserve-traps option
  2021-08-30  9:12   ` Roger Sayle
@ 2021-08-30  9:41     ` Richard Biener
  0 siblings, 0 replies; 4+ messages in thread
From: Richard Biener @ 2021-08-30  9:41 UTC (permalink / raw)
  To: Roger Sayle; +Cc: GCC Patches, Eric Botcazou

On Mon, Aug 30, 2021 at 11:13 AM Roger Sayle <roger@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.guenther@gmail.com>
> Sent: 30 August 2021 08:13
> To: Roger Sayle <roger@nextmovesoftware.com>
> Cc: GCC Patches <gcc-patches@gcc.gnu.org>; Eric Botcazou <botcazou@adacore.com>
> Subject: Re: [PATCH take 3] Experimental -fpreserve-traps option
>
> On Sun, Aug 29, 2021 at 11:28 AM Roger Sayle <roger@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  <roger@nextmovesoftware.com>
> >             Eric Botcazou  <ebotcazou@adacore.com>
> >             Richard Biener  <rguenther@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.guenther@gmail.com>
> > Sent: 12 July 2021 12:26
> > To: Roger Sayle <roger@nextmovesoftware.com>
> > Cc: Eric Botcazou <botcazou@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.
> >
> >
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-08-30  9:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-29  9:27 [PATCH take 3] Experimental -fpreserve-traps option Roger Sayle
2021-08-30  7:13 ` Richard Biener
2021-08-30  9:12   ` Roger Sayle
2021-08-30  9:41     ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).