Line 111... |
Line 111... |
}
|
}
|
}
|
}
|
dispose_list (&all_mem);
|
dispose_list (&all_mem);
|
}
|
}
|
|
|
|
/* Check if they address the same location, so we can join them */
|
|
static int same_transfers (cuc_func *f, int otype)
|
|
{
|
|
int i, j;
|
|
int modified = 0;
|
|
if (otype == MO_WEAK || otype == MO_NONE) {
|
|
for (i = 1, j = 1; i < f->nmsched; i++)
|
|
/* Exclude memory stores and different memory types */
|
|
if (f->mtype[i - 1] == f->mtype[i] && f->mtype[i] & MT_LOAD) {
|
|
cuc_insn *a = &f->INSN(f->msched[i - 1]);
|
|
cuc_insn *b = &f->INSN(f->msched[i]);
|
|
if ((a->opt[1] & OPT_REF) && f->INSN(a->op[1]).index == II_ADD
|
|
&&(b->opt[1] & OPT_REF) && f->INSN(b->op[1]).index == II_ADD) {
|
|
a = &f->INSN(a->op[1]);
|
|
b = &f->INSN(b->op[1]);
|
|
/* Not in usual form? */
|
|
if (a->opt[1] != b->opt[1] || a->op[1] != b->op[1]
|
|
|| a->opt[2] != OPT_CONST || b->opt[2] != OPT_CONST) goto keep;
|
|
|
|
//printf ("%i %i, ", a->op[2], b->op[2]);
|
|
|
|
/* Check if they are the same => do not copy */
|
|
if (a->op[2] == b->op[2]
|
|
&& REF_BB(f->msched[i - 1]) == REF_BB(f->msched[i])) {
|
|
/* yes => remove actual instruction */
|
|
int t1 = MIN (f->msched[i - 1], f->msched[i]);
|
|
int t2 = MAX (f->msched[i - 1], f->msched[i]);
|
|
int b, i, j;
|
|
cucdebug (2, "Removing %x_%x and using %x_%x instead.\n",
|
|
REF_BB(t2), REF_I(t2), REF_BB(t1), REF_I(t1));
|
|
change_insn_type (&f->INSN(t2), II_NOP);
|
|
modified = 1;
|
|
/* Update references */
|
|
for (b = 0; b < f->num_bb; b++)
|
|
for (i = 0; i < f->bb[b].ninsn; i++)
|
|
for (j = 0; j < MAX_OPERANDS; j++)
|
|
if (f->bb[b].insn[i].opt[j] & OPT_REF && f->bb[b].insn[i].op[j] == t2)
|
|
f->bb[b].insn[i].op[j] = t1;
|
|
|
|
} else goto keep;
|
|
} else goto keep;
|
|
} else {
|
|
keep:
|
|
f->msched[j] = f->msched[i];
|
|
f->mtype[j++] = f->mtype[i];
|
|
}
|
|
f->nmsched = j;
|
|
}
|
|
return modified;
|
|
}
|
|
|
|
/* Check if two consecutive lb[zs] can be joined into lhz and if
|
|
two consecutive lh[zs] can be joined into lwz */
|
|
static int join_transfers (cuc_func *f, int otype)
|
|
{
|
|
int i, j;
|
|
int modified = 0;
|
|
|
|
/* We can change width even with strong memory ordering */
|
|
if (otype == MO_WEAK || otype == MO_NONE || otype == MO_STRONG) {
|
|
for (i = 1, j = 1; i < f->nmsched; i++)
|
|
/* Exclude memory stores and different memory types */
|
|
if (f->mtype[i - 1] == f->mtype[i] && f->mtype[i] & MT_LOAD) {
|
|
cuc_insn *a = &f->INSN(f->msched[i - 1]);
|
|
cuc_insn *b = &f->INSN(f->msched[i]);
|
|
int aw = f->mtype[i - 1] & MT_WIDTH;
|
|
if ((a->opt[1] & OPT_REF) && f->INSN(a->op[1]).index == II_ADD
|
|
&&(b->opt[1] & OPT_REF) && f->INSN(b->op[1]).index == II_ADD) {
|
|
a = &f->INSN(a->op[1]);
|
|
b = &f->INSN(b->op[1]);
|
|
|
|
/* Not in usual form? */
|
|
if (a->opt[1] != b->opt[1] || a->op[1] != b->op[1]
|
|
|| a->opt[2] != OPT_CONST || b->opt[2] != OPT_CONST) goto keep;
|
|
|
|
/* Check if they touch together */
|
|
if (a->op[2] + aw == b->op[2]
|
|
&& REF_BB(f->msched[i - 1]) == REF_BB(f->msched[i])) {
|
|
/* yes => remove second instruction */
|
|
int t1 = MIN (f->msched[i - 1], f->msched[i]);
|
|
int t2 = MAX (f->msched[i - 1], f->msched[i]);
|
|
dep_list *t1dep = f->INSN(t1).dep;
|
|
int x, p;
|
|
cuc_insn *ii;
|
|
|
|
cucdebug (2, "Joining %x and %x.\n", t1, t2);
|
|
print_cuc_bb (f, "PREJT");
|
|
change_insn_type (&f->INSN(t1), II_NOP);
|
|
change_insn_type (&f->INSN(t2), II_NOP);
|
|
/* We will reuse the memadd before the first load, and add some
|
|
custom code at the end */
|
|
insert_insns (f, t1, 10);
|
|
print_cuc_bb (f, "PREJT2");
|
|
|
|
/* Remove all dependencies to second access */
|
|
for (x = 0; x < f->num_bb; x++) {
|
|
int i;
|
|
for (i = 0; i < f->bb[x].ninsn; i++) {
|
|
dep_list *d = f->bb[x].insn[i].dep;
|
|
dep_list **old = &f->bb[x].insn[i].dep;
|
|
while (d) {
|
|
if (d->ref == t2) {
|
|
d = d->next;
|
|
*old = d;
|
|
} else {
|
|
d = d->next;
|
|
old = &((*old)->next);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Build the folowing code:
|
|
l[hw]z p-1
|
|
and p-1, 0xff
|
|
sfle p-1, 0x7f
|
|
or p-2, 0xffffff00
|
|
cmov p-3, p-1, p-2
|
|
shr p-5, 8
|
|
and p-1, 0xff
|
|
sfle p-1 0x7f
|
|
or p-2 0xffffff00
|
|
cmov p-3, p-1, p-2*/
|
|
p = REF_I(t1);
|
|
printf ("%x %x\n", f->mtype[i - 1], f->mtype[i]);
|
|
for (x = 0; x < 2; x++) {
|
|
int t = f->mtype[i - 1 + x];
|
|
ii = &f->bb[REF_BB(t1)].insn[p];
|
|
if (!x) {
|
|
change_insn_type (ii, aw == 1 ? II_LH : II_LW);
|
|
ii->type = IT_MEMORY | IT_VOLATILE;
|
|
ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
|
ii->op[1] = t1 - 1; ii->opt[1] = OPT_REF;
|
|
ii->opt[2] = ii->opt[3] = OPT_NONE;
|
|
ii->dep = t1dep;
|
|
f->mtype[i - 1] = MT_LOAD | (aw == 1 ? 2 : 4);
|
|
f->msched[i - 1] = REF (REF_BB(t1), p);
|
|
} else {
|
|
change_insn_type (ii, II_SRL);
|
|
ii->type = 0;
|
|
ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
|
ii->op[1] = t1; ii->opt[1] = OPT_REF;
|
|
ii->op[2] = 8; ii->opt[2] = OPT_CONST;
|
|
ii->opt[3] = OPT_NONE;
|
|
}
|
|
|
|
printf ("1. %x %x\n", p, t);
|
|
ii = &f->bb[REF_BB(t1)].insn[++p];
|
|
change_insn_type (ii, II_AND);
|
|
ii->type = 0;
|
|
ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
|
ii->op[1] = REF (REF_BB(t1), p - 1); ii->opt[1] = OPT_REF;
|
|
ii->op[2] = 0xff; ii->opt[2] = OPT_CONST;
|
|
ii->opt[3] = OPT_NONE;
|
|
|
|
printf ("2. %x\n", p);
|
|
ii = &f->bb[REF_BB(t1)].insn[++p];
|
|
change_insn_type (ii, II_SFLE);
|
|
ii->type = IT_COND;
|
|
ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
|
ii->op[1] = REF (REF_BB(t1), p - 1); ii->opt[1] = OPT_REF;
|
|
ii->op[2] = 0x7f; ii->opt[2] = OPT_CONST;
|
|
ii->opt[3] = OPT_NONE;
|
|
|
|
printf ("3. %x\n", p);
|
|
ii = &f->bb[REF_BB(t1)].insn[++p];
|
|
change_insn_type (ii, II_OR);
|
|
ii->type = 0;
|
|
ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
|
ii->op[1] = REF (REF_BB(t1), p - 2); ii->opt[1] = OPT_REF;
|
|
if (t & MT_SIGNED) ii->op[2] = 0xffffff00;
|
|
else ii->op[2] = 0;
|
|
ii->opt[2] = OPT_CONST;
|
|
ii->opt[3] = OPT_NONE;
|
|
|
|
printf ("4. %x\n", p);
|
|
ii = &f->bb[REF_BB(t1)].insn[++p];
|
|
change_insn_type (ii, II_CMOV);
|
|
ii->type = 0;
|
|
ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
|
|
ii->op[1] = REF (REF_BB(t1), p - 1); ii->opt[1] = OPT_REF;
|
|
ii->op[2] = REF (REF_BB(t1), p - 3); ii->opt[2] = OPT_REF;
|
|
ii->op[3] = REF (REF_BB(t1), p - 2); ii->opt[3] = OPT_REF;
|
|
p++;
|
|
}
|
|
|
|
modified = 1;
|
|
|
|
{
|
|
int b, i, j;
|
|
/* Update references */
|
|
for (b = 0; b < f->num_bb; b++)
|
|
for (i = 0; i < f->bb[b].ninsn; i++)
|
|
for (j = 0; j < MAX_OPERANDS; j++)
|
|
if (REF_I (f->bb[b].insn[i].op[j]) < REF_I (t1)
|
|
|| REF_I(f->bb[b].insn[i].op[j]) >= REF_I (t1) + 10) {
|
|
if (f->bb[b].insn[i].opt[j] & OPT_REF && f->bb[b].insn[i].op[j] == t1)
|
|
f->bb[b].insn[i].op[j] = t1 + 4;
|
|
else if (f->bb[b].insn[i].opt[j] & OPT_REF && f->bb[b].insn[i].op[j] == t2)
|
|
f->bb[b].insn[i].op[j] = t1 + 9;
|
|
}
|
|
}
|
|
print_cuc_bb (f, "POSTJT");
|
|
} else goto keep;
|
|
} else goto keep;
|
|
} else {
|
|
keep:
|
|
f->msched[j] = f->msched[i];
|
|
f->mtype[j++] = f->mtype[i];
|
|
}
|
|
f->nmsched = j;
|
|
}
|
|
return modified;
|
|
}
|
|
|
/* returns nonzero if a < b */
|
/* returns nonzero if a < b */
|
int mem_ordering_cmp (cuc_func *f, cuc_insn *a, cuc_insn *b)
|
int mem_ordering_cmp (cuc_func *f, cuc_insn *a, cuc_insn *b)
|
{
|
{
|
assert (a->type & IT_MEMORY);
|
assert (a->type & IT_MEMORY);
|
assert (b->type & IT_MEMORY);
|
assert (b->type & IT_MEMORY);
|
Line 130... |
Line 345... |
} else return 0;
|
} else return 0;
|
}
|
}
|
|
|
/* Schedule memory accesses
|
/* Schedule memory accesses
|
0 - exact; 1 - strong; 2 - weak; 3 - none */
|
0 - exact; 1 - strong; 2 - weak; 3 - none */
|
void schedule_memory (cuc_func *f, int otype)
|
int schedule_memory (cuc_func *f, int otype)
|
{
|
{
|
int b, i, j;
|
int b, i, j;
|
|
int modified = 0;
|
f->nmsched = 0;
|
f->nmsched = 0;
|
|
|
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++)
|
Line 190... |
Line 406... |
f->mtype[i] = !II_IS_LOAD(a->index) ? MT_STORE : MT_LOAD;
|
f->mtype[i] = !II_IS_LOAD(a->index) ? MT_STORE : MT_LOAD;
|
f->mtype[i] |= II_MEM_WIDTH (a->index);
|
f->mtype[i] |= II_MEM_WIDTH (a->index);
|
if (a->type & IT_SIGNED) f->mtype[i] |= MT_SIGNED;
|
if (a->type & IT_SIGNED) f->mtype[i] |= MT_SIGNED;
|
}
|
}
|
|
|
/* Check if they address the same location, so we can join them */
|
if (same_transfers (f, otype)) modified = 1;
|
if (otype == MO_WEAK || otype == MO_NONE) {
|
if (join_transfers (f, otype)) modified = 1;
|
for (i = 1, j = 1; i < f->nmsched; i++)
|
|
/* Exclude memory stores and different memory types */
|
|
if (f->mtype[i - 1] == f->mtype[i] && f->mtype[i] & MT_LOAD) {
|
|
cuc_insn *a = &f->INSN(f->msched[i - 1]);
|
|
cuc_insn *b = &f->INSN(f->msched[i]);
|
|
if ((a->opt[1] & OPT_REF) && f->INSN(a->op[1]).index == II_ADD
|
|
&&(b->opt[1] & OPT_REF) && f->INSN(b->op[1]).index == II_ADD) {
|
|
a = &f->INSN(a->op[1]);
|
|
b = &f->INSN(b->op[1]);
|
|
/* Not in usual form? */
|
|
if (a->opt[1] != b->opt[1] || a->op[1] != b->op[1]
|
|
|| a->opt[2] != OPT_CONST || b->opt[2] != OPT_CONST) goto keep;
|
|
|
|
//printf ("%i %i, ", a->op[2], b->op[2]);
|
|
|
|
/* Check if they are the same => do not copy */
|
|
if (a->op[2] == b->op[2]
|
|
&& REF_BB(f->msched[i - 1]) == REF_BB(f->msched[i])) {
|
|
/* yes => remove actual instruction */
|
|
int t1 = MIN (f->msched[i - 1], f->msched[i]);
|
|
int t2 = MAX (f->msched[i - 1], f->msched[i]);
|
|
int b, i, j;
|
|
cucdebug (2, "Removing %x_%x and using %x_%x instead.\n",
|
|
REF_BB(t2), REF_I(t2), REF_BB(t1), REF_I(t1));
|
|
change_insn_type (&f->INSN(t2), II_NOP);
|
|
/* Update references */
|
|
for (b = 0; b < f->num_bb; b++)
|
|
for (i = 0; i < f->bb[b].ninsn; i++)
|
|
for (j = 0; j < MAX_OPERANDS; j++)
|
|
if (f->bb[b].insn[i].opt[j] & OPT_REF && f->bb[b].insn[i].op[j] == t2)
|
|
f->bb[b].insn[i].op[j] = t1;
|
|
|
|
} else goto keep;
|
|
} else goto keep;
|
|
} else {
|
|
keep:
|
|
f->msched[j] = f->msched[i];
|
|
f->mtype[j++] = f->mtype[i];
|
|
}
|
|
f->nmsched = j;
|
|
}
|
|
|
|
for (i = 0; i < f->nmsched; i++)
|
for (i = 0; i < f->nmsched; i++)
|
cucdebug (2, "[%x]%x%c ", f->msched[i], f->mtype[i] & MT_WIDTH, (f->mtype[i] & MT_BURST) ? (f->mtype[i] & MT_BURSTE) ? 'E' : 'B' : ' ');
|
cucdebug (2, "[%x]%x%c ", f->msched[i], f->mtype[i] & MT_WIDTH, (f->mtype[i] & MT_BURST) ? (f->mtype[i] & MT_BURSTE) ? 'E' : 'B' : ' ');
|
cucdebug (2, "\n");
|
cucdebug (2, "\n");
|
if (cuc_debug > 5) print_cuc_bb (f, "AFTER_MEM_REMOVAL");
|
if (cuc_debug > 5) print_cuc_bb (f, "AFTER_MEM_REMOVAL");
|
Line 246... |
Line 421... |
for (i = 1; i < f->nmsched; i++) {
|
for (i = 1; i < f->nmsched; i++) {
|
cuc_insn *a = &f->INSN(f->msched[i - 1]);
|
cuc_insn *a = &f->INSN(f->msched[i - 1]);
|
cuc_insn *b = &f->INSN(f->msched[i]);
|
cuc_insn *b = &f->INSN(f->msched[i]);
|
int aw = f->mtype[i - 1] & MT_WIDTH;
|
int aw = f->mtype[i - 1] & MT_WIDTH;
|
|
|
|
/* Burst can only be out of words */
|
|
if (aw != 4) continue;
|
|
|
if ((a->opt[1] & OPT_REF) && f->INSN(a->op[1]).index == II_ADD
|
if ((a->opt[1] & OPT_REF) && f->INSN(a->op[1]).index == II_ADD
|
&&(b->opt[1] & OPT_REF) && f->INSN(b->op[1]).index == II_ADD) {
|
&&(b->opt[1] & OPT_REF) && f->INSN(b->op[1]).index == II_ADD) {
|
a = &f->INSN(a->op[1]);
|
a = &f->INSN(a->op[1]);
|
b = &f->INSN(b->op[1]);
|
b = &f->INSN(b->op[1]);
|
/* Not in usual form? */
|
/* Not in usual form? */
|
Line 257... |
Line 435... |
|| a->opt[2] != OPT_CONST || b->opt[2] != OPT_CONST) continue;
|
|| a->opt[2] != OPT_CONST || b->opt[2] != OPT_CONST) continue;
|
|
|
//printf ("%i %i, ", a->op[2], b->op[2]);
|
//printf ("%i %i, ", a->op[2], b->op[2]);
|
|
|
/* Check if they touch together */
|
/* Check if they touch together */
|
if (a->op[2] + aw == b->op[2]) {
|
if (a->op[2] + aw == b->op[2]
|
|
&& REF_BB(f->msched[i - 1]) == REF_BB(f->msched[i])) {
|
/* yes => do burst */
|
/* yes => do burst */
|
f->mtype[i - 1] &= ~MT_BURSTE;
|
f->mtype[i - 1] &= ~MT_BURSTE;
|
f->mtype[i - 1] |= MT_BURST;
|
f->mtype[i - 1] |= MT_BURST;
|
f->mtype[i] |= MT_BURST | MT_BURSTE;
|
f->mtype[i] |= MT_BURST | MT_BURSTE;
|
}
|
}
|
Line 278... |
Line 457... |
cuc_insn *insn = f->bb[b].insn;
|
cuc_insn *insn = f->bb[b].insn;
|
for (i = 0; i < f->bb[b].ninsn; i++) if (!(insn[i].type & IT_MEMORY))
|
for (i = 0; i < f->bb[b].ninsn; i++) if (!(insn[i].type & IT_MEMORY))
|
dispose_list (&insn[i].dep);
|
dispose_list (&insn[i].dep);
|
}
|
}
|
|
|
|
if (cuc_debug > 5) print_cuc_bb (f, "AFTER_MEM_REMOVAL2");
|
/* Reduce number of dependecies, keeping just direct dependencies, based on memory schedule */
|
/* Reduce number of dependecies, keeping just direct dependencies, based on memory schedule */
|
{
|
{
|
int lastl[3] = {-1, -1, -1};
|
int lastl[3] = {-1, -1, -1};
|
int lasts[3] = {-1, -1, -1};
|
int lasts[3] = {-1, -1, -1};
|
int lastc[3] = {-1, -1, -1};
|
int lastc[3] = {-1, -1, -1};
|
Line 290... |
Line 470... |
int t = f->mtype[i] & MT_LOAD ? 0 : f->mtype[i] & MT_STORE ? 1 : 2;
|
int t = f->mtype[i] & MT_LOAD ? 0 : f->mtype[i] & MT_STORE ? 1 : 2;
|
int maxl = lastl[t];
|
int maxl = lastl[t];
|
int maxs = lasts[t];
|
int maxs = lasts[t];
|
int maxc = lastc[t];
|
int maxc = lastc[t];
|
dep_list *tmp = f->INSN(f->msched[i]).dep;
|
dep_list *tmp = f->INSN(f->msched[i]).dep;
|
|
printf ("!%i %x %x\n", i, f->msched[i], tmp);
|
|
fflush (stdout);
|
while (tmp) {
|
while (tmp) {
|
if (f->INSN(tmp->ref).type & IT_MEMORY && REF_BB(tmp->ref) == REF_BB(f->msched[i])) {
|
if (f->INSN(tmp->ref).type & IT_MEMORY && REF_BB(tmp->ref) == REF_BB(f->msched[i])) {
|
printf ("%i %x %x\n", i, f->msched[i], tmp->ref);
|
printf ("%i %x %x\n", i, f->msched[i], tmp->ref);
|
|
fflush (stdout);
|
/* Search for the reference */
|
/* Search for the reference */
|
for (j = 0; j < f->nmsched; j++) if (f->msched[j] == tmp->ref) break;
|
for (j = 0; j < f->nmsched; j++) if (f->msched[j] == tmp->ref) break;
|
assert (j < f->nmsched);
|
assert (j < f->nmsched);
|
if (f->mtype[j] & MT_STORE) {
|
if (f->mtype[j] & MT_STORE) {
|
if (maxs < j) maxs = j;
|
if (maxs < j) maxs = j;
|
Line 349... |
Line 532... |
lastc[t] = last_call;
|
lastc[t] = last_call;
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
return modified;
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|