mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-10-11 18:23:48 +00:00
Branch optimizations
This commit is contained in:
parent
4343292057
commit
082f10424e
@ -918,10 +918,10 @@ void release_seq(t_opseq *seq)
|
|||||||
/*
|
/*
|
||||||
* Crunch sequence (peephole optimize)
|
* Crunch sequence (peephole optimize)
|
||||||
*/
|
*/
|
||||||
int crunch_seq(t_opseq *seq)
|
int crunch_seq(t_opseq **seq)
|
||||||
{
|
{
|
||||||
t_opseq *opnext, *opnextnext;
|
t_opseq *opnext, *opnextnext;
|
||||||
t_opseq *op = seq;
|
t_opseq *op = *seq;
|
||||||
int crunched = 0;
|
int crunched = 0;
|
||||||
int freeops = 0;
|
int freeops = 0;
|
||||||
int shiftcnt;
|
int shiftcnt;
|
||||||
@ -982,26 +982,40 @@ int crunch_seq(t_opseq *seq)
|
|||||||
op->code = SAW_CODE;
|
op->code = SAW_CODE;
|
||||||
freeops = 1;
|
freeops = 1;
|
||||||
break;
|
break;
|
||||||
case BINARY_CODE(MUL_TOKEN):
|
case BRFALSE_CODE:
|
||||||
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
|
if (op->val)
|
||||||
{
|
{
|
||||||
if (op->val == (1 << shiftcnt))
|
opnextnext = opnext->nextop; // Remove never taken branch
|
||||||
{
|
if (op == *seq)
|
||||||
op->val = shiftcnt;
|
*seq = opnextnext;
|
||||||
opnext->code = BINARY_CODE(SHL_TOKEN);
|
opnext->nextop = NULL;
|
||||||
break;
|
release_seq(op);
|
||||||
|
opnext = opnextnext;
|
||||||
|
crunched = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
op->code = BRNCH_CODE; // Always taken branch
|
||||||
|
op->tag = opnext->tag;
|
||||||
|
freeops = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BINARY_CODE(DIV_TOKEN):
|
case BRTRUE_CODE:
|
||||||
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
|
if (!op->val)
|
||||||
{
|
{
|
||||||
if (op->val == (1 << shiftcnt))
|
opnextnext = opnext->nextop; // Remove never taken branch
|
||||||
{
|
if (op == *seq)
|
||||||
op->val = shiftcnt;
|
*seq = opnextnext;
|
||||||
opnext->code = BINARY_CODE(SHR_TOKEN);
|
opnext->nextop = NULL;
|
||||||
break;
|
release_seq(op);
|
||||||
|
opnext = opnextnext;
|
||||||
|
crunched = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
op->code = BRNCH_CODE; // Always taken branch
|
||||||
|
op->tag = opnext->tag;
|
||||||
|
freeops = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CONST_CODE: // Collapse constant operation
|
case CONST_CODE: // Collapse constant operation
|
||||||
@ -1082,6 +1096,28 @@ int crunch_seq(t_opseq *seq)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break; // CONST_CODE
|
break; // CONST_CODE
|
||||||
|
case BINARY_CODE(MUL_TOKEN):
|
||||||
|
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
|
||||||
|
{
|
||||||
|
if (op->val == (1 << shiftcnt))
|
||||||
|
{
|
||||||
|
op->val = shiftcnt;
|
||||||
|
opnext->code = BINARY_CODE(SHL_TOKEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BINARY_CODE(DIV_TOKEN):
|
||||||
|
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
|
||||||
|
{
|
||||||
|
if (op->val == (1 << shiftcnt))
|
||||||
|
{
|
||||||
|
op->val = shiftcnt;
|
||||||
|
opnext->code = BINARY_CODE(SHR_TOKEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break; // CONST_CODE
|
break; // CONST_CODE
|
||||||
case LADDR_CODE:
|
case LADDR_CODE:
|
||||||
@ -1222,11 +1258,10 @@ t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2)
|
|||||||
int emit_seq(t_opseq *seq)
|
int emit_seq(t_opseq *seq)
|
||||||
{
|
{
|
||||||
t_opseq *op;
|
t_opseq *op;
|
||||||
|
int emitted = 0;
|
||||||
|
|
||||||
if (!seq)
|
|
||||||
return (0);
|
|
||||||
if (outflags & OPTIMIZE)
|
if (outflags & OPTIMIZE)
|
||||||
while (crunch_seq(seq));
|
while (crunch_seq(&seq));
|
||||||
while (seq)
|
while (seq)
|
||||||
{
|
{
|
||||||
op = seq;
|
op = seq;
|
||||||
@ -1339,15 +1374,26 @@ int emit_seq(t_opseq *seq)
|
|||||||
case DUP_CODE:
|
case DUP_CODE:
|
||||||
emit_dup();
|
emit_dup();
|
||||||
break;
|
break;
|
||||||
|
break;
|
||||||
case PUSH_EXP_CODE:
|
case PUSH_EXP_CODE:
|
||||||
emit_push_exp();
|
emit_push_exp();
|
||||||
break;
|
break;
|
||||||
case PULL_EXP_CODE:
|
case PULL_EXP_CODE:
|
||||||
emit_pull_exp();
|
emit_pull_exp();
|
||||||
break;
|
break;
|
||||||
|
case BRNCH_CODE:
|
||||||
|
emit_brnch(op->tag);
|
||||||
|
break;
|
||||||
|
case BRFALSE_CODE:
|
||||||
|
emit_brfls(op->tag);
|
||||||
|
break;
|
||||||
|
case BRTRUE_CODE:
|
||||||
|
emit_brtru(op->tag);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
emitted++;
|
||||||
seq = seq->nextop;
|
seq = seq->nextop;
|
||||||
/*
|
/*
|
||||||
* Free this op
|
* Free this op
|
||||||
@ -1355,5 +1401,5 @@ int emit_seq(t_opseq *seq)
|
|||||||
op->nextop = freeop_lst;
|
op->nextop = freeop_lst;
|
||||||
freeop_lst = op;
|
freeop_lst = op;
|
||||||
}
|
}
|
||||||
return (1);
|
return (emitted);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,9 @@ typedef struct _opseq {
|
|||||||
#define DUP_CODE 0x0319
|
#define DUP_CODE 0x0319
|
||||||
#define PUSH_EXP_CODE 0x031A
|
#define PUSH_EXP_CODE 0x031A
|
||||||
#define PULL_EXP_CODE 0x031B
|
#define PULL_EXP_CODE 0x031B
|
||||||
|
#define BRNCH_CODE 0x031C
|
||||||
|
#define BRFALSE_CODE 0x031D
|
||||||
|
#define BRTRUE_CODE 0x031E
|
||||||
|
|
||||||
#define gen_uop(seq,op) gen_seq(seq,UNARY_CODE(op),0,0,0,0)
|
#define gen_uop(seq,op) gen_seq(seq,UNARY_CODE(op),0,0,0,0)
|
||||||
#define gen_op(seq,op) gen_seq(seq,BINARY_CODE(op),0,0,0,0)
|
#define gen_op(seq,op) gen_seq(seq,BINARY_CODE(op),0,0,0,0)
|
||||||
@ -87,6 +90,8 @@ typedef struct _opseq {
|
|||||||
#define gen_pushexp(seq) gen_seq(seq,PUSH_EXP_CODE,0,0,0,0)
|
#define gen_pushexp(seq) gen_seq(seq,PUSH_EXP_CODE,0,0,0,0)
|
||||||
#define gen_pullexp(seq) gen_seq(seq,PULL_EXP_CODE,0,0,0,0)
|
#define gen_pullexp(seq) gen_seq(seq,PULL_EXP_CODE,0,0,0,0)
|
||||||
#define gen_drop(seq) gen_seq(seq,DROP_CODE,0,0,0,0)
|
#define gen_drop(seq) gen_seq(seq,DROP_CODE,0,0,0,0)
|
||||||
|
#define gen_brfls(seq,tag) gen_seq(seq,BRFALSE_CODE,0,tag,0,0)
|
||||||
|
#define gen_brtru(seq,tag) gen_seq(seq,BRTRUE_CODE,0,tag,0,0)
|
||||||
|
|
||||||
void emit_flags(int flags);
|
void emit_flags(int flags);
|
||||||
void emit_header(void);
|
void emit_header(void);
|
||||||
@ -146,7 +151,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);
|
||||||
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);
|
||||||
|
@ -775,6 +775,7 @@ int parse_stmnt(void)
|
|||||||
int tag_prevbrk, tag_prevcnt, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of;
|
int tag_prevbrk, tag_prevcnt, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of;
|
||||||
int type, addr, step, cfnvals;
|
int type, addr, step, cfnvals;
|
||||||
char *idptr;
|
char *idptr;
|
||||||
|
t_opseq *seq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optimization for last function LEAVE and OF clause.
|
* Optimization for last function LEAVE and OF clause.
|
||||||
@ -784,14 +785,15 @@ int parse_stmnt(void)
|
|||||||
switch (scantoken)
|
switch (scantoken)
|
||||||
{
|
{
|
||||||
case IF_TOKEN:
|
case IF_TOKEN:
|
||||||
if (!emit_seq(parse_expr(NULL, NULL)))
|
if (!(seq = parse_expr(NULL, NULL)))
|
||||||
{
|
{
|
||||||
parse_error("Bad expression");
|
parse_error("Bad expression");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
tag_else = tag_new(BRANCH_TYPE);
|
tag_else = tag_new(BRANCH_TYPE);
|
||||||
tag_endif = tag_new(BRANCH_TYPE);
|
tag_endif = tag_new(BRANCH_TYPE);
|
||||||
emit_brfls(tag_else);
|
seq = gen_brfls(seq, tag_else);
|
||||||
|
emit_seq(seq);
|
||||||
scan();
|
scan();
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -800,13 +802,14 @@ int parse_stmnt(void)
|
|||||||
break;
|
break;
|
||||||
emit_brnch(tag_endif);
|
emit_brnch(tag_endif);
|
||||||
emit_codetag(tag_else);
|
emit_codetag(tag_else);
|
||||||
if (!emit_seq(parse_expr(NULL, NULL)))
|
if (!(seq = parse_expr(NULL, NULL)))
|
||||||
{
|
{
|
||||||
parse_error("Bad expression");
|
parse_error("Bad expression");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
tag_else = tag_new(BRANCH_TYPE);
|
tag_else = tag_new(BRANCH_TYPE);
|
||||||
emit_brfls(tag_else);
|
seq = gen_brfls(seq, tag_else);
|
||||||
|
emit_seq(seq);
|
||||||
} while (1);
|
} while (1);
|
||||||
if (scantoken == ELSE_TOKEN)
|
if (scantoken == ELSE_TOKEN)
|
||||||
{
|
{
|
||||||
@ -835,12 +838,13 @@ int parse_stmnt(void)
|
|||||||
tag_prevbrk = break_tag;
|
tag_prevbrk = break_tag;
|
||||||
break_tag = tag_wend;
|
break_tag = tag_wend;
|
||||||
emit_codetag(tag_while);
|
emit_codetag(tag_while);
|
||||||
if (!emit_seq(parse_expr(NULL, NULL)))
|
if (!(seq = parse_expr(NULL, NULL)))
|
||||||
{
|
{
|
||||||
parse_error("Bad expression");
|
parse_error("Bad expression");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
emit_brfls(tag_wend);
|
seq = gen_brfls(seq, tag_wend);
|
||||||
|
emit_seq(seq);
|
||||||
while (parse_stmnt()) next_line();
|
while (parse_stmnt()) next_line();
|
||||||
if (scantoken != LOOP_TOKEN)
|
if (scantoken != LOOP_TOKEN)
|
||||||
{
|
{
|
||||||
@ -868,12 +872,13 @@ int parse_stmnt(void)
|
|||||||
}
|
}
|
||||||
emit_codetag(cont_tag);
|
emit_codetag(cont_tag);
|
||||||
cont_tag = tag_prevcnt;
|
cont_tag = tag_prevcnt;
|
||||||
if (!emit_seq(parse_expr(NULL, NULL)))
|
if (!(seq = parse_expr(NULL, NULL)))
|
||||||
{
|
{
|
||||||
parse_error("Bad expression");
|
parse_error("Bad expression");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
emit_brfls(tag_repeat);
|
seq = gen_brfls(seq, tag_repeat);
|
||||||
|
emit_seq(seq);
|
||||||
emit_codetag(break_tag);
|
emit_codetag(break_tag);
|
||||||
break_tag = tag_prevbrk;
|
break_tag = tag_prevbrk;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user