Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Ed's "indirect addressing"

Author: Eugene Nalimov

Date: 13:28:30 01/30/03

Go up one level in this thread


On January 30, 2003 at 14:34:34, Ed Schröder wrote:

>On January 30, 2003 at 08:36:55, Russell Reagan wrote:
>
>>On January 30, 2003 at 07:02:39, Ed Schröder wrote:
>>
>>>On January 29, 2003 at 23:29:36, Russell Reagan wrote:
>>>
>>>>http://members.home.nl/matador/chess840.htm#INTRO
>>>>
>>>>From Ed's page...
>>>>
>>>>switch (piece_type) { case  0 : goto empty;
>>>>                      case  1 : goto white_pawn;    // evaluate white pawn
>>>>                      case  2 : goto white_knight;  // evaluate white knight
>>>>                      case  3 : goto white_bishop;
>>>>                      case  4 : goto white_rook;
>>>>                      case  5 : goto white_queen;
>>>>                      case  6 : goto white_king;
>>>>                      case  7 : goto black_pawn;    // evaluate black pawn
>>>>                      case  8 : goto black_knight;
>>>>                      case  9 : goto black_bishop;
>>>>                      case 10 : goto black_rook;
>>>>                      case 11 : goto black_queen;
>>>>                      case 12 : goto black_king; }
>>>
>>>Any reasonable compiler will translate the above into 2 assembler statements,
>>>someling like:
>>>
>>>      mov   EAX, dword ptr piece_type
>>>      JMP   TABLE [EAX]
>>>
>>>Nothing can beat that. Just generate an ASM file to see it work.
>>>
>>>Explanation: the trick is that the compiler will generate an internal table (not
>>>visible for the programmer) where it calculates all the effective addresses of
>>>the labels mentioned in the switch/case statement.
>>>
>>>Then using the "piece_type" in register EAX it does an "indirect jump", only a
>>>few cycles.
>>>
>>>Of course, the sequence must be in reasonable order otherwise the compiler will
>>>not recognize the possibility.
>>>
>>>Ed
>>
>>
>>Hi Ed,
>>
>>Let me see if I understand. It is an indirect jump, which will be at least as
>>slow as a mispredicted conditional. The reason this is faster is because since
>>you have 13 possible values for piece_type, you do ONE indirect jump as opposed
>>to (potentially) 12 mispredicted conditionals. Is this your reasoning?
>
>You got it!
>
>Ed

Source file:

int foo (int i)
{
    switch (i) {
    case 0:
        return 100;
    case 1:
        return 101;
    case 2:
        return 102;
    case 3:
        return 103;
    case 4:
        return 104;
    case 5:
        return 105;
    case 6:
        return 106;
    case 7:
        return 107;
    case 8:
        return 108;
    case 9:
        return 109;
    case 10:
        return 110;
    case 11:
        return 111;
    default:
        __assume(0);
    }
}

Code emitted by the compiler:

; Listing generated by Microsoft (R) Optimizing Compiler Version 13.10.2179

	TITLE	s.c
	.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT	SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA	ENDS
CONST	SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS	ENDS
$$SYMBOLS	SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS	ENDS
_TLS	SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS	ENDS
FLAT	GROUP _DATA, CONST, _BSS
	ASSUME	CS: FLAT, DS: FLAT, SS: FLAT
endif

INCLUDELIB LIBC
INCLUDELIB OLDNAMES

PUBLIC	@foo@4
; Function compile flags: /Ogty
_TEXT	SEGMENT
@foo@4	PROC NEAR
; _i$ = ecx
; File c:\repro\s.c
; Line 3
	jmp	DWORD PTR $L568[ecx*4]
$L546:
; Line 5
	mov	eax, 100				; 00000064H
; Line 31
	ret	0
$L547:
; Line 7
	mov	eax, 101				; 00000065H
; Line 31
	ret	0
$L548:
; Line 9
	mov	eax, 102				; 00000066H
; Line 31
	ret	0
$L549:
; Line 11
	mov	eax, 103				; 00000067H
; Line 31
	ret	0
$L550:
; Line 13
	mov	eax, 104				; 00000068H
; Line 31
	ret	0
$L551:
; Line 15
	mov	eax, 105				; 00000069H
; Line 31
	ret	0
$L552:
; Line 17
	mov	eax, 106				; 0000006aH
; Line 31
	ret	0
$L553:
; Line 19
	mov	eax, 107				; 0000006bH
; Line 31
	ret	0
$L554:
; Line 21
	mov	eax, 108				; 0000006cH
; Line 31
	ret	0
$L555:
; Line 23
	mov	eax, 109				; 0000006dH
; Line 31
	ret	0
$L556:
; Line 25
	mov	eax, 110				; 0000006eH
; Line 31
	ret	0
$L557:
; Line 27
	mov	eax, 111				; 0000006fH
; Line 31
	ret	0
	npad	1
$L568:
	DD	$L546
	DD	$L547
	DD	$L548
	DD	$L549
	DD	$L550
	DD	$L551
	DD	$L552
	DD	$L553
	DD	$L554
	DD	$L555
	DD	$L556
	DD	$L557
@foo@4	ENDP
_TEXT	ENDS
END

Thanks,
Eugene

>
>
>>Thanks,
>>Russell
>>
>>
>>
>>>
>>>>On one portion of Ed's discussion of Rebel (see above), he talks about using
>>>>"indirect addressing". I get the impression from Ed's words that this method is
>>>>supposed to fast. I understand his discussion to mean that if you create a
>>>>switch statement like he does, you create a jump table and avoid a bunch of
>>>>conditionals.
>>>>
>>>>However, in past discussions, I recall hearing that using a function pointer is
>>>>going to be at least as slow as conditional, so I asked someone, and was told
>>>>that Ed's example should be no different than using a function pointer or
>>>>virtual functions.
>>>>
>>>>Ed talks about this method as if it is a good thing to use. So what is the
>>>>advantage of it? Either someone is mistaken, or Ed and the guy I talked to are
>>>>talking about different things.



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.