Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #126461 > unrolled thread

The bug

Started byjacobnavia <jacob@jacob.remcomp.fr>
First post2018-02-08 22:50 +0100
Last post2018-02-15 09:45 +0100
Articles 19 — 10 participants

Back to article view | Back to comp.lang.c


Contents

  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

#126461 — The bug

Fromjacobnavia <jacob@jacob.remcomp.fr>
Date2018-02-08 22:50 +0100
SubjectThe 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]


#126464

FromKeith Thompson <kst-u@mib.org>
Date2018-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]


#126641

Fromjacobnavia <jacob@jacob.remcomp.fr>
Date2018-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]


#126644

FromDavid Brown <david.brown@hesbynett.no>
Date2018-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]


#126645

Fromjacobnavia <jacob@jacob.remcomp.fr>
Date2018-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]


#126648

FromDavid Brown <david.brown@hesbynett.no>
Date2018-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]


#126670

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2018-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]


#126714

FromDavid Brown <david.brown@hesbynett.no>
Date2018-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]


#126668

FromNoob <root@127.0.0.1>
Date2018-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]


#126860

FromTim Rentsch <txr@alumni.caltech.edu>
Date2018-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]


#126871

Fromsupercat@casperkitty.com
Date2018-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]


#126977

FromTim Rentsch <txr@alumni.caltech.edu>
Date2018-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]


#127003

Fromsupercat@casperkitty.com
Date2018-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]


#127009

FromRichard Damon <Richard@Damon-Family.org>
Date2018-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]


#127014

FromTim Rentsch <txr@alumni.caltech.edu>
Date2018-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]


#127016

FromAnton Shepelev <anton.txt@gmail.com>
Date2018-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]


#126675

FromKeith Thompson <kst-u@mib.org>
Date2018-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]


#126677

Fromasetofsymbols@gmail.com
Date2018-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]


#126712

FromNoob <root@127.0.0.1>
Date2018-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