checkedint call removal
bearophile via Digitalmars-d
digitalmars-d at puremagic.com
Wed Jul 30 02:12:55 PDT 2014
Walter Bright:
> Data flow analysis can figure that example out.
Sorry, my mistake, what I am discussing about should not need
much flow analysis. Here x and y are immutable:
void main(in string[] args) {
import std.stdio, std.conv;
assert(args.length == 3);
immutable ubyte ux = args[1].to!ubyte;
immutable ubyte uy = args[2].to!ubyte;
immutable int x = ux;
immutable int y = uy;
immutable int result = x * y;
writeln("Product: ", result);
}
In the current D compiler x and y keep a value range of ubytes
(despite they are ints), so here D knows the expression "x * y"
can't overflow, so even this is accepted with no casts needed:
immutable ushort result = x * y;
Now let's convert that code with SInt (x and y are still
immutable, unlike in my precedent post):
void main(in string[] args) {
import std.stdio, std.conv, std.experimental.safeintegral;
assert(args.length == 3);
immutable ubyte ux = args[1].to!ubyte;
immutable ubyte uy = args[2].to!ubyte;
immutable SInt x = ux;
immutable SInt y = uy;
immutable SInt result = x * y;
assert(!result.overflow);
writeln("Product: ", result);
}
What's I'd like is a way for x and y (that are of the
library-defined type SInt) to keep the value range of an ubyte.
So the compiler is able to rewrite this:
immutable SInt result = x * y;
removing the call to muls() and replacing it with a regular
multiplication, that is faster, even when no inlining happens.
(To do this SInt needs two different "instantiations" of its
opBinary("*") ).
> If it can't for a more complex one, you can do:
>
> assert(x >= 0 && x <= 255);
> assert(y >= 0 && y <= 255);
For such simple situations I don't want user annotations. The
only code needed to make this request work should be already
written inside the implementation of SInt and similar
user-defined types.
And assume() and assert() are two different things, used for
different purposes. Do not give the same name to two so different
features, if you want to keep a language sane.
Info about assume in Microsoft C++:
http://msdn.microsoft.com/en-us/library/1b3fsfxw.aspx
> The optimizer can certainly use asserts to provide semantic
> information (even though the dmd one doesn't at the moment).
This is not a good idea. That's the job for assume(), not for
assert.
In general assert() verifies something is true, and if it's
false, the program just raises an assert error, that is even
recoverable. An assert leaves a condition testing inside the
binary in debug builds.
An assume() doesn't need to leave a test condition inside the
binary, even in debug builds. It doesn't raise run-time errors.
It's just a way to tell the compiler that some predicate is true,
and the optimization stages of the compiler have to try to use
this information to optimize the code.
You can't mix or replace the two things, because a mistake in an
assert() doesn't cause your program to burn, it just raises a
compile-time error. A programmer mistake in an assume() burns
your house.
assert() can be used freely in your code, to make sure you have
not done a mistake. assume() is only for special situations where
you know something is true, that the compiler can't prove by
itself.
> Again, I know you like reading about new languages and language
> features. I think you'd enjoy that even more supplemented with
> a book on how compilers work internally, in particular, how
> data flow analysis works and what it can do.
I will read more about that topic.
Bye,
bearophile
More information about the Digitalmars-d
mailing list