On Thursday, 31 July 2014 at 10:14:06 UTC, Marc Schütz wrote:
On Thursday, 31 July 2014 at 08:23:44 UTC, Daniel Murphy wrote:
"Daniel Murphy" wrote in message
news:[email protected]...
> Wait, what? I thought the whole point of enforce is that it
> will *not*
> be removed by the compiler, no matter what?
No, the compiler is free to remove it if it can prove it will
never be triggered. eg if the condition is checking a ubyte
< 1000. If the assert in that example is never false, then
the enforce is dead code.
Actually, thinking about this some more...
In this program the enforce can be removed
assert(x < y);
enforce(x < y);
But not in this one:
enforce(x < y);
assert(x < y);
because the compiler does need to take control flow into
account when applying the information in the assert. In this
case the assert does not actually give the compiler any new
information.
No, if assert means "I promise that x < y where assert() is
called", then "x < y" also holds when "enforce()" is called,
because x and y cannot have changed between the two calls.
I think this is the biggest problem with optimizing whilst
removing the check. It seems like if you remove the check and
assume that the check was true then you get really wonky stuff
like checks before the assert being removed.
One solution that would still provide some optimization benefits
is to make the optimizations as if the check is still their.
Meaning that only things after the assert could be optimized
based on the contents of the assert.
I think that is an extension of what Daniel is saying. The assert
optimization needs to take into account control flow, but It
needs to take into account its own control flow as well(even if
the control flow is not actually inserted).
so...
enforce(x);
assert(x);
would not remove the enforce.... because the x would only be
known to be true after the assert because of the check in assert,
even if the check is not added it would optimize as if it was
added.