Added code to optimize multiplies with constants
This commit is contained in:
parent
aa0b70d921
commit
17352b8b8d
|
@ -11,6 +11,8 @@ extern unsigned linecount;
|
||||||
extern int prodepth;
|
extern int prodepth;
|
||||||
extern bool Lflag;
|
extern bool Lflag;
|
||||||
extern bool nflag;
|
extern bool nflag;
|
||||||
|
extern int repl_muls;
|
||||||
|
extern bool repl_longmuls;
|
||||||
extern byte em_flag[];
|
extern byte em_flag[];
|
||||||
extern line_p instrs,pseudos;
|
extern line_p instrs,pseudos;
|
||||||
extern FILE *outfile;
|
extern FILE *outfile;
|
||||||
|
|
|
@ -28,7 +28,7 @@ main(argc,argv) int argc; char *argv[]; {
|
||||||
while (argc-->1 && **++argv == '-')
|
while (argc-->1 && **++argv == '-')
|
||||||
flags(*argv);
|
flags(*argv);
|
||||||
if (argc>1) {
|
if (argc>1) {
|
||||||
fprintf(stderr,"Usage: %s [-Ln] [name]\n",progname);
|
fprintf(stderr,"Usage: %s [-Ln] [-m<num>] [name]\n",progname);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
if (argc)
|
if (argc)
|
||||||
|
@ -47,6 +47,11 @@ flags(s) register char *s; {
|
||||||
switch(*s) {
|
switch(*s) {
|
||||||
case 'L': Lflag = TRUE; break;
|
case 'L': Lflag = TRUE; break;
|
||||||
case 'n': nflag = TRUE; break;
|
case 'n': nflag = TRUE; break;
|
||||||
|
case 'm': if (*(s+1) == 'l') {
|
||||||
|
s++;
|
||||||
|
repl_longmuls = TRUE;
|
||||||
|
}
|
||||||
|
repl_muls = atoi(s+1); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -608,7 +608,30 @@ basicblock(alpp) line_p *alpp; {
|
||||||
|
|
||||||
lpp = alpp; madeopt = FALSE;
|
lpp = alpp; madeopt = FALSE;
|
||||||
while ((*lpp) != (line_p) 0 && ((*lpp)->l_instr&BMASK) != op_lab) {
|
while ((*lpp) != (line_p) 0 && ((*lpp)->l_instr&BMASK) != op_lab) {
|
||||||
lp = *lpp; next = &lp->l_next;
|
lp = *lpp;
|
||||||
|
if (repl_muls) {
|
||||||
|
line_p b_repl, e_repl;
|
||||||
|
int cnt = repl_mul(lp, &b_repl, &e_repl);
|
||||||
|
|
||||||
|
if (cnt > 0 && cnt <= repl_muls) {
|
||||||
|
*lpp = b_repl;
|
||||||
|
e_repl->l_next = lp->l_next->l_next;
|
||||||
|
oldline(lp->l_next);
|
||||||
|
oldline(lp);
|
||||||
|
lp = b_repl;
|
||||||
|
madeopt = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (b_repl != (line_p) 0) {
|
||||||
|
line_p n = b_repl->l_next;
|
||||||
|
|
||||||
|
oldline(b_repl);
|
||||||
|
b_repl = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next = &lp->l_next;
|
||||||
hash[0] = lp->l_instr&BMASK;
|
hash[0] = lp->l_instr&BMASK;
|
||||||
lp=lp->l_next;
|
lp=lp->l_next;
|
||||||
if (lp != (line_p) 0) {
|
if (lp != (line_p) 0) {
|
||||||
|
@ -655,3 +678,131 @@ basicblock(alpp) line_p *alpp; {
|
||||||
}
|
}
|
||||||
return madeopt;
|
return madeopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repl_mul(lp, b, e)
|
||||||
|
register line_p lp;
|
||||||
|
line_p *b, *e;
|
||||||
|
{
|
||||||
|
register line_p next = lp->l_next;
|
||||||
|
int ins;
|
||||||
|
int sz;
|
||||||
|
unsigned long n;
|
||||||
|
int n0, n1;
|
||||||
|
int virgin = 1;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
*b = 0;
|
||||||
|
if (! next) return 0;
|
||||||
|
if ((ins = (next->l_instr & BMASK)) != op_mli && ins != op_mlu) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((ins = (lp->l_instr & BMASK)) != op_loc && ins != op_ldc) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch(next->l_optyp) {
|
||||||
|
case OPNO:
|
||||||
|
return 0;
|
||||||
|
case OPSHORT:
|
||||||
|
sz = next->l_a.la_short;
|
||||||
|
break;
|
||||||
|
#ifdef LONGOFF
|
||||||
|
case OPOFFSET:
|
||||||
|
sz = next->l_a.la_offset;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
sz = (next->l_optyp & BMASK) - Z_OPMINI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ins == op_loc && sz != wordsize) return 0;
|
||||||
|
if (ins == op_ldc && sz != 2*wordsize) return 0;
|
||||||
|
if (! repl_longmuls && sz != wordsize) return 0;
|
||||||
|
switch(lp->l_optyp) {
|
||||||
|
case OPSHORT:
|
||||||
|
n = (long) lp->l_a.la_short;
|
||||||
|
break;
|
||||||
|
#ifdef LONGOFF
|
||||||
|
case OPOFFSET:
|
||||||
|
n = lp->l_a.la_offset;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
n = (long)((lp->l_optyp & BMASK) - Z_OPMINI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define newinstr(res, opcode, val) (*(res) = newline((short)(val)+Z_OPMINI), (*(res))->l_instr = (opcode))
|
||||||
|
|
||||||
|
while (n) {
|
||||||
|
/* first find "0*1*$" in n */
|
||||||
|
for (n1 = 0; n & 1; n>>=1) ++n1; /* count "1" bits */
|
||||||
|
if (n)
|
||||||
|
for (n0 = 0; !(n & 1); n>>=1) /* count "0" bits */
|
||||||
|
++n0;
|
||||||
|
else
|
||||||
|
n0 = 0;
|
||||||
|
|
||||||
|
if (n1 == 0) {
|
||||||
|
if (n0) {
|
||||||
|
newinstr(b, op_loc, n0); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_slu, sz); b = &((*b)->l_next);
|
||||||
|
retval++;
|
||||||
|
}
|
||||||
|
} else if (n1 == 1) {
|
||||||
|
if (virgin) {
|
||||||
|
newinstr(b, op_dup, sz); b = &((*b)->l_next);
|
||||||
|
virgin = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newinstr(b, op_exg, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_dup, 2*sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_asp, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_adu, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_exg, sz); b = &((*b)->l_next);
|
||||||
|
retval++;
|
||||||
|
}
|
||||||
|
if (n) {
|
||||||
|
newinstr(b, op_loc, n0+n1); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_slu, sz); b = &((*b)->l_next);
|
||||||
|
retval++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (virgin) {
|
||||||
|
newinstr(b, op_dup, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_loc, 0); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_exg, sz); b = &((*b)->l_next);
|
||||||
|
virgin = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newinstr(b, op_exg, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_dup, 2*sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_asp, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_sbu, sz); b = &((*b)->l_next);
|
||||||
|
retval++;
|
||||||
|
newinstr(b, op_exg, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_loc, n1); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_slu, sz); b = &((*b)->l_next);
|
||||||
|
retval++;
|
||||||
|
newinstr(b, op_exg, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_dup, 2*sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_asp, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_adu, sz); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_exg, sz); b = &((*b)->l_next);
|
||||||
|
retval++;
|
||||||
|
}
|
||||||
|
if (n0) {
|
||||||
|
newinstr(b, op_loc, n0); b = &((*b)->l_next);
|
||||||
|
newinstr(b, op_slu, sz); b = &((*b)->l_next);
|
||||||
|
retval++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newinstr(b, op_asp, sz);
|
||||||
|
if (virgin) {
|
||||||
|
b = &((*b)->l_next);
|
||||||
|
newinstr(b, sz == wordsize ? op_loc : op_ldc, 0);
|
||||||
|
}
|
||||||
|
*e = *b;
|
||||||
|
return retval == 0 ? 1 : retval;
|
||||||
|
#undef newinstr
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ CFLAGS= -DNDEBUG $(INCLUDES) $(COPTIONS)
|
||||||
UCFLAGS= -DNDEBUG $(INCLUDES) $(UCOPTIONS)
|
UCFLAGS= -DNDEBUG $(INCLUDES) $(UCOPTIONS)
|
||||||
LDFLAGS=$(LDOPTIONS)
|
LDFLAGS=$(LDOPTIONS)
|
||||||
ULDFLAGS=$(ULDOPTIONS)
|
ULDFLAGS=$(ULDOPTIONS)
|
||||||
LINTFLAGS=$(INCLUDES) -DNDEBUG $(LINTOPTIONS)
|
LINTFLAGS=$(INCLUDES) -DNDEBUG -DNORCSID $(LINTOPTIONS)
|
||||||
CPP=$(UTIL_HOME)/lib.bin/cpp
|
CPP=$(UTIL_HOME)/lib.bin/cpp
|
||||||
|
|
||||||
all: opt opt2
|
all: opt opt2
|
||||||
|
|
|
@ -20,6 +20,8 @@ unsigned linecount = 0; /* "line"number for errormessages */
|
||||||
int prodepth = 0; /* Level of nesting */
|
int prodepth = 0; /* Level of nesting */
|
||||||
bool Lflag = 0; /* make library module */
|
bool Lflag = 0; /* make library module */
|
||||||
bool nflag = 0; /* do not optimize */
|
bool nflag = 0; /* do not optimize */
|
||||||
|
int repl_muls = 0; /* max # of shifts/adds for replacing muls */
|
||||||
|
bool repl_longmuls = 0; /* replacing longmuls as well? */
|
||||||
line_p instrs,pseudos; /* pointers to chains */
|
line_p instrs,pseudos; /* pointers to chains */
|
||||||
sym_p symhash[NSYMHASH]; /* array of pointers to chains */
|
sym_p symhash[NSYMHASH]; /* array of pointers to chains */
|
||||||
FILE *outfile;
|
FILE *outfile;
|
||||||
|
|
Loading…
Reference in a new issue