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.