Opinions: The Best and Worst of D (for a lecture/talk I intend to give)

Dominikus Dittes Scherkl via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Jul 9 10:43:15 PDT 2014


On Wednesday, 9 July 2014 at 17:13:21 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
> On Wed, Jul 09, 2014 at 04:24:38PM +0000, Dominikus Dittes 
> Scherkl via Digitalmars-d-learn wrote:
>> /// Returns -1 if a < b, 0 if they are equal or 1 if a > b.
>> /// this will always yield a correct result, no matter which 
>> numeric types are compared.
>> /// It uses one extra comparison operation if and only if
>> /// one type is signed and the other unsigned but the signed 
>> value is >= 0
>> /// (that is what you need to pay for stupid choice of type).
> [...]
>
> Yeah, I don't see what's the problem with comparing signed and 
> unsigned
> values, as long as the result is as expected. Currently, 
> however, this
> code asserts, which is wrong:
>
> 	uint x = uint.max;
> 	int y = -1;
> 	assert(x > y);
Yes, this is really bad.
But last time I got the response that this is so to be compatible 
with C.
That is what I really thought was the reason why D throw away 
balast from C,
to fix bugs.

>>    static if(Unqual!T == Unqual!U)
>
> Nitpick: should be:
>
>     static if(is(Unqual!T == Unqual!U))
Of course.

> [...]
>>    else static if(isSigned!T && isUnsigned!U)
>>    {
>>       alias CommonType!(Unsigned!T, U) C;
>>       return (a < 0) ? -1 : opCmp!(cast(C)a, cast(C)b);
>>    }
>>    else static if(isUnsigned!T && isSigned!U)
>>    {
>>       alias CommonType!(T, Unsigned!U) C;
>>       return (b < 0) ? 1 : opCmp!(cast(C)a, cast(C)b);
>>    }
> [...]
>
> Hmm. I wonder if there's a more efficient way to do this.
I'm sure. But I think it should be done at the compiler, not in a 
library.

> {...]
> opCmp is just a single sub instruction (this is why opCmp is 
> defined the
> way it is, BTW), whereas the "smart" signed/unsigned comparison 
> is 4
> instructions long.
> [...]
> you can see, the branched version is 5 instructions long, and 
> always
> causes a CPU pipeline hazard.
>
> So I submit that the unbranched version is better. ;-)
I don't think so, because the branch will only be taken if the 
signed
type is >= 0 (in fact unsigned). So if the signed/unsigned 
comparison
is by accident, you pay the extra runtime. But if it is 
intentional
the signed value is likely to be negative, so you get a correct 
result
with no extra cost.
Even better for constants, where the compiler can not only 
evaluate expressions like (uint.max > -1) correct, but it should 
optimize them completely away!

>
> (So much for premature optimization... now lemme go and actually
> benchmark this stuff and see how well it actually performs in 
> practice.
Yes, we should do this.

> Often, such kinds of hacks often perform more poorly than 
> expected due
> to unforeseen complications with today's complex CPU's. So for 
> all I
> know, I could've just been spouting nonsense above. :P)
I don't see such a compiler change as a hack. It is a strong 
improvement IMHO.


More information about the Digitalmars-d-learn mailing list