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 "sim-config.h"
|
|
#include "abstract.h"
|
#include "cuc.h"
|
#include "cuc.h"
|
#include "insn.h"
|
#include "insn.h"
|
#include "support/profile.h"
|
#include "support/profile.h"
|
|
|
/* Print out basic blocks */
|
/* Print out basic blocks */
|
Line 44... |
Line 46... |
else printf ("*\n");
|
else printf ("*\n");
|
|
|
if (f->bb[i].insn) print_insns (f->bb[i].insn, f->bb[i].ninsn, 0);
|
if (f->bb[i].insn) print_insns (f->bb[i].insn, f->bb[i].ninsn, 0);
|
}
|
}
|
printf ("\n");
|
printf ("\n");
|
|
fflush (stdout);
|
}
|
}
|
|
|
/* Copies src basic block into destination */
|
/* Copies src basic block into destination */
|
cuc_bb *cpy_bb (cuc_bb *dest, cuc_bb *src)
|
cuc_bb *cpy_bb (cuc_bb *dest, cuc_bb *src)
|
{
|
{
|
int i;
|
int i, j;
|
|
assert (dest != src);
|
*dest = *src;
|
*dest = *src;
|
assert (dest->insn = malloc (sizeof (cuc_insn) * src->ninsn));
|
assert (dest->insn = malloc (sizeof (cuc_insn) * src->ninsn));
|
for (i = 0; i < src->ninsn; i++)
|
for (i = 0; i < src->ninsn; i++)
|
dest->insn[i] = src->insn[i];
|
dest->insn[i] = src->insn[i];
|
if (src->ntim) {
|
if (src->ntim) {
|
assert (dest->tim = malloc (sizeof (cuc_timings) * src->ntim));
|
assert (dest->tim = malloc (sizeof (cuc_timings) * src->ntim));
|
for (i = 0; i < src->ntim; i++) dest->tim[i] = src->tim[i];
|
for (i = 0; i < src->ntim; i++) {
|
|
dest->tim[i] = src->tim[i];
|
|
if (src->tim[i].nshared) {
|
|
assert (dest->tim[i].shared = malloc (sizeof (int) * src->tim[i].nshared));
|
|
for (j = 0; j < src->tim[i].nshared; j++)
|
|
dest->tim[i].shared[j] = src->tim[i].shared[j];
|
|
}
|
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Duplicates function */
|
/* Duplicates function */
|
cuc_func *dup_func (cuc_func *f)
|
cuc_func *dup_func (cuc_func *f)
|
Line 90... |
Line 101... |
int b, i;
|
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++)
|
dispose_list (&f->bb[b].insn[i].dep);
|
dispose_list (&f->bb[b].insn[i].dep);
|
if (f->bb[b].insn) free (f->bb[b].insn);
|
if (f->bb[b].insn) free (f->bb[b].insn);
|
|
for (i = 0; i < f->bb[b].ntim; i++)
|
|
if (f->bb[b].tim[i].nshared && f->bb[b].tim[i].shared)
|
|
free (f->bb[b].tim[i].shared);
|
if (f->bb[b].tim && f->bb[b].ntim) free (f->bb[b].tim);
|
if (f->bb[b].tim && f->bb[b].ntim) free (f->bb[b].tim);
|
}
|
}
|
free (f);
|
free (f);
|
}
|
}
|
|
|
Line 310... |
Line 324... |
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;
|
}
|
}
|
|
|
|
/* Relocate instructions */
|
for (j = MAX_REGS - 1; j < f->bb[i].ninsn; j++) {
|
for (j = MAX_REGS - 1; j < f->bb[i].ninsn; j++) {
|
f->bb[i].insn[j] = insn[f->bb[i].first + j - (MAX_REGS - 1)];
|
f->bb[i].insn[j] = insn[f->bb[i].first + j - (MAX_REGS - 1)];
|
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 (f->bb[i].insn[j].opt[k] & OPT_REF) {
|
int b1;
|
int b1;
|
Line 324... |
Line 340... |
f->bb[i].insn[j].op[k] = REF (b1, f->bb[i].insn[j].op[k] - f->bb[b1].first + MAX_REGS - 1);
|
f->bb[i].insn[j].op[k] = REF (b1, f->bb[i].insn[j].op[k] - f->bb[b1].first + MAX_REGS - 1);
|
}
|
}
|
if (f->bb[i].insn[j].type & IT_MEMORY) f->bb[i].nmemory++;
|
if (f->bb[i].insn[j].type & IT_MEMORY) f->bb[i].nmemory++;
|
}
|
}
|
}
|
}
|
|
|
|
/* We do a quick check if there are some anomalies */
|
|
for (i = 0; i < f->num_bb; i++)
|
|
for (j = 0; j < f->bb[i].ninsn; j++)
|
|
for (k = 0; k < MAX_OPERANDS; k++)
|
|
if (f->bb[i].insn[j].opt[k] & OPT_REF) {
|
|
int t = f->bb[i].insn[j].op[k];
|
|
assert (REF_I (t) < f->bb[REF_BB(t)].ninsn);
|
|
}
|
}
|
}
|
|
|
/* type == 0; keep predecessor condition
|
/* type == 0; keep predecessor condition
|
* type == 1; keep successor condition
|
* type == 1; keep successor condition
|
* type == 2; join loop unrolled blocks */
|
* type == 2; join loop unrolled blocks */
|
Line 335... |
Line 360... |
{
|
{
|
int i, j, k, add, ninsn, add_cond = 0;
|
int i, j, k, add, ninsn, add_cond = 0;
|
unsigned long cond_op, cond_opt;
|
unsigned long cond_op, cond_opt;
|
cuc_insn *insn;
|
cuc_insn *insn;
|
|
|
//printf ("%i <= %i+%i (%i)\n", pred, pred, succ, type);
|
cucdebug (3, "%x <= %x+%x (%i)\n", pred, pred, succ, type);
|
//printf ("%i %i\n", f->bb[pred].ninsn, f->bb[succ].ninsn);
|
cucdebug (3, "%x %x\n", f->bb[pred].ninsn, f->bb[succ].ninsn);
|
|
if (cuc_debug >= 3) fflush (stdout);
|
|
|
add = f->bb[pred].ninsn;
|
add = f->bb[pred].ninsn;
|
if (f->bb[pred].ninsn <= 0
|
if (f->bb[pred].ninsn <= 0
|
|| !(f->bb[pred].insn[f->bb[pred].ninsn - 1].type & IT_BRANCH)) type = 1;
|
|| !(f->bb[pred].insn[f->bb[pred].ninsn - 1].type & IT_BRANCH)) type = 1;
|
if (type == 0 && f->bb[succ].prev[0] == f->bb[succ].next[0]) add_cond = 1;
|
if (type == 0 && f->bb[succ].prev[0] == f->bb[succ].next[0]) add_cond = 1;
|
Line 526... |
Line 552... |
3. pred & succ share common successor
|
3. pred & succ share common successor
|
4. optional succ's second successor */
|
4. optional succ's second successor */
|
for (i = 0; i < f->num_bb; i++) if (!(f->bb[i].type & BB_DEAD))
|
for (i = 0; i < f->num_bb; i++) if (!(f->bb[i].type & BB_DEAD))
|
if (f->bb[i].prev[0] >= 0 && f->bb[i].prev[1] < 0) { /* one predecessor */
|
if (f->bb[i].prev[0] >= 0 && f->bb[i].prev[1] < 0) { /* one predecessor */
|
int p = f->bb[i].prev[0];
|
int p = f->bb[i].prev[0];
|
if (f->bb[p].next[0] == i && f->bb[p].next[1] == f->bb[p].next[1])
|
if (f->bb[p].next[0] == i && f->bb[p].next[1] == f->bb[p].next[1]) {
|
join_bb (f, f->bb[i].prev[0], i, 2);
|
join_bb (f, f->bb[i].prev[0], i, 2);
|
goto remove_lrbb;
|
goto remove_lrbb;
|
}
|
}
|
|
}
|
#endif
|
#endif
|
}
|
}
|
|
|
/* Removes BBs marked as dead */
|
/* Removes BBs marked as dead */
|
void remove_dead_bb (cuc_func *f)
|
void remove_dead_bb (cuc_func *f)
|
Line 750... |
Line 777... |
/* Mark them volatile, so optimizer does not remove them */
|
/* Mark them volatile, so optimizer does not remove them */
|
if (t >= 0) f->bb[REF_BB(t)].insn[REF_I(t)].type |= IT_OUTPUT;
|
if (t >= 0) f->bb[REF_BB(t)].insn[REF_I(t)].type |= IT_OUTPUT;
|
}
|
}
|
}
|
}
|
|
|
|
/* split the BB, based on the group numbers in .tmp */
|
|
void expand_bb (cuc_func *f, int b)
|
|
{
|
|
int n = f->num_bb;
|
|
int mg = 0;
|
|
int b1, i, j;
|
|
|
|
for (i = 0; i < f->bb[b].ninsn; i++)
|
|
if (f->bb[b].insn[i].tmp > mg) mg = f->bb[b].insn[i].tmp;
|
|
|
|
/* Create copies */
|
|
for (b1 = 1; b1 <= mg; b1++) {
|
|
assert (f->num_bb < MAX_BB);
|
|
cpy_bb (&f->bb[f->num_bb], &f->bb[b]);
|
|
f->num_bb++;
|
|
}
|
|
|
|
/* Relocate */
|
|
for (b1 = 0; b1 < f->num_bb; b1++)
|
|
for (i = 0; i < f->bb[b1].ninsn; i++) {
|
|
dep_list *d = f->bb[b1].insn[i].dep;
|
|
for (j = 0; j < MAX_OPERANDS; j++)
|
|
if (f->bb[b1].insn[i].opt[j] & OPT_REF) {
|
|
int t = f->bb[b1].insn[i].op[j];
|
|
if (REF_BB(t) == b && f->INSN(t).tmp != 0)
|
|
f->bb[b1].insn[i].op[j] = REF (n + f->INSN(t).tmp - 1, REF_I(t));
|
|
}
|
|
while (d) {
|
|
if (REF_BB (d->ref) == b && f->INSN(d->ref).tmp != 0)
|
|
d->ref = REF (n + f->INSN(d->ref).tmp - 1, REF_I(d->ref));
|
|
d = d->next;
|
|
}
|
|
}
|
|
|
|
/* Delete unused instructions */
|
|
for (j = 0; j <= mg; j++) {
|
|
if (j == 0) b1 = b;
|
|
else b1 = n + j - 1;
|
|
for (i = 0; i < f->bb[b1].ninsn; i++) {
|
|
if (f->bb[b1].insn[i].tmp != j)
|
|
change_insn_type (&f->bb[b1].insn[i], II_NOP);
|
|
f->bb[b1].insn[i].tmp = 0;
|
|
}
|
|
if (j < mg) {
|
|
f->bb[b1].next[0] = n + j;
|
|
f->bb[b1].next[1] = -1;
|
|
f->bb[n + j].prev[0] = b1;
|
|
f->bb[n + j].prev[1] = -1;
|
|
} else {
|
|
i = f->bb[b1].next[0];
|
|
f->bb[n + j].prev[0] = j == 1 ? b : b1 - 1;
|
|
f->bb[n + j].prev[1] = -1;
|
|
if (i >= 0) {
|
|
if (f->bb[i].prev[0] == b) f->bb[i].prev[0] = b1;
|
|
if (f->bb[i].prev[1] == b) f->bb[i].prev[1] = b1;
|
|
}
|
|
i = f->bb[b1].next[1];
|
|
if (i >= 0) {
|
|
if (f->bb[i].prev[0] == b) f->bb[i].prev[0] = b1;
|
|
if (f->bb[i].prev[1] == b) f->bb[i].prev[1] = b1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
/* Scans sequence of BBs and set bb[].cnt */
|
/* Scans sequence of BBs and set bb[].cnt */
|
void generate_bb_seq (cuc_func *f, char *mp_filename, char *bb_filename)
|
void generate_bb_seq (cuc_func *f, char *mp_filename, char *bb_filename)
|
{
|
{
|
FILE *fi, *fo;
|
FILE *fi, *fo;
|
struct mprofentry_struct *buf;
|
struct mprofentry_struct *buf;
|
Line 762... |
Line 854... |
unsigned long *bb_end;
|
unsigned long *bb_end;
|
int b, i, r;
|
int b, i, r;
|
int curbb, prevbb = -1;
|
int curbb, prevbb = -1;
|
unsigned long addr = -1;
|
unsigned long addr = -1;
|
unsigned long prevaddr = -1;
|
unsigned long prevaddr = -1;
|
|
int mssum = 0;
|
|
int mlsum = 0;
|
|
int mscnt = 0;
|
|
int mlcnt = 0;
|
|
|
assert (fi = fopen (mp_filename, "rb"));
|
assert (fi = fopen (mp_filename, "rb"));
|
assert (fo = fopen (bb_filename, "wb+"));
|
assert (fo = fopen (bb_filename, "wb+"));
|
|
|
assert (bb_start = (unsigned long *) malloc (sizeof (unsigned long) * f->num_bb));
|
assert (bb_start = (unsigned long *) malloc (sizeof (unsigned long) * f->num_bb));
|
Line 803... |
Line 899... |
fwrite (&curbb, sizeof (unsigned long), 1, fo);
|
fwrite (&curbb, sizeof (unsigned long), 1, fo);
|
//printf (" [%i] ", curbb);
|
//printf (" [%i] ", curbb);
|
f->bb[curbb].cnt++;
|
f->bb[curbb].cnt++;
|
prevbb = curbb;
|
prevbb = curbb;
|
}
|
}
|
|
} else {
|
|
if (verify_memoryarea(buf[i].addr))
|
|
if (buf[i].type & MPROF_WRITE) mscnt++, mssum += cur_area->delayw;
|
|
else mlcnt++, mlsum += cur_area->delayw;
|
}
|
}
|
}
|
}
|
//printf ("\n");
|
//printf ("\n");
|
} while (r == bufsize);
|
} while (r == bufsize);
|
//printf ("\n");
|
//printf ("\n");
|
|
|
|
runtime.cuc.mdelay[0] = (1. * mlsum) / mlcnt;
|
|
runtime.cuc.mdelay[1] = (1. * mlsum) / mlcnt;
|
|
runtime.cuc.mdelay[2] = runtime.cuc.mdelay[3] = 1;
|
f->num_runs = f->bb[0].cnt;
|
f->num_runs = f->bb[0].cnt;
|
fclose (fi);
|
fclose (fi);
|
fclose (fo);
|
fclose (fo);
|
free (buf);
|
free (buf);
|
free (bb_end);
|
free (bb_end);
|
Line 983... |
Line 1086... |
|
|
//print_cuc_bb (n, "unroll1");
|
//print_cuc_bb (n, "unroll1");
|
/* repair BB after loop, to point back to latest artificial BB */
|
/* repair BB after loop, to point back to latest artificial BB */
|
b1 = n->bb[prevart_b].next[0];
|
b1 = n->bb[prevart_b].next[0];
|
if (b1 >= 0) {
|
if (b1 >= 0) {
|
if (n->bb[b1].prev[0] == b) n->bb[b1].prev[0] = b1;
|
if (n->bb[b1].prev[0] == b) n->bb[b1].prev[0] = prevart_b;
|
else if (n->bb[b1].prev[1] == b) n->bb[b1].prev[1] = b1;
|
else if (n->bb[b1].prev[1] == b) n->bb[b1].prev[1] = prevart_b;
|
else assert (0);
|
else assert (0);
|
}
|
}
|
|
|
/* Relink back to start of the loop */
|
/* Relink back to start of the loop */
|
/* Set predecessor's successor */
|
/* Set predecessor's successor */
|
Line 1125... |
Line 1228... |
|
|
//print_cuc_bb (n, "preroll1");
|
//print_cuc_bb (n, "preroll1");
|
/* repair BB after loop, to point back to latest artificial BB */
|
/* repair BB after loop, to point back to latest artificial BB */
|
b1 = n->bb[prevart_b].next[0];
|
b1 = n->bb[prevart_b].next[0];
|
if (b1 >= 0) {
|
if (b1 >= 0) {
|
if (n->bb[b1].prev[0] == b) n->bb[b1].prev[0] = b1;
|
if (n->bb[b1].prev[0] == b) n->bb[b1].prev[0] = prevart_b;
|
else if (n->bb[b1].prev[1] == b) n->bb[b1].prev[1] = b1;
|
else if (n->bb[b1].prev[1] == b) n->bb[b1].prev[1] = prevart_b;
|
else assert (0);
|
else assert (0);
|
}
|
}
|
|
|
/* Relink to itself */
|
/* Relink to itself */
|
/* Set predecessor's successor */
|
/* Set predecessor's successor */
|
Line 1176... |
Line 1279... |
n = unroll_loop (t, b1, unroll);
|
n = unroll_loop (t, b1, unroll);
|
free_func (t);
|
free_func (t);
|
} else n = t;
|
} else n = t;
|
} else {
|
} else {
|
b1 = b;
|
b1 = b;
|
if (unroll > 1)
|
if (unroll > 1) n = unroll_loop (f, b1, unroll);
|
n = unroll_loop (f, b1, unroll);
|
else return dup_func (f);
|
else n = dup_func (n);
|
|
}
|
}
|
|
|
/* Assign new count to functions */
|
/* Assign new counts to functions */
|
assert (counts = (int *)malloc (sizeof (int) * (preroll - 1 + unroll)));
|
assert (counts = (int *)malloc (sizeof (int) * (preroll - 1 + unroll)));
|
count_bb_seq (n, b, bb_filename, counts, preroll, unroll);
|
count_bb_seq (n, b, bb_filename, counts, preroll, unroll);
|
for (i = 0; i < preroll - 1 + unroll; i++) {
|
for (i = 0; i < preroll - 1 + unroll; i++) {
|
if (i == 0) b1 = b;
|
if (i == 0) b1 = b;
|
else b1 = f->num_bb + (i - 1) * 2;
|
else b1 = f->num_bb + (i - 1) * 2;
|