koreth@panarthea.ebay.sun.com (Steven Grimm) (10/26/89)
Submitted-by: ncar.ucar.edu!dunike!onecom!wldrdg!hans (Johann Ruegg) Posting-number: Volume 2, Issue 100 Archive-name: sozobon1.2/part09 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 9 (of 9)." # Contents: top/PEEP2.C # Wrapped by koreth@panarthea on Tue Oct 24 18:40:47 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'top/PEEP2.C' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'top/PEEP2.C'\" else echo shar: Extracting \"'top/PEEP2.C'\" \(17904 characters\) sed "s/^X//" >'top/PEEP2.C' <<'END_OF_FILE' X/* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews X * X * Permission is granted to anyone to use this software for any purpose X * on any computer system, and to redistribute it freely, with the X * following restrictions: X * 1) No charge may be made other than reasonable charges for reproduction. X * 2) Modified versions must be clearly marked as such. X * 3) The authors are not responsible for any harmful consequences X * of using this software, even if they result from defects in it. X */ X X/* X * 2-instruction peephole optimizations X */ X X#include "top.h" X X X/* X * ipeep2(bp, i1) - look for 2-instruction optimizations at the given inst. X */ Xstatic bool Xipeep2(bp, i1) XBLOCK *bp; Xregister INST *i1; X{ X register INST *i2; /* the next instruction */ X register INST *ti2; /* "temporary" next inst */ X X register int op1, op2; /* opcodes, for speed */ X register int sm1, dm1; /* src, dst amode inst. 1 */ X register int dr1; /* dest. reg. inst. 1 */ X X i2 = i1->next; X op1 = i1->opcode; X op2 = i2->opcode; X X sm1 = i1->src.amode; X dm1 = i1->dst.amode; X dr1 = i1->dst.areg; X X /* X * Avoid stack fix-ups after a call if possible. X */ X X /* X * addq #4,sp X * ... stuff that doesn't use SP ... X * move.l ?,-(sp) => move.l ?,(sp) X */ X if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 4 && X dm1 == REG && dr1 == SP) { X X ti2 = i2; X while (!uses(ti2, SP)) { X if (ti2->next == NULL) X goto end2; X ti2 = ti2->next; X } X X if (ti2->opcode == MOVE && ti2->flags == LENL && X ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) { X ti2->dst.amode = REGI; X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } Xend2: X X /* X * addq #2,sp X * ... stuff that doesn't use SP ... X * move.w ?,-(sp) => move.w ?,(sp) X */ X if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 2 && X dm1 == REG && dr1 == SP) { X X ti2 = i2; X while (!uses(ti2, SP)) { X if (ti2->next == NULL) X goto end3; X ti2 = ti2->next; X } X X if (ti2->opcode == MOVE && ti2->flags == LENW && X ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) { X ti2->dst.amode = REGI; X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } Xend3: X X /* X * Avoid "tst" instructions following instructions that X * set the Z flag. X */ X X /* X * move.x X, Y => move.x X, Y X * tst.x X or Y ...deleted... X * beq/bne beq/bne X * X * Where Y is not An, because "movea" doesn't set the X * zero flag. X */ X if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) && X op1 == MOVE && op2 == TST && X i1->flags == i2->flags) { X X /* X * If pre-decrement is set on the dest. of the move, X * don't let that screw up the operand comparison. X */ X if (dm1 & DEC) X dm1 &= ~DEC; X X if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) { X if (dm1 != REG || ISD(dr1)) { X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X } X X /* X * and.x X, Y => and.x X, Y X * tst.x X or Y ...deleted... X * beq/bne beq/bne X * X * Where Y is not An, because "movea" doesn't set the X * zero flag. X */ X if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) && X op1 == AND && op2 == TST && X i1->flags == i2->flags) { X X /* X * If pre-decrement is set on the dest. of the move, X * don't let that screw up the operand comparison. X */ X if (dm1 & DEC) X dm1 &= ~DEC; X X if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) { X if (dm1 != REG || ISD(dr1)) { X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X } X X /* X * ext.x Dn => ext.x Dn X * tst.x Dn ...deleted... X * beq/bne beq/bne X * X * Where Y is not An, because "movea" doesn't set the X * zero flag. X */ X if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) && X op1 == EXT && op2 == TST && X i1->flags == i2->flags) { X X if (sm1 == REG && ISD(i1->src.areg) && X i2->src.amode == REG && i1->src.areg == i2->src.areg) { X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * move.? X, Dn => move.? X, Dn X * ext.? Dn ...deleted... X * beq/bne beq/bne X * X * Where Dn is dead after the "ext". X */ X if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) && X op1 == MOVE && op2 == EXT) { X X if (dm1 == REG && ISD(dr1) && X i2->src.amode == REG && dr1 == i2->src.areg) { X if ((i2->live & RM(i2->src.areg)) == 0) { X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X } X X /* X * ext.l Dm => ...deleted... X * tst.l Dm tst.w Dm X * X * where Dm is dead after the "tst". X */ X if (op1 == EXT && op2 == TST && X ((i1->flags & LENL) != 0) && ((i2->flags & LENL) != 0) && X (i1->src.areg == i2->src.areg) && ISD(i1->src.areg)) { X X if ((i2->live & RM(i2->src.areg)) == 0) { X i2->flags = LENW; X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * ext.l Dm => ...deleted... X * ??? N(An,Dm.l), ?? ??? N(An,Dm.w), ?? X * X * Where Dm is dead X */ X if ((op1 == EXT) && (i1->flags & LENL) && X (i2->src.amode == (REGIDX|XLONG)) && X (i1->src.areg == i2->src.ireg)) { X X if ((i2->live & RM(i1->src.areg)) == 0) { X i2->src.amode &= ~XLONG; X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * ext.l Dm => ...deleted... X * ??? ??, N(An,Dm.l) ??? ??, N(An,Dm.w) X * X * Where Dm is dead X */ X if ((op1 == EXT) && (i1->flags & LENL) && X (i2->dst.amode == (REGIDX|XLONG)) && X (i1->src.areg == i2->dst.ireg)) { X X if ((i2->live & RM(i1->src.areg)) == 0) { X i2->dst.amode &= ~XLONG; X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * Avoid intermediate registers. X */ X X /* X * move.x X, Dm => INST.x X, Dn X * INST.x Dm, Dn X * X * where Dm is dead, and INST is one of: add, sub, and, or, cmp X */ X if ((op1 == MOVE) && X ((op2==ADD)||(op2==SUB)||(op2==AND)||(op2==OR)||(op2==CMP)) && X (i1->flags == i2->flags) && X (dm1 == REG) && ISD(dr1) && X (i2->src.amode == REG) && ISD(i2->src.areg) && X (dr1 == i2->src.areg) && X (i2->dst.amode == REG) && ISD(i2->dst.areg)) { X X if ((i2->live & RM(i2->src.areg)) == 0) { X X i1->opcode = i2->opcode; X i1->dst.areg = i2->dst.areg; X X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * Silly moves X */ X X /* X * move.x X, Y => move.x X, Y X * move.x Y, X X */ X if ((op1 == MOVE) && (op2 == MOVE) && X (i1->flags == i2->flags) && X opeq(&i1->src, &i2->dst) && opeq(&i1->dst, &i2->src) && X ((i1->src.amode & (INC|DEC)) == 0) && X ((i1->dst.amode & (INC|DEC)) == 0)) { X X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * move.x X, Y => move.x X, Rn X * move.x Y, Rn move.x Rn, Y X * X * where Y isn't INC or DEC, and isn't register direct X */ X if ((op1 == MOVE) && (op2 == MOVE) && (i2->dst.amode == REG) && X opeq(&i1->dst, &i2->src) && ((i1->dst.amode & (INC|DEC)) == 0) && X (i1->flags == i2->flags) && (i1->dst.amode != REG)) { X X freeop(&i1->dst); X i1->dst = i2->dst; X i2->dst = i2->src; X i2->src = i1->dst; X X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * move.x Dm, X => move.x Dm, X X * move.x X, Y move.x Dm, Y X * X * Where 'x' is the same, and 'X' has no side-effects. X */ X if ((op1 == MOVE) && (op2 == MOVE) && X (sm1 == REG) && ISD(i1->src.areg) && X (i1->flags == i2->flags) && opeq(&i1->dst, &i2->src) && X ((dm1 & (DEC|INC)) == 0)) { X X X freeop(&i2->src); X i2->src = i1->src; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * move.? Rm, Rn => move.? Rm, Rn X * ... stuff ... ... stuff ... X * move.? Rm, Rn X * X * where "stuff" doesn't set Rm or Rn. Also make sure that X * the second move isn't followed by a conditional branch. X * In that case leave everything alone since the branch X * probably relies on flags set by the move. X */ X if ((op1 == MOVE) && (sm1 == REG) && (dm1 == REG)) { X int s1 = i1->src.areg; /* source reg of inst. 1 */ X X ti2 = i2; X while (ti2 != NULL && !sets(ti2, s1) && !sets(ti2, dr1)) { X X if ((ti2->opcode==MOVE) && (i1->flags==ti2->flags) && X (ti2->src.amode==REG) && (ti2->dst.amode==REG) && X (i1->src.areg == ti2->src.areg) && X (i1->dst.areg == ti2->dst.areg) && X ((bp->last != ti2) || (bp->bcond == NULL)) ) { X X delinst(bp, ti2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X ti2 = ti2->next; X } X } X X /* X * move.l Am, Dn => move.l Am, Ao X * ... stuff ... ... stuff ... X * move.l Dn, Ao X * X * where "stuff" doesn't set Dn. X */ X if ((op1 == MOVE) && (i1->flags == LENL) && X (sm1 == REG) && ISA(i1->src.areg) && X (dm1 == REG) && ISD(dr1)) { X X ti2 = i2; X while (!sets(ti2, dr1)) { X X if ((ti2->opcode == MOVE) && (ti2->flags == LENL) && X (ti2->src.amode == REG) && ISD(ti2->src.areg) && X (ti2->dst.amode == REG) && ISA(ti2->dst.areg) && X (dr1 == ti2->src.areg)) { X X /* X * If the intermediate register isn't dead, X * then we have to keep using it. X */ X if ((ti2->live & RM(ti2->src.areg)) != 0) X goto end14; X X i1->dst.areg = ti2->dst.areg; X X delinst(bp, ti2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X if (ti2->next == NULL) X goto end14; X X ti2 = ti2->next; X } X } Xend14: X X /* X * move.l Dm, An => move.l Dm, Ao X * lea (An), Ao X * X * where An is dead X */ X if ((op1 == MOVE) && (op2 == LEA) && X (sm1 == REG) && ISD(i1->src.areg) && X (dm1 == REG) && ISA(dr1) && X (i2->src.amode == REGI) && (i2->dst.amode == REG) && X ISA(i2->dst.areg) && (dr1 == i2->src.areg)) { X X if ((i2->live & RM(i2->src.areg)) == 0) { X X i1->dst.areg = i2->dst.areg; X X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * lea X, An => lea X, Ao X * lea (An), Ao X * X * where An is dead X */ X if ((op1 == LEA) && (op2 == LEA) && X (i2->src.amode == REGI) && (dr1 == i2->src.areg)) { X X if ((i2->live & RM(i2->src.areg)) == 0) { X X i1->dst.areg = i2->dst.areg; X X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * lea N(Am), Am => X * ? (Am)[,...] ? N(Am)[,...] X * X * Where Am is either dead after the second instruction or X * is a direct destination of the second instruction. X */ X if ((op1 == LEA) && (i1->src.amode == REGID) && X (i1->src.areg == i1->dst.areg) && X (i2->src.amode == REGI) && (i1->dst.areg == i2->src.areg)) { X X if (((i2->live & RM(i2->src.areg)) == 0) || X ((i2->dst.amode == REG) && (i2->dst.areg == i2->src.areg))) { X i2->src.amode = REGID; X i2->src.disp = i1->src.disp; X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * lea N(Am), Am => X * ? X, (Am) ? X, N(Am) X * X * Where X doesn't reference Am, and Am is dead after the X * second instruction. X */ X if ((op1 == LEA) && (i1->src.amode == REGID) && X (i1->src.areg == i1->dst.areg) && X (i2->dst.amode == REGI) && (i1->dst.areg == i2->dst.areg)) { X X if (((i2->live & RM(i2->dst.areg)) == 0) && X ((i2->src.amode == IMM) || (i2->src.amode == ABS) || X (i2->src.areg != i2->dst.areg))) { X i2->dst.amode = REGID; X i2->dst.disp = i1->src.disp; X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * lea X, Am => ...deleted... X * clr.x (Am) clr.x X X * X * where Am is dead X */ X if ((op1 == LEA) && (op2 == CLR) && i2->src.amode == REGI && X (i1->dst.areg == i2->src.areg)) { X X if ((i2->live & RM(i2->src.areg)) == 0) { X i2->src = i1->src; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * lea X, Am => ...deleted... X * move.x Y, (Am) move.x Y, X X * X * where Am is dead X */ X if ((op1 == LEA) && (op2 == MOVE) && i2->dst.amode == REGI && X (i1->dst.areg == i2->dst.areg)) { X X if ((i2->live & RM(i2->dst.areg)) == 0) { X i2->dst = i1->src; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * lea X, Am => ...deleted... X * move.x (Am), Y move.x X, Y X * X * where Am is dead X */ X if ((op1 == LEA) && (op2 == MOVE) && i2->src.amode == REGI && X (i1->dst.areg == i2->src.areg)) { X X if ((i2->live & RM(i2->src.areg)) == 0) { X i2->src = i1->src; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * move.x Dm, X => move.x Dm, X X * cmp.x #N, X cmp.x #N, Dm X * X * Where X isn't register direct. X * X * Since X generally references memory, we can compare X * with the register faster. X */ X if ((op1 == MOVE) && (op2 == CMP) && X (i1->flags == i2->flags) && (i2->src.amode == IMM) && X (sm1 == REG) && ISD(i1->src.areg) && (dm1 != REG) && X opeq(&i1->dst, &i2->dst) && ((dm1 & (INC|DEC)) == 0)) { X X freeop(&i2->dst); X i2->dst.amode = REG; X i2->dst.areg = i1->src.areg; X X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X X /* X * Try to use register indirect w/ displacement and/or index X */ X X /* X * add.l Am, Dn => lea 0(Am,Dn.l), Ao X * move.l Dn, Ao X * X * where Dn is dead X */ X if ((op1 == ADD) && (op2 == MOVE) && X (sm1 == REG) && ISA(i1->src.areg) && X (dm1 == REG) && ISD(dr1) && X (i2->src.amode == REG) && ISD(i2->src.areg) && X (i2->dst.amode == REG) && ISA(i2->dst.areg) && X (dr1 == i2->src.areg) && X (i1->flags & LENL) && (i2->flags & LENL)) { X X if ((i2->live & RM(i2->src.areg)) == 0) { X X i2->opcode = LEA; X i2->flags = 0; X X i2->src.amode = REGIDX|XLONG; X i2->src.disp = 0; X i2->src.areg = i1->src.areg; X i2->src.ireg = dr1; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * add.l Dm, An => move.x 0(An,Dm.l), Do X * move.x (An), Do X * X * where An is dead X */ X if ((op1 == ADD) && (op2 == MOVE) && X (sm1 == REG) && ISD(i1->src.areg) && X (dm1 == REG) && ISA(dr1) && X (i2->src.amode == REGI)&& ISA(i2->src.areg) && X (i2->dst.amode == REG) && ISD(i2->dst.areg) && X (dr1 == i2->src.areg) && (i1->flags & LENL)) { X X if ((i2->live & RM(i2->src.areg)) == 0) { X X i2->src.amode = REGIDX|XLONG; X i2->src.disp = 0; X i2->src.ireg = i1->src.areg; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * lea N(Am), An => lea N(Am,Do.l), An X * add.l Do, An X * X */ X if ((op1 == LEA) && (op2 == ADD) && X (sm1 == REGID) && X (i2->src.amode == REG) && ISD(i2->src.areg) && X (i2->dst.amode == REG) && ISA(i2->dst.areg) && X (dr1 == i2->dst.areg) && D8OK(i1->src.disp)) { X X i1->src.amode = REGIDX|XLONG; X i1->src.ireg = i2->src.areg; X delinst(bp, i2); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X X X /* X * Try to use the pre-decrement and post-increment modes X * whenever possible. X */ X X /* X * sub.l #1, Am X * ... stuff ... X * ???.b ..(Am).. => ???.b ..-(Am).. X * X * Nothing in "stuff" can refer to Am. X */ X if ((op1 == SUB) && (i1->flags & LENL) && X (sm1 == IMM) && (i1->src.disp == 1) && X (dm1 == REG) && ISA(dr1)) { X X while (i2 != NULL) { X X if (i2->src.amode == REGI && i2->src.areg == dr1) { X X if ((i2->flags & LENB) == 0) X goto end24; X X i2->src.amode |= DEC; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X if (i2->dst.amode == REGI && i2->dst.areg == dr1) { X X if ((i2->flags & LENB) == 0) X goto end24; X X i2->dst.amode |= DEC; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X if (uses(i2, RM(dr1))) X goto end24; X X if (i2->next == NULL) X goto end24; X else X i2 = i2->next; X X } X } Xend24: X X /* X * sub.l #2, Am X * ... stuff ... X * ???.w ..(Am).. => ???.w ..-(Am).. X * X * Nothing in "stuff" can refer to Am. X */ X if ((op1 == SUB) && (i1->flags & LENL) && X (sm1 == IMM) && (i1->src.disp == 2) && X (dm1 == REG) && ISA(dr1)) { X X while (i2 != NULL) { X X if (i2->src.amode == REGI && i2->src.areg == dr1) { X X if ((i2->flags & LENW) == 0) X goto end26; X X i2->src.amode |= DEC; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X if (i2->dst.amode == REGI && i2->dst.areg == dr1) { X X if ((i2->flags & LENW) == 0) X goto end26; X X i2->dst.amode |= DEC; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X if (uses(i2, RM(dr1))) X goto end26; X X if (i2->next == NULL) X goto end26; X else X i2 = i2->next; X X } X } Xend26: X X /* X * sub.l #4, Am X * ... stuff ... X * ???.l ..(Am).. => ???.l ..-(Am).. X * X * Nothing in "stuff" can refer to Am. X */ X if ((op1 == SUB) && (i1->flags & LENL) && X (sm1 == IMM) && (i1->src.disp == 4) && X (dm1 == REG) && ISA(dr1)) { X X while (i2 != NULL) { X X if (i2->src.amode == REGI && i2->src.areg == dr1) { X X if ((i2->flags & LENL) == 0) X goto end28; X X i2->src.amode |= DEC; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X if (i2->dst.amode == REGI && i2->dst.areg == dr1) { X X if ((i2->flags & LENL) == 0) X goto end28; X X i2->dst.amode |= DEC; X X delinst(bp, i1); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X if (uses(i2, RM(dr1))) X goto end28; X X if (i2->next == NULL) X goto end28; X else X i2 = i2->next; X X } X } Xend28: X X return FALSE; X} X X/* X * peep2(bp) - scan blocks starting at 'bp' X */ Xbool Xpeep2(bp) Xregister BLOCK *bp; X{ X register INST *ip; X register bool changed = FALSE; X X DBG(printf("p2 :")) X X for (; bp != NULL ;bp = bp->next) { X for (ip = bp->first; ip != NULL && ip->next != NULL ;) { X if (ipeep2(bp, ip)) { X changed = TRUE; X s_peep2++; X bprep(bp); X /* X * If we had a match, then either instruction X * may have been deleted, so the safe thing to X * do is to go to the next block. X */ X break; X } else X ip = ip->next; X } X } X DBG(printf("\n"); fflush(stdout)) X return changed; X} END_OF_FILE if test 17904 -ne `wc -c <'top/PEEP2.C'`; then echo shar: \"'top/PEEP2.C'\" unpacked with wrong size! fi # end of 'top/PEEP2.C' fi echo shar: End of archive 9 \(of 9\). cp /dev/null ark9isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 9 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0