home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews
- * Patched -- PvO -- see file patch *
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- */
-
- /*
- * 3-instruction peephole optimizations
- */
-
- #include "top.h"
-
-
- /*
- * ipeep3(bp, ip) - look for 3-instruction optimizations at the given inst.
- */
- static bool
- ipeep3(bp, i1)
- register BLOCK *bp;
- register INST *i1;
- {
- register INST *i2 = i1->next; /* the next instruction */
- INST *i3 = i1->next->next; /* the third instruction */
-
- register int op1 = i1->opcode;
- register int op2 = i2->opcode;
- register int op3 = i3->opcode;
-
- /*
- * move.l Am, Dn => lea N(Am), Ao
- * add.l #N, Dn
- * move.l Dn, Ao
- *
- * Also, Dn must be dead after the third instruction.
- */
- if ((op1 == MOVE) && (i1->flags & LENL) &&
- (i1->src.amode == REG) &&
- ISA(i1->src.areg) &&
- (i1->dst.amode == REG) &&
- ISD(i1->dst.areg)) {
-
- if (((op2 == ADD) || (op2 == ADDQ)) &&
- (i2->flags & LENL) &&
- (i2->src.amode == IMM) &&
- DOK(i2->src.disp) &&
- (i2->dst.amode == REG) &&
- (i2->dst.areg == i1->dst.areg)) {
-
- if ((op3 == MOVE) && (i3->flags & LENL) &&
- (i3->src.amode == REG) &&
- (i3->src.areg == i1->dst.areg) &&
- (i3->dst.amode == REG) &&
- ISA(i3->dst.areg) &&
- ((i3->live & RM(i3->src.areg)) == 0)) {
-
- /*
- * rewrite i1 and delete i2 and i3
- */
- i1->opcode = LEA;
- i1->flags = 0;
- i1->dst = i3->dst;
-
- i1->src.amode = REGID;
- i1->src.disp = i2->src.disp;
-
- delinst(bp, i2);
- delinst(bp, i3);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- }
- }
-
- /*
- * move.l Dm, Dn => move.l Dm, Ao
- * add.l #N, Dn lea N(Ao), Ao
- * move.l Dn, Ao
- *
- * Also, Dn must be dead after the third instruction.
- */
- if ((op1 == MOVE) && (i1->flags & LENL) &&
- (i1->src.amode == REG) &&
- ISD(i1->src.areg) &&
- (i1->dst.amode == REG) &&
- ISD(i1->dst.areg)) {
-
- if (((op2 == ADD) || (op2 == ADDQ)) &&
- (i2->flags & LENL) &&
- (i2->src.amode == IMM) &&
- DOK(i2->src.disp) &&
- (i2->dst.amode == REG) &&
- (i2->dst.areg == i1->dst.areg)) {
-
- if ((op3 == MOVE) && (i3->flags & LENL) &&
- (i3->src.amode == REG) &&
- (i3->src.areg == i1->dst.areg) &&
- (i3->dst.amode == REG) &&
- ISA(i3->dst.areg) &&
- ((i3->live & RM(i3->src.areg)) == 0)) {
-
- /*
- * rewrite i1 and i2 and delete i3
- */
- i1->dst.areg = i3->dst.areg;
-
- i2->opcode = LEA;
- i2->flags = 0;
- i2->dst = i3->dst;
-
- i2->src.amode = REGID;
- i2->src.areg = i2->dst.areg;
- i2->src.disp = i2->src.disp;
-
- delinst(bp, i3);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- }
- }
-
- /*
- * move.l Am, Dn => lea -N(Am), Ao
- * sub.l #N, Dn
- * move.l Dn, Ao
- *
- * Also, Dn must be dead after the third instruction.
- */
- if ((op1 == MOVE) && (i1->flags & LENL) &&
- (i1->src.amode == REG) &&
- ISA(i1->src.areg) &&
- (i1->dst.amode == REG) &&
- ISD(i1->dst.areg)) {
-
- if (((op2 == SUB) || (op2 == ADDQ)) &&
- (i2->flags & LENL) &&
- (i2->src.amode == IMM) &&
- DOK(i2->src.disp) &&
- (i2->dst.amode == REG) &&
- (i2->dst.areg == i1->dst.areg)) {
-
- if ((op3 == MOVE) && (i3->flags & LENL) &&
- (i3->src.amode == REG) &&
- (i3->src.areg == i1->dst.areg) &&
- (i3->dst.amode == REG) &&
- ISA(i3->dst.areg) &&
- ((i3->live & RM(i3->src.areg)) == 0)) {
-
- /*
- * rewrite i1 and delete i2 and i3
- */
- i1->opcode = LEA;
- i1->flags = 0;
- i1->dst = i3->dst;
-
- i1->src.amode = REGID;
- i1->src.disp = -i2->src.disp;
-
- delinst(bp, i2);
- delinst(bp, i3);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- }
- }
-
- /*
- * move.l Am, Dn => lea 0(Am, Do), Ap
- * add.x Do, Dn
- * move.l Dn, Ap
- *
- * The second instruction can be either a word or long add.
- * Also, Dn must be dead after the third instruction.
- */
- if ((op1 == MOVE) && (i1->flags & LENL) &&
- (i1->src.amode == REG) &&
- ISA(i1->src.areg) &&
- (i1->dst.amode == REG) &&
- ISD(i1->dst.areg)) {
-
- if (((op2 == ADD) || (op2 == ADDQ)) &&
- (i2->flags & (LENL|LENW)) &&
- (i2->src.amode == REG) &&
- ISD(i2->src.areg) && (i1->dst.areg != i2->src.areg) &&
- (i2->dst.amode == REG) &&
- (i2->dst.areg == i1->dst.areg)) {
-
- if ((op3 == MOVE) && (i3->flags & LENL) &&
- (i3->src.amode == REG) &&
- (i3->src.areg == i1->dst.areg) &&
- (i3->dst.amode == REG) &&
- ISA(i3->dst.areg) &&
- ((i3->live & RM(i3->src.areg)) == 0)) {
-
- /*
- * rewrite i1 and delete i2 and i3
- */
- i1->opcode = LEA;
- i1->flags = 0;
- i1->dst = i3->dst;
-
- i1->src.amode = REGIDX;
- if (i2->flags & LENL)
- i1->src.amode |= XLONG;
- i1->src.ireg = i2->src.areg;
- i1->src.disp = 0;
-
- delinst(bp, i2);
- delinst(bp, i3);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- }
- }
-
- /*
- * move.l X(Am), Dn => move.l X(Am), Ao
- * add.l #N, Dn
- * move.l Dn, Ao lea N(Ao), Ao
- *
- * Also, Dn must be dead after the third instruction.
- */
- if ((op1 == MOVE) && (i1->flags & LENL) &&
- (i1->src.amode == REGI || i1->src.amode == REGID) &&
- (i1->dst.amode == REG) &&
- ISD(i1->dst.areg)) {
-
- if (((op2 == ADD) || (op2 == ADDQ)) &&
- (i2->flags & LENL) &&
- (i2->src.amode == IMM) &&
- DOK(i2->src.disp) &&
- (i2->dst.amode == REG) &&
- (i2->dst.areg == i1->dst.areg)) {
-
- if ((op3 == MOVE) && (i3->flags & LENL) &&
- (i3->src.amode == REG) &&
- (i3->src.areg == i1->dst.areg) &&
- (i3->dst.amode == REG) &&
- ISA(i3->dst.areg) &&
- ((i3->live & RM(i3->src.areg)) == 0)) {
-
- /*
- * rewrite i1 and i3 and delete i2
- */
- i1->dst = i3->dst;
-
- i3->opcode = LEA;
- i3->flags = 0;
- i3->src.amode = REGID;
- i3->src.areg = i3->dst.areg;
- i3->src.disp = i2->src.disp;
-
- delinst(bp, i2);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- }
- }
-
- /*
- * move.x X, Dn => move.x X, Do
- * ext.y Dn ext.y Do
- * move.y Dn, Do
- *
- * Where Dn is dead.
- */
- if ((op1 == MOVE)&&(op2 == EXT)&&(op3 == MOVE)&&
- (i1->dst.amode == REG) && ISD(i1->dst.areg) &&
- (i2->src.amode == REG) && (i3->src.amode == REG) &&
- (i3->dst.amode == REG) && ISD(i3->dst.areg) &&
- (i1->dst.areg == i2->src.areg) && (i1->dst.areg == i3->src.areg) &&
- (i2->flags == i3->flags)) {
-
- if ((i3->live & RM(i3->src.areg)) == 0) {
- i1->dst.areg = i3->dst.areg;
- i2->src.areg = i3->dst.areg;
-
- delinst(bp, i3);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- }
-
- /*
- * move.l X, Dm => move.l X, An
- * INST INST
- * move.l Dm, An ...deleted...
- *
- * where INST doesn't modify Dm, and Dm is dead after i3
- */
- if ((op1 == MOVE) && (op3 == MOVE) &&
- (i1->dst.amode == REG) && ISD(i1->dst.areg) &&
- (i3->src.amode == REG) && (i1->dst.areg == i3->src.areg) &&
- (i3->dst.amode == REG) && ISA(i3->dst.areg) &&
- !uses(i2, i3->src.areg) && !uses(i2, i3->dst.areg)) {
-
- if ((i3->live & RM(i3->src.areg)) == 0) {
- i1->dst.areg = i3->dst.areg;
- delinst(bp, i3);
-
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- }
-
- /*
- * move.l Am, An ...deleted...
- * addq.l #1, Am ...deleted...
- * ... stuff ... ... stuff ...
- * ???.b ..(An).. => ???.b ..(Am)+..
- *
- * An must be dead after the last instruction. Nothing in
- * "stuff" can modify Am.
- */
- if ((op1 == MOVE) && (i1->flags & LENL) &&
- (i1->src.amode == REG) && ISA(i1->src.areg) &&
- (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
-
- int rm = i1->src.areg;
- int rn = i1->dst.areg;
-
- if (((op2 == ADD) || (op2 == ADDQ)) &&
- (i2->flags & LENL) &&
- (i2->src.amode == IMM) && (i2->src.disp == 1) &&
- (i2->dst.amode == REG) &&
- (i2->dst.areg == rm)) {
-
- while (i3 != NULL) {
- if (sets(i3, rm))
- goto end7;
-
- if (i3->src.amode==REGI && i3->src.areg==rn) {
- if (i3->live & RM(rn))
- goto end7;
-
- if ((i3->flags & LENB) == 0)
- goto end7;
-
- i3->src.amode |= INC;
- i3->src.areg = rm;
-
- delinst(bp, i1);
- delinst(bp, i2);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- if (i3->dst.amode==REGI && i3->dst.areg==rn) {
- if (i3->live & RM(rn))
- goto end7;
-
- if ((i3->flags & LENB) == 0)
- goto end7;
-
- i3->dst.amode |= INC;
- i3->dst.areg = rm;
-
- delinst(bp, i1);
- delinst(bp, i2);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
-
- if (i3->next == NULL)
- goto end7;
- else
- i3 = i3->next;
-
- }
- }
- }
- end7:
-
- /*
- * move.l Am, An
- * addq.l #2, Am
- * ... stuff ...
- * ???.w ..(An).. => ???.w ..(Am)+..
- *
- * An must be dead after the last instruction. Nothing in
- * "stuff" can modify Am.
- */
- if ((op1 == MOVE) && (i1->flags & LENL) &&
- (i1->src.amode == REG) && ISA(i1->src.areg) &&
- (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
-
- int rm = i1->src.areg;
- int rn = i1->dst.areg;
-
- if (((op2 == ADD) || (op2 == ADDQ)) &&
- (i2->flags & LENL) &&
- (i2->src.amode == IMM) && (i2->src.disp == 2) &&
- (i2->dst.amode == REG) &&
- (i2->dst.areg == rm)) {
-
- while (i3 != NULL) {
- if (sets(i3, rm))
- goto end9;
-
- if (i3->src.amode==REGI && i3->src.areg==rn) {
- if (i3->live & RM(rn))
- goto end9;
-
- if ((i3->flags & LENW) == 0)
- goto end9;
-
- i3->src.amode |= INC;
- i3->src.areg = rm;
-
- delinst(bp, i1);
- delinst(bp, i2);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- if (i3->dst.amode==REGI && i3->dst.areg==rn) {
- if (i3->live & RM(rn))
- goto end9;
-
- if ((i3->flags & LENW) == 0)
- goto end9;
-
- i3->dst.amode |= INC;
- i3->dst.areg = rm;
-
- delinst(bp, i1);
- delinst(bp, i2);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
-
- if (i3->next == NULL)
- goto end9;
- else
- i3 = i3->next;
-
- }
- }
- }
- end9:
-
- /*
- * move.l Am, An
- * addq.l #4, Am
- * ... stuff ...
- * ???.l ..(An).. => ???.l ..(Am)+..
- *
- * An must be dead after the last instruction. Nothing in
- * "stuff" can modify Am.
- */
- if ((op1 == MOVE) && (i1->flags & LENL) &&
- (i1->src.amode == REG) && ISA(i1->src.areg) &&
- (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
-
- int rm = i1->src.areg;
- int rn = i1->dst.areg;
-
- if (((op2 == ADD) || (op2 == ADDQ)) &&
- (i2->flags & LENL) &&
- (i2->src.amode == IMM) && (i2->src.disp == 4) &&
- (i2->dst.amode == REG) &&
- (i2->dst.areg == rm)) {
-
- while (i3 != NULL) {
- if (sets(i3, rm))
- goto end11;
-
- if (i3->src.amode==REGI && i3->src.areg==rn) {
- if (i3->live & RM(rn))
- goto end11;
-
- if ((i3->flags & LENL) == 0)
- goto end11;
-
- i3->src.amode |= INC;
- i3->src.areg = rm;
-
- delinst(bp, i1);
- delinst(bp, i2);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
- if (i3->dst.amode==REGI && i3->dst.areg==rn) {
- if (i3->live & RM(rn))
- goto end11;
-
- if ((i3->flags & LENL) == 0)
- goto end11;
-
- i3->dst.amode |= INC;
- i3->dst.areg = rm;
-
- delinst(bp, i1);
- delinst(bp, i2);
- DBG(printf("%d ", __LINE__))
- return TRUE;
- }
-
- if (i3->next == NULL)
- goto end11;
- else
- i3 = i3->next;
-
- }
- }
- }
- end11:
-
- return FALSE;
- }
-
- /*
- * peep3(bp) - scan blocks starting at 'bp'
- */
- bool
- peep3(bp)
- register BLOCK *bp;
- {
- register INST *ip;
- register bool changed = FALSE;
-
- DBG(printf("p3: "))
- for (; bp != NULL ;bp = bp->next) {
- ip = bp->first;
- while (ip!=NULL && ip->next != NULL && ip->next->next != NULL) {
- if (ipeep3(bp, ip)) {
- s_peep3++;
- bprep(bp);
- changed = TRUE;
- /*
- * If we had a match, then any instruction
- * could have been deleted, so the safe thing
- * to do is to go to the next block.
- */
- break;
- } else
- ip = ip->next;
- }
- }
- DBG(printf("\n"); fflush(stdout))
- return changed;
- }
-