Branch optimizations

This commit is contained in:
David Schmenk 2017-06-07 16:20:08 -07:00
parent 4343292057
commit 082f10424e
3 changed files with 88 additions and 32 deletions

View File

@ -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);
} }

View File

@ -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);

View File

@ -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,13 +838,14 @@ 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);
while (parse_stmnt()) next_line(); emit_seq(seq);
while (parse_stmnt()) next_line();
if (scantoken != LOOP_TOKEN) if (scantoken != LOOP_TOKEN)
{ {
parse_error("Missing WHILE/END"); parse_error("Missing WHILE/END");
@ -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;