-- file: PeepholeA.mesa -- last edited by Sweet on 7-Sep-82 11:08:01 -- last edited by Satterthwaite on December 16, 1982 9:45 am DIRECTORY Alloc: TYPE USING [Notifier], Code: TYPE USING [CodeNotImplemented], CodeDefs: TYPE USING [ Base, CCIndex, CCNull, codeType, JumpCCIndex, JumpType], FOpCodes: TYPE USING [ qADD, qAND, qDADD, qDB, qDBS, qDDUP, qDEXCH, qDMUL, qDUP, qEFC, qEXCH, qLG, qIOR, qLGD, qLL, qLLD, qLKB, qLLK, qMUL, qNULL, qPL, qPLD, qPS, qPSD, qPSDL, qPSF, qPSL, qPSLF, qR, qRD, qRDL, qREC, qREC2, qRF, qRGDI, qRGDIL, qRGI, qRGIF, qRGIL, qRGILF, qRKDI, qRKI, qRL, qRLF, qRLDI, qRLDIL, qRLI, qRLIF, qRLIL, qRLILF, qSG, qSGD, qSL, qSLD, qSUB, qW, qWD, qWDL, qWF, qWGDI, qWGDIL, qWGI, qWGIF, qWGIL, qWGILF,qWL, qWLDI, qWLDIL, qWLF, qWLI, qWLIF, qWLIL, qWLILF, qWS, qWSD, qWSDL, qWSF, qWSL, qWSLF, qXOR], OpCodeParams: TYPE USING [ BYTE, GlobalHB, HB, LocalBase, LocalHB, RiImplemented], P5: TYPE USING [C0, C1, C2, C3, LoadConstant], P5U: TYPE USING [DeleteCell], PeepholeDefs: TYPE USING [ CommuteCells, DblLoadInst, Delete2, InitParameters, LoadInst, NextInteresting, PeepState, PrevInteresting, SlidePeepState2, start]; PeepholeA: PROGRAM IMPORTS CPtr: Code, P5, P5U, PeepholeDefs EXPORTS PeepholeDefs = BEGIN OPEN PeepholeDefs, OpCodeParams, CodeDefs; -- imported definitions BYTE: TYPE = OpCodeParams.BYTE; cb: CodeDefs.Base; -- code base (local copy) PeepholeANotify: PUBLIC Alloc.Notifier = BEGIN -- called by allocator whenever table area is repacked cb ← base[codeType]; END; Peep2: PUBLIC PROC = BEGIN -- discover short magic OPEN FOpCodes; ci: CCIndex; next: CCIndex ← start; state: PeepState; canSlide: BOOL ← FALSE; UNTIL (ci ← next) = CCNull DO next ← NextInteresting[ci]; WITH cb[ci] SELECT FROM code => BEGIN OPEN state; IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]] ELSE InitParameters[@state, LOOPHOLE[ci], abc]; canSlide ← FALSE; SELECT cInst FROM -- discover family members from sequences qR => IF cP[1] IN HB THEN SELECT bInst FROM qLL => IF -- RiImplemented[read][local][short][single] AND bP[1] IN LocalHB THEN {P5.C2[qRLI, bP[1], cP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; qLG => IF -- RiImplemented[read][global][short][single] AND bP[1] IN GlobalHB THEN {P5.C2[qRGI, bP[1], cP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; qLLK => IF cP[1] = 0 THEN {P5.C1[qRKI, bP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; ENDCASE => canSlide ← TRUE; qW => IF cP[1] IN HB THEN SELECT bInst FROM qLL => IF -- RiImplemented[write][local][short][single] AND bP[1] IN LocalHB THEN {P5.C2[qWLI, bP[1], cP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; qLG => IF -- RiImplemented[write][global][short][single] AND bP[1] IN GlobalHB THEN {P5.C2[qWGI, bP[1], cP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; ENDCASE => canSlide ← TRUE; qRD => IF cP[1] IN HB THEN SELECT bInst FROM qLL => IF -- RiImplemented[read][local][short][double] AND bP[1] IN LocalHB THEN {P5.C2[qRLDI, bP[1], cP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; qLG => IF -- RiImplemented[read][global][short][double] AND bP[1] IN GlobalHB THEN {P5.C2[qRGDI, bP[1], cP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; qLLK => IF cP[1] = 0 THEN {P5.C1[qRKDI, bP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; ENDCASE => canSlide ← TRUE; qWD => IF cP[1] IN HB THEN SELECT bInst FROM qLL => IF -- RiImplemented[write][local][short][double] AND bP[1] IN LocalHB THEN {P5.C2[qWLDI, bP[1], cP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; qLG => IF -- RiImplemented[write][global][short][double] AND bP[1] IN GlobalHB THEN {P5.C2[qWGDI, bP[1], cP[1]]; Delete2[b,c]} ELSE canSlide ← TRUE; ENDCASE => canSlide ← TRUE; qRF => IF cP[1] IN HB THEN SELECT bInst FROM qLL => IF -- RiImplemented[read][local][short][field] AND bP[1] IN LocalHB THEN {P5.C3[qRLIF, bP[1], cP[1], cP[2]]; Delete2[b,c]} ELSE canSlide ← TRUE; qLG => IF -- RiImplemented[read][global][short][field] AND bP[1] IN GlobalHB THEN {P5.C3[qRGIF, bP[1], cP[1], cP[2]]; Delete2[b,c]} ELSE canSlide ← TRUE; ENDCASE => canSlide ← TRUE; qWF => IF cP[1] IN HB THEN SELECT bInst FROM qLL => IF RiImplemented[write][local][short][field] AND bP[1] IN LocalHB THEN {P5.C3[qWLIF, bP[1], cP[1], cP[2]]; Delete2[b,c]} ELSE canSlide ← TRUE; qLG => IF -- RiImplemented[write][global][short][field] AND bP[1] IN GlobalHB THEN {P5.C3[qWGIF, bP[1], cP[1], cP[2]]; Delete2[b,c]} ELSE canSlide ← TRUE; ENDCASE => canSlide ← TRUE; ENDCASE => canSlide ← TRUE; END; -- of OPEN state ENDCASE => canSlide ← FALSE; -- of WITH ENDLOOP; END; Peep10: PUBLIC PROC = BEGIN -- expand families OPEN FOpCodes; ci: CCIndex; next: CCIndex ← start; state: PeepState; canSlide: BOOL ← FALSE; UNTIL (ci ← next) = CCNull DO next ← NextInteresting[ci]; WITH cb[ci] SELECT FROM code => BEGIN OPEN state; LoadLocal: PROC = BEGIN SELECT bInst FROM qSL => IF bP[1] = cP[1] THEN {cb[b].inst ← qPL; RETURN}; qLL => IF bP[1] = cP[1] THEN {P5.C0[qDUP]; RETURN}; ENDCASE; P5.C1[qLL, cP[1]]; END; LoadGlobal: PROC = BEGIN SELECT bInst FROM qSG => IF bP[1] = cP[1] THEN {P5.C0[qREC]; RETURN}; qLG => IF bP[1] = cP[1] THEN {P5.C0[qDUP]; RETURN}; ENDCASE; P5.C1[qLG, cP[1]]; END; LoadLocalDbl: PROC = BEGIN SELECT bInst FROM qSLD => IF bP[1] = cP[1] THEN {cb[b].inst ← qPLD; RETURN}; qLLD => IF bP[1] = cP[1] THEN {P5.C0[qDDUP]; RETURN}; ENDCASE; P5.C1[qLLD, cP[1]]; END; LoadGlobalDbl: PROC = BEGIN SELECT bInst FROM qSGD => IF bP[1] = cP[1] THEN {P5.C0[qREC2]; RETURN}; qLGD => IF bP[1] = cP[1] THEN {P5.C0[qDDUP]; RETURN}; ENDCASE; P5.C1[qLGD, cP[1]]; END; IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]] ELSE InitParameters[@state, LOOPHOLE[ci], abc]; canSlide ← FALSE; SELECT cInst FROM -- expand out-of-range families qRLI => IF ~RiImplemented[read][local][short][single] THEN { LoadLocal[]; P5.C1[qR, cP[2]]; P5U.DeleteCell[c]}; qRGI => IF ~RiImplemented[read][global][short][single] THEN { LoadGlobal[]; P5.C1[qR, cP[2]]; P5U.DeleteCell[c]}; qRLDI => IF ~RiImplemented[read][local][short][double] THEN { LoadLocal[]; P5.C1[qRD, cP[2]]; P5U.DeleteCell[c]}; qRGDI => IF ~RiImplemented[read][global][short][double] THEN { LoadGlobal[]; P5.C1[qRD, cP[2]]; P5U.DeleteCell[c]}; qRLIF => IF ~RiImplemented[read][local][short][field] THEN { LoadLocal[]; P5.C2[qRF, cP[2], cP[3]]; P5U.DeleteCell[c]}; qRGIF => IF ~RiImplemented[read][global][short][field] THEN { LoadGlobal[]; P5.C2[qRF, cP[2], cP[3]]; P5U.DeleteCell[c]}; qRLIL => IF ~RiImplemented[read][local][long][single] THEN { LoadLocalDbl[]; P5.C1[qRL, cP[2]]; P5U.DeleteCell[c]}; qRGIL => IF ~RiImplemented[read][global][long][single] THEN { LoadGlobalDbl[]; P5.C1[qRL, cP[2]]; P5U.DeleteCell[c]}; qRLDIL => IF ~RiImplemented[read][local][long][double] THEN { LoadLocalDbl[]; P5.C1[qRDL, cP[2]]; P5U.DeleteCell[c]}; qRGDIL => IF ~RiImplemented[read][global][long][double] THEN { LoadGlobalDbl[]; P5.C1[qRDL, cP[2]]; P5U.DeleteCell[c]}; qRLILF => IF ~RiImplemented[read][local][long][field] THEN { LoadLocalDbl[]; P5.C2[qRLF, cP[2], cP[3]]; P5U.DeleteCell[c]}; qRGILF => IF ~RiImplemented[read][global][long][field] THEN { LoadGlobalDbl[]; P5.C2[qRLF, cP[2], cP[3]]; P5U.DeleteCell[c]}; qWLI => IF ~RiImplemented[write][local][short][single] THEN { LoadLocal[]; P5.C1[qW, cP[2]]; P5U.DeleteCell[c]}; qWGI => IF ~RiImplemented[write][global][short][single] THEN { LoadGlobal[]; P5.C1[qW, cP[2]]; P5U.DeleteCell[c]}; qWLDI => IF ~RiImplemented[write][local][short][double] THEN { LoadLocal[]; P5.C1[qWD, cP[2]]; P5U.DeleteCell[c]}; qWGDI => IF ~RiImplemented[write][global][short][double] THEN { LoadGlobal[]; P5.C1[qWD, cP[2]]; P5U.DeleteCell[c]}; qWLIF => IF ~RiImplemented[write][local][short][field] THEN { LoadLocal[]; P5.C2[qWF, cP[2], cP[3]]; P5U.DeleteCell[c]}; qWGIF => IF ~RiImplemented[write][global][short][field] THEN { LoadGlobal[]; P5.C2[qWF, cP[2], cP[3]]; P5U.DeleteCell[c]}; qWLIL => IF ~RiImplemented[write][local][long][single] THEN { LoadLocalDbl[]; P5.C1[qWL, cP[2]]; P5U.DeleteCell[c]}; qWGIL => IF ~RiImplemented[write][global][long][single] THEN { LoadGlobalDbl[]; P5.C1[qWL, cP[2]]; P5U.DeleteCell[c]}; qWLDIL => IF ~RiImplemented[write][local][long][double] THEN { LoadLocalDbl[]; P5.C1[qWDL, cP[2]]; P5U.DeleteCell[c]}; qWGDIL => IF ~RiImplemented[write][global][long][double] THEN { LoadGlobalDbl[]; P5.C1[qWDL, cP[2]]; P5U.DeleteCell[c]}; qWLILF => IF ~RiImplemented[write][local][long][field] THEN { LoadLocalDbl[]; P5.C2[qWLF, cP[2], cP[3]]; P5U.DeleteCell[c]}; qWGILF => IF ~RiImplemented[write][global][long][field] THEN { LoadGlobalDbl[]; P5.C2[qWLF, cP[2], cP[3]]; P5U.DeleteCell[c]}; ENDCASE => GO TO Slide; EXITS Slide => canSlide ← TRUE; END; -- of OPEN state ENDCASE => canSlide ← FALSE; -- of WITH ENDLOOP; END; Peep1: PUBLIC PROC = BEGIN -- expand families OPEN FOpCodes; ci: CCIndex; next: CCIndex ← start; state: PeepState; canSlide: BOOL ← FALSE; UNTIL (ci ← next) = CCNull DO next ← NextInteresting[ci]; WITH cc: cb[ci] SELECT FROM code => BEGIN OPEN state; IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]] ELSE InitParameters[@state, LOOPHOLE[ci], abc]; canSlide ← FALSE; SELECT cInst FROM -- expand out-of-range families qEFC, qLLK => IF cP[1] NOT IN BYTE THEN SIGNAL CPtr.CodeNotImplemented; qLKB => IF cP[1] NOT 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 ELSE canSlide ← TRUE; qREC => SELECT bInst FROM qWS => {cb[b].inst ← qPS; P5U.DeleteCell[c]}; qWSD => {cb[b].inst ← qPSD; P5U.DeleteCell[c]}; qWSF => {cb[b].inst ← qPSF; P5U.DeleteCell[c]}; qREC => SELECT aInst FROM qWSL => {cb[a].inst ← qPSL; Delete2[b, c]}; qWSDL => {cb[a].inst ← qPSDL; Delete2[b, c]}; qWSLF => {cb[a].inst ← qPSLF; Delete2[b, c]}; ENDCASE => GO TO Slide; ENDCASE => GO TO Slide; qREC2 => SELECT bInst FROM qWSL => {cb[b].inst ← qPSL; P5U.DeleteCell[c]}; qWSDL => {cb[b].inst ← qPSDL; P5U.DeleteCell[c]}; qWSLF => {cb[b].inst ← qPSLF; P5U.DeleteCell[c]}; ENDCASE => GO TO Slide; qDBS, qDB => BEGIN cc.parameters[1] ← cP[1]*2; -- N.B. this is exeuted only once END; qADD, qMUL, qAND, qIOR, qXOR => IF bInst = qEXCH THEN P5U.DeleteCell[b] ELSE GO TO Slide; qDADD, qDMUL => IF bInst = qDEXCH THEN P5U.DeleteCell[b] ELSE GO TO Slide; qW, qWF => IF bInst = qEXCH THEN BEGIN WSOp: ARRAY [FOpCodes.qW..FOpCodes.qWF] OF BYTE = [ FOpCodes.qWS, FOpCodes.qNULL, FOpCodes.qNULL, FOpCodes.qWSF]; P5U.DeleteCell[b]; cc.inst ← WSOp[cInst]; END ELSE GO TO Slide; qWS, qWSF => IF bInst = qEXCH AND ~NextIsPush[c] THEN BEGIN NonWS: ARRAY [FOpCodes.qWS..FOpCodes.qWSF] OF BYTE = [ FOpCodes.qW, FOpCodes.qNULL, FOpCodes.qNULL, FOpCodes.qWF]; 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]; END ELSE GO TO Slide; qDEXCH => IF bInst = qDEXCH THEN Delete2[b,c] ELSE IF DblLoadInst[b] AND DblLoadInst[a] THEN BEGIN P5U.DeleteCell[c]; CommuteCells[a,b]; END ELSE GO TO Slide; ENDCASE => GO TO Slide; EXITS Slide => canSlide ← TRUE; END; -- of OPEN state jump => BEGIN RJump: ARRAY JumpType[JumpE..UJumpLE] OF JumpType = [ JumpE, JumpN, JumpG, JumpLE, JumpL, JumpGE, UJumpG, UJumpLE, UJumpL, UJumpGE]; canSlide ← FALSE; IF cc.jtype IN [JumpE..UJumpLE] THEN BEGIN prev: CCIndex ← PrevInteresting[ci]; WITH cb[prev] SELECT FROM code => IF ~realinst AND inst = qEXCH AND ~PushFollows[LOOPHOLE[ci,JumpCCIndex]] THEN {P5U.DeleteCell[prev]; cc.jtype ← RJump[cc.jtype]}; ENDCASE; END; END; ENDCASE => canSlide ← FALSE; -- of WITH ENDLOOP; END; PushFollows: PROC [c: JumpCCIndex] RETURNS [BOOL] = BEGIN -- c is conditional jump; TRUE if PUSH follows on either branch next: CCIndex; IF NextIsPush[c] THEN RETURN [TRUE]; IF (next←NextInteresting[cb[c].destlabel]) # CCNull THEN WITH cb[next] SELECT FROM code => IF ~realinst AND inst = FOpCodes.qREC THEN RETURN [TRUE]; ENDCASE; RETURN [FALSE] END; NextIsPush: PUBLIC PROC [c: CCIndex] RETURNS [BOOL] = BEGIN -- TRUE if PUSH follows FOR next: CCIndex ← NextInteresting[c], NextInteresting[next] WHILE next # CCNull DO WITH cb[next] SELECT FROM code => IF ~realinst AND inst = FOpCodes.qREC THEN RETURN [TRUE] ELSE EXIT; label => NULL; ENDCASE => EXIT; ENDLOOP; RETURN [FALSE] END; END.