Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #126461 > unrolled thread
| Started by | jacobnavia <jacob@jacob.remcomp.fr> |
|---|---|
| First post | 2018-02-08 22:50 +0100 |
| Last post | 2018-02-15 09:45 +0100 |
| Articles | 19 — 10 participants |
Back to article view | Back to comp.lang.c
The bug jacobnavia <jacob@jacob.remcomp.fr> - 2018-02-08 22:50 +0100
Re: The bug Keith Thompson <kst-u@mib.org> - 2018-02-08 14:15 -0800
Re: The bug jacobnavia <jacob@jacob.remcomp.fr> - 2018-02-13 10:25 +0100
Re: The bug David Brown <david.brown@hesbynett.no> - 2018-02-13 10:51 +0100
Re: The bug jacobnavia <jacob@jacob.remcomp.fr> - 2018-02-13 11:19 +0100
Re: The bug David Brown <david.brown@hesbynett.no> - 2018-02-13 12:23 +0100
Re: The bug Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2018-02-13 08:19 -0800
Re: The bug David Brown <david.brown@hesbynett.no> - 2018-02-15 10:52 +0100
Re: The bug Noob <root@127.0.0.1> - 2018-02-13 16:19 +0100
Re: The bug Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-19 12:11 -0800
Re: The bug supercat@casperkitty.com - 2018-02-19 16:31 -0800
Re: The bug Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-21 23:03 -0800
Re: The bug supercat@casperkitty.com - 2018-02-23 16:40 -0800
Re: The bug Richard Damon <Richard@Damon-Family.org> - 2018-02-24 05:57 -0500
Re: The bug Tim Rentsch <txr@alumni.caltech.edu> - 2018-02-24 13:11 -0800
Re: The bug Anton Shepelev <anton.txt@gmail.com> - 2018-02-25 00:15 +0300
Re: The bug Keith Thompson <kst-u@mib.org> - 2018-02-13 11:44 -0800
Re: The bug asetofsymbols@gmail.com - 2018-02-13 12:13 -0800
Re: The bug Noob <root@127.0.0.1> - 2018-02-15 09:45 +0100
| From | jacobnavia <jacob@jacob.remcomp.fr> |
|---|---|
| Date | 2018-02-08 22:50 +0100 |
| Subject | The bug |
| Message-ID | <p5ignt$45g$1@dont-email.me> |
Consider this program:
1 #include <string.h>
2 #include <stdio.h>
3 #define MANTISSA_LENGTH 7
4 typedef struct tagQfloatAccum {
5 int sign;
6 unsigned int exponent;
7 unsigned long long mantissa[MANTISSA_LENGTH+8];
8 } QfloatAccum;
9 typedef QfloatAccum * QfloatAccump;
10 typedef unsigned long long QELT;
11 static void square(QfloatAccump a,QfloatAccump b,int prec )
12 {
13 QELT *p, *q, *r;
14 unsigned __int128 u, lp;
15 int k;
16
17 memset(b->mantissa,0,sizeof(b->mantissa));
18 r = &b->mantissa[prec+2];
19 for( k=prec+2; k>=2; k-- ) {
20 q = &a->mantissa[1];
21 p = &a->mantissa[k-1];
22 while( p >= q ) {
23 lp = ((__int128)(*p)) * (*q);
24 if( p != q ) {
25 if( ((lp >> 127) & 1 ) )
26 *(r-2) += 1;
27 lp <<= 1;
28 }
29 u = lp&0xffffffffffffffffULL;;
30 u += *r;
31 (*r) = (u&0xffffffffffffffffULL);
32 u = u >> 64;
33 u += (lp >> 64);
34 u += *(r-1);
35 *(r-1) = u;
36 *(r-2) += (u >> 64);
37 p--;
38 q++;
39 }
40 --r;
41 }
42 }
43
44 QfloatAccum a =
45 {0x0, 0x0, {0x0, 0x5c551d94ae0bf85d, 0xdf43ff68348e9f44,
0x75abbd546eb4ad2c , 0x45928b3668d09923, 0xef0e21fbaa8bb66b,
46 0xd834f79a27f3d70b, 0xe29f8b325d2f09bc, 0x22342f2796cceefe,
0x15136c1f 974cb8e4, 0x0, 0x0, 0x0, 0x0, 0x0}};
47 QfloatAccum b = {0};
48 QfloatAccum result =
49 {0x0, 0x0, {0x0, 0x214d498f853f343e, 0xd13fda08f3fdf79d,
0x6066a345e0141842 ,
50 0x8db2e50b963ec962, 0x703ffb7a840af142, 0xfebe1ffca06b368,
0xe705569e6ab 50956, 0x8c5227bc21e99054, 0x641cbb8833747c1a,
51 0xd32c84d233a9e32a, 0x12d004571d8dad0a, 0x0, 0x0, 0x0}};
52 int main(void)
53 {
54 square(&a,&b,9);
55 if (memcmp(&result,&b,sizeof(QfloatAccum))) {
56 printf("bug!\n");
57 }
58 }
---------------------------------------------------------------------------
Compiled without any optimizations, this program outputs nothing. Gcc
with -O2 will print "bug".
Why is this happening?
I have tried it with gcc in the ARM, where I discovered this problem.
Clang in the Macintosh has the same problem. gcc under linux x86 has the
same problem.
Context:
This program is squaring a number represented by a series of numbers
sotred modulo pow(2,64). ALl the data (variables) in this program are
unsigned.
It was a lot of effort to isolate this piece of code and build this
repro but I do not know where the bug is.
Following the lead that David Brown told me, I noticed that if you
compile this with
-fwrapv
the bug disappears.
The problem is in line 23. I forgot to put an "unsigned" in the cast to
force a 128 bit multiplication. If you add that, that code compiles with
-O2.
What is happening in line 23?
23 lp = ((__int128)(*p)) * (*q);
This specifies that:
1) The 64 bit unsigned value stored at the location pointed to by "p"
should be converted into a signed 128 bit value.
2) That value should be multiplied in 128 bit with the unsigned 64 bit
value pointed to by "q".
3) The result of the 128 bit multiplication should be stored in the
unsigned 128 bit number "lp".
4) Since the rank of a 128 bit integer is higher than the rank of the 64
bit value, the multiplication is a signed multiplication.
Where is here an undefined behavior?
The generated code in assembler is completely scrambled since gcc
reorganizes the operations of the machine so that the pipeline is always
doing several things. It makes the code impossible to follow. I noticed
also that gcc tries to fuse the two accesses to the same memory location
*(r-2), what could be a source of bugs but maybe has nothing to do with
the problem. (Lines 26 and 36)
The code generated both in the ARM 64 and the x86 does NOT store
anything as specified in line 25 and looks plainly wrong. This provokes
that squaring gives wrong results after the 58th decimal digit and the
whole software is unusable.
Is this a bug in the optimizer?
Or I am doing some "UB"?
Why should be forbidden to store a 128 bit signed value into a 128 bit
unsigned value?
What is the behavior of the other compilers? My copy of msvc is not
working anymore, I think that the updates screwed that up, it worked
last time I used it. Intel compiler anyone? Or MSVC?
Thanks in advance
[toc] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-02-08 14:15 -0800 |
| Message-ID | <lny3k3w2k5.fsf@kst-u.example.com> |
| In reply to | #126461 |
jacobnavia <jacob@jacob.remcomp.fr> writes:
[...]
> Following the lead that David Brown told me, I noticed that if you
> compile this with
> -fwrapv
> the bug disappears.
That's not surprising; see below.
> What is happening in line 23?
>
> 23 lp = ((__int128)(*p)) * (*q);
>
> This specifies that:
> 1) The 64 bit unsigned value stored at the location pointed to by "p"
> should be converted into a signed 128 bit value.
> 2) That value should be multiplied in 128 bit with the unsigned 64 bit
> value pointed to by "q".
> 3) The result of the 128 bit multiplication should be stored in the
> unsigned 128 bit number "lp".
> 4) Since the rank of a 128 bit integer is higher than the rank of the 64
> bit value, the multiplication is a signed multiplication.
>
> Where is here an undefined behavior?
I'll assume that __int128 is treated as a signed 128-bit integer type.
gcc doesn't quite treat it that way, but for these purposes I think the
assumption is valid and consistent with the observed behavior.
In the left operand, *p is a 64-bit unsigned integer (unsigned long
long), converted to a 128-bit signed type. The right operand, which is
also of type unsigned long long, is implicitly converted to the same
128-bit signed type.
If the result of the multiplication exceeds 2**127-1, that's an overflow
and the behavior is undefined. I added some printf calls to your
program, and you are getting results that exceed 2**127-1. gcc's
optimization assumes that the behavior is defined, causing unexpected
results.
-fwrapv causes gcc to define the behavior of signed overflow.
[...]
> Is this a bug in the optimizer?
> Or I am doing some "UB"?
The latter.
(Speaking of bugs, I recently emailed you a bug report for lcc-win64.
Did you receive it? Should I post it to comp.compilers.lcc?)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | jacobnavia <jacob@jacob.remcomp.fr> |
|---|---|
| Date | 2018-02-13 10:25 +0100 |
| Message-ID | <p5uaug$orp$1@dont-email.me> |
| In reply to | #126461 |
Le 08/02/2018 à 22:50, jacobnavia a écrit :
> Consider this program:
> 1 #include <string.h>
> 2 #include <stdio.h>
> 3 #define MANTISSA_LENGTH 7
> 4 typedef struct tagQfloatAccum {
> 5 int sign;
> 6 unsigned int exponent;
> 7 unsigned long long mantissa[MANTISSA_LENGTH+8];
> 8 } QfloatAccum;
> 9 typedef QfloatAccum * QfloatAccump;
> 10 typedef unsigned long long QELT;
> 11 static void square(QfloatAccump a,QfloatAccump b,int prec )
> 12 {
> 13 QELT *p, *q, *r;
> 14 unsigned __int128 u, lp;
> 15 int k;
> 16
> 17 memset(b->mantissa,0,sizeof(b->mantissa));
> 18 r = &b->mantissa[prec+2];
> 19 for( k=prec+2; k>=2; k-- ) {
> 20 q = &a->mantissa[1];
> 21 p = &a->mantissa[k-1];
> 22 while( p >= q ) {
> 23 lp = ((__int128)(*p)) * (*q);
> 24 if( p != q ) {
> 25 if( ((lp >> 127) & 1 ) )
> 26 *(r-2) += 1;
> 27 lp <<= 1;
> 28 }
> 29 u = lp&0xffffffffffffffffULL;;
> 30 u += *r;
> 31 (*r) = (u&0xffffffffffffffffULL);
> 32 u = u >> 64;
> 33 u += (lp >> 64);
> 34 u += *(r-1);
> 35 *(r-1) = u;
> 36 *(r-2) += (u >> 64);
> 37 p--;
> 38 q++;
> 39 }
> 40 --r;
> 41 }
> 42 }
> 43
> 44 QfloatAccum a =
> 45 {0x0, 0x0, {0x0, 0x5c551d94ae0bf85d, 0xdf43ff68348e9f44,
> 0x75abbd546eb4ad2c , 0x45928b3668d09923, 0xef0e21fbaa8bb66b,
> 46 0xd834f79a27f3d70b, 0xe29f8b325d2f09bc, 0x22342f2796cceefe,
> 0x15136c1f 974cb8e4, 0x0, 0x0, 0x0, 0x0, 0x0}};
> 47 QfloatAccum b = {0};
> 48 QfloatAccum result =
> 49 {0x0, 0x0, {0x0, 0x214d498f853f343e, 0xd13fda08f3fdf79d,
> 0x6066a345e0141842 ,
> 50 0x8db2e50b963ec962, 0x703ffb7a840af142, 0xfebe1ffca06b368,
> 0xe705569e6ab 50956, 0x8c5227bc21e99054, 0x641cbb8833747c1a,
> 51 0xd32c84d233a9e32a, 0x12d004571d8dad0a, 0x0, 0x0, 0x0}};
> 52 int main(void)
> 53 {
> 54 square(&a,&b,9);
> 55 if (memcmp(&result,&b,sizeof(QfloatAccum))) {
> 56 printf("bug!\n");
> 57 }
> 58 }
> ---------------------------------------------------------------------------
> Compiled without any optimizations, this program outputs nothing. Gcc
> with -O2 will print "bug".
>
> Why is this happening?
>
I found the root cause: gcc/clang will assume that there is no "UB" i.e.
no overflow. Then, a multiplication of two unsigned values into a signed
result can't be negative.
Then, the compilers wrongly assume, the bit 127 (the sign bit) can never
be set. Then, the test at line 25 can never yioeld anything other than
zero and the code in line 27 is dead code that is eliminated.
This chain of false reasoning starts with the assumption: Overflows
never exist.
Great.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2018-02-13 10:51 +0100 |
| Message-ID | <p5ucel$22j$1@dont-email.me> |
| In reply to | #126641 |
On 13/02/18 10:25, jacobnavia wrote: > Le 08/02/2018 à 22:50, jacobnavia a écrit : <snip> >> Compiled without any optimizations, this program outputs nothing. Gcc >> with -O2 will print "bug". >> >> Why is this happening? >> > > I found the root cause: gcc/clang will assume that there is no "UB" i.e. > no overflow. That is the way C works - it is why "undefined behaviour" is a useful thing that can lead to optimisations and more efficient code, as long as the code is correct. There is a balance between "trust the programmer and the code as written" and "be helpful to the programmer even if the code is flawed". Usually, the programmer wants the first behaviour when he/she knows their code is correct, and the second behaviour when they have made a mistake! Static warning options can help, and compilation with the "-fsanitize" options spot many run-time behaviour errors. > Then, a multiplication of two unsigned values into a signed > result can't be negative. I don't know of any real-world non-negative integers that can be multiplied together to get a negative result - it is a perfectly reasonable assumption for the compiler. > > Then, the compilers wrongly assume, the bit 127 (the sign bit) can never > be set. The compiler's assumption is correct here. > Then, the test at line 25 can never yioeld anything other than > zero and the code in line 27 is dead code that is eliminated. > So you get more efficient object code, based on the source code you wrote. > This chain of false reasoning starts with the assumption: Overflows > never exist. It is not false reasoning or a false assumption. It is /correct/ reasoning - but it comes from incorrect source code. > > Great. > It is great that you found the bug, and great that you understand the compiler logic here. It is less great that you don't understand that the compiler's logic is correct.
[toc] | [prev] | [next] | [standalone]
| From | jacobnavia <jacob@jacob.remcomp.fr> |
|---|---|
| Date | 2018-02-13 11:19 +0100 |
| Message-ID | <p5ue2q$c60$1@dont-email.me> |
| In reply to | #126644 |
I am porting the code of Stephen L. Moshier from 32 to 64 bits. I flagged all operations that needed to be changed from unsigned 64 bit operations to 128 bit operations. I missed one, forgetting the "unsigned" in that cast. The compiler logic is correct but no warnings were issued, warnings that would help the programmer to catch problems like this one.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2018-02-13 12:23 +0100 |
| Message-ID | <p5uhqq$512$1@dont-email.me> |
| In reply to | #126645 |
On 13/02/18 11:19, jacobnavia wrote: > I am porting the code of Stephen L. Moshier from 32 to 64 bits. > I flagged all operations that needed to be changed from unsigned 64 bit > operations to 128 bit operations. > > I missed one, forgetting the "unsigned" in that cast. > > The compiler logic is correct but no warnings were issued, warnings that > would help the programmer to catch problems like this one. > Warnings are nice - I am a big fan of them. But it is not always easy for a compiler to give warnings on such cases, as it can be very hard to distinguish between intentional code and errors. Often it depends on what passes the analysis is done at. You can try a few of these suggestions and see if it gives a warning (and not too many false positives): -Wall (you probably have that already) -Wextra (this can give false positives for perfectly good, correct code) -Wtype-limits (in -Wextra) -Wconversion -Wsign-compare (in -Wextra) -Wsign-conversion (in -Wconversion) Also try with newer gcc if you can - warnings improve all the time, and gcc 6 has some warnings about invalid shifts enabled by default. (Although I suppose this will not be triggered, as right-shifting an __int128 by 127 bits is defined behaviour.)
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2018-02-13 08:19 -0800 |
| Message-ID | <1ffe469b-db28-4727-9823-397866560370@googlegroups.com> |
| In reply to | #126644 |
On Tuesday, February 13, 2018 at 9:51:26 AM UTC, David Brown wrote: > > I don't know of any real-world non-negative integers that can be > multiplied together to get a negative result - it is a perfectly > reasonable assumption for the compiler. > What's an example of a real world negative integer?
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2018-02-15 10:52 +0100 |
| Message-ID | <p63l9g$l42$1@dont-email.me> |
| In reply to | #126670 |
On 13/02/18 17:19, Malcolm McLean wrote: > On Tuesday, February 13, 2018 at 9:51:26 AM UTC, David Brown wrote: >> >> I don't know of any real-world non-negative integers that can be >> multiplied together to get a negative result - it is a perfectly >> reasonable assumption for the compiler. >> > What's an example of a real world negative integer? > -42 Most real-world integers are non-negative. Signed ones are useful for relative values, positions, differences in quantities, supporting "borrowing", sub-atomic particle charges, etc. But you don't multiply (or add) two non-negative values and get a negative one, except in strange mathematical structures (like size-limited two's complement wraparound arithmetic).
[toc] | [prev] | [next] | [standalone]
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2018-02-13 16:19 +0100 |
| Message-ID | <p5uvmn$38p$1@dont-email.me> |
| In reply to | #126641 |
On 13/02/2018 10:25, jacobnavia wrote: > This chain of false reasoning starts with the assumption: > Overflows never exist. You disagree with the postulate, but the reasoning itself is correct. As you stated yourself, in the C abstract machine, signed arithmetic operations are assumed to never overflow. These are the rules of engagement. If you do not like it, there is not much that can be done.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-02-19 12:11 -0800 |
| Message-ID | <kfno9kkwxhd.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #126668 |
> in the C abstract machine, signed arithmetic > operations are assumed to never overflow. This isn't right. In fact it's backwards - it is in the abstract machine that overflow DOES occur, which gives rise to the freedom of undefined behavior that lets an actual machine do something different.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-19 16:31 -0800 |
| Message-ID | <6450af56-5c39-4e03-8c0c-1bd8f2b2eaf5@googlegroups.com> |
| In reply to | #126860 |
On Monday, February 19, 2018 at 2:11:50 PM UTC-6, Tim Rentsch wrote:
> > in the C abstract machine, signed arithmetic
> > operations are assumed to never overflow.
>
> This isn't right. In fact it's backwards - it is in the abstract
> machine that overflow DOES occur, which gives rise to the freedom
> of undefined behavior that lets an actual machine do something
> different.
Which viewpoint is correct depends how one views the existence of time
travel. If an implementation that receives inputs that would cause
overflow behaves as though it receives inputs that wouldn't cause overflow,
and as a result of that the code never attempts to perform the operations
that would cause overflow, which description would better describe such
behavior:
1. The compiler generates code that assumes overflows will never occur.
2. The compiler generates code that, when overflow occurs, uses a time
machine to adjust the program's previous behavior in ways that are
not bound by laws of causality.
While nothing in the Standard would require that the abstract machine
exist in a universe where time travel is impossible, or where it would at
least be bound by laws of causality, it is probably easier to describe
an implementation's behavior according to #1 above rather than #2.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-02-21 23:03 -0800 |
| Message-ID | <kfn8tblv74j.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #126871 |
supercat@casperkitty.com writes: > On Monday, February 19, 2018 at 2:11:50 PM UTC-6, Tim Rentsch wrote: > >>> in the C abstract machine, signed arithmetic >>> operations are assumed to never overflow. >> >> This isn't right. In fact it's backwards - it is in the abstract >> machine that overflow DOES occur, which gives rise to the freedom >> of undefined behavior that lets an actual machine do something >> different. > > Which viewpoint is correct depends how one views the existence of time > travel. [...] That's nonsense. The abstract machine doesn't exist in this physical universe.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-02-23 16:40 -0800 |
| Message-ID | <a9c289dc-d984-4c1a-84fb-9a7c06a72416@googlegroups.com> |
| In reply to | #126977 |
On Thursday, February 22, 2018 at 1:03:18 AM UTC-6, Tim Rentsch wrote:
> That's nonsense. The abstract machine doesn't exist in this
> physical universe.
No, but it might interact with the physical universe. If an
implementation does not recognize that operations on volatile
objects can have side-effects beyond possibly affecting the
values of other volatile objects, then UB that occurs after
code has performed a volatile write and a volatile read may
affect the value written. For example:
int test(int x)
{
if (x)
volatile_outputport = 1;
volatile_outputport = 2;
return volatile_inportport/x;
}
According to the Standard, unless an implementation specifies that
it recognizes the possibility of volatile operations having side-effects
that might prevent subsequent operations from being performed, calling
test(0) would invoke Undefined Behavior, thus justifying having the code
output 1 and then 2. The only way that could happen, though, would be
if either the abstract machine was assuming its behavior before it
output 2 based on an assumption that x could not be zero, or UB was able
to affect the state of a machine before an operation which was in turn
sequenced before the UB could possibly occur. The fetch from
volatile_inputport is not allowed to occur, *even in the abstract
machine*, until after the value 2 is written to volatile_outputport, and
the division is not allowed to occur until after that fetch.
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2018-02-24 05:57 -0500 |
| Message-ID | <VybkC.108690$9%2.106194@fx36.iad> |
| In reply to | #127003 |
On 2/23/18 7:40 PM, supercat@casperkitty.com wrote:
> On Thursday, February 22, 2018 at 1:03:18 AM UTC-6, Tim Rentsch wrote:
>> That's nonsense. The abstract machine doesn't exist in this
>> physical universe.
>
> No, but it might interact with the physical universe. If an
> implementation does not recognize that operations on volatile
> objects can have side-effects beyond possibly affecting the
> values of other volatile objects, then UB that occurs after
> code has performed a volatile write and a volatile read may
> affect the value written. For example:
>
> int test(int x)
> {
> if (x)
> volatile_outputport = 1;
> volatile_outputport = 2;
> return volatile_inportport/x;
> }
>
> According to the Standard, unless an implementation specifies that
> it recognizes the possibility of volatile operations having side-effects
> that might prevent subsequent operations from being performed, calling
> test(0) would invoke Undefined Behavior, thus justifying having the code
> output 1 and then 2. The only way that could happen, though, would be
> if either the abstract machine was assuming its behavior before it
> output 2 based on an assumption that x could not be zero, or UB was able
> to affect the state of a machine before an operation which was in turn
> sequenced before the UB could possibly occur. The fetch from
> volatile_inputport is not allowed to occur, *even in the abstract
> machine*, until after the value 2 is written to volatile_outputport, and
> the division is not allowed to occur until after that fetch.
>
I don't think so, I think you are assigning too much power to UB. If x
is 0, then the two (possible) assignments and the read of volatiles are
strictly ordered. and the division, since it requires the value of the
read can not be performed until after the read. Thus, if x is 0, the
first assignment must not happen, then the second must happen, then the
read, then undefined behavior happens. Unless the implementation can
ACTUALLY perform time travel, it can't change the sequence.
Now, if the last statement had been return volatile_inportport + 1/x;
Then the sub expression 1/x does not depend on the volatile value, and
might have been computed early, allowing it to affect things nominally
before it.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2018-02-24 13:11 -0800 |
| Message-ID | <kfninamt7o6.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #127003 |
supercat@casperkitty.com writes: > On Thursday, February 22, 2018 at 1:03:18 AM UTC-6, Tim Rentsch wrote: > >> That's nonsense. The abstract machine doesn't exist in this >> physical universe. > > No, but it might interact with the physical universe. Able to interact with the physical universe is the same thing as existing in the physical universe. That's what existing in the physical universe means. It can't be one without being the other.
[toc] | [prev] | [next] | [standalone]
| From | Anton Shepelev <anton.txt@gmail.com> |
|---|---|
| Date | 2018-02-25 00:15 +0300 |
| Message-ID | <20180225001514.c7dc957ce4aa6dba77e146e6@gmail.com> |
| In reply to | #127014 |
Tim Rentsch: > Able to interact with the physical universe is the > same thing as existing in the physical universe. > That's what existing in the physical universe > means. It can't be one without being the other. There is transcendental stuff... -- () ascii ribbon campaign -- against html e-mail /\ http://preview.tinyurl.com/qcy6mjc [archived]
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2018-02-13 11:44 -0800 |
| Message-ID | <lnbmgsptde.fsf@kst-u.example.com> |
| In reply to | #126641 |
jacobnavia <jacob@jacob.remcomp.fr> writes:
> Le 08/02/2018 à 22:50, jacobnavia a écrit :
>> Consider this program:
[snip]
>> Compiled without any optimizations, this program outputs nothing. Gcc
>> with -O2 will print "bug".
>>
>> Why is this happening?
>>
>
> I found the root cause: gcc/clang will assume that there is no "UB" i.e.
> no overflow. Then, a multiplication of two unsigned values into a signed
> result can't be negative.
*You* found the root cause? I posted the explanation last Thursday.
If you've killfiled me, you're free to do so, but I'd like to know about
it so I don't waste my time.
Can someone post a followup to this so jacob sees it? I'll also mention
that I recently posted an lcc-win bug report in comp.compilers.lcc;
jacob might have missed that as well.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | asetofsymbols@gmail.com |
|---|---|
| Date | 2018-02-13 12:13 -0800 |
| Message-ID | <71ea04f9-e191-4073-a646-3c8f48c9adc8@googlegroups.com> |
| In reply to | #126675 |
Per conoscenza:
-----+--
jacobnavia <ja...@jacob.remcomp.fr> writes:
> Le 08/02/2018 à 22:50, jacobnavia a écrit :
>> Consider this program:
[snip]
>> Compiled without any optimizations, this program outputs nothing. Gcc
>> with -O2 will print "bug".
>>
>> Why is this happening?
>>
>
> I found the root cause: gcc/clang will assume that there is no "UB" i.e.
> no overflow. Then, a multiplication of two unsigned values into a signed
> result can't be negative.
*You* found the root cause? I posted the explanation last Thursday.
If you've killfiled me, you're free to do so, but I'd like to know about
it so I don't waste my time.
Can someone post a followup to this so jacob sees it? I'll also mention
that I recently posted an lcc-win bug report in comp.compilers.lcc;
jacob might have missed that as well.
- hide quoted text -
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2018-02-15 09:45 +0100 |
| Message-ID | <p63hbf$sj3$1@dont-email.me> |
| In reply to | #126675 |
On 13/02/2018 20:44, Keith Thompson wrote: > jacobnavia <jacob@jacob.remcomp.fr> writes: >> Le 08/02/2018 à 22:50, jacobnavia a écrit : >>> Consider this program: > [snip] >>> Compiled without any optimizations, this program outputs nothing. Gcc >>> with -O2 will print "bug". >>> >>> Why is this happening? >>> >> >> I found the root cause: gcc/clang will assume that there is no "UB" i.e. >> no overflow. Then, a multiplication of two unsigned values into a signed >> result can't be negative. > > *You* found the root cause? I posted the explanation last Thursday. > > If you've killfiled me, you're free to do so, but I'd like to know about > it so I don't waste my time. > > Can someone post a followup to this so jacob sees it? I'll also mention > that I recently posted an lcc-win bug report in comp.compilers.lcc; > jacob might have missed that as well. OK.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web