August 29, 2014
On Friday, 29 August 2014 at 05:55:18 UTC, Ola Fosheim Gr wrote:
> On Friday, 29 August 2014 at 05:31:02 UTC, deadalnix wrote:
>> If the value in unspecified, rather than the behavior undefined, it means that no load or store can be optimized away or reordered, unless the compiler can prove that is won't fault.
>>
>> I'm talking about doubtful optimization to gain 0.5% here, but that everything single variable except locals must be considered volatile in the C sense.
>
> Why is that? If the value is unspecified then you can assume a random value, so no single store is needed unless explicitly volatile?
>
> Wrapping semantics is also bad for optimization, though. You cannot reduce length < length+N to true in generic code, so you need to establish bounds on x or create multiple execution paths. This is usually silly when using a 64 bit int...

Because, if you don't have undefined BEHAVIOR, you can't change the BEHAVIOR. So you have to prove that store/loads won't fault before doing anything with them. As per spec. Or you'll change the BEHAVIOR.
August 29, 2014
On Friday, 29 August 2014 at 08:29:50 UTC, deadalnix wrote:
> Because, if you don't have undefined BEHAVIOR, you can't change the BEHAVIOR. So you have to prove that store/loads won't fault before doing anything with them. As per spec. Or you'll change the BEHAVIOR.

By fault you mean trap an illegal address. I don't think that should be required unless it is volatile, but that would depend on the spec.

"Undefined behaviour" goes much further and can in theory propagate all over the program…

August 29, 2014
On Friday, 29 August 2014 at 08:50:59 UTC, Ola Fosheim Grøstad
wrote:
> On Friday, 29 August 2014 at 08:29:50 UTC, deadalnix wrote:
>> Because, if you don't have undefined BEHAVIOR, you can't change the BEHAVIOR. So you have to prove that store/loads won't fault before doing anything with them. As per spec. Or you'll change the BEHAVIOR.
>
> By fault you mean trap an illegal address. I don't think that should be required unless it is volatile, but that would depend on the spec.
>
> "Undefined behaviour" goes much further and can in theory propagate all over the program…

Not only illegal address. You can trap for various reason, for
instance GC read/write barrier.

Indeed, undefined behavior can be anything, by definition, and this cannot. Still, removing undefined behavior and replace it by undefined values cause the optimizer to have to prove that load/store won't fault, which is going to kill any expectation of performance.
August 29, 2014
On Friday, 29 August 2014 at 17:29:49 UTC, deadalnix wrote:
> Indeed, undefined behavior can be anything, by definition, and this cannot. Still, removing undefined behavior and replace it by undefined values cause the optimizer to have to prove that load/store won't fault, which is going to kill any expectation of performance.

I still don't understand what kind of fault your are talking about.

Granted if you store in more than one location you have to make at least one move, but if you only store in one location you have the same situation as if you are optimizing:

a=a;

Clearly you can remove this without doing any loads or stores?
August 29, 2014
On Friday, 29 August 2014 at 17:33:14 UTC, Ola Fosheim Grøstad
wrote:
> On Friday, 29 August 2014 at 17:29:49 UTC, deadalnix wrote:
>> Indeed, undefined behavior can be anything, by definition, and this cannot. Still, removing undefined behavior and replace it by undefined values cause the optimizer to have to prove that load/store won't fault, which is going to kill any expectation of performance.
>
> I still don't understand what kind of fault your are talking about.
>
> Granted if you store in more than one location you have to make at least one move, but if you only store in one location you have the same situation as if you are optimizing:
>
> a=a;
>
> Clearly you can remove this without doing any loads or stores?

No, as the load or the store involved can fault/trap.
August 29, 2014
On Friday, 29 August 2014 at 17:34:42 UTC, deadalnix wrote:
> No, as the load or the store involved can fault/trap.

What kind of trap? Not getting an exception will not necessarily change correctness. Removing a division by zero is not changing correctness:

ok = (1.0/0.0  == 1.0) || true
assert(ok==true)

I would expect a compiler to remove a non-volatile "a=a" even if a is in read-only memory. It does not change correctness?
August 29, 2014
On Friday, 29 August 2014 at 17:46:31 UTC, Ola Fosheim Grøstad wrote:
> On Friday, 29 August 2014 at 17:34:42 UTC, deadalnix wrote:
>> No, as the load or the store involved can fault/trap.
>
> What kind of trap? Not getting an exception will not necessarily change correctness.

It does. An access that can potentially fault is more or less equivalent to this:

    if(p is null)
        throw new Error();
    *p = ...;

When you remove the access, you're removing the test, which changes program semantics.
August 29, 2014
On Friday, 29 August 2014 at 18:46:20 UTC, Marc Schütz wrote:
> On Friday, 29 August 2014 at 17:46:31 UTC, Ola Fosheim Grøstad wrote:
>> On Friday, 29 August 2014 at 17:34:42 UTC, deadalnix wrote:
>>> No, as the load or the store involved can fault/trap.
>>
>> What kind of trap? Not getting an exception will not necessarily change correctness.
>
> It does. An access that can potentially fault is more or less equivalent to this:
>
>     if(p is null)
>         throw new Error();
>     *p = ...;
>
> When you remove the access, you're removing the test, which changes program semantics.

NULL or any address, as you can change memory protection on a per
page basis, and have different protection for read write and
execution.

Even better, the fault do not have to result in an exception or
other form of termination. in fact, it is demonstrated that the
fault mechanism on x86 is Turing complete.
August 29, 2014
On Friday, 29 August 2014 at 18:46:20 UTC, Marc Schütz wrote:
> It does. An access that can potentially fault is more or less equivalent to this:
>
>     if(p is null)
>         throw new Error();
>     *p = ...;
>
> When you remove the access, you're removing the test, which changes program semantics.

No, if the access can trap unexpectedly then the program was incorrect to begin with. A deliberate exception is not the same as an unexpected trap. Removing the reason for the unexpected trap does not make the program more incorrect. So you don't change the semantics of a correct program, you only change when an incorrect program is classified as incorrect.

If the semantics is that of nondeterministic evaluation then a fault (bottom) might not be incorrect, you might mitigate exceptional partial results if you can find another path that does not lead to an exception.

Like this:

return select( f(x) or g(x) or h(x) )

It is sufficient here that just one of f, g, and h produces a valid result, the other ones might go down into infinite recursion or whatever.
August 29, 2014
On Friday, 29 August 2014 at 20:41:34 UTC, Ola Fosheim Grøstad wrote:
> On Friday, 29 August 2014 at 18:46:20 UTC, Marc Schütz wrote:
>> It does. An access that can potentially fault is more or less equivalent to this:
>>
>>    if(p is null)
>>        throw new Error();
>>    *p = ...;
>>
>> When you remove the access, you're removing the test, which changes program semantics.
>
> No, if the access can trap unexpectedly then the program was incorrect to begin with. A deliberate exception is not the same as an unexpected trap.

If it was indeed unexpected then you're right, but how do you know it wasn't intentional? If accessing an invalid pointer isn't unspecified behaviour (which this discussion is about), then why shouldn't someone rely on it?