DIRECTORY
Alloc: TYPE USING [Notifier],
Code: TYPE USING [CodeNotImplemented, CodePassInconsistency, codeptr],
P5U: TYPE USING [DeleteCell],
CodeDefs: 
TYPE 
USING [
Base, CCIndex, CCNull, CodeCCIndex, codeType, JumpCCIndex, JumpType],
 
FOpCodes: 
TYPE 
USING [
qADD, qAMUL, qAND, qDADD, qDBL, qDEC, qDESCB, qDESCBS, qDIV, qDST,
qDUP, qDWDC, qEFC, qEXCH, qFDESCBS, qGADRB, qINC, qIWDC, qKFCB,
qLADRB, qLFC, qLG, qLGD, qLI, qLINKB, qLINT, qLL, qLLD, qLLK, qLST, qLSTF,
qMUL, qNEG, qNOOP, qOR, qPL, qPOP, qPORTI, qPORTO, qPS, qPSD, qPSF, qPUSH,
qR, qRD, qRET, qRF, qRFL, qRFS, qRIG, qRIGL, qRIL, qRILF, qRILL, qRL,
qRSTR, qRSTRL, qRXG, qRXGL, qRXL, qRXLL, qSDIV, qSFC, qSG, qSGD, qSHIFT,
qSL, qSLD, qSUB, qW, qWD, qWF, qWFL, qWIG, qWIGL, qWIL, qWILL, qWL, qWS,
qWSD, qWSF, qWSTR, qWSTRL, qWXG, qWXGL, qWXL, qWXLL, qXOR],
 
OpCodeParams: TYPE USING [BYTE, GlobalHB, HB, LocalBase, LocalHB, LocalPutSlots],
P5: TYPE USING [PopEffect, PushEffect, C0, C1, C2, LoadConstant],
PeepholeDefs: 
TYPE 
USING [
PeepZ, Delete2, Delete3, HalfByteGlobal, HalfByteLocal, InitJParametersBC,
InitParameters, JumpPeepState, LoadInst, NextInteresting, PeepholeUNotify,
PeepholeZNotify, PeepState, PrevInteresting, SetRealInst, SlidePeepState1,
SlidePeepState2, UnpackFD],
 
PrincOps: TYPE USING [sSignedDiv],
PrincOpsUtils: TYPE USING [BITAND, BITSHIFT];
 
PeepholeQ: 
PROGRAM
IMPORTS CPtr: Code, P5U, P5, PeepholeDefs, PrincOpsUtils
EXPORTS CodeDefs, P5, PeepholeDefs =
BEGIN OPEN PeepholeDefs, OpCodeParams, CodeDefs;
imported definitions
BYTE: TYPE = OpCodeParams.BYTE;
qNOOP: BYTE = FOpCodes.qNOOP;
cb: CodeDefs.Base;  -- code base (local copy)
RJump: 
ARRAY JumpType[JumpE..UJumpLE] 
OF JumpType = [
JumpE, JumpN, JumpG, JumpLE, JumpL, JumpGE,
UJumpG, UJumpLE, UJumpL, UJumpGE];
 
DummyProc: 
PROC =
BEGIN -- every 2 minutes of compile time helps
s: PeepState;
js: JumpPeepState;
IF FALSE THEN [] ← s;
IF FALSE THEN [] ← js;
END;
 
PeepholeNotify: 
PUBLIC Alloc.Notifier =
BEGIN  -- called by allocator whenever table area is repacked
cb ← base[codeType];
PeepholeZNotify[base];  PeepholeUNotify[base];
END;
 
start: CodeCCIndex;
PeepHole: 
PUBLIC 
PROC [s: CCIndex] =
BEGIN
start ← LOOPHOLE[s];
SetRealInst[FALSE];
Peep0[];
Peep1[];
Peep2[];
Peep3[];
Peep4[];
Peep5[];
Peep6[];
Peep7[];
SetRealInst[TRUE];
PeepZ[start];
END;
 
BackupCP: 
PROC [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 THEN EXIT;
n ← n - netEffect;
END;
 
other => IF otag = table THEN EXIT;
ENDCASE => EXIT;
 
ENDLOOP;
 
CPtr.codeptr ← cc;
RETURN [n]
END;
 
InsertPOP: 
PROC [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 => {P5.C0[qEXCH]; P5.C0[qPOP]};
2 => {P5.C0[qPOP]; P5.C0[qEXCH]; P5.C0[qPUSH]; P5.C0[qEXCH]; P5.C0[qPOP]};
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;
END;
 
Peep0: 
PROC =
BEGIN -- undo doubles
OPEN FOpCodes;
ci: CCIndex;
state: PeepState;
next: CCIndex ← start;
UNTIL (ci ← next) = CCNull 
DO
next ← NextInteresting[ci];
WITH cb[ci] 
SELECT 
FROM
code =>
BEGIN OPEN state;
InitParameters[@state, LOOPHOLE[ci], c];
SELECT cInst 
FROM
qLGD => {inst ← qLG; P5.C1[qLG, cP[1]+1]};
qLLD => {inst ← qLL; P5.C1[qLL, cP[1]+1]};
ENDCASE;
 
END; -- of OPEN state
 
ENDCASE; -- of WITH
 
ENDLOOP;
 
END;
 
Peep1: 
PROC =
BEGIN -- remove POPs by modifying previous instruction
OPEN FOpCodes;
next, ci: CCIndex;
changed: BOOL ← TRUE;
WHILE changed 
DO
next ← start;
changed ← FALSE;
UNTIL (ci ← next) = CCNull 
DO
next ← NextInteresting[ci];
WITH cb[ci] 
SELECT 
FROM
code =>
IF inst = qPOP 
AND ~realinst 
THEN
changed ← changed OR RemoveThisPop[ci];
 
 
ENDCASE;
 
ENDLOOP;
 
ENDLOOP;
 
END;
 
RemoveThisPop: 
PUBLIC 
PROC [ci: CCIndex] 
RETURNS [didThisTime: 
BOOL] =
BEGIN -- remove POP by modifying previous instruction, if possible
OPEN FOpCodes;
state: PeepState;
didThisTime ← FALSE;
WITH cb[ci] 
SELECT 
FROM
code =>
BEGIN OPEN state;
InitParameters[@state, LOOPHOLE[ci], abc];
SELECT cInst 
FROM
qPOP =>
IF Popable[bInst] 
THEN
{P5U.DeleteCell[b]; P5U.DeleteCell[c]; didThisTime ← TRUE}
 
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;
 
 
qRSTR, qADD, qSUB, qMUL, qAMUL, qDIV, qSDIV, qAND, qOR, qXOR,
qSHIFT, qRFS, qRL, qRFL =>
BEGIN
np: CCIndex;
P5U.DeleteCell[b];
CPtr.codeptr ← cb[c].blink;
P5.C0[qPOP];
np ← CPtr.codeptr;
[] ← RemoveThisPop[np];  [] ← RemoveThisPop[c];
END;
 
qDADD =>
IF Popable[aInst] 
THEN
BEGIN
Delete2[a,b];
InsertPOP[1];
P5.C0[qADD];
P5U.DeleteCell[c];
didThisTime ← TRUE;
END;
 
 
qRD => {cb[b].inst ← qR; P5U.DeleteCell[c]; didThisTime ← TRUE};
qIWDC, qDWDC => {CommuteCells[b,c]; didThisTime ← TRUE};
qEXCH => 
IF IsLoad[aInst] 
THEN
BEGIN
Delete2[b, c];
CPtr.codeptr ← cb[a].blink;
P5.C0[qPOP];
[] ← RemoveThisPop[CPtr.codeptr];
didThisTime ← TRUE;
END;
 
ENDCASE;
 
 
 
ENDCASE;
 
END;
 
ENDCASE; -- of WITH
 
END;
 
Popable: 
PROC [inst: 
BYTE] 
RETURNS [
BOOL] =
BEGIN
RETURN [inst#qNOOP 
AND
(P5.PopEffect[inst]=0 AND P5.PushEffect[inst]=1 OR inst = FOpCodes.qDUP)]
 
END;
 
IsLoad: 
PROC [inst: 
BYTE] 
RETURNS [
BOOL] =
BEGIN
RETURN [inst#qNOOP 
AND inst # FOpCodes.qPUSH 
AND
(P5.PopEffect[inst]=0 AND P5.PushEffect[inst]=1)]
 
END;
 
Peep2: 
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;
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 =>
BEGIN
IF cP[1] NOT IN BYTE THEN SIGNAL CPtr.CodeNotImplemented;
canSlide ← TRUE;
END;
 
qLINKB =>
IF cP[1] IN BYTE THEN canSlide ← TRUE
ELSE
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
parameters[1] ← cP[1]*2;
IF cInst = qFDESCBS THEN {inst ← qDESCBS; P5.C0[qSFC]};
END;
 
qSDIV => {P5.C1[qKFCB, PrincOps.sSignedDiv]; P5U.DeleteCell[c]};
qDEC => {P5.LoadConstant[1]; P5.C0[qSUB]; P5U.DeleteCell[c]};
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 canSlide ← TRUE
ELSE
BEGIN
parameters[1] ← BYTE.LAST;
P5.LoadConstant[cP[1]-BYTE.LAST]; P5.C0[qADD];
END;
 
 
qWS, qPS, qWSF, qPSF, qWSD, qPSD =>
BEGIN
IF cP[1] NOT IN BYTE THEN SIGNAL CPtr.CodePassInconsistency;
canSlide ← TRUE;
END;
 
discover family members from sequences
qR =>
IF cP[1] 
IN 
HB 
THEN
SELECT bInst 
FROM
qADD =>
IF HalfByteLocal[a] THEN {P5.C2[qRXL, aP[1], cP[1]]; Delete3[a,b,c]}
ELSE canSlide ← TRUE;
 
qLL =>
IF bP[1] IN LocalHB THEN {P5.C2[qRIL, bP[1], cP[1]]; Delete2[b,c]}
ELSE canSlide ← TRUE;
 
qLG =>
IF bP[1] IN GlobalHB THEN {P5.C2[qRIG, bP[1], cP[1]]; Delete2[b,c]}
ELSE canSlide ← TRUE;
 
ENDCASE => canSlide ← TRUE
 
 
ELSE canSlide ← TRUE;
 
qW =>
IF cP[1] 
IN 
HB 
THEN
SELECT bInst 
FROM
qADD =>
IF HalfByteLocal[a] THEN {P5.C2[qWXL, aP[1], cP[1]]; Delete3[a,b,c]}
ELSE canSlide ← TRUE;
 
qLL =>
IF bP[1] IN LocalHB THEN {P5.C2[qWIL, bP[1], cP[1]]; Delete2[b,c]}
ELSE canSlide ← TRUE;
 
ENDCASE => canSlide ← TRUE
 
 
ELSE canSlide ← TRUE;
 
qRL =>
IF cP[1] 
IN 
HB 
THEN
SELECT bInst 
FROM
qADD =>
IF aInst = qLI 
AND aP[1] = 0 
THEN
BEGIN
aa: CCIndex = PrevInteresting[a];
IF aa # CCNull 
THEN 
WITH cc: cb[aa] 
SELECT 
FROM
code => 
IF HalfByteLocal[
LOOPHOLE[aa]] 
THEN
BEGIN
P5.C2[qRXLL, cc.parameters[1], cP[1]];
Delete3[a,b,c]; P5U.DeleteCell[aa];
END
 
ELSE 
IF HalfByteGlobal[
LOOPHOLE[aa]] 
THEN
BEGIN
P5.C2[qRXGL, cc.parameters[1], cP[1]];
Delete3[a,b,c]; P5U.DeleteCell[aa];
END
 
ELSE canSlide ← TRUE;
ENDCASE
 
ELSE canSlide ← TRUE;
END
 
ELSE canSlide ← TRUE;
 
qLL =>
IF aInst = qLL 
AND aP[1] 
IN LocalHB 
AND bP[1] = aP[1]+1 
THEN
{P5.C2[qRILL, aP[1], cP[1]]; Delete3[a,b,c]}
 
ELSE canSlide ← TRUE;
 
qLG =>
IF aInst = qLL 
AND aP[1] 
IN GlobalHB 
AND bP[1] = aP[1]+1 
THEN
{P5.C2[qRIGL, aP[1], cP[1]]; Delete3[a,b,c]}
 
ELSE canSlide ← TRUE;
 
ENDCASE => canSlide ← TRUE
 
 
ELSE canSlide ← TRUE;
 
qWL =>
IF cP[1] 
IN 
HB 
THEN
SELECT bInst 
FROM
qADD =>
IF aInst = qLI 
AND aP[1] = 0 
THEN
BEGIN
aa: CCIndex = PrevInteresting[a];
IF aa # CCNull 
THEN 
WITH cc: cb[aa] 
SELECT 
FROM
code => 
IF HalfByteLocal[
LOOPHOLE[aa]] 
THEN
BEGIN
P5.C2[qWXLL, cc.parameters[1], cP[1]];
Delete3[a,b,c]; P5U.DeleteCell[aa];
END
 
ELSE 
IF HalfByteGlobal[
LOOPHOLE[aa]] 
THEN
BEGIN
P5.C2[qWXGL, cc.parameters[1], cP[1]];
Delete3[a,b,c]; P5U.DeleteCell[aa];
END
 
ELSE canSlide ← TRUE;
ENDCASE
 
ELSE canSlide ← TRUE;
END
 
ELSE canSlide ← TRUE;
 
qLL =>
IF aInst = qLL 
AND aP[1] 
IN LocalHB 
AND bP[1] = aP[1]+1 
THEN
{P5.C2[qWILL, aP[1], cP[1]]; Delete3[a,b,c]}
 
ELSE canSlide ← TRUE;
 
qLG =>
IF aInst = qLL 
AND aP[1] 
IN GlobalHB 
AND bP[1] = aP[1]+1 
THEN
{P5.C2[qWIGL, aP[1], cP[1]]; Delete3[a,b,c]}
 
ELSE canSlide ← TRUE;
 
ENDCASE => canSlide ← TRUE
 
 
ELSE canSlide ← TRUE;
 
qRXG =>
IF 
TRUE 
THEN
BEGIN
P5.C1[qLG, cP[1]]; P5.C0[qADD]; 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
{P5.C1[qLG, cP[1]]; P5.C1[qW, cP[2]]; P5U.DeleteCell[c]};
 
 
qRILF =>
IF 
TRUE 
THEN
BEGIN
P5.C1[qLL, cP[1]]; P5.C2[qRF, cP[2], cP[3]];
P5U.DeleteCell[c];
END;
 
 
ENDCASE => canSlide ← TRUE;
 
END; -- of OPEN state
 
ENDCASE => canSlide ← FALSE; -- of WITH
 
ENDLOOP;
 
END;
 
Peep3: 
PROC =
BEGIN -- sprinkle DUPs
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 ← TRUE;
IF bInst = cInst 
THEN
replace load,load with load,DUP
SELECT cInst 
FROM
qLL, qLG, qLI =>
IF cP[1] = bP[1] THEN {P5.C0[qDUP]; P5U.DeleteCell[c]; canSlide ← FALSE};
 
qRIL, qRIG, qRILL, qRIGL =>
IF cP[1] = bP[1] 
AND cP[2] = bP[2] 
THEN
{P5.C0[qDUP]; P5U.DeleteCell[c]; canSlide ← FALSE};
 
 
ENDCASE;
 
 
END; -- of OPEN state
 
ENDCASE => canSlide ← FALSE; -- of WITH
 
ENDLOOP;
 
END;
 
Peep4: 
PROC =
BEGIN -- PUTs and PUSHs, RF and WF to RSTR and WSTR
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
qLL =>
IF bInst = qSL 
AND cP[1] = bP[1] 
THEN
IF cP[1] 
IN LocalPutSlots 
THEN
{cb[b].inst ← qPL; P5U.DeleteCell[c]}
 
ELSE {CPtr.codeptr ← b; P5.C0[qPUSH]; P5U.DeleteCell[c]}
 
ELSE canSlide ← TRUE;
 
qPUSH =>
IF bInst = qSL 
AND bP[1] 
IN LocalPutSlots 
THEN
{cb[b].inst ← qPL; P5U.DeleteCell[c]}
 
ELSE canSlide ← TRUE;
 
qLG =>
IF bInst = qSG 
AND cP[1] = bP[1] 
THEN
{CPtr.codeptr ← b; P5.C0[qPUSH]; P5U.DeleteCell[c]}
 
ELSE canSlide ← TRUE;
 
qRIL =>
IF bInst = qWIL 
AND cP[1] = bP[1] 
AND cP[2] = bP[2] 
THEN
{CPtr.codeptr ← b; P5.C0[qPUSH]; P5U.DeleteCell[c]}
 
ELSE canSlide ← TRUE;
 
qRILL =>
IF bInst = qWILL 
AND cP[1] = bP[1] 
AND cP[2] = bP[2] 
THEN
{CPtr.codeptr ← b; P5.C0[qPUSH]; P5U.DeleteCell[c]}
 
ELSE canSlide ← TRUE;
 
qRIGL =>
IF bInst = qWIGL 
AND cP[1] = bP[1] 
AND cP[2] = bP[2] 
THEN
{CPtr.codeptr ← b; P5.C0[qPUSH]; P5U.DeleteCell[c]}
 
ELSE canSlide ← TRUE;
 
qRF, qWF, qRFL, qWFL =>
BEGIN
position, size: [0..16);
[position, size] ← UnpackFD[LOOPHOLE[cP[2]]];
IF size = 8 
AND cP[1] <= 
BYTE.
LAST/2 
THEN
SELECT position 
FROM
0, 8 => 
BEGIN 
P5.LoadConstant[0];
P5.C1[(
SELECT cInst 
FROM
qRF => qRSTR,
qWF => qWSTR,
qRFL => qRSTRL,
ENDCASE => qWSTRL), cP[1]*2+position/8];
 
P5U.DeleteCell[c];
END;
 
ENDCASE => canSlide ← TRUE
 
 
ELSE canSlide ← TRUE; 
END;
 
ENDCASE => canSlide ← TRUE;
 
END; -- of OPEN state
 
ENDCASE => canSlide ← FALSE; -- of WITH
 
ENDLOOP;
 
END;
 
NonWS: 
ARRAY [FOpCodes.qWS..FOpCodes.qWSD] 
OF 
BYTE = [
FOpCodes.qW, FOpCodes.qWF, FOpCodes.qWD];
 
Peep5: 
PROC =
BEGIN -- put doubles back, eliminate EXCH preceding commutative operator
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
qLL =>
IF bInst = qLL 
AND cP[1] = bP[1]+1 
THEN
{cb[b].inst ← qLLD; P5U.DeleteCell[c]}
 
ELSE GO TO Slide;
 
qSL =>
IF bInst = qSL 
AND cP[1] = bP[1]-1 
THEN
{cb[c].inst ← qSLD; P5U.DeleteCell[b]}
 
ELSE GO TO Slide;
 
qLG =>
IF bInst = qLG 
AND cP[1] = bP[1]+1 
THEN
{cb[b].inst ← qLGD; P5U.DeleteCell[c]}
 
ELSE GO TO Slide;
 
qSG =>
IF bInst = qSG 
AND cP[1] = bP[1]-1 
THEN
{cb[c].inst ← qSGD; P5U.DeleteCell[b]}
 
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 
AND ~NextIsPush[c] 
THEN 
{P5U.DeleteCell[b]; cc.inst ← NonWS[cInst]}
 
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;
 
ENDCASE => GO TO Slide;
 
EXITS
Slide => canSlide ← TRUE;
 
END; -- of OPEN state
 
jump =>
BEGIN
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;
FOR next ← NextInteresting[c], NextInteresting[next] 
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←NextInteresting[cb[c].destlabel]) # CCNull 
THEN
WITH cb[next] 
SELECT 
FROM
code => IF ~realinst AND inst = FOpCodes.qPUSH THEN RETURN [TRUE];
ENDCASE;
 
 
RETURN [FALSE]
END;
 
NextIsPush: 
PROC [c: CCIndex] 
RETURNS [
BOOL] =
BEGIN -- c is conditional jump; TRUE if PUSH follows on either branch
FOR next: CCIndex ← NextInteresting[c], NextInteresting[next] 
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;
 
RETURN [FALSE]
END;
 
CommuteCells: 
PROC [a, b: CCIndex] =
BEGIN -- could be a "source other CCItem" between,
in any case, move a to after b
see 3/5/80 notes for rationale
aPrev: CCIndex = cb[a].blink; -- never Null
aNext: CCIndex = cb[a].flink; -- probably b
bPrev: CCIndex = cb[b].blink; -- probably a
bNext: CCIndex = cb[b].flink;
cb[aPrev].flink ← aNext;
cb[aNext].blink ← aPrev;
cb[b].flink ← a;
cb[a].blink ← b;  cb[a].flink ← bNext;
IF bNext # CCNull THEN cb[bNext].blink ← a;
END;
 
Peep6: 
PROC =
BEGIN -- store double/load double, INC and DEC, MUL to SHIFT etc
OPEN FOpCodes;
ci: CCIndex;
next: CCIndex ← start;
canSlide: BOOL ← FALSE;
state: PeepState;
negate: BOOL;
D2: PROC = {Delete2[state.b, state.c]; IF negate THEN P5.C0[qNEG]};
UNTIL (ci ← next) = CCNull 
DO
next ← NextInteresting[ci];
WITH cb[ci] 
SELECT 
FROM
code =>
BEGIN OPEN state;
IF canSlide THEN SlidePeepState1[@state, LOOPHOLE[ci]]
ELSE InitParameters[@state, LOOPHOLE[ci], bc];
canSlide ← FALSE;
SELECT cInst 
FROM
qLLD =>
IF bInst = qSLD 
AND cP[1] = bP[1] 
THEN
BEGIN
CPtr.codeptr ← b;
IF cP[1] 
IN LocalPutSlots 
THEN
{P5.C1[qSL, cP[1]+1]; P5.C1[qPL, cP[1]]; P5.C0[qPUSH]; Delete2[b,c]}
 
ELSE {P5.C0[qPUSH]; P5.C0[qPUSH]; P5U.DeleteCell[c]};
END
 
ELSE GO TO Slide;
 
qLGD =>
IF bInst = qSGD 
AND cP[1] = bP[1] 
THEN
{CPtr.codeptr ← b; P5.C0[qPUSH]; P5.C0[qPUSH]; P5U.DeleteCell[c]}
 
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 {cb[c].inst ← qINC; P5U.DeleteCell[b]};
-1 => IF cInst = qSUB THEN {cb[c].inst ← qINC; P5U.DeleteCell[b]};
ENDCASE => GO TO Slide;
 
END 
 
ELSE 
IF bInst = qNEG 
THEN
{cb[c].inst ← IF cInst = qADD THEN qSUB ELSE qADD; P5U.DeleteCell[b]}
 
ELSE GO TO Slide;
 
qSHIFT =>
IF bInst = qLI 
THEN
SELECT bP[1] 
FROM
1 => {cb[c].inst ← qDBL; P5U.DeleteCell[b]};
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
{negate ← TRUE; bP[1] ← -LOOPHOLE[bP[1], INTEGER]};
 
SELECT bP[1] 
FROM
1 => D2[];
2 => {P5.C0[qDBL]; D2[]};
3 => {P5.C0[qDUP]; P5.C0[qDBL]; P5.C0[qADD]; D2[]};
4 => {P5.C0[qDBL]; P5.C0[qDBL]; D2[]};
5 => {P5.C0[qDUP]; P5.C0[qDBL]; P5.C0[qDBL]; P5.C0[qADD]; D2[]};
6 => {P5.C0[qDBL]; P5.C0[qDUP]; P5.C0[qDBL]; P5.C0[qADD]; D2[]};
ENDCASE =>
BEGIN
powerOf2: BOOL;
log: CARDINAL;
[powerOf2, log] ← Log2[LOOPHOLE[bP[1]]];
IF powerOf2 THEN {P5.LoadConstant[log]; P5.C0[qSHIFT]; D2[]}
ELSE GO TO Slide;
END;
 
 
END;
 
 
ENDCASE => GO TO Slide;
 
EXITS
Slide => canSlide ← TRUE;
 
END; -- of OPEN state
 
ENDCASE => canSlide ← FALSE; -- of WITH
 
ENDLOOP;
 
END;
 
Log2: 
PROC [i: 
INTEGER] 
RETURNS [
BOOL, 
CARDINAL] =
BEGIN OPEN PrincOpsUtils;
IF i = 0 THEN RETURN [FALSE, 0];
i ← ABS[i];
IF BITAND[i, i-1] # 0 THEN RETURN [FALSE, 0];
FOR shift: 
CARDINAL 
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: 
PROC =
BEGIN -- find special jumps
OPEN FOpCodes;
ci: CCIndex;
next: CCIndex ← start;
jstate: JumpPeepState;
UNTIL (ci ← next) = CCNull 
DO
next ← NextInteresting[ci];
WITH cb[ci] 
SELECT 
FROM
jump =>
BEGIN OPEN jstate;
InitJParametersBC[@jstate, LOOPHOLE[ci]];
SELECT jtype 
FROM
JumpE =>
IF bInst = qLI AND bP[1] = 0 THEN {jtype ← ZJumpE; P5U.DeleteCell[b]};
 
JumpN =>
IF bInst = qLI AND bP[1] = 0 THEN {jtype ← ZJumpN; P5U.DeleteCell[b]};
 
ENDCASE;
 
END; -- of OPEN jstate
 
ENDCASE; -- of WITH
 
ENDLOOP;
 
END;
 
END.