home *** CD-ROM | disk | FTP | other *** search
/ AMIGA PD 1 / AMIGA-PD-1.iso / Programme_zum_Heft / Programmieren / Kurztests / PascalPCQ / Examples / Peep.p < prev    next >
Text File  |  1991-04-09  |  16KB  |  725 lines

  1. Program Optimizer;
  2.  
  3. {
  4.     Peep.p from PCQ Pascal
  5.  
  6. Peep is a peephole optimizer that works on the assembly code
  7. produced by PCQ Pascal.  It is not designed to work on any other
  8. code, so be careful.  It reads in the assembly program, optimizes
  9. whatever it can, then writes out a slightly shorter, slightly
  10. faster equivalent file.
  11.  
  12. Peep makes all sorts of assumptions about the source code, one of
  13. which is that the source code is correct.  For example, if an
  14. instruction takes two operands, Peep expects there to be two
  15. operands.  That's O.K. for the compiler output, but you might run
  16. into trouble if you tried using it on normal assembly programs.
  17. It is highly unlikely that anything written in assembly could be
  18. improved by Peep anyway.
  19.  
  20. Using Peep is entirely optional.
  21. }
  22.  
  23.  
  24.  
  25. {$I "Include:Utils/StringLib.i"}
  26. {$I "Include:Utils/Parameters.i"}
  27. {$I "Include:Utils/Break.i"}
  28.  
  29. Const
  30.     MaxPeeps = 199;
  31.  
  32. type
  33.     Operation = (
  34.         op_ADD,
  35.         op_ADDA,
  36.         op_ADDQ,
  37.         op_AND,
  38.         op_ASL,
  39.         op_ASR,
  40.         op_BEQ,
  41.         op_BGE,
  42.         op_BGT,
  43.         op_BLE,
  44.         op_BLT,
  45.         op_BNE,
  46.         op_BPL,
  47.         op_BRA,
  48.         op_BSET,
  49.         op_CLR,
  50.         op_CMP,
  51.         op_CNOP,
  52.         op_DBRA,
  53.         op_DC,
  54.         op_DIVS,
  55.         op_DS,
  56.         op_END,
  57.         op_EOR,
  58.         op_EXG,
  59.         op_EXT,
  60.         op_JSR,
  61.         op_LEA,
  62.         op_LINK,
  63.         op_LSL,
  64.         op_LSR,
  65.         op_MOVE,
  66.         op_MOVEM,
  67.         op_MOVEQ,
  68.         op_MULS,
  69.         op_NEG,
  70.         op_NOT,
  71.         op_OR,
  72.         op_PEA,
  73.         op_RTS,
  74.         op_SECTION,
  75.         op_SEQ,
  76.         op_SGE,
  77.         op_SGT,
  78.         op_SLE,
  79.         op_SLT,
  80.         op_SNE,
  81.         op_SUB,
  82.         op_SUBQ,
  83.         op_SWAP,
  84.         op_TRAP,
  85.         op_TST,
  86.         op_UNLK,
  87.         op_XDEF,
  88.         op_XREF,
  89.         op_None,
  90.         op_LABEL,
  91.         op_EOF);
  92.  
  93.     CodeCell = record
  94.     OpCode    : Operation;
  95.     OSize    : Char;
  96.     Deleted    : Boolean;
  97.     Operand1,
  98.     Operand2,
  99.     Trailer  : String;
  100.     Buffer    : Array [0..127] of Char;
  101.     end;
  102.     CodeCellPtr = ^CodeCell;
  103.  
  104.     PeepArray = Array [0..MaxPeeps] of CodeCell;
  105.  
  106. const
  107.     OpCodes : Array [op_ADD..op_XREF] of String = (
  108.         "add",
  109.         "adda",
  110.         "addq",
  111.         "and",
  112.         "asl",
  113.         "asr",
  114.         "beq",
  115.         "bge",
  116.         "bgt",
  117.         "ble",
  118.         "blt",
  119.         "bne",
  120.         "bpl",
  121.         "bra",
  122.         "bset",
  123.         "clr",
  124.         "cmp",
  125.         "cnop",
  126.         "dbra",
  127.         "dc",
  128.         "divs",
  129.         "ds",
  130.         "end",
  131.         "eor",
  132.         "exg",
  133.         "ext",
  134.         "jsr",
  135.         "lea",
  136.         "link",
  137.         "lsl",
  138.         "lsr",
  139.         "move",
  140.         "movem",
  141.         "moveq",
  142.         "muls",
  143.         "neg",
  144.         "not",
  145.         "or",
  146.         "pea",
  147.         "rts",
  148.         "section",
  149.         "seq",
  150.         "sge",
  151.         "sgt",
  152.         "sle",
  153.         "slt",
  154.         "sne",
  155.         "sub",
  156.         "subq",
  157.         "swap",
  158.         "trap",
  159.         "tst",
  160.         "unlk",
  161.         "xdef",
  162.         "xref");
  163.  
  164. var
  165.     FirstPeep,
  166.     LastPeep    : Integer;
  167.     PeepHole    : PeepArray;
  168.     InputLine    : String;
  169.     InputFileName : String;
  170.     InputFile    : Text;
  171.     OutputFileName : String;
  172.     OutputFile    : Text;
  173.     EndOfFile    : Boolean;
  174.     Changed    : Boolean;
  175.  
  176.  
  177.  
  178. Procedure Die(ExitCode : Integer);
  179. begin
  180.     Close(InputFile);
  181.     Close(OutputFile);
  182.     Exit(ExitCode);
  183. end;
  184.  
  185. Procedure FindOperand(var c : CodeCell; SymText : String);
  186.  
  187. {
  188.     This just does a binary chop search of the list of operations
  189. }
  190.  
  191. var
  192.     top,
  193.     middle,
  194.     bottom    : Operation;
  195.     compare    : Short;
  196. begin
  197.     Bottom := op_ADD;
  198.     Top := op_XREF;
  199.  
  200.     compare := strpos(SymText, '.');
  201.     if compare = -1 then
  202.     c.OSize := ' '
  203.     else begin
  204.     c.OSize := SymText[Succ(Compare)];
  205.     SymText[compare] := '\0';
  206.     end;
  207.  
  208.     while Bottom <= Top do begin
  209.     middle := Operation((Byte(bottom) + Byte(top)) shr 1);
  210.     Compare := stricmp(OpCodes[Middle], SymText);
  211.     if Compare = 0 then begin
  212.         c.Opcode := Middle;
  213.         return;
  214.     end else if Compare < 0 then
  215.         Bottom := Succ(Middle)
  216.     else
  217.         Top := Pred(Middle);
  218.     end;
  219.     Writeln('Unknown instruction "', SymText, '"');
  220.     Die(10);
  221. end;
  222.  
  223. Procedure ReadWord(InLine : String; var pos : Integer;
  224.             var dest : String; delim : Char);
  225. begin
  226.     while isspace(InLine[pos]) do
  227.     Inc(pos);
  228.     dest := Adr(Inline[pos]);
  229.     while (not isspace(Inline[pos])) and
  230.       (Inline[pos] <> '\0') and
  231.       (Inline[pos] <> delim) do
  232.     Inc(pos);
  233.     Inline[pos] := '\0';
  234.     Inc(pos);
  235. end;
  236.  
  237. Procedure ReadInstruction(var c : CodeCell);
  238. var
  239.     OpStorage : String;
  240.     Leave     : Boolean;
  241.     InputPos,
  242.     LastPos   : Integer;
  243. begin
  244.     with c do begin
  245.     OpCode := op_NONE;
  246.     OSize  := ' ';
  247.     Deleted:= False;
  248.     Operand1 := "";
  249.     Operand2 := "";
  250.     Trailer  := "";
  251.     InputLine := Adr(c.Buffer);
  252.     end;
  253.     repeat
  254.     Leave := True;
  255.     repeat
  256.         if eof(InputFile) then begin
  257.         c.OpCode := op_EOF;
  258.         return;
  259.         end;
  260.         ReadLn(InputFile, InputLine);
  261.     until (strlen(InputLine) > 0) and (InputLine[0] <> '*');
  262.  
  263.     if isspace(InputLine[0]) then begin { It's not a label }
  264.         InputPos := 0;
  265.         ReadWord(InputLine, InputPos, OpStorage, '\0');
  266.         if strlen(OpStorage) > 0 then begin
  267.         FindOperand(c, OpStorage);
  268.         case c.OpCode of
  269.           op_ADD..op_ASR,
  270.           op_BSET,op_CMP..op_DBRA,
  271.           op_DIVS,op_EOR,op_EXG,
  272.           op_LEA..op_MULS,
  273.           op_OR, op_SUB, OP_SUBQ :
  274.             begin
  275.                 ReadWord(InputLine, InputPos, c.Operand1, ',');
  276.                 ReadWord(InputLine, InputPos, c.Operand2, '\0');
  277.             end;
  278.           op_BEQ..op_BRA,op_CLR,
  279.           op_EXT,op_JSR,
  280.           op_NEG,op_NOT,op_PEA,
  281.           op_SECTION..op_SNE,
  282.           op_SWAP..op_UNLK,
  283.           op_XDEF,op_XREF :
  284.             begin
  285.                 ReadWord(InputLine, InputPos, c.Operand1, '\0');
  286.             end;
  287.           op_DC, OP_DS :
  288.             begin
  289.                 while isspace(InputLine[InputPos]) do
  290.                 Inc(InputPos);
  291.                 c.Operand1 := Adr(InputLine[Inputpos]);
  292.             end;
  293.           op_END,op_RTS : ;
  294.         end;
  295.         end else
  296.         Leave := False;
  297.     end else     { It's a label }
  298.         c.OpCode := op_LABEL;
  299.  
  300.     until Leave;
  301. end;
  302.  
  303.  
  304. Procedure FillPeepholeArray;
  305. var
  306.     WasLabel : Boolean;
  307. begin
  308.     LastPeep := 0;
  309.     FirstPeep := 0;
  310.     repeat
  311.     ReadInstruction(PeepHole[LastPeep]);
  312.     WasLabel := PeepHole[LastPeep].OpCode = op_LABEL;
  313.     Inc(LastPeep);
  314.     until WasLabel or (LastPeep > MaxPeeps) or (EOF(InputFile));
  315. end;
  316.  
  317.  
  318. Procedure WriteInstruction(CellNum : Integer);
  319. begin
  320.     with PeepHole[CellNum] do begin
  321.  
  322.     if OpCode = op_EOF then
  323.         return;
  324.  
  325.     if Deleted then
  326.         return;
  327.  
  328.     if OpCode = op_LABEL then begin
  329.         Writeln(OutputFile, String(Adr(Buffer)));
  330.         return;
  331.     end;
  332.  
  333.     Write(OutputFile, '\t', OpCodes[OpCode]);
  334.  
  335.     if OSize <> ' ' then
  336.         write(OutputFile, '.', OSize);
  337.  
  338.     if strlen(Operand1) > 0 then
  339.         Write(OutputFile, '\t', Operand1);
  340.  
  341.     if strlen(Operand2) > 0 then
  342.         Write(OutputFile, ',', Operand2);
  343.  
  344.     Writeln(OutputFile);
  345.     end;
  346. end;
  347.  
  348. Procedure EmptyPeepholeArray;
  349. var
  350.     i : Integer;
  351. begin
  352.     for i := FirstPeep to Pred(LastPeep) do
  353.     WriteInstruction(i);
  354. end;
  355.  
  356. Function NextInstruction(Current : Integer) : Integer;
  357. begin
  358.     repeat
  359.     Inc(Current);
  360.     if Current > LastPeep then
  361.         NextInstruction := -1;
  362.     until not PeepHole[Current].Deleted;
  363.     NextInstruction := Current;
  364. end;
  365.  
  366. Function IsDataRegister(op : String) : Boolean;
  367. begin
  368.     IsDataRegister := (strlen(op) = 2) and
  369.               (toupper(op[0]) = 'D') and
  370.               isdigit(op[1]);
  371. end;
  372.  
  373.  
  374. Function IsAddressRegister(op : String) : Boolean;
  375. begin
  376.     IsAddressRegister := ((strlen(op) = 2) and
  377.              (toupper(op[0]) = 'A') and
  378.              isdigit(op[1])) or
  379.              strieq(op, "sp");
  380. end;
  381.  
  382.  
  383. Function IsRegister(op : String) : Boolean;
  384. begin
  385.     IsRegister := (strlen(op) = 2) and
  386.           ((toupper(op[0]) = 'A') or (toupper(op[0]) = 'D')) and
  387.           isdigit(op[1]);
  388. end;
  389.  
  390. {
  391.     Carry out optimizations in a three-instruction window.
  392.     The optimizations are:
  393.  
  394.     scc    Dn
  395.     tst.b    Dn    =>  scc    Dn
  396.     beq    lab        b~cc   lab
  397.  
  398.     scc    Dn
  399.     tst.b    Dn    =>  scc    Dn
  400.     bne    lab     =>  bcc    lab
  401.  
  402.     move.x    ??,Dn
  403.     any.x    ???,Dn    =>  any.x  ???,??  not done - sub and add
  404.     move.x    Dn,??               require one operand to
  405.                        be a register
  406.  
  407.     beq    lab1
  408.     bra    lab2    =>  bne   lab2  (happens in case statements)
  409.     lab1            lab1
  410. }
  411.  
  412. Procedure Optimize3(Op1 : Integer);
  413. var
  414.     Op2, Op3 : Integer;
  415. begin
  416.     if Peephole[Op1].Deleted then
  417.     return;
  418.  
  419.     Op2 := NextInstruction(Op1);
  420.     if Op2 = -1 then
  421.     return;
  422.     Op3 := NextInstruction(Op2);
  423.     if Op3 = -1 then
  424.     return;
  425.  
  426. {    if (Peephole[Op1].OpCode = op_MOVE) and
  427.     (Peephole[Op3].OpCode = op_MOVE) and
  428.     (Peephole[Op1].OSize = Peephole[Op3].OSize) and
  429.     IsDataRegister(Peephole[Op1].Operand2) and
  430.     streq(Peephole[Op1].Operand1,Peephole[Op3].Operand2) and
  431.     streq(Peephole[Op1].Operand2,Peephole[Op3].Operand1) then begin
  432.     case Peephole[Op2].OpCode of
  433.       op_ADD..op_ASR,
  434.       op_CMP,op_DIVS,
  435.       op_EOR,
  436.       op_LSL,op_LSR,
  437.       op_MULS,op_OR,
  438.       op_SUB,op_SUBQ :
  439.         if (Peephole[Op2].OSize = Peephole[Op1].OSize) and
  440.             streq(Peephole[Op2].Operand2,Peephole[Op1].Operand2) then begin
  441.             Peephole[Op2].Operand2 := Peephole[Op1].Operand1;
  442.             Peephole[Op1].Deleted := True;
  443.             Peephole[Op3].Deleted := True;
  444.             Changed := True;
  445.         end;
  446.       op_CLR,op_NEG,
  447.       op_NOT,op_TST :
  448.         if (Peephole[Op2].OSize = Peephole[Op1].OSize) and
  449.             streq(Peephole[Op2].Operand1,Peephole[Op1].Operand2) then begin
  450.             Peephole[Op2].Operand1 := Peephole[Op1].Operand1;
  451.             Peephole[Op1].Deleted := True;
  452.             Peephole[Op3].Deleted := True;
  453.             Changed := True;
  454.         end;
  455.     end;
  456.     end else} if ((Peephole[Op1].OpCode >= op_SEQ) or
  457.         (Peephole[Op1].OpCode <= op_SNE)) and
  458.         IsDataRegister(Peephole[Op1].Operand1) and
  459.         (Peephole[Op2].OpCode = op_TST) and
  460.         streq(Peephole[Op1].Operand1, Peephole[Op2].Operand1) and
  461.         ((Peephole[Op3].OpCode = op_BEQ) or
  462.         (Peephole[Op3].OpCode = op_BNE)) then begin
  463.     if Peephole[Op3].OpCode = op_BEQ then begin
  464.         case Peephole[Op1].OpCode of
  465.           op_SEQ : Peephole[Op3].OpCode := op_BNE;
  466.           op_SGE : Peephole[Op3].OpCode := op_BLT;
  467.           op_SGT : Peephole[Op3].OpCode := op_BLE;
  468.           op_SLE : Peephole[Op3].OpCode := op_BGT;
  469.           op_SLT : Peephole[Op3].OpCode := op_BGE;
  470.           op_SNE : Peephole[Op3].OpCode := op_BEQ;
  471.         end;
  472.     end else begin
  473.         case Peephole[Op1].OpCode of
  474.           op_SEQ : Peephole[Op3].OpCode := op_BEQ;
  475.           op_SGE : Peephole[Op3].OpCode := op_BGE;
  476.           op_SGT : Peephole[Op3].OpCode := op_BGT;
  477.           op_SLE : Peephole[Op3].OpCode := op_BLE;
  478.           op_SLT : Peephole[Op3].OpCode := op_BLT;
  479.           op_SNE : Peephole[Op3].OpCode := op_BNE;
  480.         end;
  481.     end;
  482.     Peephole[Op2].Deleted := True;
  483.     Changed := True;
  484.     end else if (Peephole[Op1].OpCode = op_BEQ) and
  485.         (Peephole[Op2].OpCode = op_BRA) and
  486.         (Peephole[Op3].OpCode = op_LABEL) and
  487.         streq(Peephole[Op1].Operand1,Adr(Peephole[Op3].Buffer)) then begin
  488.     Peephole[Op2].OpCode := op_BNE;
  489.     Peephole[Op1].Deleted := True;
  490.     Changed := True;
  491.     end;
  492. end;
  493.  
  494. {
  495.     Carry out optimizations in a two-instruction window.
  496.     The optimizations are:
  497.  
  498.     move.x    ??,Dn
  499.     move.x    Dn,???    =>    move.x    ??,??? (?? <> (a0)+ )
  500.  
  501.     move.x    ??,Dn
  502.     add.x    Dn,???    =>    add.l    ??,???
  503.  
  504.     move.x    Dn,???
  505.     move.x    ???,Dn    =>    move.x    Dn,???
  506.  
  507.     move.x    Dn,???        move.x    Dn,???
  508.     move.x    ???,??    =>    move.x    Dn,??
  509.  
  510.     any.x    ??,Dn
  511.     cmp.x    #0,Dn    =>    any.x    ??,Dn
  512.  
  513.     move.x    Dn,??
  514.     cmp.x    #0,Dn    =>    move.x    Dn,?? (?? <> An)
  515.  
  516.     rts
  517.     anything    =>    rts
  518.  
  519.     any.x    ??,Dn
  520.     tst.x    Dn    =>    any.x    ??,Dn
  521.  
  522.     any.x    Dn
  523.     tst.x    Dn    =>    any.x    Dn
  524.  
  525.     move.x    ??,Dn    =>    tst.x    ??
  526.     scc    Dn        scc    Dn
  527.  
  528.     move.b    #?,Dn
  529.     and.x    #255,Dn    =>    move.x    #?,Dn
  530.  
  531. }
  532.  
  533. Procedure Optimize2(Op1 : Integer);
  534. var
  535.     Op2 : Integer;
  536. begin
  537.     if Peephole[Op1].deleted then
  538.     return;
  539.  
  540.     Op2 := NextInstruction(Op1);
  541.     if Op2 = -1 then
  542.     return;
  543.  
  544.     if (Peephole[Op1].OpCode = op_MOVE) and
  545.     (Peephole[Op2].OpCode = op_MOVE) and
  546.     (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  547.  
  548.     if IsDataRegister(Peephole[Op1].Operand1) and
  549.        streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) then begin
  550.  
  551.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) then
  552.         Peephole[Op2].Deleted := True
  553.         else
  554.         Peephole[Op2].Operand1 := Peephole[Op1].Operand1;  
  555.         Changed := True;
  556.     end else if IsRegister(Peephole[Op1].Operand2) and
  557.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) and
  558.         (not streq(Peephole[Op1].Operand1,"(a0)+")) and
  559.         (not IsRegister(Peephole[Op2].Operand2)) then begin
  560.         Peephole[Op1].Operand2 := Peephole[Op2].Operand2;
  561.         Peephole[Op2].Deleted := True;
  562.         Changed := True;
  563.     end;
  564.     end else if Peephole[Op1].OpCode = op_RTS then begin
  565.     case Peephole[Op2].OpCode of
  566.       op_ADD..op_CMP,
  567.       op_DBRA,op_DIVS,
  568.       op_EOR..op_RTS,
  569.       op_SEQ..op_UNLK : begin
  570.                 Peephole[Op2].Deleted := True;
  571.                 Changed := True;
  572.                 end;
  573.     end;
  574.     end else if (Peephole[Op2].OpCode = op_CMP) and
  575.         (streq(Peephole[Op2].Operand1,"#0") or
  576.          streq(Peephole[Op2].Operand1, "#$0")) and
  577.         IsDataRegister(Peephole[Op2].Operand2) then begin
  578.     case Peephole[Op1].OpCode of
  579.       op_NEG,op_NOT,op_EXT :
  580.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) and
  581.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  582.             Peephole[Op2].Deleted := True;
  583.             Changed := True;
  584.         end;
  585.       op_ADD,op_ADDQ,op_AND,
  586.       op_ASL,op_ASR,op_DIVS,op_EOR,
  587.       op_EXG,op_LSL,op_LSR,
  588.       op_MULS,op_OR,
  589.       op_SUB,op_SUBQ :
  590.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  591.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  592.             Peephole[Op2].Deleted := True;
  593.             Changed := True;
  594.         end;
  595.       op_MOVE, op_MOVEQ :
  596.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  597.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  598.             Peephole[Op2].Deleted := True;
  599.             Changed := True;
  600.         end else if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) and
  601.             (Peephole[Op1].OSize = Peephole[Op2].OSize) and
  602.             (not IsAddressRegister(Peephole[Op1].Operand1)) then begin
  603.             Peephole[Op2].Deleted := True;
  604.             Changed := True;
  605.         end;
  606.     end;
  607.     end else if (Peephole[Op2].OpCode = op_TST) and
  608.         IsDataRegister(Peephole[Op2].Operand1) then begin
  609.     case Peephole[Op1].OpCode of
  610.       op_NEG,op_NOT,op_EXT :
  611.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand1) and
  612.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  613.             Peephole[Op2].Deleted := True;
  614.             Changed := True;
  615.         end;
  616.       op_ADD,op_ADDQ,op_AND,
  617.       op_ASL,op_ASR,op_DIVS,op_EOR,
  618.       op_EXG,op_LSL,op_LSR,
  619.       op_MOVE,op_MOVEQ,op_MULS,
  620.       op_OR,op_SUB,op_SUBQ :
  621.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) and
  622.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  623.             Peephole[Op2].Deleted := True;
  624.             Changed := True;
  625.         end;
  626.     end;
  627.     end else if (Peephole[Op1].OpCode = op_MOVE) and
  628.         (Peephole[Op2].OpCode >= op_SEQ) and
  629.         (Peephole[Op2].OpCode <= op_SNE) and
  630.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) then begin
  631.     with Peephole[Op1] do begin
  632.         OpCode := op_TST;
  633.         Operand2 := "";
  634.     end;
  635.     Changed := True;
  636.     end else if (Peephole[Op1].OpCode = op_MOVE) and
  637.         (Peephole[Op1].Operand1[0] = '#') and
  638.         (Peephole[Op2].OpCode = op_AND) and
  639.         streq(Peephole[Op2].Operand1,"#255") and
  640.         IsDataRegister(Peephole[Op1].Operand2) and
  641.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  642.         (Peephole[Op1].OSize = 'b') then begin
  643.     Peephole[Op1].OSize := Peephole[Op2].OSize;
  644.     Peephole[Op2].Deleted := True;
  645.     Changed := True;
  646. {    end else if (Peephole[Op1].OpCode = op_MOVE) and
  647.         (Peephole[Op2].OpCode = op_CMP) and
  648.         IsDataRegister(Peephole[Op1].Operand2) and
  649.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  650.         (Peephole[Op2].Operand1[0] = '#') and
  651.         (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  652.     Peephole[Op2].Operand2 := Peephole[Op1].Operand1;
  653.     Peephole[Op1].Deleted := True;
  654.     Changed := True; }
  655.     end;
  656. end;
  657.  
  658. {
  659.     Carry out optimizations in a one-instruction window.
  660.     The optimizations are:
  661.  
  662.     move.x    #0,??    =>    clr.x ?? (if x <> l and ?? <> Dn )
  663. }
  664.  
  665. Procedure Optimize1(Op : Integer);
  666. begin
  667.     if Peephole[Op].Deleted then
  668.     return;
  669.  
  670.     with Peephole[Op] do begin
  671.     if (OpCode = op_MOVE) and
  672.        (streq(Operand1, "#0") or streq(Operand1, "#$0")) and
  673.        ((not IsDataRegister(Operand2)) or (OSize <> 'l')) then begin
  674.         Operand1 := Operand2;
  675.         Operand2 := "";
  676.         OpCode := op_CLR;
  677.         Changed := True;
  678.     end;
  679.     end;
  680. end;
  681.  
  682. var
  683.     i : Integer;
  684. begin
  685.     Writeln('PCQ Peephole optimizer');
  686.  
  687.     InputFileName := AllocString(256);
  688.     OutputFileName := AllocString(256);
  689.  
  690.     GetParam(1,InputFileName);
  691.     GetParam(2,OutputFileName);
  692.  
  693.     if (strlen(InputfileName) <= 0) or 
  694.        (strlen(OutputFileName) <= 0) then begin
  695.     Writeln('Usage: Optimize filename');
  696.     Exit(20);
  697.     end;
  698.  
  699.     FirstPeep := 0;
  700.     LastPeep  := 0;
  701.  
  702.     if not open(OutputFileName, OutputFile) then begin
  703.     Writeln('Could not open output file: ', OutputFileName);
  704.     Exit(10);
  705.     end;
  706.  
  707.     if reopen(InputFileName, InputFile) then begin
  708.     while not eof(InputFile) do begin
  709.         FillPeepholeArray;
  710.         repeat
  711.         Changed := False;
  712.         for i := FirstPeep to LastPeep do begin
  713.             Optimize3(i);
  714.             Optimize2(i);
  715.             Optimize1(i);
  716.         end;
  717.         if CheckBreak then
  718.             Die(20);
  719.         until not Changed;
  720.         EmptyPeepholeArray;
  721.     end;
  722.     Die(0);
  723.     end;
  724. end.
  725.