Mir Random [WIP]
John Colvin via Digitalmars-d
digitalmars-d at puremagic.com
Thu Nov 24 01:46:16 PST 2016
On Thursday, 24 November 2016 at 08:55:18 UTC, Kagamin wrote:
> On Wednesday, 23 November 2016 at 21:18:27 UTC, Andrei
> Alexandrescu wrote:
>> [Details needed]
>>
>> I just took a look https://godbolt.org/g/EMy6X4, it's
>> happening.
>
> That's three instructions instead of one shr eax,1
That's because of the cast(int), dividing by two is optimised
just fine. You can even do this:
int foo(int a) { return a / 2; }
uint foo(uint a) { return a / 2; }
int bar(int a)
{
if (a > 0) return a / 2;
else assert(0);
}
and get
int example.foo(int): // slow, to deal with sign
mov eax, edi
shr eax, 31
add eax, edi
sar eax
ret
uint example.foo(uint): // fast because no sign
mov eax, edi
shr eax
ret
int example.bar(int): // single shift because sign always 0
test edi, edi
jle .L8
mov eax, edi
sar eax
ret
.L8:
ud2
This should help explain why the extra/different instructions are
necessary for signed:
int foo0(int a)
{
asm
{
naked;
mov EAX, EDI;
shr EAX, 31;
add EAX, EDI;
sar EAX, 1;
ret;
}
}
int foo1(int a)
{
asm
{
naked;
mov EAX, EDI;
sar EAX, 1;
ret;
}
}
int foo2(int a)
{
asm
{
naked;
mov EAX, EDI;
shr EAX, 1;
ret;
}
}
void main()
{
import std.stdio;
foreach(i; [int.min, -1, 0, 1, int.max])
writeln(foo0(i), ' ', foo1(i), ' ', foo2(i));
}
output:
-1073741824 -1073741824 1073741824
0 -1 2147483647
0 0 0
0 0 0
1073741823 1073741823 1073741823
More information about the Digitalmars-d
mailing list