Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Question for compiler gurus

Author: Gerd Isenberg

Date: 14:14:19 10/01/04

Go up one level in this thread


On October 01, 2004 at 11:48:25, Dan Honeycutt wrote:

>On October 01, 2004 at 11:14:43, Reinhard Scharnagl wrote:
>
>>On October 01, 2004 at 10:58:43, Dan Honeycutt wrote:
>>
>>>If I have an inline function, ie:
>>>
>>>_inline int Distance(int square1, int square2)
>>>
>>>which is going to return the max rank/file difference but is not going to alter
>>>the arguements, would I be better off passing the arguements by reference, ie:
>>>
>>>_inline int Distance(int & square1, int & square2)
>>>
>>>so as to save having to make a copy of the arguements.  Or would the compiler
>>>figure that out on it's own since the function is inline?  I'm using MS VC 6.
>>>
>>
>>Well I am not a guru, but taking an int not by value does only make sense if
>>the original data should be changed. Copying an address could never be faster
>>than copying an int. And a good compiler will work within inline parts with the
>>original variables not with copies. But may be I have not seen your problem yet.
>>
>>Reinhard.
>
>Hi Reinhard:
>Let me clarify a bit.  The body of Distance() looks like:
>
>return Max(RankDiff(square1, square2), FileDiff(square1, square2));
>
>The calling function looks like:
>
>square1 = ...
>square2 = ...
>d = Distance(square1, square2);
>
>When the function is inlined I want:
>
>square1 = ...
>square2 = ...
>d = Max(RankDiff(square1, square2), FileDiff(square1, square2));
>
>But do I get
>
>square1 = ...
>square2 = ...
>copy1 = square1;
>copy2 = square2;
>d = Max(RankDiff(copy1, copy2), FileDiff(copy1, copy2));
>
>And if i do get the latter form, would a pass by reference be better?
>

Not if copy is a register "incarnation" of an int.

mov   ecx, [square1]
mov   edx, [square2]
....
cmp   ecx, edx
jle  ...


Even without fastcall, in the first case two values are pushed on the stack, and
inside the routine you can access the values immediatly via base or stack
pointer:

push square1
push square2
...
mov  eax, [copy1] ; ebp/esp-K1
cmp  eax, [copy2] ; ebp/esp-K2
jle  ...

With pointers or references you have to push memory addresses on the stack.
Since there are no pointers/references to registers - there is no chance to keep
square1,2 inside registers.

Inside your routine, you don't have direct access to the values via base- or
stackpointer, but only to the addresses. So you have first to load the pointer,
the memory address, inside a register to access the date via this register.

Each additional register needed increases the register pressure, causing more
push/pop instructions to save registers temporary on the stack.


push offset square1 ; or lea eax, square1; push eax
push offset square2
...
mov  esi, [ptrSquare1] ; ebp/esp-K1
mov  eax, [esi] ; square1
mov  esi, [ptrSquare2] ; ebp/esp-K2
cmp  eax, [esi] ; square2
jle  ...

As you can see, there are at least two additional instructions.

Btw. can you post your implementation of Max, RankDiff and FileDiff?

I think with random or alternating squares with no easy pattern you may get some
misspredictions, if you use up to three compares and conditional jumps per
distance.

Had you have a closer look on 0x88 square differences?

Lookup table(s) e.g. with packed 32-bit structs for distance, taxi-distance and
may be two other byte values with square related stuff is an option too, you may
look for "UDR" or unique distance relationship with CCC search engine.

Gerd


>Thanks
>Dan H



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.