Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #174243 > unrolled thread
| Started by | candycane@f172.n1.z21.fsxnet (candycane) |
|---|---|
| First post | 2023-09-06 19:53 +1300 |
| Last post | 2023-09-09 10:23 -0700 |
| Articles | 9 on this page of 129 — 12 participants |
Back to article view | Back to comp.lang.c
Re: bart again (UCX64) candycane@f172.n1.z21.fsxnet (candycane) - 2023-09-06 19:53 +1300
Re: bart again (UCX64) Richard Damon <Richard@Damon-Family.org> - 2023-09-07 12:00 -0700
Re: bart again (UCX64) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-07 16:33 -0700
Re: bart again (UCX64) Richard Damon <Richard@Damon-Family.org> - 2023-09-07 20:55 -0700
Re: bart again (UCX64) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-07 22:16 -0700
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-08 07:09 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 10:10 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-08 01:30 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 11:26 +0200
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-08 10:44 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 13:26 +0200
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 01:57 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-09 18:36 +0200
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 18:19 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 13:28 +0200
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-10 13:20 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 15:19 +0200
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-10 16:07 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 18:33 +0200
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-10 15:44 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 18:36 +0200
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 01:48 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-09 19:04 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-08 02:47 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 16:03 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-08 16:06 -0700
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-09 01:52 +0100
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-08 18:16 -0700
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-09 21:31 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 12:03 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-10 21:36 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 08:51 +0200
Re: bart again (UCX64) "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-09-10 23:59 -0700
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 01:01 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 11:17 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 03:16 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 14:58 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 06:35 -0700
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-11 14:13 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 16:24 +0200
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 14:55 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 16:42 +0200
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-11 14:29 +0000
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 11:25 +0100
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 03:59 -0700
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-11 13:57 +0000
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 09:52 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 16:07 +0200
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-11 16:26 +0100
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 16:47 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 19:14 +0200
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-11 22:30 +0100
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 23:07 +0100
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-11 23:31 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 09:18 +0200
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 03:01 +0100
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 10:08 -0700
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-11 23:18 +0100
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 23:37 +0100
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 15:46 -0700
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-11 23:40 +0000
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 01:50 +0100
Re: bart again (UCX64) Richard Damon <Richard@Damon-Family.org> - 2023-09-11 17:59 -0700
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-12 01:03 +0000
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 02:39 +0100
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 11:28 +0100
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 14:49 +0100
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 15:18 +0100
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 03:58 +0100
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-12 02:25 -0700
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 16:17 +0100
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 17:28 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 21:07 +0200
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 03:01 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 09:38 +0200
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 10:00 +0200
Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-19 05:22 -0700
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-19 14:29 +0100
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 13:35 +0100
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 20:48 +0100
Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-19 05:53 -0700
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-12 09:33 -0700
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-12 16:48 +0000
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-12 10:57 -0700
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-12 18:07 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 21:23 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 02:07 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 12:43 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 04:04 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 14:07 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 01:47 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 13:02 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 04:45 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 14:36 +0200
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-13 13:43 +0000
Re: bart again (UCX64) James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-09-13 11:10 -0400
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-13 17:12 +0000
[meta] spam in thread Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 11:22 -0700
Re: [meta] spam in thread Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-13 18:40 +0000
Re: [meta] spam in thread Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 11:48 -0700
Re: [meta] spam in thread David Brown <david.brown@hesbynett.no> - 2023-09-13 21:01 +0200
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 19:58 +0100
Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-18 12:36 -0700
Re: bart again (UCX64) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-18 13:40 -0700
Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-20 19:43 -0700
Re: bart again (UCX64) "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-09-20 20:14 -0700
Re: bart again (UCX64) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-20 22:10 -0700
Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-10-01 11:03 -0700
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 07:39 -0700
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-13 15:18 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 18:39 +0200
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 15:44 +0100
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 08:42 -0700
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 22:35 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 18:49 +0200
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 15:40 -0700
Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 03:36 +0100
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 12:58 +0200
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 12:49 +0200
Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 12:52 +0100
Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-12 05:22 -0700
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 15:05 +0200
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 02:17 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 14:44 +0200
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-08 14:36 +0000
Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 01:50 +0000
Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-09 15:40 +0000
Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 09:57 +0200
Re: bart again (UCX64) Richard Damon <Richard@Damon-Family.org> - 2023-09-09 10:23 -0700
Page 7 of 7 — ← Prev page 1 2 3 4 5 6 [7]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2023-09-12 05:22 -0700 |
| Message-ID | <c187a2fe-441d-4ad9-a062-4f3855189578n@googlegroups.com> |
| In reply to | #175193 |
On Tuesday, 12 September 2023 at 12:52:24 UTC+1, Bart wrote: > On 12/09/2023 11:49, David Brown wrote: > > On 11/09/2023 19:08, Malcolm McLean wrote: > > >> But things which are liley to be helpful and things which are > >> likely not to be. Bascially programs fall into two categories. Life > >> support > >> systems, where the worst thing you can do is return wrong results. And > >> video games, where the worst thing you can do is return no results. > > > > You're mad. Or you are trolling. > > > > It's a spectrum - obviously. > It's more of a gamut. > If a program has an error in it, then it cannot return correct results. It can return wrong results. Or it can return no results at all. Now every user must have a preference. Would you prefer wrong results, or no results? Some stupid users would say "neither" but of course that's not an option. It's a given that the program is incorrect. I suppose they could say "both are exactly equal", but that's very unlikely. There must be an ordering. If the user is a life support system, you definitely want no results rather than wrong results, because you can detect no results easily, whilst wrong results might slip through. If the user is a video games player, you definitely want wrong results rather than no results. If the game terminates with an error message it is dead and enjoyment is ruined. If some of the results are wrong, most likely it will be only a glitch and it will recover, and the user can continue playing. Now of course other programs can be less extreme. No-one is going to die if a scientific spreadsheet returns wrong results for a statistical analysis. But errors will creep into the published paper. Clearly you want no results. A wordprocessor, bugs are far more annoying than in a video game. But the user can usually see any errors immediately. So you want to display wrong results rather than have no results. Every user must be in one of those two classes. Either no results are better than wrong results, or wrong results are better than no results.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-09-12 15:05 +0200 |
| Message-ID | <udpnmh$1ii0s$1@dont-email.me> |
| In reply to | #175193 |
On 12/09/2023 13:52, Bart wrote:
> On 12/09/2023 11:49, David Brown wrote:
>> On 11/09/2023 19:08, Malcolm McLean wrote:
>
>>> But things which are liley to be helpful and things which are
>>> likely not to be. Bascially programs fall into two categories. Life
>>> support
>>> systems, where the worst thing you can do is return wrong results. And
>>> video games, where the worst thing you can do is return no results.
>>
>> You're mad. Or you are trolling.
>>
>> It's a spectrum - obviously.
>
> It's more of a gamut.
Fair enough - it is not one-dimensional. But it is certainly not binary!
>
>> Mistakes do happen. Hiding them is a bad idea. Examples of that
>> would include a language/compiler having a default "return 0;" on
>> non-void functions, explicitly adding a "return 0;" when code flow
>> should never reach that point, or having a function that should never
>> be given a NaN have handling for NaNs.
>
> And yet, such default initialisations do exist in C, and they could well
> hide certain kinds of errors.
Yes, there are always tradeoffs here. The efficiency benefits of
initialising data to 0 can be significant, so it is worth doing for
static data at startup, and it is often useful for dynamic memory
allocation. (It is also useful in some environments to prevent the risk
of leaking data from one process to another.) It would have been
reasonable for C to insist that every statically allocated variable had
an explicit initialiser, but I think it is clear enough that you get 0
by default and other initialisations override that. It would, perhaps,
have been better if using uninitialised statically allocated data could
be detected at compile time and an error message given, but I can't see
how that would be feasible.
For local non-static variables, on the other hand, it is a much more
realistic task to detect when they are used without initialisation, so
it is a good thing that there is no default initialisation here.
(Sometimes it would be convenient to have a standardised syntax for
saying that a variable should be left uninitialised. In my line of
work, that would make sense for buffers and the like - there is no
advantage in clearing them at startup.)
>
> For example, static objects are set to all zeros unless explicitly
> initialised. That is generally considered useful, and has come to be
> something you can confidently rely on.
It has, AFAIK, /always/ been something you can confidently rely on
except for one or two terrible C implementations. (The biggest sinner
here is Texas Instrument's C implementations, many of which do not
zero-initialise uninitialised static data. It is really a PITA.)
>
>> An "unreachable();" statement is clearer and avoids misconceptions,
>> as well as giving more efficient code in some cases, and potentially
>> allowing more static error checking. It should be possible to turn it
>> into a trap of some sort (abort, run-time error message, debugger
>> breakpoint, etc.) via either compiler options or changing the
>> definition of a macro or the function - this is something you cannot
>> do with a "return 0;" or "return x;" statement.
>
> I might use 'return 0' in my language to satisfy a constraint. But I
> might sometimes return an error code, such as -1, 9999, or i64.min, just
> in case control does reach that point. I might after all make a
> modification that could make that possible.
>
> Alternately, I can add a call to an error function, one that is defined
> to have a suitable return type to satisfy the constraint (so no separate
> return is needed).
>
> On PCs, such things have insignificant overheads. I can understand that
> on your targets, they could be significant.
/Sometimes/ on PC's they have insignificant overhead - certainly more
often than in embedded systems. But sometimes on PC's they have
significant overheads too.
Consider the infamous sign function :
int sign(double x) {
if (x < 0.0) return -1;
if (x == 0.0) return 0;
if (x > 0.0) return 1;
unreachable();
}
When "unreachable()" has no effect (other than informing the compiler
and the reader that control flow never reaches this point), the function
is a "pure" function. The output depends solely on the input. (This is
also true if it were replaced by "return 0;" or "return x;".) Such
functions are /much/ nicer to handle for optimisation and analysis, both
by humans and software. A compiler that knows a function is "pure"
(such as by using gcc or C23 attributes, or simply because the
definition is available - probably as an inline function) can move the
call around, in and out of loops, or eliminate or pre-calculate calls.
A human trying to understand the code knows it is "safe" and cannot
affect other parts of the program.
However, if "unreachable()" can print an error message or halt the
program, it is a completely different situation. Now the function has
very significant observable behaviour, and cannot be optimised or
analysed in the same way. You have a totally different call graph for
the function, totally different stack usage analysis (that's important
in small embedded systems), different effects on things like stderr or
stdout streams, and so on. And that is all to handle a situation that
will never occur (at least, not once the calling code is debugged).
And you've got a line in your code that has major and potentially
catastrophic effects if it is run, but is completely untestable().
To me, these are very significant overheads. But to be clear - these
are overheads if the last line is an "abort()" or run-time error
handler. The overheads of a "return 0;" or the like are much smaller.
The caller still gets the wrong return value - but it can't expect
anything better when it gave an invalid argument.
I prefer a macro-based approach, or compiler flag option (or whatever
the equivalent solutions are in your language) that lets the user write
"unreachable();" for efficiency, while being able to easily make a
temporary halt or error message when fault-finding and debugging.
>
> But what you are arguing for is to use such leaner, less foolproof
> mechanisms even on systems where there are plenty of resources.
I am actually arguing that these are /better/ - not just leaner, but
give more possibilities for finding and fixing problems.
> Ironically, ones which require compilers that need plenty of their own
> resources to use effectively.
The PC I use for compiling code has a million times more ram than than
the target device for a program I am working on at the moment. I don't
mind that the compiler uses lots of resources if it saves resources on
the target.
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <864-117-4973@kylheku.com> |
|---|---|
| Date | 2023-09-09 02:17 +0000 |
| Message-ID | <20230908185812.914@kylheku.com> |
| In reply to | #174513 |
On 2023-09-08, David Brown <david.brown@hesbynett.no> wrote:
> So if you are not sure the code point is unreachable, don't "call"
> unreachable(). It's very simple.
Here is a bit of evening entertainment.
In a Lisp compiler I developed I was suprised to see that it optimized
away the return sequence from a function due to that being unreachable
(not by being declared that way, just deduced trhough control flow
analysis).
Watch what happens to at optimization levels 0, 3 and 5 to the
expression (while t (put-line "hello")), an infinite loop:
I was surprised because I was not "after" that at all; the optimizations were
not developed with that specific situation in mind.
It's a like when people write chess programs which then surprise them
by playing betetr than their makers.
Baseline code geneartion at level zero:
1> (let ((*opt-level* 0)) (disassemble (compile-toplevel '(while t (put-line "hello")))))
data:
0: t
1: "hello"
syms:
0: put-line
code:
0: 4C00000B block t2 nil 11
1: 00020000
2: 04020000 frame 2 0
3: 38000008 if d0 8
4: 00000400
5: 20010005 gcall t5 0 d1
6: 04010000
7: 34000003 jmp 3
8: 10000000 end nil
9: 2C020000 movsr t2 nil
10: 10000002 end t2
11: 10000002 end t2
instruction count:
9
#<sys:vm-desc: 9009a60>
At level 3, the block and frame are removed. However, "if d0 5" is being
stupidly executed. This means branch off to the instruction at offset 5 if the
condition is NOT true, otherwise proceed. d0 refers to a static data register,
which holds the t symbol; the condition is always true.
2> (let ((*opt-level* 3)) (disassemble (compile-toplevel '(while t (put-line "hello")))))
data:
0: t
1: "hello"
syms:
0: put-line
code:
0: 38000005 if d0 5
1: 00000400
2: 20010005 gcall t5 0 d1
3: 04010000
4: 34000000 jmp 0
5: 10000000 end nil
instruction count:
4
#<sys:vm-desc: 90cd530>
At level 5, things get more clever. The pointless if instruction is removed.
The "5 ... end nil" instruction was only reachable through that instruction
taking the branch, and so that instruction is gone:
3> (let ((*opt-level* 5)) (disassemble (compile-toplevel '(while t (put-line "hello")))))
data:
0: "hello"
syms:
0: put-line
code:
0: 20010005 gcall t5 0 d0
1: 04000000
2: 34000000 jmp 0
instruction count:
2
#<sys:vm-desc: 927f610>
So now the function doesn't include a wasteful end instruction.
That stood out to my eyes right away because right until that point I was so
used to seeing those terminating "end" instructions.
In C, a compiler could do something similar: when the end of the function is
not reachable, it could omit emitting any register restoring code and ret
instruction, making the function smaller.
Now if you lie to the compiler that the end is unreachable, even though it is,
it could do the optimization code anyway, and leave the branch in place. Or
remove the branch also, and adjust the jmp so that the loop becomes infinite.
For instance suppose the instruction tested some register t4, which gets
loaded from some global variable that could be changing. that "if t4 5",
in the false case, jumps to code that we have declard unreachable.
There is no point in that, so the instruction gets erased.
Since the instruction gets erased, the instruction which calculated t4
now by accessing the global variable now a dead t4 register.
So that instruction gets removed. The backwards jmp in the loop
now goes to whatever instruction follows: the loop has become infinite;
repeating without testing that global variable.
Wrong facts that you declare trigger a cascade of deductions that are
increasingly removed from the circumstances of that fact.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-09-10 14:44 +0200 |
| Message-ID | <udkdn0$it6d$1@dont-email.me> |
| In reply to | #174667 |
On 09/09/2023 04:17, Kaz Kylheku wrote:
> On 2023-09-08, David Brown <david.brown@hesbynett.no> wrote:
>> So if you are not sure the code point is unreachable, don't "call"
>> unreachable(). It's very simple.
>
> Here is a bit of evening entertainment.
>
> In a Lisp compiler I developed I was suprised to see that it optimized
> away the return sequence from a function due to that being unreachable
> (not by being declared that way, just deduced trhough control flow
> analysis).
>
> Watch what happens to at optimization levels 0, 3 and 5 to the
> expression (while t (put-line "hello")), an infinite loop:
>
> I was surprised because I was not "after" that at all; the optimizations were
> not developed with that specific situation in mind.
>
> It's a like when people write chess programs which then surprise them
> by playing betetr than their makers.
>
(I'm snipping the Lisp stuff that I can't easily follow - but keeping
your analogy, since I can follow that!)
>
> So now the function doesn't include a wasteful end instruction.
> That stood out to my eyes right away because right until that point I was so
> used to seeing those terminating "end" instructions.
>
> In C, a compiler could do something similar: when the end of the function is
> not reachable, it could omit emitting any register restoring code and ret
> instruction, making the function smaller.
Yes, and C compilers often do that.
There's no point in manually adding "unreachable()" unless it conveys
useful information to the compiler and/or the reader. So it would be
pointless here:
int negabs(int x) {
if (x < 0) {
return x;
} else {
return -x;
}
unreachable();
}
But it would be entirely appropriate here:
// uartNo must be 0, 1 or 2
uart_t * get_uart_instance(int uartNo) {
if (uartNo == 0) return UART0;
if (uartNo == 1) return UART1;
if (uartNo == 2) return UART2;
unreachable();
}
Alternatively, you could write:
// uartNo must be 0, 1 or 2
uart_t * get_uart_instance(int uartNo) {
if ((uartNo < 0) || (uartNo > 2)) unreachable();
if (uartNo == 0) return UART0;
if (uartNo == 1) return UART1;
if (uartNo == 2) return UART2;
}
We could also write:
// uartNo must be 0, 1 or 2
uart_t * get_uart_instance(int uartNo) {
static uart_t * const uarts[] = { UART0, UART1, UART2 };
return uarts[uartNo];
}
Would you be as concerned about the implicit undefined behaviour in this
third version as you are with the explicit cases?
A smart enough compiler can figure out many things, but sometimes the
programmer has more information than is available to the compiler, and
sometimes compilers are not as smart as we'd like. C does not really
have a good way to tell the compile useful things, or to give clear
specifications to functions. (C++ is getting some of the in C++23.)
>
> Now if you lie to the compiler that the end is unreachable, even though it is,
> it could do the optimization code anyway, and leave the branch in place. Or
> remove the branch also, and adjust the jmp so that the loop becomes infinite.
Yes, lying to your compiler always ends in tears.
>
> For instance suppose the instruction tested some register t4, which gets
> loaded from some global variable that could be changing. that "if t4 5",
> in the false case, jumps to code that we have declard unreachable.
> There is no point in that, so the instruction gets erased.
>
> Since the instruction gets erased, the instruction which calculated t4
> now by accessing the global variable now a dead t4 register.
> So that instruction gets removed. The backwards jmp in the loop
> now goes to whatever instruction follows: the loop has become infinite;
> repeating without testing that global variable.
>
> Wrong facts that you declare trigger a cascade of deductions that are
> increasingly removed from the circumstances of that fact.
>
Yes. And correct facts that you declare can trigger a cascade of
deductions that increasingly improve the effectiveness of the code and
of static analysis.
So don't lie to your compiler - but /do/ tell it useful truths.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2023-09-08 14:36 +0000 |
| Message-ID | <7kGKM.80955$Wk53.72758@fx01.iad> |
| In reply to | #174505 |
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes: >On Friday, 8 September 2023 at 09:10:20 UTC+1, David Brown wrote: >> >> Note that since trying to execute "unreachable()" (as the C23 function >> is called) is undefined behaviour, compilers can freely add debugging >> and fault-finding options to give a run-time diagnostic if the code is >> actually reached. But if the standard had defined the behaviour of >> "unreachable()" to be somewhat like "abort()", compilers would not be >> free to use it for efficient optimisation, or to aid static analysis. >> >The difference is that the programmer might want to deliberately call >abort() as part of the expected runtime behaviour of the program. Not in any company I've worked with. abort() is extremely user-unfriendly.
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <864-117-4973@kylheku.com> |
|---|---|
| Date | 2023-09-09 01:50 +0000 |
| Message-ID | <20230908184909.736@kylheku.com> |
| In reply to | #174589 |
On 2023-09-08, Scott Lurndal <scott@slp53.sl.home> wrote: > Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes: >>On Friday, 8 September 2023 at 09:10:20 UTC+1, David Brown wrote: >>> >>> Note that since trying to execute "unreachable()" (as the C23 function >>> is called) is undefined behaviour, compilers can freely add debugging >>> and fault-finding options to give a run-time diagnostic if the code is >>> actually reached. But if the standard had defined the behaviour of >>> "unreachable()" to be somewhat like "abort()", compilers would not be >>> free to use it for efficient optimisation, or to aid static analysis. >>> >>The difference is that the programmer might want to deliberately call >>abort() as part of the expected runtime behaviour of the program. > > Not in any company I've worked with. abort() is extremely user-unfriendly. It's better than exit. More than once I had to fix a well-meaning exit(0) or exit(1) in error handling code to abort. For instance if you have the program under the debugger, abort will stop and you ahve a call stack. To get that from exit, you have to put a breakpoint on exit. abort() can leave core dumps. If all you do is call abort, it's user unfriendly because there is no diagnostic. However, the astute Unix graybeard will notice that the program died due to signal 6. :) -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal Mastodon: @Kazinator@mstdn.ca NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2023-09-09 15:40 +0000 |
| Message-ID | <Cl0LM.1449506$GMN3.722040@fx16.iad> |
| In reply to | #174665 |
Kaz Kylheku <864-117-4973@kylheku.com> writes: >On 2023-09-08, Scott Lurndal <scott@slp53.sl.home> wrote: >> Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes: >>>On Friday, 8 September 2023 at 09:10:20 UTC+1, David Brown wrote: >>>> >>>> Note that since trying to execute "unreachable()" (as the C23 function >>>> is called) is undefined behaviour, compilers can freely add debugging >>>> and fault-finding options to give a run-time diagnostic if the code is >>>> actually reached. But if the standard had defined the behaviour of >>>> "unreachable()" to be somewhat like "abort()", compilers would not be >>>> free to use it for efficient optimisation, or to aid static analysis. >>>> >>>The difference is that the programmer might want to deliberately call >>>abort() as part of the expected runtime behaviour of the program. >> >> Not in any company I've worked with. abort() is extremely user-unfriendly. > >It's better than exit. More than once I had to fix a well-meaning >exit(0) or exit(1) in error handling code to abort. I do not disagree with that statement; I did not intend to imply that simply exit was a proper error handling mechanism. There are a number of ways to produce useful information in such a situation if it cannot be recovered from (which should be the first choice, when possible).
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-09-08 09:57 +0200 |
| Message-ID | <udek5q$3cm04$1@dont-email.me> |
| In reply to | #174478 |
On 08/09/2023 07:16, Keith Thompson wrote: > Richard Damon <Richard@Damon-Family.org> writes: >> One option would be to allow an [[unreachable]] attribute to mark that >> you can't get here, even if the base rules don't prove it, and leave >> the results Undefined if you somehow do get there. > > I like it. It's similar to the /*NOTREACHED*/ comment recognized by > many lint implementations. > Even better, IMHO, would be a clearly named function (or function-like macro) to indicate unreachable code. Fortunately for me, C23 has already thought of that! <https://en.cppreference.com/w/c/program/unreachable> Until C23 comes out, many of us can use "__builtin_unreachable()" in gcc, clang, icc, etc., or "__assume(false))" in MSVC. > It could be added *instead* of requiring reachability analysis, and a > programmer could add [[unreachable]] before the closing } of a non-void > function. But adding the requirement I propose would catch errors made > by programmers who don't do that. > Why not have both? Each solution is useful in situations where the other is not.
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2023-09-09 10:23 -0700 |
| Message-ID | <jS1LM.329455$f7Ub.121965@fx47.iad> |
| In reply to | #174478 |
On 9/7/23 10:16 PM, Keith Thompson wrote:
> Richard Damon <Richard@Damon-Family.org> writes:
>> On 9/7/23 4:33 PM, Keith Thompson wrote:
>>> Richard Damon <Richard@Damon-Family.org> writes:
>>>> On 9/5/23 11:53 PM, candycane wrote:
>>>>> KK> This doesn't:
>>>>> KK> int fred(void)
>>>>> KK> {
>>>>> KK> while (1) {
>>>>> KK> }
>>>>> KK> }
>>>>> KK> The previous one will be a nuisance diagnosic since the
>>>>> always_true
>>>>> KK> function always returns true.
>>>>> KK> If the belief is correct, why not restructure the code:
>>>>> KK> int fred(void)
>>>>> KK> {
>>>>> KK> extern int always_true(void);
>>>>> KK> for (;;) {
>>>>> KK> always_true(); // call for its side effect only
>>>>> KK> }
>>>>> KK> }
>>>>> I may be reading this wrong, but aren't you getting into the Halting
>>>>> Problem at this point?
>>>>
>>>> Fulling solving the problem would be the Halting Problem, but there
>>>> are shortcuts that can get the vast majority.
>>>>
>>>> Mark functions that don't ever return with -Noreturn or [[noreturn]]
>>>> (or an equivalent).
>>>>
>>>> Assume loops with a non-constant control expression will at some point
>>>> terminate (yes, this isn't strictly true, but is a reasonable
>>>> assumption, and is made elsewhere in the standard).
>>>>
>>>> Since the above program has a for loop with an always true condition,
>>>> that can be assumed never to end (since there is no "break" in the
>>>> loop).
>>> It's not necessary to assume that such loops always terminate. Just
>>> don't assume anything one way or the other.
>>
>> Except that if you want to make falling off the end of an non-void
>> function an error, you can't do that.
>>
>> Note, from 6.8.5 p6 which states (using N2596):
>>
>> An iteration statement may be assumed by the implementation to
>> terminate if its controlling expression is not a constant
>> expression,171) and none of the following operations are performed in
>> its body, controlling expression or (in the case of a for statement)
>> its expression-3:172)
>> — input/output operations
>> — accessing a volatile object
>> — synchronization or atomic operations.
>>
>> This is a rule that allows optimizations to remove a loop that has no
>> external effect. A similar rule could be used to determine if the end
>> of the function is potentially reachable.
>
> That does complicate things. Note that currently an implementation is
> allowed but not required to "assume" that the loop terminates.
> Currently, the standard never requires control flow analysis to
> determine whether a constraint is violated.
>
> I'm not sure what the best solution is. I'd like to say that 6.8.5p6
> should be ignored when determining whether a diagnostic is required for
> potentially reaching a closing }.
The issue is that many functions DON'T reach the final }. and some
return values (particularly structures) might be "expensive", so it
would be desired to minimize cases where a dummy return statement is needed.
Using a simple test, will catch almost every real case. It will be rare
for real code to use a non-constant expression that the programmer KNOWS
the value will always be true, and if being done for side effects, could
just be changed to add a comma operator followed by true to make it
constant.
That, or you can add the dummy return statement if cheap (like it
normally will be).
>
> Full disclosure: I really dislike that statement in the standard, both
> because of its semantics and because it's written to permit an
> implementation to "assume" certain things rather than in terms of
> permitted behavior.
My guess is that some library + optimizer ran into the issue that some
cases generated "worthless" looping looking for something that was never
used. Seeing that the results of the loop had no effect, just removing
it helped speed up the code.
Note, the actual cases where it can be used is fairly limited, as it
says, in effect, that the loop creates no observable behavior, and the
compiler can determine the value of any variable changed in the loop
that is used later.
Note, that standard if FULL of such assumptions, because any statement
that can Undefined Behavior in certain conditions means the
implementation is allowed to assume that those conditions don't exists.
And that assumption can even precede the statement with Undefined
Behavior if no observable behavior happens between.
The assumption just isn't as clearly spelled out.
>
>>> For example:
>>> int fred(void) {
>>> while (1) {
>>> ;
>>> }
>>> }
>>> Since the condition is a constant expression, a reasonably clever
>>> compiler can prove that the closing } is unreachable, so no warning is
>>> necessary. But:
>>> int barney(void) {
>>> while (some_function()) {
>>> ;
>>> }
>>> }
>>> Since the condition is not constant, the compiler doesn't know
>>> whether
>>> the closing } is reachable. If, as I've suggested, C were to adopt the
>>> C# rules, a diagnostic message would be mandatory, because the closing }
>>> *might* be reached. (Even if the compiler is able to determine that
>>> some_function() always returns 1, because it's defined in the same
>>> translation unit, the diagnostic message would still be required.)
>>
>> Right, because we need to define the level of effort the compiler
>> needs to do. And it should avoid "surprizes" as much as possible.
>>
>>> In other words, define a straightforward set of rules for
>>> determining
>>> whether a point in the code (particularly the closing } of a non-void
>>> function other than main) is potentially reachable, rules that do not
>>> make any assumptions about non-constant values.
>>>
>>
>> Right, and using the existing "rule" about loops with non-constant
>> control expressions makes the most sense.
Which is why I suggested it.
>>
>>> Such a change to C would break some existing code. That's absolutely a
>>> valid reason to oppose it. On the other hand, every major edition of
>>> the C standard has broken some existing code, and compilers have always
>>> supported older versions and/or used non-fatal warnings, so such code
>>> would not be *fatally* broken.
>>> With the C# rules, there are some unavoidable false positives, such
>>> as:
>>> int sign(int n) {
>>> if (n < 0) return -1;
>>> if (n == 0) return 0;
>>> if (n > 0) return 1;
>>> }
>>> which are fairly easy to "fix". There are, if I'm not mistaken, no
>>> false negatives.
>>
>> Right. But make the function take a double instead of an int, and it
>> CAN fall through (on some implementations) since there exist double
>> values that are none of >0, <0 or == 0.
>
> That's a different function. I wrote the sign() function above to make
> the point I wanted to make.
>
>> One option would be to allow an [[unreachable]] attribute to mark that
>> you can't get here, even if the base rules don't prove it, and leave
>> the results Undefined if you somehow do get there.
>
> I like it. It's similar to the /*NOTREACHED*/ comment recognized by
> many lint implementations.
>
> It could be added *instead* of requiring reachability analysis, and a
> programmer could add [[unreachable]] before the closing } of a non-void
> function. But adding the requirement I propose would catch errors made
> by programmers who don't do that.
>
[toc] | [prev] | [standalone]
Page 7 of 7 — ← Prev page 1 2 3 4 5 6 [7]
Back to top | Article view | comp.lang.c
csiph-web