mirror of
https://github.com/dschmenk/PLASMA.git
synced 2025-02-21 08:29:13 +00:00
Allow optimiser to introduce DUP opcodes
This commit is contained in:
parent
e9c4e062c3
commit
b6efb90995
@ -908,10 +908,67 @@ void release_seq(t_opseq *seq)
|
|||||||
freeop_lst = op;
|
freeop_lst = op;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Indicate if an address is (or might be) memory-mapped hardware; used to avoid
|
||||||
|
* optimising away accesses to such addresses.
|
||||||
|
*/
|
||||||
|
int is_hardware_address(int addr)
|
||||||
|
{
|
||||||
|
// TODO: I think this is reasonable for Apple hardware but I'm not sure.
|
||||||
|
// It's a bit too strong for Acorn hardware but code is unlikely to try to
|
||||||
|
// read from high addresses anyway, so there's no real harm in not
|
||||||
|
// optimising such accesses anyway.
|
||||||
|
return addr >= 0xC000;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Replace all but the first of a series of identical load opcodes by DUP. This
|
||||||
|
* doesn't reduce the number of opcodes but does reduce their size in bytes.
|
||||||
|
* This is only called on the second optimisation pass because the DUP opcodes
|
||||||
|
* may inhibit other peephole optimisations which are more valuable.
|
||||||
|
*/
|
||||||
|
int try_dupify(t_opseq *op)
|
||||||
|
{
|
||||||
|
int crunched = 0;
|
||||||
|
t_opseq *opn = op->nextop;
|
||||||
|
for (; opn; opn = opn->nextop)
|
||||||
|
{
|
||||||
|
if (op->code != opn->code)
|
||||||
|
return crunched;
|
||||||
|
|
||||||
|
switch (op->code)
|
||||||
|
{
|
||||||
|
case CONST_CODE:
|
||||||
|
if (op->val != opn->val)
|
||||||
|
return crunched;
|
||||||
|
break;
|
||||||
|
case LADDR_CODE:
|
||||||
|
case LLB_CODE:
|
||||||
|
case LLW_CODE:
|
||||||
|
if (op->offsz != opn->offsz)
|
||||||
|
return crunched;
|
||||||
|
break;
|
||||||
|
case GADDR_CODE:
|
||||||
|
case LAB_CODE:
|
||||||
|
case LAW_CODE:
|
||||||
|
if ((op->tag != opn->tag) || (op->offsz != opn->offsz) ||
|
||||||
|
(op->type != opn->type))
|
||||||
|
return crunched;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return crunched;
|
||||||
|
}
|
||||||
|
|
||||||
|
opn->code = DUP_CODE;
|
||||||
|
crunched = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crunched;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Crunch sequence (peephole optimize)
|
* Crunch sequence (peephole optimize)
|
||||||
*/
|
*/
|
||||||
int crunch_seq(t_opseq **seq)
|
int crunch_seq(t_opseq **seq, int pass)
|
||||||
{
|
{
|
||||||
t_opseq *opnext, *opnextnext, *opprev = 0;
|
t_opseq *opnext, *opnextnext, *opprev = 0;
|
||||||
t_opseq *op = *seq;
|
t_opseq *op = *seq;
|
||||||
@ -1006,7 +1063,8 @@ int crunch_seq(t_opseq **seq)
|
|||||||
freeops = 1;
|
freeops = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CONST_CODE: // Collapse constant operation
|
case CONST_CODE:
|
||||||
|
// Collapse constant operation
|
||||||
if ((opnextnext = opnext->nextop))
|
if ((opnextnext = opnext->nextop))
|
||||||
switch (opnextnext->code)
|
switch (opnextnext->code)
|
||||||
{
|
{
|
||||||
@ -1083,6 +1141,9 @@ int crunch_seq(t_opseq **seq)
|
|||||||
freeops = 2;
|
freeops = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// End of collapse constant operation
|
||||||
|
if ((pass > 0) && (freeops == 0) && (op->val != 0))
|
||||||
|
crunched = try_dupify(op);
|
||||||
break; // CONST_CODE
|
break; // CONST_CODE
|
||||||
case BINARY_CODE(MUL_TOKEN):
|
case BINARY_CODE(MUL_TOKEN):
|
||||||
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
|
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
|
||||||
@ -1143,6 +1204,8 @@ int crunch_seq(t_opseq **seq)
|
|||||||
freeops = 1;
|
freeops = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ((pass > 0) && (freeops == 0))
|
||||||
|
crunched = try_dupify(op);
|
||||||
break; // LADDR_CODE
|
break; // LADDR_CODE
|
||||||
case GADDR_CODE:
|
case GADDR_CODE:
|
||||||
switch (opnext->code)
|
switch (opnext->code)
|
||||||
@ -1183,7 +1246,13 @@ int crunch_seq(t_opseq **seq)
|
|||||||
freeops = 1;
|
freeops = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ((pass > 0) && (freeops == 0))
|
||||||
|
crunched = try_dupify(op);
|
||||||
break; // GADDR_CODE
|
break; // GADDR_CODE
|
||||||
|
case LLB_CODE:
|
||||||
|
if (pass > 0)
|
||||||
|
crunched = try_dupify(op);
|
||||||
|
break; // LLB_CODE
|
||||||
case LLW_CODE:
|
case LLW_CODE:
|
||||||
// LLW [n]:CB 8:SHR -> LLB [n+1]
|
// LLW [n]:CB 8:SHR -> LLB [n+1]
|
||||||
if ((opnext->code == CONST_CODE) && (opnext->val == 8))
|
if ((opnext->code == CONST_CODE) && (opnext->val == 8))
|
||||||
@ -1199,7 +1268,13 @@ int crunch_seq(t_opseq **seq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((pass > 0) && (freeops == 0))
|
||||||
|
crunched = try_dupify(op);
|
||||||
break; // LLW_CODE
|
break; // LLW_CODE
|
||||||
|
case LAB_CODE:
|
||||||
|
if ((pass > 0) && (op->type || !is_hardware_address(op->offsz)))
|
||||||
|
crunched = try_dupify(op);
|
||||||
|
break; // LAB_CODE
|
||||||
case LAW_CODE:
|
case LAW_CODE:
|
||||||
// LAW x:CB 8:SHR -> LAB x+1
|
// LAW x:CB 8:SHR -> LAB x+1
|
||||||
if ((opnext->code == CONST_CODE) && (opnext->val == 8))
|
if ((opnext->code == CONST_CODE) && (opnext->val == 8))
|
||||||
@ -1215,6 +1290,9 @@ int crunch_seq(t_opseq **seq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((pass > 0) && (freeops == 0) &&
|
||||||
|
(op->type || !is_hardware_address(op->offsz)))
|
||||||
|
crunched = try_dupify(op);
|
||||||
break; // LAW_CODE
|
break; // LAW_CODE
|
||||||
case LOGIC_NOT_CODE:
|
case LOGIC_NOT_CODE:
|
||||||
switch (opnext->code)
|
switch (opnext->code)
|
||||||
@ -1351,7 +1429,8 @@ int emit_seq(t_opseq *seq)
|
|||||||
int emitted = 0;
|
int emitted = 0;
|
||||||
|
|
||||||
if (outflags & OPTIMIZE)
|
if (outflags & OPTIMIZE)
|
||||||
while (crunch_seq(&seq));
|
for (int pass = 0; pass < 2; pass++)
|
||||||
|
while (crunch_seq(&seq, pass));
|
||||||
while (seq)
|
while (seq)
|
||||||
{
|
{
|
||||||
op = seq;
|
op = seq;
|
||||||
|
@ -142,7 +142,7 @@ void emit_start(void);
|
|||||||
void emit_rld(void);
|
void emit_rld(void);
|
||||||
void emit_esd(void);
|
void emit_esd(void);
|
||||||
void release_seq(t_opseq *seq);
|
void release_seq(t_opseq *seq);
|
||||||
int crunch_seq(t_opseq **seq);
|
int crunch_seq(t_opseq **seq, int pass);
|
||||||
t_opseq *gen_seq(t_opseq *seq, int opcode, long cval, int tag, int offsz, int type);
|
t_opseq *gen_seq(t_opseq *seq, int opcode, long cval, int tag, int offsz, int type);
|
||||||
t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2);
|
t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2);
|
||||||
int emit_seq(t_opseq *seq);
|
int emit_seq(t_opseq *seq);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user