[comp.lang.forth] RTX2000 optimizer

rob@idacom.UUCP (Rob Chapman) (02/20/89)

Is anyone out there working on a code optimizer for the RTX2000?  At present
I'm writing one which is based pretty much on Chuck's optimizer for the
NC4000.  Basic Forth instructions become immediate words which try to blend
themselves into the previous instruction.  For instance:
	SWAP DROP can be blended into one instruction,
	then OR can blend into it,
	then NOT can blend into it,
	then 2* can blend into it,
	and finally ; can blend into it.
This results in 6 instructions progressively blended into one instruction.
This progression is nice since there is an intermediate resultant instruction
at every step.  On the other hand the following sequence cannot follow this
simple scheme:
	SWAP OVER +
because there is no intermediate instruction corresponding to SWAP OVER 
(F83 TUCK) even though there is one instruction which will do the entire
sequence.  It would seem that + would have to look back two instructions
to be able to optimize.  This can get complicated.

The code for a single lookback is fairly straight forward but when you have to 
look back two instructions then you have to worry about maintaining an
instruction pipeline and if there are long literals in there...  Also the
sequence SWAP OVER + is the same as DUP ROT +.  But SWAP OVER - is not the
same as DUP ROT -.

I suppose I could create a bunch of intermediate instructions like TUCK but
this would sacrifice speed and creating a bunch of nOVER's doesn't seem like
a good idea.

I welcome discussions, suggestions, contributions or radically new ideas.
Included is a copy of the current optimizer.  Let's see what PD can do for
optimizers.

( Selected portions from the kernel )

0 VARIABLE inst  ( contains last compiled data to be used by optimizer )

: \\  ( -- )  0 inst ! ;  ( turn off optimizer )
: ,  ( n -- )  DUP inst !  HERE !  2 ALLOT ;
: LITERAL  ( n -- )  state @
   IF HERE >R  DUP ABS  20 U< IF DUP 0< IF NOT BF40  ELSE BE40  ENDIF  OR
                              ELSE DE00 , ENDIF  ,  R> @ inst !
   ENDIF ; IMMEDIATE

( Optimizing compilers )

HEX
( ---- Optimizer tools ---- )
: inst?  ( -- 0 | inst ) ( return 0 if last inst not at here-2 or here-4 )
   inst @  DUP F000 AND D000 = 2*  HERE +  2 -  @  OVER - IF DROP 0 ENDIF ;
: TEST  ( mask \ comparee -- )  SWAP inst? AND = ;
: OPT,  ( inst -- )  HERE 2 -  F000 D000 TEST 2* +  OVER inst !  ! ;

( ---- Optimizing compilers ---- )
: NOT  ( -- ) state @ 0= IF NOT EXIT ENDIF
   0200 DUP TEST DUP  0E00 0000 TEST OR
   E000 C000 TEST  E040 E000 TEST OR  F000 B000 TEST OR  F010 A000 TEST OR  AND
   IF  0800 0000 TEST AND  IF inst? 0400 XOR  ELSE inst? ENDIF  0100 XOR OPT,
   ELSE DROP  A100 , ENDIF ; IMMEDIATE

: SHIFT  ( inst -- )  <BUILDS IMMEDIATE 20 OR ,
   DOES> state @ IF @ FFDF AND   F01F A000 TEST  IF inst? OR  OPT,  ELSE , ENDIF
                 ELSE >R ENDIF ;

    A001 SHIFT 0<		A002 SHIFT 2*
    A004 SHIFT cU2/		A006 SHIFT U2/		A007 SHIFT 2/

: ALU  ( inst \ alu-code -- )  <BUILDS IMMEDIATE ,  20 OR ,
   DOES> state @
	 IF CFC0 CE00 TEST  FF80 BE00 TEST OR  FF9F AE80 TEST OR
            IF @ inst?  F000 A000 TEST
              IF F040 AND  40 XOR  ELSE F0FF AND  80 OR  ENDIF  OR  OPT,
            ELSE 2 + @  FFDF AND  , ENDIF
         ELSE 2 + >R ENDIF ;

    A240 200 ALU AND		AC40 400 ALU -		A640 600 ALU OR
    A840 800 ALU +		AA40 A00 ALU XOR

: BRANCH?  ( -- flag )  \\ inst? 0 > ( make sure its a call )
   inst? 2* FC00 AND  HERE FC00 AND  - ABS 800 <  AND ;
: JUMP,  ( -- )  -2 ALLOT  HERE 9000 ,  inst @ 2*  0600  RESOLVE ;
: EXIT  ( -- )  F07E B000 TEST  inst? A000 U< OR
   IF  BRANCH? IF JUMP, ELSE  A020 , ENDIF
   ELSE inst? 20 OR  OPT, ENDIF ; IMMEDIATE
: ;  ( -- )  \ EXIT  \ [  UNSMUDGE ; IMMEDIATE

: OF(  ( -- )  COMPILE OF(  \ \  \\ ; IMMEDIATE
: COMPILE  ( -- )  COMPILE COMPILE  \ \  \\ ; IMMEDIATE

: 0branch  ( -- code )  inst? 2* ' ?DUP = IF -2 ALLOT 8000 ELSE 8800 ENDIF ;
: IF  ( -- addr )  0branch , >MARK 2 - ; IMMEDIATE
: WHILE  ( -- addr )  \ IF ; IMMEDIATE
: UNTIL  ( addr -- )  \ IF DROP <RESOLVE ;  IMMEDIATE

Notes:
	1. inst is a variable which contains the just layed down instruction
	   It is set by ','.  It is checked against HERE 2- (or 4- for long
	   lits) by inst?.
	2. \ is a synomym for [COMPILE] which forces compilation of the next
	   word in the input stream.
	3. COMPILE and OF( become active at run time and use the word following
	   them.  OF( is the same as TIMES on the NC4000.
	4. EXIT tries to embed a return bit or lay down a branch.