-- file: PeepholeQ.mesa, edited by Sweet on March 19, 1979 10:53 AM DIRECTORY Code: FROM "code" USING [CodeNotImplemented, CodePassInconsistency, codeptr, dStar], P5U: FROM "p5u" USING [DeleteCell], CodeDefs: FROM "codedefs" USING [CCIndex, CCNull, CodeCCIndex, JumpCCIndex, JumpType, NULLfileindex], ComData: FROM "comdata" USING [switches], FOpCodes: FROM "fopcodes" USING [qADD, qAND, qBCAST, qBCASTL, qBLT, qBLTC, qBLTCL, qBLTL, qDADD, qDBL, qDEC, qDESCB, qDESCBS, qDST, qDUP, qDWDC, qEFC, qEXCH, qFDESCBS, qGADRB, qINC, qIWDC, qKFCB, qLADRB, qLFC, qLG, qLGD, qLI, qLINKB, qLINT, qLL, qLLD, qLLK, qLP, qLST, qLSTF, qME, qMEL, qMRE, qMREL, qMUL, qMXD, qMXDL, qMXW, qMXWL, qNEG, qNILCK, qNILCKL, qNOOP, qNOTIFY, qNOTIFYL, qOR, qPL, qPOP, qPORTI, qPORTO, qPS, qPSD, qPSF, qPUSH, qR, qRD, qRDL, qREQUEUE, qREQUEUEL, qRET, qRF, qRFL, qRFS, qRFSL, qRIG, qRIGL, qRIL, qRILF, qRILL, qRL, qRSTR, qRSTRL, qRXG, qRXGL, qRXL, qRXLL, qSDIV, qSFC, qSG, qSGD, qSHIFT, qSL, qSLD, qSUB, qW, qWD, qWDL, qWF, qWFL, qWIG, qWIGL, qWIL, qWILL, qWL, qWS, qWSD, qWSF, qWSTR, qWSTRL, qWXG, qWXGL, qWXL, qWXLL, qXOR], InlineDefs: FROM "inlinedefs" USING [BITAND, BITSHIFT], OpCodeParams: FROM "opcodeparams" USING [BYTE, GlobalHB, HB, LocalBase, LocalHB, LocalPutSlots], P5: FROM "p5" USING [PopEffect, PushEffect, C0, C1, C2, LoadConstant], PeepholeDefs: FROM "peepholedefs" USING [PeepZ, Delete2, Delete3, HalfByteLocal, InitJParametersBC, InitParametersABC, InitParametersBC, InitParametersC, JumpPeepState, LoadInst, MC0, PeepholeUNotify, PeepholeZNotify, PeepState, SetRealInst, SetSourceIndex, SlidePeepState1, SlidePeepState2, UnpackFD], SDDefs: FROM "sddefs" USING [sBLTE, sBLTEC, sBLTECL, sBLTEL, sBYTBLTE, sBYTBLTEC, sBYTBLTECL, sBYTBLTEL, sSignedDiv], Table: FROM "table" USING [Base, Notifier], Tree: FROM "tree" USING [treeType]; PeepholeQ: PROGRAM IMPORTS CPtr: Code, MPtr: ComData, InlineDefs, P5U, P5, PeepholeDefs EXPORTS CodeDefs, P5, PeepholeDefs = BEGIN OPEN PeepholeDefs, OpCodeParams, CodeDefs; -- imported definitions BYTE: TYPE = OpCodeParams.BYTE; qNOOP: BYTE = FOpCodes.qNOOP; cb: Table.Base; -- code base (local copy) RJump: ARRAY JumpType[JumpE..UJumpLE] OF JumpType = [ JumpE, JumpN, JumpG, JumpLE, JumpL, JumpGE, UJumpG, UJumpLE, UJumpL, UJumpGE]; DummyProc: PROCEDURE = BEGIN -- every 2 minutes of compile time helps s: PeepState; js: JumpPeepState; IF FALSE THEN [] _ s; IF FALSE THEN [] _ js; END; PeepholeNotify: PUBLIC Table.Notifier = BEGIN -- called by allocator whenever table area is repacked cb _ base[Tree.treeType]; PeepholeZNotify[base]; PeepholeUNotify[base]; RETURN END; start: CodeCCIndex; PeepHole: PUBLIC PROCEDURE [s: CCIndex] = BEGIN start _ LOOPHOLE[s]; SetRealInst[FALSE]; IF ~(CPtr.dStar OR MPtr.switches['l]) THEN RemoveLongs[]; Peep0[]; Peep1[]; Peep2[]; Peep3[]; Peep4[]; Peep5[]; Peep6[]; Peep7[]; SetRealInst[TRUE]; PeepZ[start]; SetSourceIndex[NULLfileindex]; END; RemoveLongs: PROCEDURE = BEGIN -- remove long instructions OPEN FOpCodes; next: CodeCCIndex; state: PeepState; newinst: BYTE; BEGIN OPEN state; next _ start; UNTIL (c _ next) = CCNull DO next _ LOOPHOLE[cb[c].flink]; newinst _ qNOOP; WITH cb[LOOPHOLE[c,CCIndex]] SELECT FROM code => BEGIN InitParametersC[@state]; SELECT cInst FROM qRL => BEGIN newinst _ qR; GOTO pop0 END; qRDL => BEGIN newinst _ qRD; GOTO pop0 END; qRFL => BEGIN newinst _ qRF; GOTO pop0 END; qWL => BEGIN newinst _ qW; GOTO pop0 END; qWFL => BEGIN newinst _ qWF; GOTO pop0 END; qRFSL => BEGIN newinst _ qRFS; GOTO pop1 END; qRSTRL => BEGIN newinst _ qRSTR; GOTO pop1 END; qWDL => BEGIN newinst _ qWD; GOTO pop0 END; qWSTRL => BEGIN newinst _ qWSTR; GOTO pop1 END; qRXLL => newinst _ qRXL; qWXLL => newinst _ qWXL; qRXGL => newinst _ qRXG; qWXGL => newinst _ qWXG; qRILL => newinst _ qRIL; qWILL => newinst _ qWIL; qRIGL => newinst _ qRIG; qWIGL => newinst _ qWIG; qBLTCL => BEGIN newinst _ qBLTC; GOTO pop0 END; qBLTL => BEGIN newinst _ qBLT; InsertPOP[0]; GOTO pop2 END; qMEL => BEGIN newinst _ qME; GOTO pop0 END; qMREL => BEGIN newinst _ qMRE; InsertPOP[0]; GOTO pop1 END; qMXWL => BEGIN newinst _ qMXW; InsertPOP[1]; GOTO pop2 END; qMXDL => BEGIN newinst _ qMXD; GOTO pop0 END; qNOTIFYL => BEGIN newinst _ qNOTIFY; GOTO pop0 END; qBCASTL => BEGIN newinst _ qBCAST; GOTO pop0 END; qREQUEUEL => BEGIN newinst _ qREQUEUE; InsertPOP[1]; GOTO pop2 END; qKFCB => BEGIN OPEN SDDefs; newp1: WORD; SELECT cP[1] FROM sBLTEL => BEGIN newp1 _ sBLTE; InsertPOP[0] END; sBYTBLTEL => BEGIN newp1 _ sBYTBLTE; InsertPOP[0] END; sBLTECL => newp1 _ sBLTEC; sBYTBLTECL => newp1 _ sBYTBLTEC; ENDCASE => GO TO notspecial; cb[c].parameters[1] _ newp1; GO TO pop2; EXITS notspecial => NULL; END; ENDCASE; EXITS pop0 => InsertPOP[0]; pop1 => InsertPOP[1]; pop2 => InsertPOP[2]; END; ENDCASE; -- of WITH IF newinst # qNOOP THEN cb[c].inst _ newinst; ENDLOOP; END; -- of OPEN RETURN END; BackupCP: PROCEDURE [n: INTEGER] RETURNS [INTEGER] = BEGIN OPEN FOpCodes; -- back up codeptr n stack positions cc: CCIndex _ CPtr.codeptr; neteffect: INTEGER; WHILE (cc _ cb[cc].blink) # CCNull AND n # 0 DO WITH cb[cc] SELECT FROM code => BEGIN IF realinst THEN EXIT; SELECT inst FROM qEFC, qLFC, qSFC, qKFCB, qRET, qPORTO, qPORTI, qLST, qLSTF, qDST => EXIT; ENDCASE; neteffect _ P5.PushEffect[inst] - P5.PopEffect[inst]; IF n-neteffect < 0 THEN EXIT; n _ n - neteffect; END; ENDCASE => EXIT; ENDLOOP; CPtr.codeptr _ cc; RETURN[n] END; InsertPOP: PROCEDURE [n: INTEGER] = BEGIN OPEN FOpCodes; -- insert (or simulate) a POP of the word at tos-n savecodeptr: CCIndex _ CPtr.codeptr; n _ BackupCP[n]; SELECT n FROM 0 => P5.C0[qPOP]; 1 => BEGIN P5.C0[qEXCH]; P5.C0[qPOP] END; 2 => BEGIN P5.C0[qPOP]; P5.C0[qEXCH]; P5.C0[qPUSH]; P5.C0[qEXCH]; P5.C0[qPOP] END; 3 => BEGIN P5.C0[qPOP]; P5.C0[qPOP]; P5.C0[qEXCH]; P5.C0[qPUSH]; P5.C0[qEXCH]; P5.C0[qPUSH]; P5.C0[qEXCH]; P5.C0[qPOP] END; ENDCASE => SIGNAL CPtr.CodePassInconsistency; CPtr.codeptr _ savecodeptr; RETURN END; Peep0: PROCEDURE = BEGIN -- undo doubles OPEN FOpCodes; next: CodeCCIndex; state: PeepState; next _ start; BEGIN OPEN state; UNTIL (c _ next) = CCNull DO next _ LOOPHOLE[cb[c].flink]; WITH cb[LOOPHOLE[c,CCIndex]] SELECT FROM code => BEGIN InitParametersC[@state]; SELECT cInst FROM qLGD => BEGIN inst _ qLG; P5.C1[qLG, cP[1]+1]; END; qLLD => BEGIN inst _ qLL; P5.C1[qLL, cP[1]+1]; END; ENDCASE; END; ENDCASE; -- of WITH ENDLOOP; END; -- of OPEN state RETURN END; Peep1: PROCEDURE = BEGIN -- remove POPs by modifying previous instruction OPEN FOpCodes; next, ci: CCIndex; didsomething: BOOLEAN _ TRUE; WHILE didsomething DO next _ start; didsomething _ FALSE; UNTIL (ci _ next) = CCNull DO next _ cb[ci].flink; WITH cb[ci] SELECT FROM code => IF inst = qPOP AND ~realinst THEN didsomething _ didsomething OR RemoveThisPop[ci]; ENDCASE; ENDLOOP; ENDLOOP; RETURN END; RemoveThisPop: PUBLIC PROCEDURE [ci: CCIndex] RETURNS [didThisTime: BOOLEAN] = BEGIN -- remove POP by modifying previous instruction, if possible OPEN FOpCodes; state: PeepState; didThisTime _ FALSE; WITH cb[ci] SELECT FROM code => BEGIN OPEN state; c _ LOOPHOLE[ci]; InitParametersABC[@state]; SELECT cInst FROM qPOP => IF Popable[bInst] THEN BEGIN P5U.DeleteCell[b]; P5U.DeleteCell[c]; didThisTime _ TRUE; END ELSE SELECT bInst FROM qR, qRF, qRXL, qNEG, qDESCBS, qINC, qDEC => BEGIN P5U.DeleteCell[b]; [] _ RemoveThisPop[c]; -- the blink may be popable now -- above is unnecessary if called from Peep1 -- but useful if called from jump elimination didThisTime _ TRUE; END; qDADD => IF Popable[aInst] THEN BEGIN Delete2[a,b]; InsertPOP[1]; MC0[qADD, bMin]; P5U.DeleteCell[c]; didThisTime _ TRUE; END; qRD => BEGIN cb[b].inst _ qR; P5U.DeleteCell[c]; didThisTime _ TRUE; END; qIWDC, qDWDC => BEGIN CommuteCells[b,c]; didThisTime _ TRUE; END; qNILCKL => BEGIN cb[b].inst _ qNILCK; CommuteCells[b,c]; -- no recursive call since jump elimination needs code -- to go to nothing. didThisTime _ TRUE; END; ENDCASE; ENDCASE; END; ENDCASE; -- of WITH END; Popable: PROCEDURE [inst: BYTE] RETURNS [BOOLEAN] = BEGIN OPEN FOpCodes; RETURN[inst#qNOOP AND (P5.PopEffect[inst]=0 AND P5.PushEffect[inst]=1 OR inst = qLP OR inst = qDUP)] END; Peep2: PROCEDURE = BEGIN -- expand families OPEN FOpCodes; next, ci: CCIndex; state: PeepState; canSlide: BOOLEAN _ FALSE; next _ start; BEGIN OPEN state; UNTIL (ci _ next) = CCNull DO next _ cb[ci].flink; WITH cb[ci] SELECT FROM code => BEGIN IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]] ELSE BEGIN c _ LOOPHOLE[ci]; InitParametersABC[@state]; END; canSlide _ FALSE; SELECT cInst FROM -- expand out-of-range families qRIG => IF cP[1] ~IN GlobalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLG, cP[1]]; P5.C1[qR, cP[2]]; P5U.DeleteCell[c]; END; qRIL => IF cP[1] ~IN LocalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLL, cP[1]]; P5.C1[qR, cP[2]]; P5U.DeleteCell[c]; END; qRXL => IF cP[1] ~IN LocalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLL, cP[1]]; MC0[qADD, cMin]; P5.C1[qR, cP[2]]; P5U.DeleteCell[c]; END; qWXL => IF cP[1] ~IN LocalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLL, cP[1]]; P5.C0[qADD]; P5.C1[qW, cP[2]]; P5U.DeleteCell[c]; END; qWIL => IF cP[1] ~IN LocalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLL, cP[1]]; P5.C1[qW, cP[2]]; P5U.DeleteCell[c]; END; qRXG => IF TRUE THEN BEGIN P5.C1[qLG, cP[1]]; MC0[qADD, cMin]; P5.C1[qR, cP[2]]; P5U.DeleteCell[c]; END; qWXG => IF TRUE THEN BEGIN P5.C1[qLG, cP[1]]; P5.C0[qADD]; P5.C1[qW, cP[2]]; P5U.DeleteCell[c]; END; qWIG => IF TRUE THEN BEGIN P5.C1[qLG, cP[1]]; P5.C1[qW, cP[2]]; P5U.DeleteCell[c]; END; qRIGL => IF cP[1] ~IN GlobalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLGD, cP[1]]; P5.C1[qRL, cP[2]]; P5U.DeleteCell[c]; END; qRILL => IF cP[1] ~IN LocalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLLD, cP[1]]; P5.C1[qRL, cP[2]]; P5U.DeleteCell[c]; END; qRXLL => IF cP[1] ~IN LocalHB OR cP[2] ~IN HB THEN BEGIN P5.LoadConstant[0]; P5.C1[qLLD, cP[1]]; P5.C0[qDADD]; P5.C1[qRL, cP[2]]; P5U.DeleteCell[c]; END; qWXLL => IF cP[1] ~IN LocalHB OR cP[2] ~IN HB THEN BEGIN P5.LoadConstant[0]; P5.C1[qLLD, cP[1]]; P5.C0[qDADD]; P5.C1[qWL, cP[2]]; P5U.DeleteCell[c]; END; qWILL => IF cP[1] ~IN LocalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLLD, cP[1]]; P5.C1[qWL, cP[2]]; P5U.DeleteCell[c]; END; qRXGL => IF cP[1] ~IN GlobalHB OR cP[2] ~IN HB THEN BEGIN P5.LoadConstant[0]; P5.C1[qLGD, cP[1]]; P5.C0[qDADD]; P5.C1[qRL, cP[2]]; P5U.DeleteCell[c]; END; qWXGL => IF cP[1] ~IN GlobalHB OR cP[2] ~IN HB THEN BEGIN P5.LoadConstant[0]; P5.C1[qLGD, cP[1]]; P5.C0[qDADD]; P5.C1[qWL, cP[2]]; P5U.DeleteCell[c]; END; qWIGL => IF cP[1] ~IN GlobalHB OR cP[2] ~IN HB THEN BEGIN P5.C1[qLGD, cP[1]]; P5.C1[qWL, cP[2]]; P5U.DeleteCell[c]; END; qRILF => IF TRUE THEN BEGIN P5.C1[qLL, cP[1]]; P5.C2[qRF, cP[2], cP[3]]; P5U.DeleteCell[c]; END; qEFC, qLLK => IF cP[1] ~IN BYTE THEN SIGNAL CPtr.CodeNotImplemented; qLINKB => IF cP[1] ~IN BYTE THEN BEGIN cb[c].parameters[1] _ 377B; P5.C1[qLL, LocalBase]; P5.LoadConstant[cP[1]-377B]; P5.C0[qSUB]; P5.C1[qSL, LocalBase]; END; qDESCBS, qDESCB, qFDESCBS => BEGIN IF cP[1]/2 ~IN BYTE OR cP[1] MOD 2 = 0 THEN SIGNAL CPtr.CodeNotImplemented; parameters[1] _ cP[1]/2; IF cInst = qFDESCBS THEN BEGIN inst _ qDESCBS; P5.C0[qSFC]; END; END; qSDIV => BEGIN P5.C1[qKFCB, SDDefs.sSignedDiv]; P5U.DeleteCell[c]; END; qDEC => IF cMin THEN BEGIN P5.LoadConstant[0-1]; MC0[qADD, TRUE]; P5U.DeleteCell[c] END ELSE BEGIN P5.LoadConstant[1]; P5.C0[qSUB]; P5U.DeleteCell[c] END; qLINT => BEGIN P5.C0[qDUP]; P5.LoadConstant[0-15]; P5.C0[qSHIFT]; P5.C0[qNEG]; P5U.DeleteCell[c]; END; qGADRB, qLADRB => IF cP[1] ~IN BYTE THEN BEGIN parameters[1] _ LAST[BYTE]; P5.LoadConstant[cP[1]-LAST[BYTE]]; MC0[qADD, cMin]; END; qWS, qPS, qWSF, qPSF, qWSD, qPSD => IF cP[1] ~IN BYTE THEN SIGNAL CPtr.CodePassInconsistency; -- discover family members from sequences qR => IF cP[1] IN HB THEN SELECT bInst FROM qADD => IF HalfByteLocal[a] THEN BEGIN P5.C2[qRXL, aP[1], cP[1]]; Delete3[a,b,c]; END; qLL => IF bP[1] IN LocalHB THEN BEGIN P5.C2[qRIL, bP[1], cP[1]]; Delete2[b,c]; END; qLG => IF bP[1] IN GlobalHB THEN BEGIN P5.C2[qRIG, bP[1], cP[1]]; Delete2[b,c]; END; ENDCASE; qW => IF cP[1] IN HB THEN SELECT bInst FROM qADD => IF HalfByteLocal[a] THEN BEGIN P5.C2[qWXL, aP[1], cP[1]]; Delete3[a,b,c]; END; qLL => IF bP[1] IN LocalHB THEN BEGIN P5.C2[qWIL, bP[1], cP[1]]; Delete2[b,c]; END; ENDCASE; ENDCASE => canSlide _ TRUE; END; ENDCASE => canSlide _ FALSE; -- of WITH ENDLOOP; END; -- of OPEN state RETURN END; Peep3: PROCEDURE = BEGIN -- sprinkle DUPs OPEN FOpCodes; next, ci: CCIndex; state: PeepState; canSlide: BOOLEAN _ FALSE; next _ start; BEGIN OPEN state; UNTIL (ci _ next) = CCNull DO next _ cb[ci].flink; WITH cb[ci] SELECT FROM code => BEGIN IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]] ELSE BEGIN c _ LOOPHOLE[ci]; InitParametersABC[@state]; END; canSlide _ FALSE; SELECT cInst FROM -- replace load,load with load,DUP qLL, qLG, qLI => IF bInst = cInst AND cP[1] = bP[1] THEN BEGIN P5.C0[qDUP]; P5U.DeleteCell[c] END; qRIL, qRIG, qRILL, qRIGL => IF bInst = cInst AND cP[1] = bP[1] AND cP[2] = bP[2] THEN BEGIN P5.C0[qDUP]; P5U.DeleteCell[c] END; ENDCASE => canSlide _ TRUE; END; ENDCASE => canSlide _ FALSE; -- of WITH ENDLOOP; END; -- of OPEN state RETURN END; Peep4: PROCEDURE = BEGIN -- PUTs and PUSHs, RF and WF to RSTR and WSTR OPEN FOpCodes; next, ci: CCIndex; state: PeepState; pos, size: [0..16); canSlide: BOOLEAN _ FALSE; next _ start; BEGIN OPEN state; UNTIL (ci _ next) = CCNull DO next _ cb[ci].flink; WITH cb[ci] SELECT FROM code => BEGIN IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]] ELSE BEGIN c _ LOOPHOLE[ci]; InitParametersABC[@state]; END; canSlide _ FALSE; SELECT cInst FROM qLL => IF bInst = qSL AND cP[1] = bP[1] THEN IF cP[1] IN LocalPutSlots THEN BEGIN cb[b].inst _ qPL; P5U.DeleteCell[c]; END ELSE BEGIN P5.C0[qPUSH]; P5U.DeleteCell[c]; END ELSE GO TO Slide; qPUSH => IF bInst = qSL AND bP[1] IN LocalPutSlots THEN BEGIN cb[b].inst _ qPL; P5U.DeleteCell[c]; END ELSE GO TO Slide; qLG => IF bInst = qSG AND cP[1] = bP[1] THEN BEGIN P5.C0[qPUSH]; P5U.DeleteCell[c]; END ELSE GO TO Slide; qRIL => IF bInst = qWIL AND cP[1] = bP[1] AND cP[2] = bP[2] THEN BEGIN P5.C0[qPUSH]; P5U.DeleteCell[c] END ELSE GO TO Slide; qRILL => IF bInst = qWILL AND cP[1] = bP[1] AND cP[2] = bP[2] THEN BEGIN P5.C0[qPUSH]; P5U.DeleteCell[c] END ELSE GO TO Slide; qRIGL => IF bInst = qWIGL AND cP[1] = bP[1] AND cP[2] = bP[2] THEN BEGIN P5.C0[qPUSH]; P5U.DeleteCell[c] END ELSE GO TO Slide; qRF, qWF, qRFL, qWFL => BEGIN [pos, size] _ UnpackFD[LOOPHOLE[cP[2]]]; IF size = 8 AND cP[1] <= LAST[BYTE]/2 THEN SELECT pos FROM 0, 8 => BEGIN P5.LoadConstant[0]; P5.C1[(SELECT cInst FROM qRF => qRSTR, qWF => qWSTR, qRFL => qRSTRL, ENDCASE => qWSTRL), cP[1]*2+pos/8]; P5U.DeleteCell[c]; END; ENDCASE => GO TO Slide ELSE GO TO Slide; END; ENDCASE => GO TO Slide; EXITS Slide => canSlide _ TRUE; END; ENDCASE => canSlide _ FALSE; -- of WITH ENDLOOP; END; -- of OPEN state RETURN END; NonWS: ARRAY [FOpCodes.qWS..FOpCodes.qWSD] OF BYTE = [FOpCodes.qW, FOpCodes.qWF, FOpCodes.qWD]; Peep5: PROCEDURE = BEGIN -- put doubles back, eliminate EXCH preceding commutative operator OPEN FOpCodes; next, ci: CCIndex; state: PeepState; canSlide: BOOLEAN _ FALSE; next _ start; BEGIN OPEN state; UNTIL (ci _ next) = CCNull DO next _ cb[ci].flink; WITH cc:cb[ci] SELECT FROM code => BEGIN IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]] ELSE BEGIN c _ LOOPHOLE[ci]; InitParametersABC[@state]; END; canSlide _ FALSE; SELECT cInst FROM qLL => IF bInst = qLL AND cP[1] = bP[1]+1 THEN BEGIN cb[b].inst _ qLLD; P5U.DeleteCell[c]; END ELSE GO TO Slide; qSL => IF bInst = qSL AND cP[1] = bP[1]-1 THEN BEGIN cb[c].inst _ qSLD; P5U.DeleteCell[b]; END ELSE GO TO Slide; qLG => IF bInst = qLG AND cP[1] = bP[1]+1 THEN BEGIN cb[b].inst _ qLGD; P5U.DeleteCell[c]; END ELSE GO TO Slide; qSG => IF bInst = qSG AND cP[1] = bP[1]-1 THEN BEGIN cb[c].inst _ qSGD; P5U.DeleteCell[b]; END ELSE GO TO Slide; qADD, qMUL, qAND, qOR, qXOR => IF bInst = qEXCH THEN P5U.DeleteCell[b] ELSE GO TO Slide; qWS, qWSF, qWSD => IF bInst = qEXCH THEN BEGIN P5U.DeleteCell[b]; cc.inst _ NonWS[cInst]; END ELSE GO TO Slide; qEXCH => IF bInst = qEXCH THEN Delete2[b,c] ELSE IF LoadInst[b] AND LoadInst[a] THEN BEGIN P5U.DeleteCell[c]; CommuteCells[a,b]; cb[a].minimalStack _ bMin; cb[b].minimalStack _ aMin; END ELSE GO TO Slide; ENDCASE => GO TO Slide; EXITS Slide => canSlide _ TRUE; END; jump => BEGIN canSlide _ FALSE; IF cc.jtype IN [JumpE..UJumpLE] THEN WITH cb[cc.blink] SELECT FROM code => IF ~realinst AND inst = qEXCH AND ~PushFollows[LOOPHOLE[ci,JumpCCIndex]] THEN BEGIN P5U.DeleteCell[cc.blink]; cc.jtype _ RJump[cc.jtype]; END; ENDCASE; END; ENDCASE => canSlide _ FALSE; -- of WITH ENDLOOP; END; -- of OPEN state RETURN END; PushFollows: PROCEDURE [c: JumpCCIndex] RETURNS [BOOLEAN] = BEGIN -- c is conditional jump; TRUE if PUSH follows on either branch next: CCIndex; FOR next _ cb[c].flink, cb[next].flink WHILE next # CCNull DO WITH cb[next] SELECT FROM code => IF ~realinst AND inst = FOpCodes.qPUSH THEN RETURN[TRUE] ELSE EXIT; label => NULL; ENDCASE => EXIT; ENDLOOP; IF (next_cb[cb[c].destlabel].flink) # CCNull THEN WITH cb[next] SELECT FROM code => IF ~realinst AND inst = FOpCodes.qPUSH THEN RETURN[TRUE]; ENDCASE; RETURN[FALSE] END; CommuteCells: PROCEDURE [a, b: CCIndex] = BEGIN prev, next: CCIndex; prev _ cb[a].blink; -- never Null next _ cb[b].flink; cb[prev].flink _ b; cb[b].blink _ prev; cb[b].flink _ a; cb[a].blink _ b; cb[a].flink _ next; IF next # CCNull THEN cb[next].blink _ a; RETURN END; Peep6: PROCEDURE = BEGIN -- store double/load double, INC and DEC, MUL to SHIFT etc OPEN FOpCodes; next, ci: CCIndex; canSlide: BOOLEAN _ FALSE; state: PeepState; negate, powerof2: BOOLEAN; log: CARDINAL; d2: PROCEDURE = BEGIN Delete2[state.b, state.c]; IF negate THEN P5.C0[qNEG]; RETURN END; next _ start; BEGIN OPEN state; UNTIL (ci _ next) = CCNull DO next _ cb[ci].flink; WITH cb[ci] SELECT FROM code => BEGIN IF canSlide THEN SlidePeepState1[@state, LOOPHOLE[ci]] ELSE BEGIN c _ LOOPHOLE[ci]; InitParametersBC[@state]; END; canSlide _ FALSE; SELECT cInst FROM qLLD => IF bInst = qSLD AND cP[1] = bP[1] THEN IF cP[1] IN LocalPutSlots THEN BEGIN P5.C1[qSL, cP[1]+1]; P5.C1[qPL, cP[1]]; P5.C0[qPUSH]; Delete2[b,c]; END ELSE BEGIN P5.C0[qPUSH]; P5.C0[qPUSH]; P5U.DeleteCell[c] END ELSE GO TO Slide; qLGD => IF bInst = qSGD AND cP[1] = bP[1] THEN BEGIN P5.C0[qPUSH]; P5.C0[qPUSH]; P5U.DeleteCell[c] END ELSE GO TO Slide; qADD, qSUB => IF bInst = qLI THEN BEGIN SELECT LOOPHOLE[bP[1], INTEGER] FROM 0 => Delete2[b,c]; 1 => IF cInst = qADD THEN BEGIN cb[c].inst _ qINC; P5U.DeleteCell[b]; END; -1 => IF cInst = qSUB THEN BEGIN cb[c].inst _ qINC; P5U.DeleteCell[b]; END; ENDCASE => GO TO Slide; END ELSE IF bInst = qNEG THEN BEGIN cb[c].inst _ IF cInst = qADD THEN qSUB ELSE qADD; P5U.DeleteCell[b]; END ELSE GO TO Slide; qSHIFT => IF bInst = qLI THEN SELECT bP[1] FROM 1 => BEGIN cb[c].inst _ qDBL; P5U.DeleteCell[b] END; 0 => Delete2[b,c]; ENDCASE => GO TO Slide ELSE GO TO Slide; qMUL => IF bInst = qLI THEN BEGIN negate _ FALSE; IF LOOPHOLE[bP[1], INTEGER] < 0 THEN BEGIN negate _ TRUE; bP[1] _ -LOOPHOLE[bP[1],INTEGER]; END; SELECT bP[1] FROM 1 => d2[]; 2 => BEGIN P5.C0[qDBL]; d2[]; END; 3 => BEGIN P5.C0[qDUP]; P5.C0[qDBL]; MC0[qADD, cMin]; d2[]; END; 4 => BEGIN P5.C0[qDBL]; P5.C0[qDBL]; d2[]; END; 5 => BEGIN P5.C0[qDUP]; P5.C0[qDBL]; P5.C0[qDBL]; MC0[qADD, cMin]; d2[]; END; 6 => BEGIN P5.C0[qDBL]; P5.C0[qDUP]; P5.C0[qDBL]; MC0[qADD, cMin]; d2[]; END; ENDCASE => BEGIN [powerof2, log] _ Log2[LOOPHOLE[bP[1]]]; IF powerof2 THEN BEGIN P5.LoadConstant[log]; P5.C0[qSHIFT]; d2[]; END ELSE GO TO Slide; END; END; ENDCASE => GO TO Slide; EXITS Slide => canSlide _ TRUE; END; ENDCASE => canSlide _ FALSE; -- of WITH ENDLOOP; END; -- of OPEN state RETURN END; Log2: PROCEDURE [i: INTEGER] RETURNS [BOOLEAN, CARDINAL] = BEGIN OPEN InlineDefs; shift: CARDINAL; IF i = 0 THEN RETURN [FALSE, 0]; i _ ABS[i]; IF BITAND[i, i-1] # 0 THEN RETURN [FALSE, 0]; FOR shift IN [0..16) DO IF BITAND[i,1] = 1 THEN RETURN[TRUE, shift]; i _ BITSHIFT[i, -1]; ENDLOOP; ERROR; -- can't be reached END; Peep7: PROCEDURE = BEGIN -- find special jumps OPEN FOpCodes; next: JumpCCIndex; jstate: JumpPeepState; next _ LOOPHOLE[start]; BEGIN OPEN jstate; UNTIL (c _ next) = CCNull DO next _ LOOPHOLE[cb[c].flink]; WITH cb[LOOPHOLE[c,CCIndex]] SELECT FROM jump => BEGIN InitJParametersBC[@jstate]; CPtr.codeptr _ c; SELECT jtype FROM JumpE => IF bInst = qLI THEN IF bP[1] = 0 THEN BEGIN jtype _ ZJumpE; P5U.DeleteCell[b] END; JumpN => IF bInst = qLI THEN IF bP[1] = 0 THEN BEGIN jtype _ ZJumpN; P5U.DeleteCell[b] END; ENDCASE; END; ENDCASE; -- of WITH ENDLOOP; END; -- of OPEN state RETURN END; END...