INCLUDE "ERCC07.TRIMP_TFORM1S" INCLUDE "ERCC07.TRIPCNSTS" EXTRINSICRECORD (WORKAF) WORKA EXTRINSICRECORD (PARMF) PARM CONSTINTEGER YES=1 CONSTINTEGER NO=0 EXTERNALROUTINESPEC IMPABORT EXTERNALROUTINESPEC FAULT(INTEGER N,DATA,IDENT) EXTERNALROUTINESPEC PRINT TRIPS(RECORD (TRIPF) ARRAYNAME TRIPLES) CONSTBYTEINTEGERARRAY WORDS(0:7)=0(3),1,1,1,2,4; ROUTINE EXTRACT(RECORD (RD) NAME OPND, INTEGERNAME VAL, LONGREALNAME RVAL, STRINGNAME STRVAL) !*********************************************************************** !* EXTRACTS A CONTANT OPERAND RETURNING REAL &INT VALUES * !*********************************************************************** INTEGER TYPE,PREC,I,AD TYPE=OPND_PTYPE; PREC=TYPE>>4 TYPE=TYPE&15 VAL=0; RVAL=0; STRVAL="" IF TYPE=5 START LENGTH(STRVAL)=WORKA_A(OPND_D) FOR I=1,1,OPND_XTRA CYCLE CHARNO(STRVAL,I)=WORKA_A(OPND_D+I) REPEAT FINISHELSEIF TYPE=1 THENSTART VAL=OPND_D RVAL=VAL FINISHELSESTART IF PREC=5 THEN RVAL=OPND_R ELSE RVAL=OPND_LR FINISH END EXTERNALROUTINE CTOP(INTEGERNAME FLAG,MASK, INTEGER XTRA, RECORD (RD) NAME OPND1,OPND2) !*********************************************************************** !* AN OPERATION HAS BEEN FOUND WHERE BOTH OPERANDS ARE * !* CONSTANTS OR KNOWN AT COMPILE TIME. THIS ROUTINE INTERPRETS * !* THE OPERATION * !* ON EXIT FLAG=0 IF INTERPRETED. REFRAINS FROM INTERPRETING * !* X=1/0 FOR EXAMPLE. CODE IS PLANTED FOR THESE FUNNIES * !*********************************************************************** CONSTINTEGER UTRUNCMASK=X'00000800',BTRUNCMASK=X'00000013' CONSTBYTEINTEGERARRAY FCOMP(1:14)= C 8,10,2,7,12,4,7, 8,12,4,7,10,2,7 INTEGER K,TYPEP,PRECP,OP,VAL,SVAL1,SVAL2,C,D,JJ,KK,TRUNCMASK STRING (255) STRVAL1,STRVAL2 !%LONGINTEGER VAL1,VAL2 INTEGER VAL1,VAL2 !%LONGLONGREAL RVAL1,RVAL2 LONGREAL RVAL1,RVAL2 SWITCH UISW,URSW(10:40),BISW,BRSW(0:24) ONEVENT 1,2 START RETURN FINISH TYPEP=OPND1_PTYPE&7; PRECP=OPND1_PTYPE>>4&15; OP=FLAG EXTRACT(OPND1,VAL1,RVAL1,STRVAL1) SVAL1<-VAL1 IF OP<128 START ; ! UNARY RETURNUNLESS 10<=OP<=40 TRUNCMASK=UTRUNCMASK IF TYPEP=2 THEN ->URSW(OP) ELSE ->UISW(OP) FINISH OP=OP-128 RETURNIF OP>24 EXTRACT(OPND2,VAL2,RVAL2,STRVAL2) SVAL2<-VAL2 IF TYPEP=2 THEN ->BRSW(OP) ELSE ->BISW(OP) UISW(10): ! ¬ VAL1=¬VAL1 INTEND: ! %IF PRECP=6 %THEN %START ! OPND1_D<-VAL1>>32 ! OPND1_XTRA<-VAL1 ! FLAG=0 ! %FINISH %ELSE %START VAL<-VAL1 IF VAL=VAL1 OR 1<<OP&TRUNCMASK=0 THEN FLAG=0 AND OPND1_D=VAL ! NO ARITH OFLOW CONDITION ! %FINISH IF FLAG=0 START OPND1_PTYPE=PRECP<<4!1 IF X'FFFF8000'<=VAL1<=X'FFFF' THEN OPND1_FLAG=0 ELSE OPND1_FLAG=1 FINISH RETURN UISW(11): ! INTEGER NEGATE VAL1=-VAL1; ->INT END UISW(13): ! INTEGER ABS VAL1=IMOD(VAL1); ->INT END UISW(12): ! INTEGER FLOAT RVAL1=VAL1; PRECP=PRECP+1 ->REAL END URSW(15): ! STRETCH REAL PRECP=PRECP+1 REAL END:OPND1_FLAG=1 IF PRECP=5 THEN OPND1_R=RVAL1 ELSE OPND1_LR=RVAL1 ! %IF PRECP=7 %THEN %START ! OPND1_FLAG=3 ! OPND1_XTRA=ADDR(A(R)) ! %CYCLE K=0,1,15 ! A(R)=BYTEINTEGER(ADDR(RVAL1)+K) ! R=R+1 ! %REPEAT ! %FINISH FLAG=0; OPND1_PTYPE=16*PRECP+2 RETURN UISW(15): ! STRETCH INTEGER IF PRECP=4 THEN PRECP=5 AND ->INT END RETURN UISW(14): ! SHORTEN INTEGER IF IMOD(VAL1)<=X'7FFF' THEN PRECP=4 AND ->INT END RETURN URSW(14): ! SHORTEN REAL PRECP=PRECP-1 ->REAL END URSW(12): ! FLOAT REAL IMPABORT UISW(16): ! SHORTEN FOR <- IF PRECP=5 THEN VAL1=VAL1&X'FFFF' AND PRECP=4 AND ->INTEND RETURN URSW(36): ! INT RETURNUNLESS MOD(RVAL1)<X'7FFFFFFE' VAL1=INT(RVAL1) PRECP=5 ->INTEND URSW(37): ! INTPT RETURNUNLESS MOD(RVAL1)<X'7FFFFFFE' VAL1=INTPT(RVAL1) PRECP=5 ->INTEND UISW(38): ! TOSTRING STRVAL1=TOSTRING(VAL1) ->STREND BISW(0): ! ADD BISW(14): ! COMBINE VMY RESULTS VAL1=VAL1+VAL2; ->INT END BISW(1): ! MINUS VAL1=VAL1-VAL2; ->INT END BISW(2): ! EXCLUSIVE OR VAL1=VAL1!!VAL2; ->INT END BISW(3): ! OR VAL1=VAL1!VAL2; ->INT END BISW(4): ! MULT VAL1=VAL1*VAL2; ->INT END BISW(6):RETURN ; ! / DIVISION BISW(5):RETURNIF VAL2=0; ! // DIVISION VAL1=VAL1//VAL2; ->INT END BISW(7): ! AND VAL1=VAL1&VAL2; ->INT END BISW(9): ! SLL IF PRECP=6 THEN VAL1=VAL1<<SVAL2 ELSE VAL1=SVAL1<<SVAL2 ->INT END BISW(8): ! SRL IF PRECP=6 THEN VAL1=VAL1>>SVAL2 ELSE VAL1=SVAL1>>SVAL2 ->INT END BISW(13): ! VMY & CHK BOUNDS C=VAL2>>24; ! DIMENSION D=VAL2&X'FFFF'; ! DV POINTER RETURNUNLESS D>0; ! UNLESS DV AVAILABLE IF VAL1<WORKA_CTABLE(D+3*C+1) OR VAL1>WORKA_CTABLE(D+3*C) THEN C FAULT(50,VAL1,XTRA&X'FFFF') VAL1=VAL1*WORKA_CTABLE(D+3*C-1) UNLESS C=1 ->INT END BISW(18): ! ARRAY SCALE D=VAL2>>16&31; ! TOTAL NO OF DIMENSIONS KK=VAL2&X'FFFF'; ! DV DISP RETURNUNLESS KK>0 JJ=WORKA_CTABLE(KK+4); ! LB(1) C=6 WHILE C<=3*D CYCLE JJ=JJ+WORKA_CTABLE(KK+C-1)*WORKA_CTABLE(KK+C+1) C=C+3 REPEAT VAL1=VAL1-JJ ->INT END BISW(11): BISW(12): ! COMPARISONS BRSW(11): BRSW(12): ! REAL COMPARISONS MASK=FCOMP(XTRA) FLAG=0 IF TYPEP=2 THEN ->RCOMP IF (MASK&8#0 AND VAL1=VAL2) OR (MASK&4#0 AND VAL1<VAL2) OR C (MASK&2#0 AND VAL1>VAL2) THEN MASK=15 ELSE MASK=0 RETURN RCOMP: IF (MASK&8#0 AND RVAL1=RVAL2) OR (MASK&4#0 AND RVAL1<RVAL2) OR C (MASK&2#0 AND RVAL1>RVAL2) THEN MASK=15 ELSE MASK=0 RETURN URSW(11): ! NEGATE RVAL1=-RVAL1; ->REAL END BRSW(13): ! ABS RVAL1=MOD(RVAL1); ->REAL END BRSW(0): ! ADD RVAL1=RVAL1+RVAL2; ->REAL END BRSW(1): ! SUBTRACT RVAL1=RVAL1-RVAL2; ->REAL END BRSW(4): ! MULT RVAL1=RVAL1*RVAL2; ->REAL END BRSW(6): ! DIVISION RETURNIF RVAL2=0; ! AVOID DIV BY ZERO RVAL1=RVAL1/RVAL2; ->REAL END BISW(10): ! '**' WITH 2 INTEGER OPERANDS BRSW(10): ! '**' WITH AT LEAST 1 REAL RETURNUNLESS OPND2_PTYPE&7=1 AND -63<=VAL2<=63 RVAL1=RVAL1**VAL2 ->REALEND BISW(17): ! '****' WITH 2 INTEGER OPERAND RETURNUNLESS 0<=VAL2<=63 VAL2=1 WHILE SVAL2>0 CYCLE VAL2=VAL2*VAL1 SVAL2=SVAL2-1 ! %RETURN %IF VAL2#INTEGER(ADDR(VAL2)+4) REPEAT VAL1=VAL2; ->INT END BISW(24): ! CONCAT RETURNIF LENGTH(STRVAL1)+LENGTH(STRVAL2)>255 STRVAL1=STRVAL1.STRVAL2 STREND: ! RETURN VALUE OPND1_PTYPE=X'35' OPND1_FLAG=LCONST OPND1_XTRA=LENGTH(STRVAL1) JJ=WORKA_ARTOP WORKA_A(JJ)=OPND1_XTRA FOR K=1,1,OPND1_XTRA CYCLE WORKA_A(JJ+K)=CHARNO(STRVAL1,K) REPEAT OPND1_D=JJ WORKA_ARTOP=(JJ+OPND1_XTRA+2)&(-2); ! PERQ KEEP 16 BIT ALIGNED FLAG=0 RETURN URSW(*): UISW(*): BRSW(*): BISW(*): END EXTERNALROUTINE FLAG AND FOLD(RECORD (TRIPF) ARRAYNAME TRIPLES) !*********************************************************************** !* WORKS DOWN AN ARRAY OF TRIPLES SETTING BITS FOR CODE GENERATOR * !* ALSO FOLDS OUT ANY REMAINING CONSTANT OPERATIONS * !*********************************************************************** INTEGER STPTR,CURRTRIPNO,I,J,DEPTH CONSTINTEGER FOLDI=X'1C00007F'; ! FOLD 10-16 & 36-38 CONSTINTEGER FOLDR=X'0107FFFF'; ! FOLD 128-146 &152 RECORD (TRIPF) NAME CURRT,REFT ROUTINESPEC INSPECT OPND(INTEGER NO) ROUTINESPEC REPLACE TRIPREF(INTEGER TRIP, RECORD (RD) NAME OPND) STPTR=TRIPLES(0)_FLINK DEPTH=0 ! WHILE STPTR>0 CYCLE CURRT==TRIPLES(STPTR) CURRTRIPNO=STPTR STPTR=CURRT_FLINK INSPECT OPND(1) IF CURRT_OPERN>=128 THEN INSPECT OPND(2) ! IF CURRT_FLAGS&CONSTANTOP#0 AND ((CURRT_OPERN<128 AND C FOLDI&1<<(CURRT_OPERN-10)#0) OR (CURRT_OPND1_FLAG<=1 AND C CURRT_OPND2_FLAG<=1 AND FOLDR&1<<(CURRT_OPERN&31)#0)) START I=CURRT_OPERN CTOP(I,J,CURRT_X1,CURRT_OPND1,CURRT_OPND2) IF I=0 THENSTART CURRT_X1=CURRT_OPERN; ! FOR DEBUGGING OPTIMISATIONS CURRT_OPERN=NULLT REPLACE TRIPREF(CURR TRIPNO,CURRT_OPND1) FINISH FINISH IF CURRT_OPERN=LASS AND CURRT_FLAGS&CONSTANTOP#0 AND C CURRT_CNT>0 THEN REPLACE TRIPREF(CURRTRIPNO,CURRT_OPND2) CURRT_DPTH<-DEPTH IF CURRT_CNT>0 AND CURRT_OPTYPE&7#2 C THEN DEPTH=DEPTH+WORDS(CURRT_OPTYPE>>4) REPEAT RETURN ROUTINE INSPECT OPND(INTEGER NO) RECORD (TRIPF) NAME RTRIP RECORD (RD) NAME OPND CONSTBYTEINTEGERARRAY LOAD ALLOW(0:199)=LOAD OP1(128){UNARY}, LOADOP1!LOADOP2(10), LOADOP1{**}, LOADOP1!LOADOP2(2), LOADOP1{VMY}, LOADOP1!LOADOP2, LOADOP2(2){ASS AND JAM ASS}, LOADOP1{****}, LOADOP1{SCALE}, LOADOP1!LOADOP2, LOADOP2{INDEXED FETCH}, LOADOP2{LASS}, LOADOP1!LOADOP2(3), LOADOP2{IOCP DONT LOAD EPNO}, LOADOP2(6){P PASSING}, 0(6){LABELS AND SWITCH DECLS}, LOADOP2{GOTO SW LOAD OPERAND}, LOADOP2(7){STR,PTR&RESULT ASSMNT}, LOADOP1!LOADOP2(2){STR COMP&DCOMP}, LOADOP2(2){PRE RES DONT LD WKAREA}, LOADOP1{RESLN DONT LOAD LABEL}, LOADOP2{RES FINALE DONT LOAD WKAREA}, LOADOP1!LOADOP2{SIG EVNT UNUSED}, LOADOP2{REC ASSNMNT}, LOADOP1!LOADOP2(*); INTEGER I,LOADOP OPND==CURRT_OPND1 LOADOP=LOAD OP1 IF NO=2 THEN OPND==CURRT_OPND2 AND LOADOP=LOAD OP2 LOADOP=LOADOP&LOAD ALLOW(CURRT_OPERN) IF OPND_FLAG<=1 THEN CURRT_FLAGS=CURRT_FLAGS!CONSTANTOP IF OPND_FLAG<8 THEN CURRT_FLAGS=CURRT_FLAGS!LOADOP IF OPND_FLAG=REFTRIP OR OPND_FLAG=INDIRECT START RTRIP==TRIPLES(OPND_D) IF RTRIP_PUSE#CURRTRIPNO OR C (RTRIP_OPERN=LASS AND RTRIP_FLINK#CURRTRIPNO) OR C RTRIP_OPERN=PRECC OR RTRIP_OPERN=CONCAT OR C RTRIP_OPERN=ITOS1 THEN CURRT_FLAGS=CURRT_FLAGS!LOADOP IF RTRIP_PUSE=CURRTRIPNO AND RTRIP_OPTYPE&7#2 C THEN DEPTH=DEPTH-WORDS(RTRIP_OPTYPE>>4) FINISH END ROUTINE REPLACE TRIPREF(INTEGER TRIP, RECORD (RD) NAME OPND) INTEGER PTR BYTEINTEGERNAME COUNT RECORD (TRIPF) NAME RTRIP PTR=STPTR COUNT==TRIPLES(TRIP)_CNT WHILE COUNT>0 AND PTR>0 CYCLE RTRIP==TRIPLES(PTR) PTR=RTRIP_FLINK IF RTRIP_OPND1_FLAG=REFTRIP AND RTRIP_OPND1_D=TRIP START RTRIP_OPND1=OPND COUNT=COUNT-1 FINISH IF RTRIP_OPERN>=128 AND RTRIP_OPND2_FLAG=REFTRIP AND C RTRIP_OPND2_D=TRIP START RTRIP_OPND2=OPND COUNT=COUNT-1 FINISH REPEAT END END EXTERNALROUTINE TRIP OPT(RECORD (TRIPF) ARRAYNAME TRIPLES, INTEGERNAME NEXT TRIP) !*********************************************************************** !* SCANS A TRIPLES LIST FOR POSSIBLE OPTIMISATIONS * !*********************************************************************** INTEGER CHANGES,DUPS,DUPTNO,PTR,I,J,K,VAL,XVAL,CURR,NEXT,OP1,OP2, CTOPOP,REVOP BYTEINTEGERARRAYNAME A RECORD (TRIPF) NAME CURRT,NEWT,NEXTT RECORD (RD) NAME OPND1,OPND2,POPND ROUTINESPEC SWOP OPERANDS(RECORD (TRIPF)NAME CURRT) INTEGERFNSPEC POWEROF2(INTEGER VAL) INTEGERFNSPEC PRELOAD PLACE(INTEGER TRIP) ROUTINESPEC NOOP(INTEGER TRIPLE, RECORD (RD) NAME ROPND) INTEGERFNSPEC SAME OPND(RECORD (RD) NAME OPND1,OPND2) ROUTINESPEC CHECK DUPS(INTEGER STRIPNO,STRIPNO) ROUTINESPEC DUPLICATE TRIP(INTEGER TRIPNO,DTRIPNO) ROUTINESPEC DEC USE(INTEGER TRIPLE NO) ROUTINESPEC DELETE TRIPLE(INTEGER TRIPLE NO) CONSTBYTEINTEGERARRAY FOLD NOOP INFO(0:199)= 0(128), X'89',X'41',X'89',X'89',X'B6',{+,-,!!,!,*} C 2,0,X'A4',1,1,{//,/,&,>>,<<} C 2,0,0,3,X'89',{**,COMP,DCOMP,VMY,COMB} C 0,0,2,0,1,{=,<-,****,SCALE,INDEX} C 0{IFETCH},0(3), X'40'{CONCAT},0(*) ! 2**0 SET IF SECOND OPERAND ZERO IS NOOP ! 2**1 SET IF SECOND OPERAND 1 IS A NOOP ! 2**2 SET IF SECOND OPERAND 0 MEANS RESULT=0 ! 2**3 SET IF FIRST OPERAND ZERO IS NOOP ! 2**4 SET IF FIRST OPERAND 1 IS A NOOP ! 2**5 SET IF FIRST OPERAND ZERO MEANS RESULT=0 ! 2**6 SET IF FOLDING WITH ITSELF POSSIBLE BUT NOT SIMPE ! 2**7 SET FOR NORMAL FOLDING ! CHANGES=0; ! NO CHANGES AS YET DUPS=0; ! NO DUPLICATES YET FLAG AND FOLD(TRIPLES) A==WORKA_A ! ! ADVANCED FOLDING FACTOR CONSTANTS OUT OF 2 OR MORE TRIPLES ! TO SAVE AN OPERATION. ONLY MORE USUSAL CASE CATERED FOR AS IN ! VAR+CONST+CONST. ! PTR=TRIPLES(0)_FLINK WHILE PTR>0 CYCLE CURRT==TRIPLES(PTR) NEXT=CURRT_FLINK EXITIF NEXT<=0 NEXTT==TRIPLES(NEXT) WHILE NEXTT_OPERN=NULLT AND NEXTT_FLINK>0 CYCLE NEXT=NEXTT_FLINK; ! SKIP OVER ANY NOOPS NEXTT==TRIPLES(NEXT) REPEAT UNLESS CURRT_CNT=1 AND NEXTT_CNT=1 AND C CURRT_FLAGS&NEXTT_FLAGS&CONSTANTOP#0 AND CURRT_PUSE=NEXT THEN C PTR=NEXT ANDCONTINUE PTR=NEXT ANDCONTINUEUNLESS (CURRT_FLAGS!NEXTT_FLAGS)&DONT OPT=0 J=CURRT_OPERN K=NEXTT_OPERN UNLESS FOLD NOOP INFO(J)>>6#0 AND FOLD NOOP INFO(K)>>6#0 THEN C PTR=NEXT ANDCONTINUE IF CURRT_OPND1_FLAG<=1 THEN OP1=1 AND OPND1==CURRT_OPND1 ELSE C OP1=2 AND OPND1==CURRT_OPND2 IF NEXTT_OPND1_FLAG<=1 THEN OP2=1 AND OPND2==NEXTT_OPND1 ELSE C OP2=2 AND OPND2==NEXTT_OPND2 CTOPOP=0; REVOP=0 IF J=K AND FOLD NOOP INFO(J)&X'80'#0 THEN CTOPOP=J IF J=K=SUB START IF OP2=2 START IF OP1=2 THEN CTOPOP=ADD ELSE CTOPOP=SUB FINISH ELSE START ; ! OP2=1 CASE IF OP1=1 THEN CTOPOP=SUB AND REVOP=ADD ELSE CTOPOP=ADD FINISH FINISH IF J=ADD AND K=SUB AND OP2=2 THEN CTOPOP=SUB IF J=SUB AND K=ADD THENSTART IF OP1=1 THEN CTOPOP=ADD ELSE CTOPOP=SUB FINISH IF J=K=CONCAT AND OP1=OP2=2 THEN CTOPOP=CONCAT IF CTOPOP#0 START CTOP(CTOPOP,K,0,OPND1,OPND2) IF CTOPOP=0 THENSTART IF OP2=2 THEN OPND2==NEXTT_OPND1 ELSE OPND2==NEXTT_OPND2 NOOP(NEXT,OPND2) IF REVOP#0 THEN CURRT_OPERN=REVOP CONTINUE FINISH FINISH PTR=NEXT REPEAT ! %IF CHANGES>0 %THEN PRINT TRIPS(TRIPLES) ! ! FIRST REAL OPTIMISATION IS TO SEARCH FOR AND REMOVE NOPS ! LIKE *1 OR <<0 OR +0 ETC. THESE ARE SURPRISINGLY COMMON ! IN PROGRAMS MADE MACHINE INDEPENDENT BY LIBERAL USE ! OF CONSTANT VARIABLES ! ! ALSO DOES A FEW REARRANGEMENTS OF SIMPLE COMPARISONS AND ARITHMETICS ! PTR=TRIPLES(0)_FLINK WHILE PTR>0 CYCLE CURRT==TRIPLES(PTR); ! EXAMINE EACH TRIPLE CURR=PTR PTR=CURRT_FLINK CONTINUEIF CURRT_FLAGS&DONT OPT#0 OR CURRT_FLAGS&CONSTANTOP=0 I=CURRT_OPERN OPND1==CURRT_OPND1 OPND2==CURRT_OPND2 IF OPND1_FLAG<=1 THEN OP1=1 AND VAL=OPND1_D AND XVAL=OPND1_XTRA C ELSE OP1=2 AND VAL=OPND2_D AND XVAL=OPND2_XTRA IF I=DCOMP AND OP1=2 START ;! EXPAND I=0=J ETC I=COMP; CURRT_OPERN=COMP NEXTT==TRIPLES(CURRT_PUSE) NEXTT_OPND1=OPND2 NEXTT_FLAGS=NEXTT_FLAGS!LOADOP1 FINISH IF I=COMP START J=CURRT_X1&15; ! IBM COND MASK IF CURRT_OPTYPE&7=1 START ;! TRANSFORM I>=1 TO I>0 ETC IF (OP1=2 AND ((VAL=1 AND (J=4 OR J=10)) C OR (VAL=-1 AND (J=2 OR J=12)))) C OR (OP1=1 AND ((VAL=1 AND (J=2 OR J=12)) C OR (VAL=-1 AND (J=4 OR J=10)))) START J=J!!8 CURRT_X1=CURRT_X1!!8 NEXTT==TRIPLES(CURRT_FLINK) NEXTT_X1=NEXTT_X1!!8; ! ALSO ALTER MASK IN THE JUMP VAL=0 IF OP1=2 THEN OPND2_D=0 ELSE OPND1_D=0 FINISH FINISH IF VAL=0 AND 7<=J<=8 AND (XVAL=0 OR CURRT_OPTYPE>>4<=5) START CURRT_OPERN=ZCOMP IF OP1=1 THEN SWOP OPERANDS(CURRT) CURRT_FLAGS=CURRT_FLAGS&(¬LOADOP2)!DONT OPT FINISH FINISH IF (I=LSHIFT OR I=RSHIFT) AND 1<=VAL<=31 AND C OP1=2 START ; ! <<CONST AND >> CONST CURRT_OPERN=CLSHIFT IF I=RSHIFT THEN VAL=-VAL AND OPND2_D=VAL I=CLSHIFT CURRT_FLAGS=CURRT_FLAGS&(¬LOADOP2) FINISH IF I=INTDIV AND OP1=2 AND VAL>1 START J=POWEROF2(VAL) IF J>0 START CURRT_OPERN=CASHIFT I=CASHIFT OPND2_D=-J CURRT_FLAGS=CURRT_FLAGS&(¬LOADOP2) FINISH FINISH IF I=MULT AND VAL>1 AND CURRT_OPTYPE&15=1 START J=POWEROF2(VAL) IF J>0 START IF OP1=1 THEN SWOP OPERANDS(CURRT) CURRT_OPERN=CASHIFT I=CASHIFT OPND2_D=J CURRT_FLAGS=CURRT_FLAGS&(¬LOADOP2) FINISH FINISH IF I>=128 THENSTART ; ! BINARY OPERATIONS IF I=VMY THEN VAL=VAL>>24;! DIM=1 IS NOOP J=FOLD NOOP INFO(I)&X'3F' CONTINUEUNLESS VAL<=1 AND J#0 AND CURRT_OPTYPE&7=1 POPND==OPND1; ! FOR PASSING FORWARD IF OP1=1 THEN K=3 AND POPND==OPND2 ELSE K=0;! BIT SHIFT FOR MASK IF (J&(1<<K)#0 AND VAL=0) OR (J&(2<<K)#0 AND VAL=1) START NOOP(CURR,POPND); ! THIS IS NOOP CONTINUE FINISH IF J&(4<<K)#0 AND VAL=0 THENSTART IF OPND1_FLAG=REFTRIP THEN DEC USE(OPND1_D) IF OP1=2 THEN OPND1=OPND2; ! RESULT IS ZERO NOOP(CURR,OPND1) ! MAY CAUSE OTHER NOOPS ! GE I=(A+B)*0 FINISH IF VAL=0 AND OP1=1 AND CURRT_OPERN=SUB THEN C OPND1=OPND2 AND CURRT_OPERN=LNEG;! OPTIMISE"0-X" FINISH REPEAT ! ! PASS TO CHECK FOR COMMON SUBEXPRESSIONS. DONE IN SUCH A WAY THAT ! SEQUENCES ARE DETECTED AND COMBINED ! PTR=TRIPLES(0)_FLINK WHILE PTR>0 CYCLE CURRT==TRIPLES(PTR) IF CURRT_FLAGS&DONT OPT=0 THEN CHECK DUPS(PTR,CURRT_FLINK) PTR=CURRT_FLINK REPEAT ! ! NESTED ACCUMULATOR PASS. AVOID EXCHANGES BY ARRANGING EARLY LOADS ! OF OPERANDS FOR NON COMMUTABLE OPERATIONS ! PTR=TRIPLES(0)_FLINK WHILE PTR>0 CYCLE CURRT==TRIPLES(PTR) IF CURRT_OPERN>=128 AND CURRT_OPERN#VASS AND CURRT_OPERN#VJASS C AND CURRT_OPTYPE&7#2 AND CURRT_FLAGS&(LOADOP1!LOADOP2!COMMUTABLE)=LOADOP1 C AND CURRT_OPND2_FLAG=REFTRIP AND 1<<CURRT_OPND1_FLAG&BTREFMASK=0 START J=PRELOAD PLACE(CURRT_OPND2_D) IF J>=0 AND CURRT_DPTH=TRIPLES(J)_DPTH START ;! PLACE ACCESSIBLE I=J; K=0 WHILE I#PTR CYCLE ; ! CHECK FOR DEPTH OF NESTING NEXTT==TRIPLES(I) IF NEXTT_OPERN=IOCPC OR NEXTT_OPERN=PRECL C THEN K=999 AND EXIT IF K<NEXTT_DPTH THEN K=NEXTT_DPTH I=NEXTT_FLINK REPEAT IF K+WORDS(CURRT_OPTYPE>>4)>=6 THEN C PTR=CURRT_FLINK ANDCONTINUE NEXTT==TRIPLES(J) NEWT==TRIPLES(NEXT TRIP) NEWT=0 NEWT_OPERN=PRELOAD; ! PRELOAD NEWT_CNT=1 NEWT_OPTYPE=CURRT_OPTYPE NEWT_FLAGS=LOADOP1!LEAVE STACKED NEWT_PUSE=PTR NEWT_OPND1=CURRT_OPND1 CURRT_FLAGS=CURRT_FLAGS&(¬LOAD OP1); ! OP1 DOES NOT NEED LOAD CURRT_OPND1_FLAG=REFTRIP CURRT_OPND1_D=NEXT TRIP CURRT_OPND1_XTRA=0 ! LINK IN NEW TRIPLE NEWT_FLINK=J NEWT_BLINK=NEXTT_BLINK NEXTT_BLINK=NEXT TRIP TRIPLES(NEWT_BLINK)_FLINK=NEXT TRIP NEXT TRIP=NEXT TRIP+1 ! ! CORRECT DEPTH OF NESTING FIELD ! NEWT_DPTH=NEXTT_DPTH WHILE J#PTR CYCLE NEXTT_DPTH=NEXTT_DPTH+WORDS(NEWT_OPTYPE>>4) J=NEXTT_FLINK NEXTT==TRIPLES(J) REPEAT ! CHANGES=CHANGES+1 FINISH FINISH PTR=CURRT_FLINK REPEAT ! ! PASS TO TRY TO KEEP DUPLICTE TRIPLES IN ESTACK. THE SAVING ! HERE IS SO LARGE THAT IT IS WORTH THE EFFORT TO FIND THESE ! RATHER RARE CASES. OFTEN THE FORM IS A(I)=A(I)+B. ! IF DUPS>0 START ; ! THERE IS AT LEST ONE PTR=TRIPLES(0)_FLINK WHILE PTR>0 CYCLE CURRT==TRIPLES(PTR) NEXTT==CURRT CYCLE NEXT=NEXTT_FLINK NEXTT==TRIPLES(NEXT) REPEAT UNTIL NEXTT_OPERN#NULLT IF CURRT_CNT=2 AND CURRT_OPTYPE&7#2 START ;! ONLY DUPILCATES POSSIBLE IF CURRT_PUSE#NEXT AND ((NEXTT_OPND1_FLAG=REFTRIP AND C NEXTT_OPND1_D=PTR) OR (NEXTT_OPND2_FLAG=REFTRIP AND C NEXTT_FLAGS&(COMMUTABLE!LOADOP1)=COMMUTABLE!LOADOP1 AND C NEXTT_OPND2_D=PTR)) START CURRT_FLAGS=CURRT_FLAGS!USE ESTACK CHANGES=CHANGES+1 PTR=NEXT CONTINUE FINISH IF CURRT_PUSE=NEXT AND C NEXTT_OPND1_FLAG=REFTRIP=NEXTT_OPND2_FLAG AND C NEXTT_OPND1_D=PTR=NEXTT_OPND2_D THENSTART CURRT_FLAGS=CURRT_FLAGS!USE ESTACK CHANGES=CHANGES+1 PTR=NEXT; CONTINUE FINISH IF CURRT_PUSE=NEXT AND NEXTT_FLINK=NEXTT_PUSE#0 AND C (NEXTT_FLAGS&COMMUTABLE#0 OR (NEXTT_OPND1_FLAG=REFTRIP AND C NEXTT_OPND1_D=PTR)) START NEWT==TRIPLES(NEXTT_FLINK) NEWT==TRIPLES(NEWT_FLINK) WHILE NEWT_OPERN=NULLT IF (NEWT_OPND2_FLAG=REFTRIP AND NEWT_OPND2_D=PTR) OR C (NEWT_FLAGS&COMMUTABLE#0 AND C NEWT_OPND1_FLAG=REFTRIP AND NEWT_OPND1_D=PTR) START CURRT_FLAGS=CURRT_FLAGS!USE ESTACK CHANGES=CHANGES+1 PTR=NEXT CONTINUE FINISH FINISH FINISH PTR=NEXT REPEAT FINISH ! %IF CHANGES>0 %AND PARM_DCOMP#0 %THEN PRINT TRIPS(TRIPLES) RETURN INTEGERFN POWEROF2(INTEGER VAL) !*********************************************************************** !* CHECKS IF VAL IS A POWER OF 2 * !*********************************************************************** INTEGER I,J FOR I=1,1,30 CYCLE J=1<<I IF J=VAL THEN RESULT =I IF J>VAL THEN RESULT =0 REPEAT RESULT =0 END ROUTINE SWOP OPERANDS(RECORD (TRIPF)NAME CURRT) !*********************************************************************** !* EXCHANGE OPND1&OPND2 KEEPING THE FLAGS CORRECT * !*********************************************************************** RECORD (RD)TOPND INTEGER FLAGS,NEWFLAGS TOPND=CURRT_OPND1 CURRT_OPND1=CURRT_OPND2 CURRT_OPND2=TOPND FLAGS=CURRT_FLAGS NEWFLAGS=FLAGS&(¬(LOADOP1+LOADOP2)) IF FLAGS&LOADOP1#0 THEN NEWFLAGS=NEWFLAGS!LOADOP2 IF FLAGS&LOADOP2#0 THEN NEWFLAGS=NEWFLAGS!LOADOP1 CURRT_FLAGS=NEWFLAGS END INTEGERFN PRELOAD PLACE(INTEGER TRIP) !*********************************************************************** !* LOOK FOR FIRST TRIPLE IN THE CHAIN THAT LEADS TO TRIP * !* CAN BE VERY COMPILCATED. RETURN -1 IF NOT SIMPLE * !*********************************************************************** CONSTINTEGER TRIPREFS=X'140'; ! BITMASK OF OPERAND FORMATS RECORD (RD) NAME OPND1,OPND2 RECORD (TRIPF) NAME CURRT CURRT==TRIPLES(TRIP) OPND1==CURRT_OPND1 OPND2==CURRT_OPND2 IF CURRT_OPERN<128 OR 1<<CURRT_OPND2_FLAG&TRIPREFS=0 START ; ! BACK VIA OPND1 IF 1<<CURRT_OPND1_FLAG&TRIPREFS=0 THENRESULT =TRIP RESULT =PRELOAD PLACE(OPND1_D) FINISH IF 1<<CURRT_OPND1_FLAG&TRIPREFS=0 OR OPND1_D=CURRT_BLINK THEN C RESULT =PRELOAD PLACE(OPND2_D) ! ! BOTH OPERANDS ARE LOADED TRIPLES ! IF CURRT_BLINK=OPND2_D THENRESULT =PRELOADPLACE(OPND1_D) RESULT =-1; ! TOO COMPLICATED END ROUTINE NOOP(INTEGER TRIPLE NO, RECORD (RD) NAME ROPND) !*********************************************************************** !* THIS TRIPLE HAS BECOME A NOOP.DELETE IT AND PASS ITS ENTRY TRIPLE* !* FORWARD TO ANT WHO USE IT * !*********************************************************************** RECORD (TRIPF) NAME CURRT,NOOPT RECORD (RD) NAME OPND1,OPND2 INTEGER PTR,CNT NOOPT==TRIPLES(TRIPLE NO); ! THIS ONE TO BECOME NOOP CNT=NOOPT_CNT; ! HOW MANY TIMES USED IMPABORT UNLESS CNT=1; ! NO OPS ELIMINATED BEFORE DUPS PTR=NOOPT_BLINK WHILE PTR>0 CYCLE CURRT==TRIPLES(PTR) IF CURRT_PUSE=TRIPLE NO THEN CURRT_PUSE=NOOPT_PUSE PTR=CURRT_BLINK REPEAT PTR=NOOPT_FLINK CYCLE CURRT==TRIPLES(PTR) PTR=CURRT_FLINK CONTINUE IF CURRT_OPERN=NULLT OPND1==CURRT_OPND1 OPND2==CURRT_OPND2 IF (OPND1_FLAG=REFTRIP OR OPND1_FLAG=INDIRECT) C AND OPND1_D=TRIPLE NO THENSTART IF OPND1_FLAG=INDIRECT THEN RETURN ;! CAN OPTIMISE AT PRESESNT OPND1=ROPND CNT=CNT-1 IF OPND1_FLAG#REFTRIP THEN CURRT_FLAGS=CURRT_FLAGS!LOAD OP1 FINISH IF CURRT_OPERN>=128 AND OPND2_D=TRIPLE NO AND C (OPND2_FLAG=REFTRIP OR OPND2_FLAG=INDIRECT) START IF OPND2_FLAG=INDIRECT THEN RETURN OPND2=ROPND CNT=CNT-1 IF OPND2_FLAG#REFTRIP THEN CURRT_FLAGS=CURRT_FLAGS!LOAD OP2 FINISH IF CNT=0 OR PTR=0 THENEXIT IF NOOPT_OPND1_FLAG#REFTRIP THEN C CURRT_DPTH<-CURRT_DPTH-WORDS(NOOPT_OPTYPE>>4) REPEAT NOOPT_X1=NOOPT_OPERN; ! FOR DEBUGGING NOOPT_OPERN=NULLT; ! SET AS NOOP NOOPT_PUSE=0 NOOPT_FLAGS=NOOPT_FLAGS!DONT OPT;! SKIP DUP CHECKING CHANGES=CHANGES+1 END ROUTINE DEC USE(INTEGER TRIPLE NO) !*********************************************************************** !* A TRIPLE HAS BEEN PASSED INTO 'DEAD' CODE. DECREMENT ITS USE * !* AND IF RELEVANT DELETE OPERATIONS LEADING TO IT * !*********************************************************************** RECORD (TRIPF) NAME CURRT CURRT==TRIPLES(TRIPLE NO) CURRT_CNT=CURRT_CNT-1 IF CURRT_CNT=1 THEN DUPS=DUPS-1 IF CURRT_CNT=0 THEN DELETE TRIPLE(TRIPLE NO) END ROUTINE DELETE TRIPLE(INTEGER TRIPLE NO) RECORD (TRIPF) NAME DELT DELT==TRIPLES(TRIPLE NO) IF DELT_OPND1_FLAG=REFTRIP OR DELT_OPND1_FLAG=INDIRECT THEN C DEC USE(DELT_OPND1_D) IF DELT_OPERN>=128 AND (DELT_OPND2_FLAG=REFTRIP OR C DELT_OPND2_FLAG=INDIRECT) THEN DEC USE(DELT_OPND2_D) DELT_X1=DELT_OPERN; ! FOR DEBUGGING DELT_OPERN=NULLT; ! NO OP DELT_FLAGS=DELT_FLAGS!DONT OPT END ROUTINE DUPLICATE TRIP(INTEGER TRIPNO,DTRIPNO) !*********************************************************************** !* DTRIPNO IS A DUPLICATE OF TRIPNO. CHANGE ALL REFERENCES * !* AND DELETE IT * !*********************************************************************** RECORD (RD) NAME OPND1,OPND2 RECORD (TRIPF) NAME MASTER,CURRT,DUPT INTEGER CNT,PTR DUPS=DUPS+1 DUPTNO=TRIPNO MASTER==TRIPLES(TRIPNO) DUPT==TRIPLES(DTRIPNO) CNT=DUPT_CNT PTR=DUPT_FLINK ! WHILE CNT>0 AND PTR>0 CYCLE CURRT==TRIPLES(PTR) PTR=CURRT_FLINK IF CURRT_OPERN=NULLT THEN CONTINUE OPND1==CURRT_OPND1 OPND2==CURRT_OPND2 IF OPND1_D=DTRIPNO AND (OPND1_FLAG=REFTRIP OR C OPND1_FLAG=INDIRECT) START MASTER_CNT=MASTER_CNT+1 OPND1_D=TRIPNO CURRT_FLAGS=CURRT_FLAGS!LOAD OP1 CNT=CNT-1 FINISH IF CURRT_OPERN>=128 AND OPND2_D=DTRIPNO AND C (OPND2_FLAG=REFTRIP OR OPND2_FLAG=INDIRECT) START MASTER_CNT=MASTER_CNT+1 OPND2_D=TRIPNO CURRT_FLAGS=CURRT_FLAGS!LOAD OP2 CNT=CNT-1 FINISH REPEAT DELETE TRIPLE(DTRIPNO) END ROUTINE CHECK DUPS(INTEGER TRIPNO,STRIPNO) !*********************************************************************** !* CHECK STARTING FROM STRIPNO FOR DUPLICATES OF TRIPNO * !* MAY BE MORE THAN ONE * !*********************************************************************** RECORD (TRIPF) NAME CURRT,DUPT INTEGER OPERN,F,NEXT DUPT==TRIPLES(TRIPNO) OPERN=DUPT_OPERN F=DUPT_FLAGS WHILE STRIPNO>0 CYCLE CURRT==TRIPLES(STRIPNO) EXITIF CURRT_OPERN=TLAB OR CURRT_OPERN=RTXIT OR CURRT_OPERN=RCALL EXITIF CURRT_OPERN=VASS OR CURRT_OPERN=VJASS;! PRO TEM NEXT=CURRT_FLINK IF CURRT_OPERN=OPERN AND ((OPERN<128 AND C SAME OPND(DUPT_OPND1,CURRT_OPND1)=YES) OR (OPERN>=128 AND C SAME OPND(DUPT_OPND1,CURRT_OPND1)=YES AND C SAME OPND(DUPT_OPND2,CURRT_OPND2)=YES) OR (F&COMMUTABLE#0 AND C SAME OPND(DUPT_OPND1,CURRT_OPND2)=YES AND C SAME OPND(DUPT_OPND2,CURRT_OPND1)=YES)) START DUPLICATE TRIP(TRIPNO,STRIPNO) CHANGES=CHANGES+1 FINISH STRIPNO=NEXT REPEAT END INTEGERFN SAME OPND(RECORD (RD) NAME OPND1,OPND2) !*********************************************************************** !* ARE THESE OPERANDS THE SAME ? * !*********************************************************************** INTEGER F,I RESULT =NO UNLESS OPND1_S1=OPND2_S1 F=OPND1_FLAG IF F=2 OR F=5 START RESULT =NO UNLESS OPND1_D=OPND2_D AND C OPND1_XTRA=OPND2_XTRA AND OPND1_PTYPE&X'3000'=0 RESULT =YES FINISH IF F<=1 START ; ! CONSTANTS IF OPND1_PTYPE=X'35' START RESULT =NO UNLESS OPND1_XTRA=OPND2_XTRA FOR I=1,1,OPND1_XTRA CYCLE RESULT =NO UNLESS A(OPND1_D+I)=A(OPND2_D+I) REPEAT RESULT =YES FINISH RESULT =YES IF OPND1_D=OPND2_D AND (OPND1_XTRA=OPND2_XTRA OR C OPND1_PTYPE&X'F0'<=X'50') RESULT =NO FINISH RESULT =YES IF OPND1_D=OPND2_D AND OPND1_XTRA=OPND2_XTRA RESULT =NO END END ENDOFFILE