Line 250... |
Line 250... |
}
|
}
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
/* First primary input */
|
|
static unsigned long tmp_op, tmp_opt;
|
|
|
|
/* Recursive function that searches for primary inputs;
|
|
returns 0 if cmov can be replaced by add */
|
|
static int cmov_needed (cuc_func *f, int ref)
|
|
{
|
|
cuc_insn *ii = &f->INSN(ref);
|
|
int j;
|
|
|
|
//printf (" %x", ref);
|
|
/* mark visited, if already marked, we have a loop, ignore */
|
|
if (ii->tmp) return 0;
|
|
ii->tmp = 1;
|
|
|
|
/* handle normal movs separately */
|
|
if ((ii->index == II_ADD || !(ii->type & IT_VOLATILE))
|
|
&& ii->opt[2] == OPT_CONST && ii->op[2] == 0) {
|
|
if (ii->opt[1] == OPT_REF) {
|
|
if (cmov_needed (f, ii->op[1])) {
|
|
ii->tmp = 0;
|
|
return 1;
|
|
}
|
|
} else {
|
|
if (tmp_opt == OPT_NONE) {
|
|
tmp_op = ii->op[1];
|
|
tmp_opt = ii->opt[1];
|
|
} else if (tmp_opt != ii->opt[1] || tmp_op != ii->op[1]) {
|
|
ii->tmp = 0;
|
|
return 1;
|
|
}
|
|
}
|
|
ii->tmp = 0;
|
|
return 0;
|
|
}
|
|
|
|
/* Is this instruction CMOV? no => add to primary inputs */
|
|
if (ii->index != II_CMOV || ii->type & IT_VOLATILE)
|
|
if (tmp_opt == OPT_NONE) {
|
|
tmp_op = ref;
|
|
tmp_opt = OPT_REF;
|
|
ii->tmp = 0;
|
|
return 0;
|
|
} else if (tmp_opt != OPT_REF || tmp_op != ref) {
|
|
ii->tmp = 0;
|
|
return 1;
|
|
}
|
|
|
|
for (j = 1; j < 3; j++) {
|
|
//printf ("(%x:%i)", ref, j);
|
|
if (ii->opt[j] == OPT_REF) {
|
|
if (cmov_needed (f, ii->op[j])) {
|
|
ii->tmp = 0;
|
|
return 1;
|
|
}
|
|
} else {
|
|
if (tmp_opt == OPT_NONE) {
|
|
tmp_op = ii->op[j];
|
|
tmp_opt = ii->opt[j];
|
|
} else if (tmp_opt != ii->opt[j] || tmp_op != ii->op[j]) {
|
|
ii->tmp = 0;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
ii->tmp = 0;
|
|
return 0;
|
|
}
|
|
|
|
/* Search and optimize complex cmov assignments */
|
|
void optimize_cmovs (cuc_func *f)
|
|
{
|
|
int b, i, j;
|
|
|
|
/* Mark all instructions unvisited */
|
|
for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD))
|
|
for (i = 0; i < f->bb[b].ninsn; i++) f->bb[b].insn[i].tmp = 0;
|
|
|
|
for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD)) {
|
|
for (i = 0; i < f->bb[b].ninsn; i++) {
|
|
cuc_insn *ii = &f->bb[b].insn[i];
|
|
if (ii->index == II_CMOV && !(ii->type & IT_VOLATILE)) {
|
|
tmp_opt = OPT_NONE;
|
|
printf ("\n");
|
|
if (!cmov_needed (f, REF(b, i))) {
|
|
assert (tmp_opt != OPT_NONE);
|
|
change_insn_type (ii, II_ADD);
|
|
ii->op[1] = tmp_op; ii->opt[1] = tmp_opt;
|
|
ii->op[2] = 0; ii->opt[2] = OPT_CONST;
|
|
ii->opt[3] = OPT_NONE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
/* Optimizes dataflow tree */
|
/* Optimizes dataflow tree */
|
void optimize_tree (cuc_func *f)
|
void optimize_tree (cuc_func *f)
|
{
|
{
|
int b, i, j;
|
int b, i, j;
|
int modified;
|
int modified;
|
Line 478... |
Line 575... |
/* Determine register usage */
|
/* Determine register usage */
|
for (i = 0; i < MAX_REGS; i++) {
|
for (i = 0; i < MAX_REGS; i++) {
|
f->lur[i] = -1;
|
f->lur[i] = -1;
|
f->used_regs[i] = 0;
|
f->used_regs[i] = 0;
|
}
|
}
|
|
if (cuc_debug > 5) print_cuc_bb (f, "SET_IO");
|
for (b = 0; b < f->num_bb; b++) {
|
for (b = 0; b < f->num_bb; b++) {
|
for (i = 0; i < f->bb[b].ninsn; i++)
|
for (i = 0; i < f->bb[b].ninsn; i++)
|
for (j = 0; j < MAX_OPERANDS; j++)
|
for (j = 0; j < MAX_OPERANDS; j++)
|
if (f->bb[b].insn[i].opt[j] & OPT_REGISTER && f->bb[b].insn[i].op[j] >= 0)
|
if (f->bb[b].insn[i].opt[j] & OPT_REGISTER && f->bb[b].insn[i].op[j] >= 0)
|
if (f->bb[b].insn[i].opt[j] & OPT_DEST) f->lur[f->bb[b].insn[i].op[j]] = REF (b, i);
|
if (f->bb[b].insn[i].opt[j] & OPT_DEST) f->lur[f->bb[b].insn[i].op[j]] = REF (b, i);
|