Line 318... |
Line 318... |
|
|
/* We do a quick check if there are some anomalies with references */
|
/* We do a quick check if there are some anomalies with references */
|
void cuc_check (cuc_func *f)
|
void cuc_check (cuc_func *f)
|
{
|
{
|
int i, j, k;
|
int i, j, k;
|
|
if (cuc_debug) printf ("cuc_check\n");
|
for (i = 0; i < f->num_bb; i++) {
|
for (i = 0; i < f->num_bb; i++) {
|
if (!f->bb[i].insn && f->bb[i].ninsn) {
|
if (!f->bb[i].insn && f->bb[i].ninsn) goto err;
|
printf ("Anomaly detected at BB%x (insn NULL)\n", i);
|
for (j = 0; j < f->bb[i].ninsn; j++) {
|
print_cuc_bb (f, "ANOMALY");
|
cuc_insn *ii = &f->bb[i].insn[j];
|
exit (1);
|
if (ii->index == II_CMOV && ii->type & IT_COND) {
|
|
k = 0;
|
|
assert (ii->opt[k] & OPT_REGISTER);
|
|
if ((signed)ii->op[k] >= 0 && ii->op[k] != FLAG_REG && ii->op[k] != LRBB_REG) {
|
|
printf ("%x %x\n", ii->opt[0], ii->op[0]);
|
|
goto err;
|
|
}
|
}
|
}
|
for (j = 0; j < f->bb[i].ninsn; j++)
|
|
for (k = 0; k < MAX_OPERANDS; k++)
|
for (k = 0; k < MAX_OPERANDS; k++)
|
if (f->bb[i].insn[j].opt[k] & OPT_REF) {
|
if (ii->opt[k] & OPT_REF) {
|
int t = f->bb[i].insn[j].op[k];
|
int t = ii->op[k];
|
if (REF_BB(t) >= f->num_bb || REF_I (t) >= f->bb[REF_BB(t)].ninsn) {
|
if (REF_BB(t) >= f->num_bb || REF_I (t) >= f->bb[REF_BB(t)].ninsn
|
printf ("Anomaly detected at %x.%x[%i]\n", i, j, k);
|
|| ii->index == II_CMOV && (
|
print_cuc_bb (f, "ANOMALY");
|
(f->INSN(t).type & IT_COND) != (ii->type & IT_COND) && k < 3
|
exit (1);
|
|| !(f->INSN(t).type & IT_COND) && k == 3)) goto err;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
return;
|
|
err:
|
|
printf ("Anomaly detected at %x.%x[%i]\n", i, j, k);
|
|
print_cuc_bb (f, "ANOMALY");
|
|
exit (1);
|
}
|
}
|
|
|
/* Build basic blocks */
|
/* Build basic blocks */
|
void build_bb (cuc_func *f)
|
void build_bb (cuc_func *f)
|
{
|
{
|
Line 353... |
Line 364... |
f->bb[i].unrolled = 1;
|
f->bb[i].unrolled = 1;
|
|
|
/* Save space for conditional moves, exclude r0, place lrbb instead */
|
/* Save space for conditional moves, exclude r0, place lrbb instead */
|
change_insn_type (&f->bb[i].insn[0], II_LRBB);
|
change_insn_type (&f->bb[i].insn[0], II_LRBB);
|
strcpy (f->bb[i].insn[0].disasm, "lrbb");
|
strcpy (f->bb[i].insn[0].disasm, "lrbb");
|
f->bb[i].insn[0].type = IT_UNUSED;
|
f->bb[i].insn[0].type = IT_UNUSED | IT_COND;
|
f->bb[i].insn[0].dep = NULL;
|
f->bb[i].insn[0].dep = NULL;
|
f->bb[i].insn[0].op[0] = LRBB_REG; f->bb[i].insn[0].opt[0] = OPT_REGISTER | OPT_DEST;
|
f->bb[i].insn[0].op[0] = LRBB_REG; f->bb[i].insn[0].opt[0] = OPT_REGISTER | OPT_DEST;
|
f->bb[i].insn[0].opt[1] = OPT_LRBB;
|
f->bb[i].insn[0].opt[1] = OPT_LRBB;
|
f->bb[i].insn[0].opt[2] = f->bb[i].insn[0].opt[3] = OPT_NONE;
|
f->bb[i].insn[0].opt[2] = f->bb[i].insn[0].opt[3] = OPT_NONE;
|
for (j = 1; j < MAX_REGS - 1; j++) {
|
for (j = 1; j < MAX_REGS - 1; j++) {
|
change_insn_type (&f->bb[i].insn[j], II_CMOV);
|
change_insn_type (&f->bb[i].insn[j], II_CMOV);
|
strcpy (f->bb[i].insn[j].disasm, "cmov");
|
strcpy (f->bb[i].insn[j].disasm, "cmov");
|
f->bb[i].insn[j].type = 0;
|
f->bb[i].insn[j].type = j == FLAG_REG || j == LRBB_REG ? IT_COND : 0;
|
f->bb[i].insn[j].dep = NULL;
|
f->bb[i].insn[j].dep = NULL;
|
f->bb[i].insn[j].opt[0] = f->bb[i].insn[j].opt[1] = f->bb[i].insn[j].opt[2] = OPT_REGISTER;
|
f->bb[i].insn[j].opt[0] = f->bb[i].insn[j].opt[1] = f->bb[i].insn[j].opt[2] = OPT_REGISTER;
|
f->bb[i].insn[j].opt[0] |= OPT_DEST;
|
f->bb[i].insn[j].opt[0] |= OPT_DEST;
|
f->bb[i].insn[j].op[0] = f->bb[i].insn[j].op[1] = f->bb[i].insn[j].op[2] = j;
|
f->bb[i].insn[j].op[0] = f->bb[i].insn[j].op[1] = f->bb[i].insn[j].op[2] = j;
|
f->bb[i].insn[j].op[3] = LRBB_REG; f->bb[i].insn[j].opt[3] = OPT_REGISTER;
|
f->bb[i].insn[j].op[3] = LRBB_REG; f->bb[i].insn[j].opt[3] = OPT_REGISTER;
|
Line 497... |
Line 508... |
int b = f->bb[succ].last_used_reg[i];
|
int b = f->bb[succ].last_used_reg[i];
|
|
|
if (b < 0) change_insn_type (ii, II_NOP);
|
if (b < 0) change_insn_type (ii, II_NOP);
|
else if (a < 0) {
|
else if (a < 0) {
|
change_insn_type (ii, II_ADD);
|
change_insn_type (ii, II_ADD);
|
ii->type = 0;
|
ii->type = i == FLAG_REG || i == LRBB_REG ? IT_COND : 0;
|
ii->dep = NULL;
|
ii->dep = NULL;
|
ii->op[0] = i; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
ii->op[0] = i; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
ii->op[1] = b; ii->opt[1] = OPT_REF;
|
ii->op[1] = b; ii->opt[1] = OPT_REF;
|
ii->op[2] = 0; ii->opt[2] = OPT_CONST;
|
ii->op[2] = 0; ii->opt[2] = OPT_CONST;
|
ii->opt[3] = OPT_NONE;
|
ii->opt[3] = OPT_NONE;
|
if (i == FLAG_REG) ii->type |= IT_COND;
|
|
} else if (b >= 0) {
|
} else if (b >= 0) {
|
change_insn_type (ii, II_CMOV);
|
change_insn_type (ii, II_CMOV);
|
ii->type = 0;
|
ii->type = i == FLAG_REG || i == LRBB_REG ? IT_COND : 0;
|
ii->dep = NULL;
|
ii->dep = NULL;
|
ii->op[0] = i; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
ii->op[0] = i; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
ii->op[1] = a; ii->opt[1] = OPT_REF;
|
ii->op[1] = a; ii->opt[1] = OPT_REF;
|
ii->op[2] = b; ii->opt[2] = OPT_REF;
|
ii->op[2] = b; ii->opt[2] = OPT_REF;
|
ii->op[3] = cond_op; ii->opt[3] = cond_opt;
|
ii->op[3] = cond_op; ii->opt[3] = cond_opt;
|
reloc[REF_I(a)] = REF (pred, n1 + n2 + i);
|
reloc[REF_I(a)] = REF (pred, n1 + n2 + i);
|
if (i == FLAG_REG) ii->type |= IT_COND;
|
|
}
|
}
|
sprintf (ii->disasm, "cmov (join BB)");
|
sprintf (ii->disasm, "cmov (join BB)");
|
}
|
}
|
}
|
}
|
|
|
Line 550... |
Line 559... |
if (f->bb[pred].next[0] == f->bb[pred].next[1]) f->bb[pred].next[1] = -1;
|
if (f->bb[pred].next[0] == f->bb[pred].next[1]) f->bb[pred].next[1] = -1;
|
|
|
/* We just did something stupid -- we joined two predecessors into one;
|
/* We just did something stupid -- we joined two predecessors into one;
|
succ may need the information from which block we came. We will repair
|
succ may need the information from which block we came. We will repair
|
this by converting LRBB to CMOV */
|
this by converting LRBB to CMOV */
|
for (i = 0; i < 2; i++) {
|
for (j = 0; j < 2; j++) {
|
int nb = f->bb[pred].next[i];
|
int nb = f->bb[pred].next[j];
|
int t;
|
int t;
|
|
|
/* check just valid connections */
|
/* check just valid connections */
|
if (nb < 0 || nb == BBID_END) continue;
|
if (nb < 0 || nb == BBID_END) continue;
|
|
|
/* check type */
|
/* check type */
|
if (f->bb[nb].prev[0] == pred && f->bb[nb].prev[1] == succ) t = 1;
|
if (f->bb[nb].prev[0] == pred && f->bb[nb].prev[1] == succ) t = 1;
|
else if (f->bb[nb].prev[1] == pred && f->bb[nb].prev[0] == succ) t = 0;
|
else if (f->bb[nb].prev[1] == pred && f->bb[nb].prev[0] == succ) t = 0;
|
else continue;
|
else continue;
|
|
|
/* LRBB can only be first instruction. */
|
/* check all LRBB instructions. */
|
if (f->bb[nb].insn[0].index == II_LRBB) {
|
for (i = 0; i < f->bb[nb].ninsn; i++)
|
cuc_insn *lrbb =&f->bb[nb].insn[0];
|
if (f->bb[nb].insn[i].index == II_LRBB) {
|
|
cuc_insn *lrbb =&f->bb[nb].insn[i];
|
change_insn_type (lrbb, II_CMOV);
|
change_insn_type (lrbb, II_CMOV);
|
lrbb->op[1] = t; lrbb->opt[1] = OPT_CONST;
|
lrbb->op[1] = t; lrbb->opt[1] = OPT_CONST;
|
lrbb->op[2] = 1 - t; lrbb->opt[2] = OPT_CONST;
|
lrbb->op[2] = 1 - t; lrbb->opt[2] = OPT_CONST;
|
lrbb->op[3] = cond_op; lrbb->opt[3] = cond_opt;
|
lrbb->op[3] = cond_op; lrbb->opt[3] = cond_opt;
|
lrbb->type |= IT_COND;
|
lrbb->type |= IT_COND;
|
Line 1209... |
Line 1219... |
} else {
|
} else {
|
assert (pb->insn[pb->ninsn - 1].type & IT_COND);
|
assert (pb->insn[pb->ninsn - 1].type & IT_COND);
|
ii->op[3] = REF (prevart_b, pb->ninsn - 1); ii->opt[3] = OPT_REF;
|
ii->op[3] = REF (prevart_b, pb->ninsn - 1); ii->opt[3] = OPT_REF;
|
}
|
}
|
ii->dep = NULL;
|
ii->dep = NULL;
|
ii->type = 0;
|
ii->type = ob->insn[i].type & IT_COND;
|
} else {
|
} else {
|
change_insn_type (ii, II_NOP);
|
change_insn_type (ii, II_NOP);
|
}
|
}
|
}
|
}
|
|
|
Line 1235... |
Line 1245... |
ii->op[2] = REF (b1 - 1, pb->ninsn - 1);
|
ii->op[2] = REF (b1 - 1, pb->ninsn - 1);
|
ii->opt[2] = OPT_REF;
|
ii->opt[2] = OPT_REF;
|
}
|
}
|
/* {z = x || y;} is same as {z = x ? x : y;} */
|
/* {z = x || y;} is same as {z = x ? x : y;} */
|
ii->op[3] = ii->op[1]; ii->opt[3] = ii->opt[1];
|
ii->op[3] = ii->op[1]; ii->opt[3] = ii->opt[1];
|
ii->type = IT_COND;
|
ii->type |= IT_COND;
|
|
|
/* Only one should be in loop, so we remove any INLOOP flags from duplicates */
|
/* Only one should be in loop, so we remove any INLOOP flags from duplicates */
|
n->bb[b1].type &= ~(BB_END | BB_INLOOP);
|
n->bb[b1].type &= ~(BB_END | BB_INLOOP);
|
n->bb[b1].prev[0] = prevart_b;
|
n->bb[b1].prev[0] = prevart_b;
|
n->bb[b1].prev[1] = b1 - 1;
|
n->bb[b1].prev[1] = b1 - 1;
|
Line 1353... |
Line 1363... |
} else {
|
} else {
|
assert (pb->insn[pb->ninsn - 1].type & IT_COND);
|
assert (pb->insn[pb->ninsn - 1].type & IT_COND);
|
ii->op[3] = REF (prevart_b, pb->ninsn - 1); ii->opt[3] = OPT_REF;
|
ii->op[3] = REF (prevart_b, pb->ninsn - 1); ii->opt[3] = OPT_REF;
|
}
|
}
|
ii->dep = NULL;
|
ii->dep = NULL;
|
ii->type = 0;
|
ii->type = ob->insn[i].type & IT_COND;
|
} else {
|
} else {
|
change_insn_type (ii, II_NOP);
|
change_insn_type (ii, II_NOP);
|
}
|
}
|
}
|
}
|
|
|
Line 1379... |
Line 1389... |
ii->op[2] = REF (b1 - 1, pb->ninsn - 1);
|
ii->op[2] = REF (b1 - 1, pb->ninsn - 1);
|
ii->opt[2] = OPT_REF;
|
ii->opt[2] = OPT_REF;
|
}
|
}
|
/* {z = x || y;} is same as {z = x ? x : y;} */
|
/* {z = x || y;} is same as {z = x ? x : y;} */
|
ii->op[3] = ii->op[1]; ii->opt[3] = ii->opt[1];
|
ii->op[3] = ii->op[1]; ii->opt[3] = ii->opt[1];
|
ii->type = IT_COND;
|
ii->type |= IT_COND;
|
|
|
/* Only one should be in loop, so we remove any INLOOP flags from duplicates */
|
/* Only one should be in loop, so we remove any INLOOP flags from duplicates */
|
n->bb[b1].type &= ~(BB_END | BB_INLOOP);
|
n->bb[b1].type &= ~(BB_END | BB_INLOOP);
|
n->bb[b1].prev[0] = prevart_b;
|
n->bb[b1].prev[0] = prevart_b;
|
n->bb[b1].prev[1] = b1 - 1;
|
n->bb[b1].prev[1] = b1 - 1;
|