Line 19... |
Line 19... |
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <stdarg.h>
|
#include <stdarg.h>
|
#include <assert.h>
|
#include <assert.h>
|
|
|
|
#include "abstract.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "cuc.h"
|
#include "cuc.h"
|
#include "insn.h"
|
#include "insn.h"
|
|
|
/* Table of known instructions. Watch out for indexes I_*! */
|
/* Table of known instructions. Watch out for indexes I_*! */
|
Line 89... |
Line 91... |
char tmp[10];
|
char tmp[10];
|
dep_list *l = insn[i].dep;
|
dep_list *l = insn[i].dep;
|
sprintf (tmp, "[%x_%x]", bb, i);
|
sprintf (tmp, "[%x_%x]", bb, i);
|
PRINTF ("%-8s%c %-4s ", tmp, insn[i].index >= 0 ? ':' : '?', cuc_insn_name (&insn[i]));
|
PRINTF ("%-8s%c %-4s ", tmp, insn[i].index >= 0 ? ':' : '?', cuc_insn_name (&insn[i]));
|
if (verbose) {
|
if (verbose) {
|
PRINTF ("%-20s insn = %08x, index = %i, type = %04x ",
|
PRINTF ("%-20s insn = %08lx, index = %i, type = %04x ",
|
insn[i].disasm, insn[i].insn, insn[i].index, insn[i].type);
|
insn[i].disasm, insn[i].insn, insn[i].index, insn[i].type);
|
} else PRINTF ("type = %04x ", insn[i].type);
|
} else PRINTF ("type = %04x ", insn[i].type);
|
for (j = 0; j < MAX_OPERANDS; j++) {
|
for (j = 0; j < MAX_OPERANDS; j++) {
|
if (insn[i].opt[j] & OPT_DEST) PRINTF ("*");
|
if (insn[i].opt[j] & OPT_DEST) PRINTF ("*");
|
switch (insn[i].opt[j] & ~OPT_DEST) {
|
switch (insn[i].opt[j] & ~OPT_DEST) {
|
case OPT_NONE: break;
|
case OPT_NONE:
|
case OPT_CONST: if (insn[i].type & IT_COND && (insn[i].index == II_CMOV
|
break;
|
|| insn[i].index == II_ADD)) PRINTF ("%x, ", insn[i].op[j]);
|
case OPT_CONST:
|
else PRINTF ("0x%08x, ", insn[i].op[j]); break;
|
if (insn[i].type & IT_COND && (insn[i].index == II_CMOV
|
case OPT_JUMP: PRINTF ("J%x, ", insn[i].op[j]); break;
|
|| insn[i].index == II_ADD))
|
case OPT_REGISTER: PRINTF ("r%i, ", insn[i].op[j]); break;
|
PRINTF ("%lx, ", insn[i].op[j]);
|
case OPT_REF: PRINTF ("[%x_%x], ", REF_BB(insn[i].op[j]), REF_I(insn[i].op[j])); break;
|
else
|
case OPT_BB: PRINTF ("BB "); print_bb_num (insn[i].op[j]); PRINTF (", "); break;
|
PRINTF ("0x%08lx, ", insn[i].op[j]);
|
case OPT_LRBB: PRINTF ("LRBB, "); break;
|
break;
|
|
case OPT_JUMP:
|
|
PRINTF ("J%lx, ", insn[i].op[j]);
|
|
break;
|
|
case OPT_REGISTER:
|
|
PRINTF ("r%li, ", insn[i].op[j]);
|
|
break;
|
|
case OPT_REF:
|
|
PRINTF ("[%lx_%lx], ", REF_BB(insn[i].op[j]), REF_I(insn[i].op[j]));
|
|
break;
|
|
case OPT_BB:
|
|
PRINTF ("BB ");
|
|
print_bb_num (insn[i].op[j]);
|
|
PRINTF (", ");
|
|
break;
|
|
case OPT_LRBB:
|
|
PRINTF ("LRBB, ");
|
|
break;
|
default:
|
default:
|
fprintf (stderr, "Invalid operand type %s(%x_%x) = %x\n",
|
fprintf (stderr, "Invalid operand type %s(%x_%x) = %x\n",
|
cuc_insn_name (&insn[i]), i, j, insn[i].opt[j]);
|
cuc_insn_name (&insn[i]), i, j, insn[i].opt[j]);
|
assert (0);
|
assert (0);
|
}
|
}
|
}
|
}
|
if (l) {
|
if (l) {
|
PRINTF ("\n\tdep:");
|
PRINTF ("\n\tdep:");
|
while (l) {
|
while (l) {
|
PRINTF (" [%x_%x],", REF_BB (l->ref), REF_I (l->ref));
|
PRINTF (" [%lx_%lx],", REF_BB (l->ref), REF_I (l->ref));
|
l = l->next;
|
l = l->next;
|
}
|
}
|
}
|
}
|
PRINTF ("\n");
|
PRINTF ("\n");
|
}
|
}
|
Line 148... |
Line 167... |
}
|
}
|
|
|
void add_data_dep (cuc_func *f)
|
void add_data_dep (cuc_func *f)
|
{
|
{
|
int b, i, j;
|
int b, i, j;
|
dep_list *tmp;
|
|
for (b = 0; b < f->num_bb; b++) {
|
for (b = 0; b < f->num_bb; b++) {
|
cuc_insn *insn = f->bb[b].insn;
|
cuc_insn *insn = f->bb[b].insn;
|
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++) {
|
fflush (stdout);
|
fflush (stdout);
|
Line 448... |
Line 466... |
ii->tmp = 0;
|
ii->tmp = 0;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Is this instruction CMOV? no => add to primary inputs */
|
/* Is this instruction CMOV? no => add to primary inputs */
|
if (ii->index != II_CMOV || ii->type & IT_VOLATILE)
|
if ((ii->index != II_CMOV) || (ii->type & IT_VOLATILE)) {
|
if (tmp_opt == OPT_NONE) {
|
if (tmp_opt == OPT_NONE) {
|
tmp_op = ref;
|
tmp_op = ref;
|
tmp_opt = OPT_REF;
|
tmp_opt = OPT_REF;
|
ii->tmp = 0;
|
ii->tmp = 0;
|
return 0;
|
return 0;
|
Line 461... |
Line 479... |
return 1;
|
return 1;
|
} else {
|
} else {
|
ii->tmp = 0;
|
ii->tmp = 0;
|
return 0;
|
return 0;
|
}
|
}
|
|
}
|
|
|
for (j = 1; j < 3; j++) {
|
for (j = 1; j < 3; j++) {
|
cucdebug (4, "(%x:%i)", ref, j);
|
cucdebug (4, "(%x:%i)", ref, j);
|
if (ii->opt[j] == OPT_REF) {
|
if (ii->opt[j] == OPT_REF) {
|
if (cmov_needed (f, ii->op[j])) {
|
if (cmov_needed (f, ii->op[j])) {
|
Line 488... |
Line 507... |
|
|
/* Search and optimize complex cmov assignments */
|
/* Search and optimize complex cmov assignments */
|
int optimize_cmovs (cuc_func *f)
|
int optimize_cmovs (cuc_func *f)
|
{
|
{
|
int modified = 0;
|
int modified = 0;
|
int b, i, j;
|
int b, i;
|
|
|
/* Mark all instructions unvisited */
|
/* Mark all instructions unvisited */
|
for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD))
|
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 (i = 0; i < f->bb[b].ninsn; i++) f->bb[b].insn[i].tmp = 0;
|
|
|
Line 629... |
Line 648... |
cuc_insn tmp, cmov;
|
cuc_insn tmp, cmov;
|
int ref2 = REF (REF_BB (ref), REF_I (ref) + 1);
|
int ref2 = REF (REF_BB (ref), REF_I (ref) + 1);
|
insert_insns (f, ref, 1);
|
insert_insns (f, ref, 1);
|
a = &f->INSN(f->INSN(ref2).op[1]);
|
a = &f->INSN(f->INSN(ref2).op[1]);
|
b = &f->INSN(f->INSN(ref2).op[2]);
|
b = &f->INSN(f->INSN(ref2).op[2]);
|
cucdebug (4, "ref = %x %x %x\n", ref, f->INSN(ref2).op[1], f->INSN(ref2).op[2]);
|
cucdebug (4, "ref = %x %lx %lx\n", ref, f->INSN(ref2).op[1],
|
|
f->INSN(ref2).op[2]);
|
if (cuc_debug >= 7) {
|
if (cuc_debug >= 7) {
|
print_cuc_bb (f, "AAA");
|
print_cuc_bb (f, "AAA");
|
cuc_check (f);
|
cuc_check (f);
|
}
|
}
|
tmp = *a;
|
tmp = *a;
|
Line 642... |
Line 662... |
cmov.op[0] = -1; cmov.opt[0] = OPT_REGISTER | OPT_DEST;
|
cmov.op[0] = -1; cmov.opt[0] = OPT_REGISTER | OPT_DEST;
|
cmov.op[1] = a->op[diff]; cmov.opt[1] = a->opt[diff];
|
cmov.op[1] = a->op[diff]; cmov.opt[1] = a->opt[diff];
|
cmov.op[2] = b->op[diff]; cmov.opt[2] = b->opt[diff];
|
cmov.op[2] = b->op[diff]; cmov.opt[2] = b->opt[diff];
|
change_insn_type (&cmov, II_CMOV);
|
change_insn_type (&cmov, II_CMOV);
|
cmov.type &= ~IT_COND;
|
cmov.type &= ~IT_COND;
|
cucdebug (4, "ref2 = %x %x %x\n", ref2, cmov.op[1], cmov.op[2]);
|
cucdebug (4, "ref2 = %x %lx %lx\n", ref2, cmov.op[1], cmov.op[2]);
|
if (cmov.opt[1] & OPT_REF && cmov.opt[2] & OPT_REF
|
if (cmov.opt[1] & OPT_REF && cmov.opt[2] & OPT_REF
|
&& f->INSN(cmov.op[1]).type & IT_COND) {
|
&& f->INSN(cmov.op[1]).type & IT_COND) {
|
assert (f->INSN(cmov.op[2]).type & IT_COND);
|
assert (f->INSN(cmov.op[2]).type & IT_COND);
|
cmov.type |= IT_COND;
|
cmov.type |= IT_COND;
|
}
|
}
|
Line 708... |
Line 728... |
if (f->INSN(ii->op[j]).index == II_ADD
|
if (f->INSN(ii->op[j]).index == II_ADD
|
&& f->INSN(ii->op[j]).opt[2] & OPT_CONST
|
&& f->INSN(ii->op[j]).opt[2] & OPT_CONST
|
&& f->INSN(ii->op[j]).op[2] == 0
|
&& f->INSN(ii->op[j]).op[2] == 0
|
&& !(ii->type & IT_MEMORY && t->type & IT_MEMADD)) {
|
&& !(ii->type & IT_MEMORY && t->type & IT_MEMADD)) {
|
/* do not promote through add-mem, and branches */
|
/* do not promote through add-mem, and branches */
|
modified = 1; cucdebug (2, "%8x:promote%i %8x %8x\n", REF (b, i), j, ii->op[j], t->op[1]);
|
modified = 1;
|
ii->op[j] = t->op[1]; ii->opt[j] = t->opt[1];
|
cucdebug (2, "%8x:promote%i %8lx %8lx\n", REF (b, i), j, ii->op[j], t->op[1]);
|
|
ii->op[j] = t->op[1];
|
|
ii->opt[j] = t->opt[1];
|
}
|
}
|
}
|
}
|
|
|
/* handle some CMOV cases more deeply */
|
/* handle some CMOV cases more deeply */
|
if (ii->index == II_CMOV && optimize_cmov_more (f, REF (b, i))) {
|
if (ii->index == II_CMOV && optimize_cmov_more (f, REF (b, i))) {
|
Line 758... |
Line 780... |
cuc_insn *prev = &f->INSN(ii->op[1]);
|
cuc_insn *prev = &f->INSN(ii->op[1]);
|
/* Is this just a move? */
|
/* Is this just a move? */
|
if (ii->index == II_ADD
|
if (ii->index == II_ADD
|
&& !(ii->type & IT_MEMADD) && ii->op[2] == 0) {
|
&& !(ii->type & IT_MEMADD) && ii->op[2] == 0) {
|
int b1, i1, j1;
|
int b1, i1, j1;
|
cucdebug (2, "%8x:link %8x: ", REF(b, i), ii->op[1]);
|
cucdebug (2, "%8x:link %8lx: ", REF(b, i), ii->op[1]);
|
if (!(prev->type & (IT_OUTPUT | IT_VOLATILE))) {
|
if (!(prev->type & (IT_OUTPUT | IT_VOLATILE))) {
|
assert (ii->opt[0] & OPT_DEST);
|
assert (ii->opt[0] & OPT_DEST);
|
prev->op[0] = ii->op[0]; prev->opt[0] = ii->opt[0];
|
prev->op[0] = ii->op[0]; prev->opt[0] = ii->opt[0];
|
prev->type |= ii->type & IT_OUTPUT;
|
prev->type |= ii->type & IT_OUTPUT;
|
for (b1 = 0; b1 < f->num_bb; b1++) if (!(f->bb[b1].type & BB_DEAD))
|
for (b1 = 0; b1 < f->num_bb; b1++) if (!(f->bb[b1].type & BB_DEAD))
|
Line 873... |
Line 895... |
}
|
}
|
|
|
/* Remove unused assignments */
|
/* Remove unused assignments */
|
int remove_dead (cuc_func *f)
|
int remove_dead (cuc_func *f)
|
{
|
{
|
int b, i, j;
|
int b, i;
|
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++)
|
f->bb[b].insn[i].type |= IT_UNUSED;
|
f->bb[b].insn[i].type |= IT_UNUSED;
|
|
|
for (b = 0; b < f->num_bb; b++)
|
for (b = 0; b < f->num_bb; b++)
|
Line 937... |
Line 959... |
}
|
}
|
if (cuc_debug > 5) print_cuc_bb (f, "SET_IO");
|
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);
|
else f->used_regs[f->bb[b].insn[i].op[j]] = 1;
|
else f->used_regs[f->bb[b].insn[i].op[j]] = 1;
|
}
|
}
|
}
|
}
|
|
}
|
|
|
/* relocate all accesses inside of BB b to back/fwd */
|
/* relocate all accesses inside of BB b to back/fwd */
|
static void relocate_bb (cuc_bb *bb, int b, int back, int fwd)
|
static void relocate_bb (cuc_bb *bb, int b, int back, int fwd)
|
{
|
{
|
int i, j;
|
int i, j;
|
Line 1043... |
Line 1066... |
|
|
/* CSE -- common subexpression elimination */
|
/* CSE -- common subexpression elimination */
|
int cse (cuc_func *f)
|
int cse (cuc_func *f)
|
{
|
{
|
int modified = 0;
|
int modified = 0;
|
int b, i, j, b1, i1, b2, i2, j2;
|
int b, i, j, b1, i1, b2, i2;
|
for (b1 = 0; b1 < f->num_bb; b1++)
|
for (b1 = 0; b1 < f->num_bb; b1++)
|
for (i1 = 0; i1 < f->bb[b1].ninsn; i1++) if (f->bb[b1].insn[i1].index != II_NOP
|
for (i1 = 0; i1 < f->bb[b1].ninsn; i1++) if (f->bb[b1].insn[i1].index != II_NOP
|
&& f->bb[b1].insn[i1].index != II_LRBB && !(f->bb[b1].insn[i1].type & IT_MEMORY)
|
&& f->bb[b1].insn[i1].index != II_LRBB && !(f->bb[b1].insn[i1].type & IT_MEMORY)
|
&& !(f->bb[b1].insn[i1].type & IT_MEMADD))
|
&& !(f->bb[b1].insn[i1].type & IT_MEMADD))
|
for (b2 = 0; b2 < f->num_bb; b2++)
|
for (b2 = 0; b2 < f->num_bb; b2++)
|
Line 1377... |
Line 1400... |
Situation here is much simpler than with analysis -- we know the instruction sequence
|
Situation here is much simpler than with analysis -- we know the instruction sequence
|
we are going to share, but we are going to do this on whole function, not just one BB.
|
we are going to share, but we are going to do this on whole function, not just one BB.
|
We can find sequence in reference function, as pointed from "shared" */
|
We can find sequence in reference function, as pointed from "shared" */
|
void csm_gen (cuc_func *f, cuc_func *rf, cuc_shared_item *shared, int nshared)
|
void csm_gen (cuc_func *f, cuc_func *rf, cuc_shared_item *shared, int nshared)
|
{
|
{
|
int b, i, j, cnt = 0;
|
int b, i, cnt = 0;
|
#warning some code here (2)
|
#warning some code here (2)
|
PRINTF ("Replacing: ");
|
PRINTF ("Replacing: ");
|
print_shared (rf, shared, nshared);
|
print_shared (rf, shared, nshared);
|
|
|
for (b = 0; b < f->num_bb; b++)
|
for (b = 0; b < f->num_bb; b++)
|