-- 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.