July 31, 2014
On 7/31/2014 1:23 AM, Daniel Murphy wrote:
> "Walter Bright"  wrote in message news:lrbpvj$mih$1@digitalmars.com...
>
>> 5. assert(0); is equivalent to a halt, and the compiler won't remove it.
>
> This is not the same definition the spec gives.  The spec says assert(0) can be
> treated as unreachable, and the compiler is allowed to optimize accordingly.

It says more than that:

"The expression assert(0) is a special case; it signifies that it is unreachable code. Either AssertError is thrown at runtime if it is reachable, or the execution is halted (on the x86 processor, a HLT instruction can be used to halt execution). The optimization and code generation phases of compilation may assume that it is unreachable code."

  -- http://dlang.org/expression.html#AssertExpression

July 31, 2014
On Thursday, 31 July 2014 at 09:13:53 UTC, Walter Bright wrote:
> On 7/31/2014 1:23 AM, Daniel Murphy wrote:
>> "Walter Bright"  wrote in message news:lrbpvj$mih$1@digitalmars.com...
>>
>>> 5. assert(0); is equivalent to a halt, and the compiler won't remove it.
>>
>> This is not the same definition the spec gives.  The spec says assert(0) can be
>> treated as unreachable, and the compiler is allowed to optimize accordingly.
>
> It says more than that:
>
> "The expression assert(0) is a special case; it signifies that it is unreachable code. Either AssertError is thrown at runtime if it is reachable, or the execution is halted (on the x86 processor, a HLT instruction can be used to halt execution). The optimization and code generation phases of compilation may assume that it is unreachable code."
>
>   -- http://dlang.org/expression.html#AssertExpression

You said "the compiler won't remove it".
http://dlang.org/expression.html#AssertExpression says: "The optimization and code generation phases of compilation may assume that it is unreachable code."

Who is right?

If I write:

---
switch(expr())
{
case 0: doIt();
case 1: doThat();
default:
  assert(0);
}
---

Will the optimizer be able to remove the default: case?
Because If I use assert(0) it's on purpose and do not want it to be elided, ever.
MSVC has __assume(0); for unreachable code, GCC has __builtin_unreachable()
July 31, 2014
On Thursday, 31 July 2014 at 10:24:07 UTC, ponce wrote:
> If I write:
>
> ---
> switch(expr())
> {
> case 0: doIt();
> case 1: doThat();
> default:
>   assert(0);
> }
> ---
>
> Will the optimizer be able to remove the default: case?

Assuming fall-through (`goto case`), not only the default case. The entire switch could be removed, under the condition that the compiler can prove that neither `expr()`, `doIt()`, nor `doThat()` throws, even if they have side effects. And maybe even the entire function, and all functions that call it, depending on how exactly the control flow is.
July 31, 2014
On Thursday, 31 July 2014 at 08:08:43 UTC, Walter Bright wrote:
> On 7/31/2014 12:40 AM, David Bregman wrote:
>> On Wednesday, 30 July 2014 at 22:01:23 UTC, Walter Bright wrote:
>>> I'd like to sum up my position and intent on all this.
>>>
>>> 1. I can discern no useful, practical difference between the notions of assume
>>> and assert.
>>
>> People have explained the difference repeatedly, a ridiculous number of times
>> now. Could you please take a minute to understand it this time instead of
>> flippantly dismissing it again?
>>
>> assert does a runtime check, assume does not
>> assume affects code generation/optimization, assert does not
>> assert is for debugging, assume is not
>> assume is for optimization, assert is not
>>
>> In terms of what they practically do, they have *nothing* in common, their
>> functions are entirely orthogonal.
>
> They are inextricably entangled. Consider:
>
>    if (x == 0) abort();   // essentially what assert(x) does
>    ... at this point, the optimizer knows, beyond doubt, that x!=0 ...
>    if (x)  // optimizer can remove this check
>       ...
>
> which has the behavior of assume as you listed above, yet it is assert. We can pretend assert doesn't affect code, like we can pretend to have massless points in physics class, but in reality points have a mass and assert most definitely affects code generation, and does in every compiler I've checked, and it affects it in just the way the assume does.
>
>
>> Still think there is no practical difference?
>
> Yes.

Sigh. Of course you can assume the condition after a runtime check has been inserted. You just showed that

assert(x); assume(x);

is semantically equivalent to
assert(x);

as long as the runtime check is not elided. (no -release)

You didn't show that assert and assume are the same, they are not.

The code generated by one will be different than the code generated by the other, that is because they are functionally different. This is really indisputable..

>
>
>>> 2. The compiler can make use of assert expressions to improve optimization,
>>> even in -release mode.
>>
>> This will introduce a lot of undefined behavior, including making @safe code
>> with asserts unsafe. I really think this needs to be acknowledged. As far as I
>> can tell from the other thread, it still hasn't been.
>
> I did acknowledge it for the array bounds case.

Ok, thanks! But you still want to assert to become assume in release mode? How will you handle the safety issue?

>
> Note that your assume() will have the same effect, and worse, there will be no option to have the compiler insert a check, because then it would be an assert() and you might as well just use assert().

So what? I did not suggest to use assume() instead of assert() to avoid the problem. In fact, that _is_ the problem, _you_ are suggesting that assert becomes assume in release mode. assume() is not @safe, that is the whole point.

July 31, 2014
On Thursday, 31 July 2014 at 06:57:15 UTC, Walter Bright wrote:
> For LinearCongruentialEngine() and initialize(), passing invalid arguments are programming bugs, and so they should be asserting.

Isn't phobos compiled in release mode? And since those asserts are never compiled, what purpose do they serve?
July 31, 2014
Am Wed, 30 Jul 2014 17:32:10 -0700
schrieb Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>:

> On 7/30/14, 5:29 PM, Andrei Alexandrescu wrote:
> > On 7/30/14, 4:51 PM, Tobias Müller wrote:
> >> With relatively 'dumb' compilers, this is not a big problem, but
> >> optimizers
> >> are more and more clever and will take profit of such assumptions
> >> if they can.
> >
> > That's true, and it seems like a growing trend. Relevant threads:
> >
> > https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/9S5jNRW-5wY
> >
> >
> > http://www.spinics.net/lists/gcchelp/msg41714.html
> >
> > Recent versions of gcc and clang have become increasingly aggressive about optimizing code by taking advantage of making undefined behavior _really_ undefined. There's been a couple of posts in the news recently that I can't find at the moment.
> 
> I think I found it: http://www.redfelineninja.org.uk/daniel/?p=307
> 
> Andreu
> 

Also this:

Linus Torvalds On GCC 4.9: Pure & Utter Crap http://www.phoronix.com/scan.php?page=news_item&px=MTc1MDQ

(This actually is a GCC bug, but valid behaviour for normal C++ code. GCC only broke the compiler switch to explicitly force non-standard behaviour)

July 31, 2014
Am 31.07.2014 15:32, schrieb Johannes Pfau:
> Am Wed, 30 Jul 2014 17:32:10 -0700
> schrieb Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>:
>
>> On 7/30/14, 5:29 PM, Andrei Alexandrescu wrote:
>>> On 7/30/14, 4:51 PM, Tobias Müller wrote:
>>>> With relatively 'dumb' compilers, this is not a big problem, but
>>>> optimizers
>>>> are more and more clever and will take profit of such assumptions
>>>> if they can.
>>>
>>> That's true, and it seems like a growing trend. Relevant threads:
>>>
>>> https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/9S5jNRW-5wY
>>>
>>>
>>> http://www.spinics.net/lists/gcchelp/msg41714.html
>>>
>>> Recent versions of gcc and clang have become increasingly aggressive
>>> about optimizing code by taking advantage of making undefined
>>> behavior _really_ undefined. There's been a couple of posts in the
>>> news recently that I can't find at the moment.
>>
>> I think I found it: http://www.redfelineninja.org.uk/daniel/?p=307
>>
>> Andreu
>>
>
> Also this:
>
> Linus Torvalds On GCC 4.9: Pure & Utter Crap
> http://www.phoronix.com/scan.php?page=news_item&px=MTc1MDQ
>
> (This actually is a GCC bug, but valid behaviour for normal C++ code.
> GCC only broke the compiler switch to explicitly force non-standard
> behaviour)
>

And don't forget this (rather old) case: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=8537
(I really don't get why anyone would want such an optimization: I want an optimizer to use clever inlining, use SSE etc where it makes sense and stuff like that - but not to remove code I wrote.)

Cheers,
Daniel
July 31, 2014
On Thursday, 31 July 2014 at 11:01:56 UTC, Marc Schütz wrote:
> On Thursday, 31 July 2014 at 10:24:07 UTC, ponce wrote:
>> If I write:
>>
>> ---
>> switch(expr())
>> {
>> case 0: doIt();
>> case 1: doThat();
>> default:
>>  assert(0);
>> }
>> ---
>>
>> Will the optimizer be able to remove the default: case?
>
> Assuming fall-through (`goto case`), not only the default case. The entire switch could be removed, under the condition that the compiler can prove that neither `expr()`, `doIt()`, nor `doThat()` throws, even if they have side effects. And maybe even the entire function, and all functions that call it, depending on how exactly the control flow is.

Ok my example was wrong, I meant:

---
switch(expr())
{
case 0: doIt(); break;
case 1: doThat(); break;
default:
     assert(0);
     break;
}
---
July 31, 2014
On 07/31/14 15:44, Daniel Gibson via Digitalmars-d wrote:
> And don't forget this (rather old) case: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=8537
> (I really don't get why anyone would want such an optimization: I want an optimizer to use clever inlining, use SSE etc where it makes sense and stuff like that - but not to remove code I wrote.)

That is actually not a bug, but a perfectly valid optimization. The compiler isn't clairvoyant and can not know that some data that you wrote, but never read back, matters.

The solution is to tell the compiler that you really need that newly
(over-)written data. Eg

   asm {"" : : "m" (*cast(typeof(password[0])[9999999]*)password.ptr); }

(yes, stdizing compiler barriers would be a good idea)

artur
July 31, 2014
Am 31.07.2014 17:26, schrieb Artur Skawina via Digitalmars-d:
> On 07/31/14 15:44, Daniel Gibson via Digitalmars-d wrote:
>> And don't forget this (rather old) case: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=8537
>> (I really don't get why anyone would want such an optimization: I want an optimizer to use clever inlining, use SSE etc where it makes sense and stuff like that - but not to remove code I wrote.)
>
> That is actually not a bug, but a perfectly valid optimization. The
> compiler isn't clairvoyant and can not know that some data that you
> wrote, but never read back, matters.

I don't want the compiler to care about that. When I tell it to write something, I want it to do that, even if it might look like nonsense (if anything, it could create a warning).

>
> The solution is to tell the compiler that you really need that newly
> (over-)written data. Eg
>
>     asm {"" : : "m" (*cast(typeof(password[0])[9999999]*)password.ptr); }

inline asm is not portable

>
> (yes, stdizing compiler barriers would be a good idea)

C11 defines a memset_s which is guaranteed not to be optimized away..
that's 9 years after that bugreport and will probably never be supported by MSVC (they don't even support C99).
One could write a memset_s oneself.. that does a memset, reads the data and writes a char of it or something to a global variable (hoping that the compiler won't optimize that to "just set that variable to 0").

The thing is: I don't want a compiler to remove code I wrote just because it "thinks" it's superfluous.
It could tell me about it as a warning, but it shouldn't just silently do it. If removing code makes my code faster, I can do it myself.

Cheers,
Daniel