home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 6
/
FreshFish_September1994.bin
/
new
/
dev
/
c
/
hce
/
hcesource
/
top
/
source
/
peep2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-02
|
18KB
|
837 lines
/* Copyright (c) 1988,1991 by Sozobon, Limited. Author: Tony Andrews
*
* 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.
*/
/*
* 2-instruction peephole optimizations
*/
#include "top.h"
/*
* ipeep2(bp, i1) - look for 2-instruction optimizations at the given inst.
*/
static bool
ipeep2(bp, i1)
BLOCK *bp;
register INST *i1;
{
register INST *i2; /* the next instruction */
register INST *ti2; /* "temporary" next inst */
register int op1, op2; /* opcodes, for speed */
register int sm1, dm1; /* src, dst amode inst. 1 */
register int dr1; /* dest. reg. inst. 1 */
i2 = i1->next;
op1 = i1->opcode;
op2 = i2->opcode;
sm1 = i1->src.amode;
dm1 = i1->dst.amode;
dr1 = i1->dst.areg;
/*
* Avoid stack fix-ups after a call if possible.
*/
if (gflag) /* V2 */
goto skip_stack_stuff; /* V2 */
/*
* addq #4,sp
* ... stuff that doesn't use SP ...
* move.l ?,-(sp) => move.l ?,(sp)
*/
if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 4 &&
dm1 == REG && dr1 == SP) {
ti2 = i2;
while (!uses(ti2, SP)) {
if (ti2->next == NULL)
goto end2;
ti2 = ti2->next;
}
if (ti2->opcode == MOVE && ti2->flags == LENL &&
ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
ti2->dst.amode = REGI;
delinst(bp, i1);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
end2:
/*
* addq #2,sp
* ... stuff that doesn't use SP ...
* move.w ?,-(sp) => move.w ?,(sp)
*/
if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 2 &&
dm1 == REG && dr1 == SP) {
ti2 = i2;
while (!uses(ti2, SP)) {
if (ti2->next == NULL)
goto end3;
ti2 = ti2->next;
}
if (ti2->opcode == MOVE && ti2->flags == LENW &&
ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
ti2->dst.amode = REGI;
delinst(bp, i1);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
end3:
skip_stack_stuff: /* V2 */
/*
* Avoid "tst" instructions following instructions that
* set the Z flag.
*/
/*
* move.x X, Y => move.x X, Y
* tst.x X or Y ...deleted...
* beq/bne beq/bne
*
* Where Y is not An, because "movea" doesn't set the
* zero flag.
*/
if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
op1 == MOVE && op2 == TST &&
i1->flags == i2->flags) {
/*
* If pre-decrement is set on the dest. of the move,
* don't let that screw up the operand comparison.
*/
if (dm1 & DEC)
dm1 &= ~DEC;
if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
if (dm1 != REG || ISD(dr1)) {
delinst(bp, i2);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
}
/*
* and.x X, Y => and.x X, Y
* tst.x X or Y ...deleted...
* beq/bne beq/bne
*
* Where Y is not An, because "movea" doesn't set the
* zero flag.
*/
if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
op1 == AND && op2 == TST &&
i1->flags == i2->flags) {
/*
* If pre-decrement is set on the dest. of the move,
* don't let that screw up the operand comparison.
*/
if (dm1 & DEC)
dm1 &= ~DEC;
if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
if (dm1 != REG || ISD(dr1)) {
delinst(bp, i2);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
}
/*
* ext.x Dn => ext.x Dn
* tst.x Dn ...deleted...
* beq/bne beq/bne
*
* Where Y is not An, because "movea" doesn't set the
* zero flag.
*/
if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
op1 == EXT && op2 == TST &&
i1->flags == i2->flags) {
if (sm1 == REG && ISD(i1->src.areg) &&
i2->src.amode == REG && i1->src.areg == i2->src.areg) {
delinst(bp, i2);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
/*
* move.? X, Dn => move.? X, Dn
* ext.? Dn ...deleted...
* beq/bne beq/bne
*
* Where Dn is dead after the "ext".
*/
if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
op1 == MOVE && op2 == EXT) {
if (dm1 == REG && ISD(dr1) &&
i2->src.amode == REG && dr1 == i2->src.areg) {
if ((i2->live & RM(i2->src.areg)) == 0) {
delinst(bp, i2);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
}
/*
* ext.l Dm => ...deleted...
* tst.l Dm tst.w Dm
*
* where Dm is dead after the "tst".
*/
if (op1 == EXT && op2 == TST &&
((i1->flags & LENL) != 0) && ((i2->flags & LENL) != 0) &&
(i1->src.areg == i2->src.areg) && ISD(i1->src.areg)) {
if ((i2->live & RM(i2->src.areg)) == 0) {
i2->flags = LENW;
delinst(bp, i1);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
/*
* ext.l Dm => ...deleted...
* ??? N(An,Dm.l), ?? ??? N(An,Dm.w), ??
*
* Where Dm is dead
*/
if ((op1 == EXT) && (i1->flags & LENL) &&
(i2->src.amode == (REGIDX|XLONG)) &&
(i1->src.areg == i2->src.ireg)) {
if ((i2->live & RM(i1->src.areg)) == 0) {
i2->src.amode &= ~XLONG;
delinst(bp, i1);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
/*
* ext.l Dm => ...deleted...
* ??? ??, N(An,Dm.l) ??? ??, N(An,Dm.w)
*
* Where Dm is dead
*/
if ((op1 == EXT) && (i1->flags & LENL) &&
(i2->dst.amode == (REGIDX|XLONG)) &&
(i1->src.areg == i2->dst.ireg)) {
if ((i2->live & RM(i1->src.areg)) == 0) {
i2->dst.amode &= ~XLONG;
delinst(bp, i1);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
/*
* Avoid intermediate registers.
*/
/*
* move.x X, Dm => INST.x X, Dn
* INST.x Dm, Dn
*
* where Dm is dead, and INST is one of: add, sub, and, or, cmp
*/
if ((op1 == MOVE) &&
((op2==ADD)||(op2==SUB)||(op2==AND)||(op2==OR)||(op2==CMP)) &&
(i1->flags == i2->flags) &&
(dm1 == REG) && ISD(dr1) &&
(i2->src.amode == REG) && ISD(i2->src.areg) &&
(dr1 == i2->src.areg) &&
(i2->dst.amode == REG) && ISD(i2->dst.areg)) {
if ((i2->live & RM(i2->src.areg)) == 0) {
i1->opcode = i2->opcode;
i1->dst.areg = i2->dst.areg;
delinst(bp, i2);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
/*
* Silly moves
*/
/*
* move.x X, Y => move.x X, Y
* move.x Y, X
*/
if ((op1 == MOVE) && (op2 == MOVE) &&
(i1->flags == i2->flags) &&
opeq(&i1->src, &i2->dst) && opeq(&i1->dst, &i2->src) &&
((i1->src.amode & (INC|DEC)) == 0) &&
((i1->dst.amode & (INC|DEC)) == 0)) {
delinst(bp, i2);
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* move.x X, Y => move.x X, Rn
* move.x Y, Rn move.x Rn, Y
*
* where Y isn't INC or DEC, and isn't register direct
* and Y doesn't depend on Rn
*/
if ((op1 == MOVE) && (op2 == MOVE) && (i2->dst.amode == REG) &&
opeq(&i1->dst, &i2->src) && ((i1->dst.amode & (INC|DEC)) == 0) &&
(i1->flags == i2->flags) && (i1->dst.amode != REG) &&
!uses(i1, i2->dst.areg)) {
freeop(&i1->dst);
i1->dst = i2->dst;
i2->dst = i2->src;
i2->src = i1->dst;
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* move.x Dm, X => move.x Dm, X
* move.x X, Y move.x Dm, Y
*
* Where 'x' is the same, and 'X' has no side-effects.
*/
if ((op1 == MOVE) && (op2 == MOVE) &&
(sm1 == REG) && ISD(i1->src.areg) &&
(i1->flags == i2->flags) && opeq(&i1->dst, &i2->src) &&
((dm1 & (DEC|INC)) == 0)) {
freeop(&i2->src);
i2->src = i1->src;
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* move.? Rm, Rn => move.? Rm, Rn
* ... stuff ... ... stuff ...
* move.? Rm, Rn
*
* where "stuff" doesn't set Rm or Rn. Also make sure that
* the second move isn't followed by a conditional branch.
* In that case leave everything alone since the branch
* probably relies on flags set by the move.
*/
if ((op1 == MOVE) && (sm1 == REG) && (dm1 == REG)) {
int s1 = i1->src.areg; /* source reg of inst. 1 */