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