OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc3/] [or1ksim/] [cuc/] [bb.c] - Blame information for rev 906

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 879 markom
/* bb.c -- OpenRISC Custom Unit Compiler, Basic Block handling
2
 *    Copyright (C) 2002 Marko Mlinar, markom@opencores.org
3
 *
4
 *    This file is part of OpenRISC 1000 Architectural Simulator.
5
 *
6
 *    This program is free software; you can redistribute it and/or modify
7
 *    it under the terms of the GNU General Public License as published by
8
 *    the Free Software Foundation; either version 2 of the License, or
9
 *    (at your option) any later version.
10
 *
11
 *    This program is distributed in the hope that it will be useful,
12
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *    GNU General Public License for more details.
15
 *
16
 *    You should have received a copy of the GNU General Public License
17
 *    along with this program; if not, write to the Free Software
18
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <stdarg.h>
23
#include <assert.h>
24 897 markom
#include "sim-config.h"
25
#include "abstract.h"
26 879 markom
#include "cuc.h"
27
#include "insn.h"
28
#include "support/profile.h"
29
 
30
/* Print out basic blocks */
31
void print_cuc_bb (cuc_func *f, char *s)
32
{
33
  int i;
34
  printf ("------- %s -------\n", s);
35
  for (i = 0; i < f->num_bb; i++) {
36
    if (f->bb[i].insn) printf ("\n---- BB%-2x * %x ---- ", i, f->bb[i].cnt);
37
    else printf ("BB%-2x: %4x-%-4x", i, f->bb[i].first, f->bb[i].last);
38
    printf (" type %02x tmp %i ", f->bb[i].type, f->bb[i].tmp);
39
    if (f->bb[i].next[0] >= 0) printf ("next %2x ", f->bb[i].next[0]);
40
    else printf ("next * ");
41
    if (f->bb[i].next[1] >= 0) printf ("%2x ", f->bb[i].next[1]);
42
    else printf ("* ");
43
    if (f->bb[i].prev[0] >= 0) printf ("prev %2x ", f->bb[i].prev[0]);
44
    else printf ("prev * ");
45
    if (f->bb[i].prev[1] >= 0) printf ("%2x\n", f->bb[i].prev[1]);
46
    else printf ("*\n");
47
 
48
    if (f->bb[i].insn) print_insns (f->bb[i].insn, f->bb[i].ninsn, 0);
49
  }
50
  printf ("\n");
51 897 markom
  fflush (stdout);
52 879 markom
}
53
 
54
/* Copies src basic block into destination */
55
cuc_bb *cpy_bb (cuc_bb *dest, cuc_bb *src)
56
{
57 897 markom
  int i, j;
58
  assert (dest != src);
59 879 markom
  *dest = *src;
60
  assert (dest->insn = malloc (sizeof (cuc_insn) * src->ninsn));
61
  for (i = 0; i < src->ninsn; i++)
62
    dest->insn[i] = src->insn[i];
63
  if (src->ntim) {
64
    assert (dest->tim = malloc (sizeof (cuc_timings) * src->ntim));
65 897 markom
    for (i = 0; i < src->ntim; i++) {
66
      dest->tim[i] = src->tim[i];
67
      if (src->tim[i].nshared) {
68
        assert (dest->tim[i].shared = malloc (sizeof (int) * src->tim[i].nshared));
69
        for (j = 0; j < src->tim[i].nshared; j++)
70
          dest->tim[i].shared[j] = src->tim[i].shared[j];
71
      }
72
    }
73 879 markom
  }
74
}
75
 
76
/* Duplicates function */
77
cuc_func *dup_func (cuc_func *f)
78
{
79
  cuc_func *n = (cuc_func *) malloc (sizeof (cuc_func));
80
  int b, i;
81
  for (b = 0; b < f->num_bb; b++) cpy_bb (&n->bb[b], &f->bb[b]);
82
  n->num_bb = f->num_bb;
83
  assert (n->init_bb_reloc = (int *)malloc (sizeof (int) * f->num_init_bb));
84
  for (b = 0; b < f->num_init_bb; b++) n->init_bb_reloc[b] = f->init_bb_reloc[b];
85
  n->num_init_bb = f->num_init_bb;
86
  for (i = 0; i < MAX_REGS; i++) n->saved_regs[i] = f->saved_regs[i];
87
  n->start_addr = f->start_addr;
88
  n->end_addr = f->end_addr;
89
  n->orig_time = f->orig_time;
90
  n->nmsched = f->nmsched;
91
  for (i = 0; i < f->nmsched; i++) {
92
    n->msched[i] = f->msched[i];
93
    n->mtype[i] = f->mtype[i];
94
  }
95 906 markom
  n->nfdeps = f->nfdeps;
96
  if (f->nfdeps) {
97
    f->fdeps = (cuc_func **) malloc (sizeof (cuc_func *) * f->nfdeps);
98
    for (i = 0; i < f->nfdeps; i++) n->fdeps[i] = f->fdeps[i];
99
  }
100 879 markom
  return n;
101
}
102
 
103
/* Releases memory allocated by function */
104
void free_func (cuc_func *f)
105
{
106
  int b, i;
107
  for (b = 0; b < f->num_bb; b++) {
108
    for (i = 0; i < f->bb[b].ninsn; i++)
109
      dispose_list (&f->bb[b].insn[i].dep);
110
    if (f->bb[b].insn) free (f->bb[b].insn);
111 897 markom
    for (i = 0; i < f->bb[b].ntim; i++)
112
      if (f->bb[b].tim[i].nshared && f->bb[b].tim[i].shared)
113
        free (f->bb[b].tim[i].shared);
114 879 markom
    if (f->bb[b].tim && f->bb[b].ntim) free (f->bb[b].tim);
115
  }
116
  free (f);
117
}
118
 
119
 
120
/* Recalculates last_used_reg */
121
void recalc_last_used_reg (cuc_func *f, int b)
122
{
123
  int i;
124
  cuc_bb *bb = &f->bb[b];
125
 
126
  /* rebuild last used reg array */
127
  if (bb->insn[0].index == II_LRBB) bb->last_used_reg[LRBB_REG] = 0;
128
  else bb->last_used_reg[LRBB_REG] = -1;
129
 
130
  for (i = 1; i < MAX_REGS - 1; i++) bb->last_used_reg[i] = -1;
131
 
132
    /* Create references */
133
  for (i = 0; i < bb->ninsn; i++) {
134
    int k;
135
    /* Now check for destination operand(s) */
136
    for (k = 0; k < MAX_OPERANDS; k++) if (bb->insn[i].opt[k] & OPT_DEST)
137
      if ((bb->insn[i].opt[k] & ~OPT_DEST) == OPT_REGISTER
138
        && (int)bb->insn[i].op[k] >= 0) {
139
        bb->last_used_reg[bb->insn[i].op[k]] = REF (b, i);
140
      }
141
  }
142
}
143
 
144
/* Set the BB limits */
145
void detect_bb (cuc_func *f)
146
{
147
  int i, j, end_bb = 0, eb = 0;
148
 
149
  /* Mark block starts/ends */
150
  for (i = 0; i < num_insn; i++) {
151
    if (end_bb) insn[i].type |= IT_BBSTART;
152
    end_bb = 0;
153
    if (insn[i].type & IT_BRANCH) {
154
      int jt = insn[i].op[0];
155
      insn[i].type |= IT_BBEND;
156
      end_bb = 1;
157
      if (jt < 0 || jt >= num_insn) {
158
        fprintf (stderr, "Instruction #%i:Jump out of function '%s'.\n", i, insn[i].disasm);
159
        exit (1);
160
      }
161
      if (jt > 0) insn[jt - 1].type |= IT_BBEND;
162
      insn[jt].type |= IT_BBSTART;
163
    }
164
  }
165
 
166
  /* Initialize bb array */
167
  insn[0].type |= IT_BBSTART;
168
  insn[num_insn - 1].type |= IT_BBEND;
169
  f->num_bb = 0;
170
  for (i = 0; i < num_insn; i++) {
171
    if (insn[i].type & IT_BBSTART) {
172
      f->bb[f->num_bb].first = i;
173
      f->bb[f->num_bb].cnt = 0;
174
    }
175
    /* Determine repetitions of a loop */
176
    if (insn[i].type & IT_BBEND) {
177
      f->bb[f->num_bb].type = 0;
178
      f->bb[f->num_bb].last = i;
179
      f->bb[f->num_bb].next[0] = f->bb[f->num_bb].next[1] = -1;
180
      f->bb[f->num_bb].tmp = 0;
181
      f->bb[f->num_bb].ntim = 0;
182
      f->num_bb++;
183
      assert (f->num_bb < MAX_BB);
184
    }
185
  }
186 883 markom
  if (cuc_debug >= 3) print_cuc_bb (f, "AFTER_INIT");
187 879 markom
 
188
  /* Build forward connections between BBs */
189
  for (i = 0; i < f->num_bb; i++)
190
    if (insn[f->bb[i].last].type & IT_BRANCH) {
191
      int j;
192
      assert (insn[f->bb[i].last].index == II_BF);
193
      /* Find block this instruction jumps to */
194
      for (j = 0; j < f->num_bb; j++)
195
        if (f->bb[j].first == insn[f->bb[i].last].op[0]) break;
196
      assert (j < f->num_bb);
197
 
198
      /* Convert the jump address to BB link */
199
      insn[f->bb[i].last].op[0] = j; insn[f->bb[i].last].opt[0] = OPT_BB;
200
 
201
      /* Make a link */
202
      f->bb[i].next[0] = j;
203
      if (++f->bb[j].tmp > 2) eb++;
204
      f->bb[i].next[1] = i + 1;
205
      if (++f->bb[i + 1].tmp > 2) eb++;
206
    } else if (f->bb[i].last == num_insn - 1) { /* Last instruction doesn't have to do anything */
207
      f->bb[i].type |= BB_END;
208
    } else {
209
      f->bb[i].next[0] = i + 1;
210
      if (++f->bb[i + 1].tmp > 2) eb++;
211
    }
212
 
213 883 markom
  if (cuc_debug >= 3) print_cuc_bb (f, "AFTER_NEXT");
214 879 markom
 
215
  /* Build backward connections, but first insert artificial blocks
216
   * to handle more than 2 connections */
217 883 markom
  cucdebug (6, "artificial %i %i\n", f->num_bb, eb);
218 879 markom
  end_bb = f->num_bb + eb;
219
  for (i = f->num_bb - 1; i >= 0; i--) {
220
    j = f->bb[i].tmp;
221
    if (f->bb[i].tmp > 2) f->bb[i].tmp = -f->bb[i].tmp;
222
    f->bb[--end_bb] = f->bb[i];
223
    reloc[i] = end_bb;
224
    while (j-- > 2) {
225
      f->bb[--end_bb].first = f->bb[i].first;
226
      f->bb[end_bb].last = -1;
227
      f->bb[end_bb].next[0] = -1;
228
      f->bb[end_bb].next[1] = -1;
229
      f->bb[end_bb].tmp = 0;
230
      f->bb[end_bb].cnt = f->bb[i].cnt;
231
      f->bb[end_bb].ntim = 0;
232
    }
233
  }
234
  f->num_bb += eb;
235
 
236
  /* relocate jump instructions */
237
  for (i = 0; i < num_insn; i++)
238
    for (j = 0; j < MAX_OPERANDS; j++)
239
      if (insn[i].opt[j] & OPT_BB)
240
        insn[i].op[j] = reloc[insn[i].op[j]];
241 883 markom
  if (cuc_debug >= 3) print_cuc_bb (f, "AFTER_INSERT-reloc");
242 879 markom
  for (i = 0; i < f->num_bb; i++) {
243
    if (f->bb[i].next[0] >= 0) {
244
      int t = reloc[f->bb[i].next[0]];
245
      if (f->bb[t].tmp < 0) {
246
        f->bb[t].tmp = -f->bb[t].tmp;
247
        t -= f->bb[t].tmp - 2;
248
      } else if (f->bb[t].tmp > 2) t -= f->bb[t].tmp-- - 2;
249
      f->bb[i].next[0] = t;
250
    }
251
    if (f->bb[i].next[1] >= 0) {
252
      int t = reloc[f->bb[i].next[1]];
253
      if (f->bb[t].tmp < 0) {
254
        f->bb[t].tmp = -f->bb[t].tmp;
255
        t -= f->bb[t].tmp - 2;
256
      } else if (f->bb[t].tmp > 2) t -= f->bb[t].tmp-- - 2;
257
      f->bb[i].next[1] = t;
258
    }
259
    /* artificial blocks do not have relocations, hardcode them */
260
    if (f->bb[i].last < 0) f->bb[i].next[0] = i + 1;
261
  }
262 883 markom
  if (cuc_debug >= 3) print_cuc_bb (f, "AFTER_INSERT");
263 879 markom
 
264
  /* Uncoditional branched do not continue to next block */
265
  for (i = 0; i < f->num_bb; i++) {
266
    cuc_insn *ii;
267
    if (f->bb[i].last < 0) continue;
268
    ii = &insn[f->bb[i].last];
269
    /* Unconditional branch? */
270
    if (ii->type & IT_BRANCH && ii->opt[1] & OPT_CONST) {
271
      change_insn_type (ii, II_NOP);
272
      if (f->bb[i].next[1] == i + 1) f->bb[i].next[0] = f->bb[i].next[1];
273
      f->bb[i].next[1] = -1;
274
    }
275
  }
276 883 markom
  if (cuc_debug >= 3) print_cuc_bb (f, "AFTER_UNCOND_JUMP");
277 879 markom
 
278
  /* Add backward connections */
279
  for (i = 0; i < f->num_bb; i++)
280
    f->bb[i].prev[0] = f->bb[i].prev[1] = -1;
281
 
282
  for (i = 0; i < f->num_bb; i++) {
283
    if (f->bb[i].next[0] >= 0) {
284
      int t = f->bb[i].next[0];
285
      if (f->bb[t].prev[0] < 0) f->bb[t].prev[0] = i;
286
      else {
287
        assert (f->bb[t].prev[1] < 0);
288
        f->bb[t].prev[1] = i;
289
      }
290
    }
291
    if (f->bb[i].next[1] >= 0) {
292
      int t = f->bb[i].next[1];
293
      if (f->bb[t].prev[0] < 0) f->bb[t].prev[0] = i;
294
      else {
295
        assert (f->bb[t].prev[1] < 0);
296
        f->bb[t].prev[1] = i;
297
      }
298
    }
299
  }
300 883 markom
  if (cuc_debug >= 3) print_cuc_bb (f, "AFTER_PREV");
301 879 markom
}
302
 
303 905 markom
/* We do a quick check if there are some anomalies with references */
304
void cuc_check (cuc_func *f)
305
{
306
  int i, j, k;
307
  for (i = 0; i < f->num_bb; i++) {
308
    if (!f->bb[i].insn && f->bb[i].ninsn) {
309
      printf ("Anomaly detected at BB%x (insn NULL)\n", i);
310
      print_cuc_bb (f, "ANOMALY");
311
      exit (1);
312
    }
313
    for (j = 0; j < f->bb[i].ninsn; j++)
314
      for (k = 0; k < MAX_OPERANDS; k++)
315
        if (f->bb[i].insn[j].opt[k] & OPT_REF) {
316
          int t = f->bb[i].insn[j].op[k];
317
          if (REF_BB(t) >= f->num_bb || REF_I (t) >= f->bb[REF_BB(t)].ninsn) {
318
            printf ("Anomaly detected at %x.%x[%i]\n", i, j, k);
319
            print_cuc_bb (f, "ANOMALY");
320
            exit (1);
321
          }
322
        }
323
  }
324
}
325
 
326 879 markom
/* Build basic blocks */
327
void build_bb (cuc_func *f)
328
{
329
  int i, j, k;
330
  for (i = 0; i < f->num_bb; i++) {
331
    if (f->bb[i].last < 0) f->bb[i].ninsn = MAX_REGS - 1;
332
    else f->bb[i].ninsn = f->bb[i].last - f->bb[i].first + 1 + MAX_REGS - 1;
333
    assert (f->bb[i].ninsn >= MAX_REGS - 1);
334
    f->bb[i].insn = (cuc_insn *) malloc (sizeof (cuc_insn) * f->bb[i].ninsn);
335
    assert (f->bb[i].insn);
336
    f->bb[i].nmemory = 0;
337
    f->bb[i].unrolled = 1;
338
 
339
    /* Save space for conditional moves, exclude r0, place lrbb instead */
340
    change_insn_type (&f->bb[i].insn[0], II_LRBB);
341
    strcpy (f->bb[i].insn[0].disasm, "lrbb");
342
    f->bb[i].insn[0].type = IT_UNUSED;
343
    f->bb[i].insn[0].dep = NULL;
344
    f->bb[i].insn[0].op[0] = LRBB_REG; f->bb[i].insn[0].opt[0] = OPT_REGISTER | OPT_DEST;
345
    f->bb[i].insn[0].opt[1] = OPT_LRBB;
346
    f->bb[i].insn[0].opt[2] = f->bb[i].insn[0].opt[3] = OPT_NONE;
347
    for (j = 1; j < MAX_REGS - 1; j++) {
348
      change_insn_type (&f->bb[i].insn[j], II_CMOV);
349
      strcpy (f->bb[i].insn[j].disasm, "cmov");
350
      f->bb[i].insn[j].type = 0;
351
      f->bb[i].insn[j].dep = NULL;
352
      f->bb[i].insn[j].opt[0] = f->bb[i].insn[j].opt[1] = f->bb[i].insn[j].opt[2] = OPT_REGISTER;
353
      f->bb[i].insn[j].opt[0] |= OPT_DEST;
354
      f->bb[i].insn[j].op[0] = f->bb[i].insn[j].op[1] = f->bb[i].insn[j].op[2] = j;
355
      f->bb[i].insn[j].op[3] = LRBB_REG; f->bb[i].insn[j].opt[3] = OPT_REGISTER;
356
    }
357 897 markom
 
358
    /* Relocate instructions */
359 879 markom
    for (j = MAX_REGS - 1; j < f->bb[i].ninsn; j++) {
360
      f->bb[i].insn[j] = insn[f->bb[i].first + j - (MAX_REGS - 1)];
361
      for (k = 0; k < MAX_OPERANDS; k++)
362
        if (f->bb[i].insn[j].opt[k] & OPT_REF) {
363
          int b1;
364
          for (b1 = 0; b1 < i; b1++)
365 898 markom
            if (f->bb[b1].first <= (signed) f->bb[i].insn[j].op[k]
366
              && (signed)f->bb[i].insn[j].op[k] <= f->bb[b1].last) break;
367 879 markom
          assert (b1 < f->num_bb);
368
          f->bb[i].insn[j].op[k] = REF (b1, f->bb[i].insn[j].op[k] - f->bb[b1].first + MAX_REGS - 1);
369
        }
370
      if (f->bb[i].insn[j].type & IT_MEMORY) f->bb[i].nmemory++;
371
    }
372
  }
373 905 markom
  cuc_check (f);
374 879 markom
}
375
 
376
/* type == 0; keep predecessor condition
377
 * type == 1; keep successor condition
378
 * type == 2; join loop unrolled blocks */
379
static void join_bb (cuc_func *f, int pred, int succ, int type)
380
{
381 905 markom
  int i, j, k, n1, n2, ninsn, add_cond = 0;
382 879 markom
  unsigned long cond_op, cond_opt;
383
  cuc_insn *insn;
384
 
385 905 markom
  if (cuc_debug) cuc_check (f);
386 897 markom
  cucdebug (3, "%x <= %x+%x (%i)\n", pred, pred, succ, type);
387
  cucdebug (3, "%x %x\n", f->bb[pred].ninsn, f->bb[succ].ninsn);
388
  if (cuc_debug >= 3) fflush (stdout);
389 879 markom
 
390 905 markom
  n1 = f->bb[pred].ninsn;
391
  n2 = f->bb[succ].ninsn;
392
  if (n1 <= 0
393
   || !(f->bb[pred].insn[n1 - 1].type & IT_BRANCH)) type = 1;
394 879 markom
  if (type == 0 && f->bb[succ].prev[0] == f->bb[succ].next[0]) add_cond = 1;
395 905 markom
  if (type == 2) add_cond = 1;
396
 
397
  assert (f->bb[pred].next[0] == f->bb[succ].next[0] || type != 2); /* not supported */
398 879 markom
 
399 905 markom
  ninsn = n1 + n2 + (type == 1 ? 0 : 1) + (add_cond ? MAX_REGS : 0);
400 879 markom
 
401
  insn = (cuc_insn *) malloc (ninsn * sizeof (cuc_insn));
402 905 markom
  for (i = 0; i < n1; i++) insn[i] = f->bb[pred].insn[i];
403
  /* when type == 0, we move the last (jump) instruction to the end */
404 879 markom
  if (type == 0 || type == 2) {
405 905 markom
    /* Move first branch instruction to the end */
406
    assert (insn[n1 - 1].type & IT_BRANCH);
407
    insn[ninsn - 1] = insn[n1 - 1];
408
    cond_op = insn[n1 - 1].op[1];
409
    cond_opt = insn[n1 - 1].opt[1];
410
 
411
    /* Remove old branch */
412
    change_insn_type (&insn[n1 - 1], II_NOP);
413 879 markom
  }
414
  /* Copy second block */
415 905 markom
  for (i = 0; i < n2; i++) insn[i + n1] = f->bb[succ].insn[i];
416 902 markom
 
417
  /* and when type == 2, we may need to add sfor instruction, to quit when either is true */
418
  if (type == 2) {
419 905 markom
    /* Move second branch instruction to the end */
420
    if (insn[n1 + n2 - 1].type & IT_BRANCH) {
421
      insn[ninsn - 1] = insn[n1 + n2 - 1];
422
 
423
      /* Use conditional from cmov FLAG_REG, c_p, c_s, c_p */
424
      insn[ninsn - 1].op[1] = REF (pred, n1 + n2 + FLAG_REG); insn[ninsn - 1].opt[1] = OPT_REF;
425
 
426
      /* Remove old one */
427
      change_insn_type (&insn[n1 + n2 - 1], II_NOP);
428
    } else change_insn_type (&insn[ninsn - 1], II_NOP); /* do not use branch slot */
429 902 markom
  }
430
 
431 905 markom
#if 1
432 902 markom
  /* LRBB at start of succ BB is not valid, it should be set when */
433 905 markom
  if (insn[n1].index == II_LRBB) {
434 902 markom
    assert (0); /* not tested yet */
435 905 markom
    change_insn_type (&insn[n1], II_NOP);
436
    for (i = n1; i < ninsn; i++)
437
      if (insn[i].index == II_CMOV && insn[i].op[3] == REF (pred, n1)) {
438 902 markom
        assert (insn[i].opt[3] == OPT_REF);
439
        insn[i].op[3] = cond_op;
440
        insn[i].opt[3] = cond_opt;
441
        if (f->bb[pred].next[0] != succ) {
442
          unsigned long t; /* negate conditional -- exchange */
443
          assert (f->bb[pred].next[1] == succ);
444
          t = insn[i].op[1];
445
          insn[i].op[1] = insn[i].op[2];
446
          insn[i].op[2] = t;
447
          t = insn[i].opt[1];
448
          insn[i].opt[1] = insn[i].opt[2];
449
          insn[i].opt[2] = t;
450
        }
451
      }
452
  }
453 905 markom
#endif
454 879 markom
 
455
  for (i = 0; i < ninsn; i++) reloc[i] = -1;
456
 
457
  /* Add conditional instructions if required */
458
  if (add_cond) {
459
    recalc_last_used_reg (f, pred);
460
    recalc_last_used_reg (f, succ);
461
 
462
    /* r0 -- add nop for it */
463 905 markom
    change_insn_type (&insn[n1 + n2], II_NOP);
464 879 markom
    for (i = 1; i < MAX_REGS; i++) {
465 905 markom
      cuc_insn *ii = &insn[n1 + n2 + i];
466 879 markom
      int a = f->bb[pred].last_used_reg[i];
467
      int b = f->bb[succ].last_used_reg[i];
468
 
469
      if (b < 0) change_insn_type (ii, II_NOP);
470
      else if (a < 0) {
471
        change_insn_type (ii, II_ADD);
472
        ii->type = 0;
473
        ii->dep = NULL;
474
        ii->op[0] = i; ii->opt[0] = OPT_REGISTER | OPT_DEST;
475
        ii->op[1] = b; ii->opt[1] = OPT_REF;
476
        ii->op[2] = 0; ii->opt[2] = OPT_CONST;
477 905 markom
        ii->opt[3] = OPT_NONE;
478
        if (i == FLAG_REG) ii->type |= IT_COND;
479 879 markom
      } else if (b >= 0) {
480
        change_insn_type (ii, II_CMOV);
481
        ii->type = 0;
482
        ii->dep = NULL;
483
        ii->op[0] = i; ii->opt[0] = OPT_REGISTER | OPT_DEST;
484
        ii->op[1] = a; ii->opt[1] = OPT_REF;
485
        ii->op[2] = b; ii->opt[2] = OPT_REF;
486
        ii->op[3] = cond_op; ii->opt[3] = cond_opt;
487 905 markom
        reloc[REF_I(a)] = REF (pred, n1 + n2 + i);
488
        if (i == FLAG_REG) ii->type |= IT_COND;
489 879 markom
      }
490
      sprintf (ii->disasm, "cmov (join BB)");
491
    }
492
  }
493
 
494 905 markom
  if (cuc_debug) cuc_check (f);
495 879 markom
  f->bb[pred].type |= f->bb[succ].type;
496
  i = 0;
497
  assert (f->bb[pred].next[0] >= 0);
498
  switch (type) {
499
  case 0:
500
    if (f->bb[pred].next[0] == succ) f->bb[pred].next[0] = f->bb[succ].next[0];
501
    if (f->bb[pred].next[1] == succ) f->bb[pred].next[1] = f->bb[succ].next[0];
502
    assert (f->bb[succ].next[1] < 0);
503
    break;
504
  case 1:
505
    f->bb[pred].next[0] = f->bb[succ].next[0];
506
    f->bb[pred].next[1] = f->bb[succ].next[1];
507
    break;
508 905 markom
  case 2:
509
    f->bb[pred].next[0] = f->bb[succ].next[0];
510
    f->bb[pred].next[1] = f->bb[succ].next[1];
511
    break;
512 879 markom
  }
513
  if (f->bb[pred].next[0] == f->bb[pred].next[1]) f->bb[pred].next[1] = -1;
514
  f->bb[succ].type = BB_DEAD;
515 905 markom
  /* remove branch instruction, if there is only one successor */
516
  if (f->bb[pred].next[1] < 0 && insn[ninsn - 1].type & IT_BRANCH
517
    && f->bb[pred].next[0] != pred) /* not when end BB, loop */
518
    change_insn_type (&insn[ninsn - 1], II_NOP);
519 879 markom
 
520
  /* Set max count */
521
  if (f->bb[pred].cnt < f->bb[succ].cnt) f->bb[pred].cnt = f->bb[succ].cnt;
522
  f->bb[pred].ninsn = ninsn;
523 905 markom
  f->bb[succ].ninsn = 0;
524 879 markom
  free (f->bb[pred].insn); f->bb[pred].insn = NULL;
525
  free (f->bb[succ].insn); f->bb[succ].insn = NULL;
526
  f->bb[pred].insn = insn;
527
  for (i = 0; i < f->num_bb; i++) if (!(f->bb[i].type & BB_DEAD)) {
528
    if (f->bb[i].prev[0] == succ) f->bb[i].prev[0] = pred;
529
    if (f->bb[i].prev[1] == succ) f->bb[i].prev[1] = pred;
530
    if (f->bb[i].prev[0] == f->bb[i].prev[1]) f->bb[i].prev[1] = -1;
531
    for (j = 0; j < f->bb[i].ninsn; j++)
532
      for (k = 0; k < MAX_OPERANDS; k++)
533
        if (f->bb[i].insn[j].opt[k] & OPT_REF) {
534
          /* Check if we are referencing successor BB -> relocate to second part of
535
             the new block */
536
          if (REF_BB (f->bb[i].insn[j].op[k]) == succ) {
537 905 markom
            int t = f->bb[i].insn[j].op[k];
538
            int ndest = REF (pred, REF_I (t) + n1);
539
            //printf ("%x: %x %x\n", REF(i, j), t, ndest);
540 879 markom
 
541 905 markom
            /* We've found a reference to succ. block, being removed, relocate */
542
            f->bb[i].insn[j].op[k] = ndest;
543 879 markom
          } else if (REF_BB(f->bb[i].insn[j].op[k]) == pred) {
544
            if (i != pred && reloc[REF_I(f->bb[i].insn[j].op[k])] >= 0) {
545
              f->bb[i].insn[j].op[k] = reloc[REF_I(f->bb[i].insn[j].op[k])];
546
            }
547
          }
548
        }
549
  }
550
 
551 905 markom
  if (cuc_debug) cuc_check (f);
552 883 markom
  if (cuc_debug >= 3) print_cuc_bb (f, "join");
553 879 markom
}
554
 
555
/* Optimize basic blocks */
556
void optimize_bb (cuc_func *f)
557
{
558
  int i, j;
559
remove_lrbb:
560
  /* we can remove lrbb instructions from blocks with just one predecessor */
561
  for (i = 0; i < f->num_bb; i++) if (!(f->bb[i].type & BB_DEAD)) {
562
    if (f->bb[i].prev[0] >= 0 && f->bb[i].prev[1] < 0) { /* exactly one predecessor */
563
      for (j = 0; j < f->bb[i].ninsn; j++)
564
        if (f->bb[i].insn[j].index == II_LRBB) {
565
          cuc_insn *t;
566 883 markom
          cucdebug (4, "-lrbb %i.%i\n", i, j);
567 879 markom
 
568
          /* Change to add LRBB, 0, 0 */
569
          change_insn_type (&f->bb[i].insn[j], II_ADD);
570
          f->bb[i].insn[j].type &= ~IT_VOLATILE;
571
          t = &f->bb[f->bb[i].prev[0]].insn[f->bb[f->bb[i].prev[0]].ninsn - 1];
572
          f->bb[i].insn[j].opt[1] = f->bb[i].insn[j].opt[2] = OPT_CONST;
573
          f->bb[i].insn[j].op[1] = f->bb[i].insn[j].op[2] = 0; /* always use left block */
574
          f->bb[i].insn[j].opt[3] = OPT_NONE;
575
 
576
          /* If the predecessor still has a conditional jump instruction, we must be careful.
577
             This could only have occured when we found out that next[0] == next[1] and have
578
             joined them. Now we will link lrbb and correct the situation */
579
          if (t->type & IT_BRANCH) { /* We must set a reference to branch result */
580
            f->bb[i].insn[j].opt[1] = t->opt[1];
581
            f->bb[i].insn[j].op[1] = t->op[1];
582
            change_insn_type (t, II_NOP);
583
          }
584
        }
585
    }
586
  }
587
 
588
  /* Type 0 joining
589
     1. link between pred & succ
590
     2. no memory accesses in succ
591
     3. optional pred's second successors
592
     4. max. one succ's successors */
593
  for (i = 0; i < f->num_bb; i++) if (!(f->bb[i].type & BB_DEAD))
594
    if (f->bb[i].prev[0] >= 0 && f->bb[i].prev[1] < 0 /* one predecessor */
595
     && f->bb[i].next[1] < 0 /* max. one successor */
596
     && f->bb[i].nmemory == 0) {                  /* and no memory acceses */
597
      join_bb (f, f->bb[i].prev[0], i, 0);
598
      goto remove_lrbb;
599
    }
600
 
601
  /* Type 1 joining
602
     1. link between pred & succ
603
     2. no other pred's successors
604
     3. no other succ's predecessors */
605
  for (i = 0; i < f->num_bb; i++) if (!(f->bb[i].type & BB_DEAD))
606
    if (f->bb[i].prev[0] >= 0 && f->bb[i].prev[1] < 0 /* one predecessor */
607
     && f->bb[f->bb[i].prev[0]].next[0] >= 0 && f->bb[f->bb[i].prev[0]].next[1] < 0) { /* one successor */
608
      join_bb (f, f->bb[i].prev[0], i, 1);
609
      goto remove_lrbb;
610
    }
611
 
612
#if 1
613
  /* Type 2 joining
614
     1. link between pred & succ
615
     2. succ has exactly one predeccessor
616
     3. pred & succ share common successor
617
     4. optional succ's second successor */
618
  for (i = 0; i < f->num_bb; i++) if (!(f->bb[i].type & BB_DEAD))
619
    if (f->bb[i].prev[0] >= 0 && f->bb[i].prev[1] < 0) { /* one predecessor */
620
      int p = f->bb[i].prev[0];
621 905 markom
#if 0 /* not yet supported */
622
      if (f->bb[p].next[0] == i
623
       && (f->bb[i].next[1] == f->bb[p].next[1]
624
        || f->bb[i].next[1] == f->bb[p].next[0])) {
625
        join_bb (f, p, i, 2);
626 897 markom
        goto remove_lrbb;
627
      }
628 905 markom
#endif
629
      if (f->bb[p].next[1] == i
630
       && (f->bb[i].next[0] == f->bb[p].next[1]
631
        || f->bb[i].next[0] == f->bb[p].next[0])) {
632
        join_bb (f, p, i, 2);
633
        goto remove_lrbb;
634
      }
635 879 markom
    }
636
#endif
637
}
638
 
639
/* Removes BBs marked as dead */
640
void remove_dead_bb (cuc_func *f)
641
{
642
  int i, j, k, d = 0;
643
 
644
  for (i = 0; i < f->num_bb; i++) if (f->bb[i].type & BB_DEAD) {
645
    if (f->bb[i].insn) free (f->bb[i].insn);
646
    f->bb[i].insn = NULL;
647
    reloc[i] = -1;
648
  } else {
649
    reloc[i] = d;
650
    f->bb[d++] = f->bb[i];
651
  }
652
  f->num_bb = d;
653
 
654
  /* relocate initial blocks */
655
  for (i = 0; i < f->num_init_bb; i++)
656
    f->init_bb_reloc[i] = reloc[f->init_bb_reloc[i]];
657
 
658
  /* repair references */
659
  for (i = 0; i < f->num_bb; i++) if (!(f->bb[i].type & BB_DEAD)) {
660
    if (f->bb[i].prev[0] >= 0) assert ((f->bb[i].prev[0] = reloc[f->bb[i].prev[0]]) >= 0);
661
    if (f->bb[i].prev[1] >= 0) assert ((f->bb[i].prev[1] = reloc[f->bb[i].prev[1]]) >= 0);
662
    if (f->bb[i].next[0] >= 0) assert ((f->bb[i].next[0] = reloc[f->bb[i].next[0]]) >= 0);
663
    if (f->bb[i].next[1] >= 0) assert ((f->bb[i].next[1] = reloc[f->bb[i].next[1]]) >= 0);
664
    if (f->bb[i].prev[0] == f->bb[i].prev[1]) f->bb[i].prev[1] = -1;
665
    if (f->bb[i].next[0] == f->bb[i].next[1]) f->bb[i].next[1] = -1;
666
 
667
    for (j = 0; j < f->bb[i].ninsn; j++)
668
      for (k = 0; k < MAX_OPERANDS; k++)
669
        if (f->bb[i].insn[j].opt[k] & OPT_BB && (signed)f->bb[i].insn[j].op[k] >= 0)
670
          assert ((f->bb[i].insn[j].op[k] = reloc[f->bb[i].insn[j].op[k]]) >= 0);
671
        else if (f->bb[i].insn[j].opt[k] & OPT_REF) {
672
          int t = f->bb[i].insn[j].op[k];
673
          assert (reloc[REF_BB(t)] >= 0);
674
          f->bb[i].insn[j].op[k] = REF (reloc[REF_BB(t)], REF_I (t));
675
        }
676
  }
677
}
678
 
679
/* Recursive calculation of dependencies */
680
static int reg_dep_rec (cuc_func *f, int cur)
681
{
682
  int i, j;
683
  cuc_insn *insn = f->bb[cur].insn;
684
 
685
  //printf ("\n %i", cur); 
686
  /* Spread only, do not loop */
687
  if (f->bb[cur].tmp) return;
688
  f->bb[cur].tmp = 1;
689
  //printf ("!   ");
690
 
691
  for (i = 0; i < f->bb[cur].ninsn; i++) {
692
    /* Check for destination operand(s) */
693
    for (j = 0; j < MAX_OPERANDS; j++) if (insn[i].opt[j] & OPT_DEST)
694
      if ((insn[i].opt[j] & ~OPT_DEST) == OPT_REGISTER && (signed)insn[i].op[j] >= 0) {
695
        //printf ("%i:%i,%x ", insn[i].op[j], i, REF (cur, i));
696
        assert (insn[i].op[j] > 0 && insn[i].op[j] < MAX_REGS); /* r0 should never be dest */
697
        f->bb[cur].last_used_reg[insn[i].op[j]] = REF (cur, i);
698
      }
699
  }
700
 
701
  if (f->bb[cur].next[0] >= 0) reg_dep_rec (f, f->bb[cur].next[0]);
702
  if (f->bb[cur].next[1] >= 0) reg_dep_rec (f, f->bb[cur].next[1]);
703
}
704
 
705
/* Detect register dependencies */
706
void reg_dep (cuc_func *f)
707
{
708
  int i, b, c;
709
 
710
  /* Set dead blocks */
711
  for (b = 0; b < f->num_bb; b++) {
712
    f->bb[b].tmp = 0;
713
    for (i = 0; i < MAX_REGS; i++) f->bb[b].last_used_reg[i] = -1;
714
  }
715
 
716
  /* Start with first block and set dependecies of all reachable blocks */
717
  /* At the same time set last_used_regs */
718
  reg_dep_rec (f, 0);
719
 
720
  for (i = 0; i < f->num_bb; i++)
721
    if (f->bb[i].tmp) f->bb[i].tmp = 0;
722
    else f->bb[i].type |= BB_DEAD;
723
 
724
  /* Detect loops; mark BBs where loops must be broken */
725
  for (c = 0; c < f->num_bb; c++) {
726
    int min = 3, minb;
727
 
728
    /* search though all non-visited for minimum number of unvisited predecessors */
729
    for (b = 0; b < f->num_bb; b++) if (!f->bb[b].tmp) {
730
      int tmp = 0;
731
      if (f->bb[b].prev[0] >= 0 && !f->bb[f->bb[b].prev[0]].tmp) tmp++;
732
      if (f->bb[b].prev[1] >= 0 && !f->bb[f->bb[b].prev[1]].tmp) tmp++;
733
      if (tmp < min) {
734
        minb = b;
735
        min = tmp;
736
        if (tmp == 0) break; /* We already have the best one */
737
      }
738
    }
739
    b = minb;
740
    f->bb[b].tmp = 1; /* Mark visited */
741 883 markom
    cucdebug (3, "minb %i min %i\n", minb, min);
742 879 markom
    if (min) { /* We just broke the loop */
743
      f->bb[b].type |= BB_INLOOP;
744
    }
745
  }
746
 
747
  /* Set real predecessors in cmov instructions to previous blocks */
748
  for (b = 0; b < f->num_bb; b++)
749
    for (i = 1; i < MAX_REGS - 1; i++) {
750
      int pa, pb;
751
      assert (f->bb[b].insn[i].index ==  II_CMOV);
752
      assert (f->bb[b].insn[i].opt[0] == OPT_REGISTER | OPT_DEST);
753
      assert (f->bb[b].insn[i].op[0] == i);
754
      if (f->bb[b].prev[0] < 0) pa = -1;
755
      else pa = f->bb[f->bb[b].prev[0]].last_used_reg[i];
756
      if (f->bb[b].prev[1] < 0) pb = -1;
757
      else pb = f->bb[f->bb[b].prev[1]].last_used_reg[i];
758
 
759
      /* We do some very simple optimizations right away to make things more readable */
760
      if (pa < 0 && pb < 0) {
761
        /* Was not used at all */
762
        change_insn_type (&f->bb[b].insn[i], II_ADD);
763
        f->bb[b].insn[i].op[2] = 0; f->bb[b].insn[i].opt[2] = OPT_CONST;
764
        f->bb[b].insn[i].opt[3] = OPT_NONE;
765
      } else if (pa < 0) {
766
        change_insn_type (&f->bb[b].insn[i], II_ADD);
767
        assert (f->INSN(pb).opt[0] == (OPT_REGISTER | OPT_DEST));
768
        f->bb[b].insn[i].op[1] = pb; f->bb[b].insn[i].opt[1] = OPT_REF;
769
        f->bb[b].insn[i].op[2] = 0; f->bb[b].insn[i].opt[2] = OPT_CONST;
770
        f->bb[b].insn[i].opt[3] = OPT_NONE;
771
      } else if (pb < 0) {
772
        change_insn_type (&f->bb[b].insn[i], II_ADD);
773
        assert (f->INSN(pa).opt[0] == (OPT_REGISTER | OPT_DEST));
774
        f->bb[b].insn[i].op[1] = pa; f->bb[b].insn[i].opt[1] = OPT_REF;
775
        f->bb[b].insn[i].op[2] = 0; f->bb[b].insn[i].opt[2] = OPT_CONST;
776
        f->bb[b].insn[i].opt[3] = OPT_NONE;
777
      } else {
778
        int t = REF (b, 0); /* lrbb should be first instruction */
779
        assert (f->INSN(t).index == II_LRBB);
780
 
781
        f->bb[b].insn[i].op[1] = pa; f->bb[b].insn[i].opt[1] = OPT_REF;
782
        assert (f->INSN(pa).opt[0] == (OPT_REGISTER | OPT_DEST));
783
 
784
        f->bb[b].insn[i].op[2] = pb; f->bb[b].insn[i].opt[2] = OPT_REF;
785
        assert (f->INSN(pb).opt[0] == (OPT_REGISTER | OPT_DEST));
786
 
787
        /* Update op[3] -- flag register */
788
        assert (f->bb[b].insn[i].opt[3] == OPT_REGISTER);
789
        assert (f->bb[b].insn[i].op[3] == LRBB_REG);
790
        assert (t >= 0);
791
        f->bb[b].insn[i].opt[3] = OPT_REF; /* Convert already used regs to references */
792
        f->bb[b].insn[i].op[3] = t;
793
        assert (f->INSN(t).opt[0] == (OPT_REGISTER | OPT_DEST));
794
      }
795
    }
796
 
797
  /* assign register references */
798
  for (b = 0; b < f->num_bb; b++) {
799
    /* rebuild last used reg array */
800
    f->bb[b].last_used_reg[0] = -1;
801
    if (f->bb[b].insn[0].index == II_LRBB) f->bb[b].last_used_reg[LRBB_REG] = 0;
802
    else f->bb[b].last_used_reg[LRBB_REG] = -1;
803
 
804
    for (i = 1; i < MAX_REGS - 1; i++)
805
      f->bb[b].last_used_reg[i] = -1;
806
 
807
    /* Create references */
808
    for (i = 0; i < f->bb[b].ninsn; i++) {
809
      int k;
810
      /* Check for source operands first */
811
      for (k = 0; k < MAX_OPERANDS; k++) {
812
        if (!(f->bb[b].insn[i].opt[k] & OPT_DEST))
813
        if (f->bb[b].insn[i].opt[k] & OPT_REGISTER) {
814
          int t = f->bb[b].last_used_reg[f->bb[b].insn[i].op[k]];
815
 
816
          if (f->bb[b].insn[i].op[k] == 0) { /* Convert r0 to const0 */
817
            f->bb[b].insn[i].opt[k] = OPT_CONST;
818
            f->bb[b].insn[i].op[k] = 0;
819
          } else if (t >= 0) {
820
            f->bb[b].insn[i].opt[k] = OPT_REF; /* Convert already used regs to references */
821
            f->bb[b].insn[i].op[k] = t;
822
            assert (f->INSN(t).opt[0] == (OPT_REGISTER | OPT_DEST));
823
            //f->INSN(t).op[0] = -1;
824
          }
825
        } else if (f->bb[b].insn[i].opt[k] & OPT_REF) {
826
          //f->INSN(f->bb[b].insn[i].op[k]).op[0] = -1; /* Mark referenced */
827
          f->INSN(f->bb[b].insn[i].op[k]).type &= ~IT_UNUSED;
828
        }
829
      }
830
 
831
      /* Now check for destination operand(s) */
832
      for (k = 0; k < MAX_OPERANDS; k++) if (f->bb[b].insn[i].opt[k] & OPT_DEST)
833
        if ((f->bb[b].insn[i].opt[k] & ~OPT_DEST) == OPT_REGISTER
834
          && (int)f->bb[b].insn[i].op[k] >= 0) {
835
          int t = f->bb[b].last_used_reg[f->bb[b].insn[i].op[k]];
836
          assert (f->bb[b].insn[i].op[k] != 0); /* r0 should never be dest */
837
          f->bb[b].last_used_reg[f->bb[b].insn[i].op[k]] = REF (b, i);
838
        }
839
    }
840
  }
841
 
842
  /* Remove all unused lrbb */
843
  for (b = 0; b < f->num_bb; b++)
844
    for (i = 0; i < f->bb[b].ninsn; i++)
845
      if (f->bb[b].insn[i].type & IT_UNUSED) change_insn_type (&f->bb[b].insn[i], II_NOP);
846
 
847
  /* SSAs with final register value are marked as outputs */
848
  assert (f->bb[f->num_bb - 1].type & BB_END);
849
  for (i = 0; i < MAX_REGS; i++) if (!call_saved[i]) {
850
    int t = f->bb[f->num_bb - 1].last_used_reg[i];
851
    /* Mark them volatile, so optimizer does not remove them */
852
    if (t >= 0) f->bb[REF_BB(t)].insn[REF_I(t)].type |= IT_OUTPUT;
853
  }
854
}
855
 
856 897 markom
/* split the BB, based on the group numbers in .tmp */
857
void expand_bb (cuc_func *f, int b)
858
{
859
  int n = f->num_bb;
860
  int mg = 0;
861
  int b1, i, j;
862
 
863
  for (i = 0; i < f->bb[b].ninsn; i++)
864
    if (f->bb[b].insn[i].tmp > mg) mg = f->bb[b].insn[i].tmp;
865
 
866
  /* Create copies */
867
  for (b1 = 1; b1 <= mg; b1++) {
868
    assert (f->num_bb < MAX_BB);
869
    cpy_bb (&f->bb[f->num_bb], &f->bb[b]);
870
    f->num_bb++;
871
  }
872
 
873
  /* Relocate */
874
  for (b1 = 0; b1 < f->num_bb; b1++)
875
    for (i = 0; i < f->bb[b1].ninsn; i++) {
876
      dep_list *d = f->bb[b1].insn[i].dep;
877
      for (j = 0; j < MAX_OPERANDS; j++)
878
        if (f->bb[b1].insn[i].opt[j] & OPT_REF) {
879
          int t = f->bb[b1].insn[i].op[j];
880
          if (REF_BB(t) == b && f->INSN(t).tmp != 0)
881
            f->bb[b1].insn[i].op[j] = REF (n + f->INSN(t).tmp - 1, REF_I(t));
882
        }
883
      while (d) {
884
        if (REF_BB (d->ref) == b && f->INSN(d->ref).tmp != 0)
885
          d->ref = REF (n + f->INSN(d->ref).tmp - 1, REF_I(d->ref));
886
        d = d->next;
887
      }
888
    }
889
 
890
  /* Delete unused instructions */
891
  for (j = 0; j <= mg; j++) {
892
    if (j == 0) b1 = b;
893
    else b1 = n + j - 1;
894
    for (i = 0; i < f->bb[b1].ninsn; i++) {
895
      if (f->bb[b1].insn[i].tmp != j)
896
        change_insn_type (&f->bb[b1].insn[i], II_NOP);
897
      f->bb[b1].insn[i].tmp = 0;
898
    }
899
    if (j < mg) {
900
      f->bb[b1].next[0] = n + j;
901
      f->bb[b1].next[1] = -1;
902
      f->bb[n + j].prev[0] = b1;
903
      f->bb[n + j].prev[1] = -1;
904
    } else {
905
      i = f->bb[b1].next[0];
906
      f->bb[n + j].prev[0] = j == 1 ? b : b1 - 1;
907
      f->bb[n + j].prev[1] = -1;
908
      if (i >= 0) {
909
        if (f->bb[i].prev[0] == b) f->bb[i].prev[0] = b1;
910
        if (f->bb[i].prev[1] == b) f->bb[i].prev[1] = b1;
911
      }
912
      i = f->bb[b1].next[1];
913
      if (i >= 0) {
914
        if (f->bb[i].prev[0] == b) f->bb[i].prev[0] = b1;
915
        if (f->bb[i].prev[1] == b) f->bb[i].prev[1] = b1;
916
      }
917
    }
918
  }
919
}
920
 
921 879 markom
/* Scans sequence of BBs and set bb[].cnt */
922
void generate_bb_seq (cuc_func *f, char *mp_filename, char *bb_filename)
923
{
924
  FILE *fi, *fo;
925
  struct mprofentry_struct *buf;
926
  const int bufsize = 256;
927
  unsigned long *bb_start;
928
  unsigned long *bb_end;
929
  int b, i, r;
930
  int curbb, prevbb = -1;
931
  unsigned long addr = -1;
932
  unsigned long prevaddr = -1;
933 897 markom
  int mssum = 0;
934
  int mlsum = 0;
935
  int mscnt = 0;
936
  int mlcnt = 0;
937 879 markom
 
938
  assert (fi = fopen (mp_filename, "rb"));
939
  assert (fo = fopen (bb_filename, "wb+"));
940
 
941
  assert (bb_start = (unsigned long *) malloc (sizeof (unsigned long) * f->num_bb));
942
  assert (bb_end = (unsigned long *) malloc (sizeof (unsigned long) * f->num_bb));
943
  for (b = 0; b < f->num_bb; b++) {
944
    bb_start[b] = f->start_addr + f->bb[b].first * 4;
945
    bb_end[b] = f->start_addr + f->bb[b].last * 4;
946
    //printf ("%i %x %x\n", b, bb_start[b], bb_end[b]);
947
    f->bb[0].cnt = 0;
948
  }
949
 
950
  buf = (struct mprofentry_struct *) malloc (sizeof (struct mprofentry_struct) * bufsize);
951
  assert (buf);
952
 
953
  //printf ("BBSEQ:\n");
954
  do {
955
    r = fread (buf, sizeof (struct mprofentry_struct), bufsize, fi);
956
    //printf ("r%i : ", r);
957
    for (i = 0; i < r; i++) {
958
      if (buf[i].type & MPROF_FETCH) {
959
        //printf ("%x, ", buf[i].addr);
960
        if (buf[i].addr >= f->start_addr && buf[i].addr <= f->end_addr) {
961
          assert (buf[i].type & MPROF_32);
962
          prevaddr = addr;
963
          addr = buf[i].addr;
964
          for (b = 0; b < f->num_bb; b++)
965
            if (bb_start[b] <= addr && addr <= bb_end[b]) break;
966
          assert (b < f->num_bb);
967
          curbb = b;
968
          if (prevaddr + 4 != addr) prevbb = -1;
969
        } else curbb = -1;
970
 
971
#warning TODO: do not count interrupts
972
        if (curbb != prevbb && curbb >= 0) {
973
          fwrite (&curbb, sizeof (unsigned long), 1, fo);
974
          //printf (" [%i] ", curbb);
975
          f->bb[curbb].cnt++;
976
          prevbb = curbb;
977
        }
978 897 markom
      } else {
979
        if (verify_memoryarea(buf[i].addr))
980
          if (buf[i].type & MPROF_WRITE) mscnt++, mssum += cur_area->delayw;
981
          else mlcnt++, mlsum += cur_area->delayw;
982 879 markom
      }
983
    }
984
    //printf ("\n");
985
  } while (r == bufsize);
986
  //printf ("\n");
987
 
988 897 markom
  runtime.cuc.mdelay[0] = (1. * mlsum) / mlcnt;
989
  runtime.cuc.mdelay[1] = (1. * mlsum) / mlcnt;
990
  runtime.cuc.mdelay[2] = runtime.cuc.mdelay[3] = 1;
991 883 markom
  f->num_runs = f->bb[0].cnt;
992 879 markom
  fclose (fi);
993
  fclose (fo);
994
  free (buf);
995
  free (bb_end);
996
  free (bb_start);
997
 
998
  /* Initialize basic block relocations */
999
  f->num_init_bb = f->num_bb;
1000
  //printf ("num_init_bb = %i\n", f->num_init_bb);
1001
  assert (f->init_bb_reloc = (int *)malloc (sizeof (int) * f->num_init_bb));
1002
  for (b = 0; b < f->num_init_bb; b++) f->init_bb_reloc[b] = b;
1003
}
1004
 
1005
/* Scans sequence of BBs and set counts for pre/unrolled loop for BB b */
1006
void count_bb_seq (cuc_func *f, int b, char *bb_filename, int *counts, int preroll, int unroll)
1007
{
1008
  FILE *fi;
1009
  const int bufsize = 256;
1010
  int i, r;
1011
  int *buf;
1012
  int cnt = 0;
1013
  int times = preroll - 1 + unroll;
1014
 
1015
  assert (fi = fopen (bb_filename, "rb"));
1016
  for (i = 0; i < times; i++) counts[i] = 0;
1017
  assert (buf = (int *) malloc (sizeof (int) * bufsize));
1018
 
1019
  do {
1020
    r = fread (buf, sizeof (int), bufsize, fi);
1021
    for (i = 0; i < r; i++) {
1022
      /* count consecutive acesses */
1023
      if (f->init_bb_reloc[buf[i]] == b) {
1024
        counts[cnt]++;
1025
        if (++cnt >= times) cnt = preroll - 1;
1026
      } else cnt = 0;
1027
    }
1028
  } while (r == bufsize);
1029
 
1030
  log ("Counts %i,%i :", preroll, unroll);
1031
  for (i = 0; i < times; i++) log ("%x ", counts[i]);
1032
  log ("\n");
1033
 
1034
  fclose (fi);
1035
  free (buf);
1036
}
1037
 
1038
/* relocate all accesses inside of BB b to back/fwd */
1039
static void relocate_bb (cuc_bb *bb, int b, int back, int fwd)
1040
{
1041
  int i, j;
1042
  for (i = 0; i < bb->ninsn; i++)
1043
    for (j = 0; j < MAX_OPERANDS; j++)
1044
      if (bb->insn[i].opt[j] & OPT_REF
1045
       && REF_BB (bb->insn[i].op[j]) == b) {
1046
        int t = REF_I (bb->insn[i].op[j]);
1047
        if (t < i) bb->insn[i].op[j] = REF (back, t);
1048
        else bb->insn[i].op[j] = REF (fwd, t);
1049
      }
1050
}
1051
 
1052
/* Unroll loop b unroll times and return new function. Original
1053
   function is unmodified. */
1054
static cuc_func *unroll_loop (cuc_func *f, int b, int unroll)
1055
{
1056
  int b1, t, i, j, prevb, prevart_b;
1057
  cuc_func *n = dup_func (f);
1058
  cuc_bb *ob = &f->bb[b];
1059
  cuc_insn *ii;
1060
 
1061
  assert (unroll > 1);
1062
  //printf ("unroll BB%i x %i (num_bb %i)\n", b, unroll, n->num_bb);
1063
  unroll--;
1064
  assert (n->num_bb + unroll * 2 < MAX_BB);
1065
 
1066
  prevb = b;
1067
  prevart_b = b;
1068
  /* Duplicate the BB */
1069
  for (t = 0; t < unroll; t++) {
1070
    cuc_bb *pb = &n->bb[prevart_b];
1071
    /* Add new block and set links */
1072
    b1 = n->num_bb++;
1073
    cpy_bb (&n->bb[b1], ob);
1074
    /* Only one should be in loop, so we remove any INLOOP flags from duplicates */
1075
    n->bb[b1].type &= ~(BB_END | BB_INLOOP);
1076
 
1077
    /* Set predecessor's successor */
1078
    if (n->bb[prevb].next[0] == b) {
1079
      n->bb[prevb].next[0] = b1;
1080
      if (pb->next[0] < 0) pb->next[0] = b1 + 1;
1081
      else pb->next[1] = b1 + 1;
1082
      n->bb[b1].next[1] = b1 + 1;
1083
    } else if (n->bb[prevb].next[1] == b) {
1084
      if (pb->next[0] < 0) pb->next[0] = b1 + 1;
1085
      else pb->next[1] = b1 + 1;
1086
      n->bb[b1].next[0] = b1 + 1;
1087
      n->bb[prevb].next[1] = b1;
1088
    } else assert (0);
1089
 
1090
    /* Set predecessor */
1091
    n->bb[b1].prev[0] = prevb;
1092
    n->bb[b1].prev[1] = -1;
1093
 
1094
    /* Relocate backward references to current instance and forward references
1095
       to previous one */
1096
    relocate_bb (&n->bb[b1], b, b1, prevb);
1097
 
1098
    /* add artificial block, just to join accesses */
1099
    b1 = n->num_bb++;
1100
    cpy_bb (&n->bb[b1], ob);
1101
    n->bb[b1].cnt = 0;
1102
 
1103
    for (i = 0; i < ob->ninsn - 1; i++) {
1104
      ii = &n->bb[b1].insn[i];
1105
      if (ob->insn[i].opt[0] & OPT_DEST) {
1106
        change_insn_type (ii, II_CMOV);
1107
        ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
1108
        ii->op[1] = REF (prevart_b, i); ii->opt[1] = OPT_REF;
1109
        ii->op[2] = REF (b1 - 1, i); ii->opt[2] = OPT_REF;
1110
 
1111
        /* Take left one, if we should have finished the first iteration*/
1112
        if (pb->insn[pb->ninsn - 1].type & IT_BRANCH) {
1113
          ii->op[3] = pb->insn[pb->ninsn - 1].op[1]; ii->opt[3] = pb->insn[pb->ninsn - 1].opt[1];
1114
        } else {
1115
          assert (pb->insn[pb->ninsn - 1].type & IT_COND);
1116
          ii->op[3] = REF (prevart_b, pb->ninsn - 1); ii->opt[3] = OPT_REF;
1117
        }
1118
        ii->dep = NULL;
1119
        ii->type = 0;
1120
      } else {
1121
        change_insn_type (ii, II_NOP);
1122
      }
1123
    }
1124
 
1125
    /* Add sfor instruction at the end, prioritizing flags */
1126
    ii = &n->bb[b1].insn[ob->ninsn - 1];
1127
    change_insn_type (ii, II_SFOR);
1128
    ii->op[0] = FLAG_REG; ii->opt[0] = OPT_REGISTER | OPT_DEST;
1129
    if (pb->insn[pb->ninsn - 1].type & IT_BRANCH) {
1130
      ii->op[1] = pb->insn[pb->ninsn - 1].op[1];
1131
      ii->opt[1] = pb->insn[pb->ninsn - 1].opt[1];
1132
    } else {
1133
      ii->op[1] = REF (prevart_b, pb->ninsn - 1);
1134
      ii->opt[1] = OPT_REF;
1135
    }
1136
    if (n->bb[b1 - 1].insn[pb->ninsn - 1].type & IT_BRANCH) {
1137
      ii->op[2] = n->bb[b1 - 1].insn[pb->ninsn - 1].op[1];
1138
      ii->opt[2] = n->bb[b1 - 1].insn[pb->ninsn - 1].opt[1];
1139
    } else {
1140
      ii->op[2] = REF (b1 - 1, pb->ninsn - 1);
1141
      ii->opt[2] = OPT_REF;
1142
    }
1143
    ii->opt[3] = OPT_NONE;
1144
    ii->type = IT_COND;
1145
 
1146
    /* Only one should be in loop, so we remove any INLOOP flags from duplicates */
1147
    n->bb[b1].type &= ~(BB_END | BB_INLOOP);
1148
    n->bb[b1].prev[0] = prevart_b;
1149
    n->bb[b1].prev[1] = b1 - 1;
1150
    n->bb[b1].next[0] = ob->next[0] == b ? ob->next[1] : ob->next[0];
1151
    n->bb[b1].next[1] = -1;
1152
 
1153
    prevb = b1 - 1;
1154
    prevart_b = b1;
1155
  }
1156
  if (ob->type & BB_END) {
1157
    n->bb[prevart_b].type |= BB_END;
1158
    n->bb[b].type &= ~BB_END;
1159
  }
1160
 
1161
  //print_cuc_bb (n, "unroll1");
1162
  /* repair BB after loop, to point back to latest artificial BB */
1163
  b1 = n->bb[prevart_b].next[0];
1164
  if (b1 >= 0) {
1165 897 markom
    if (n->bb[b1].prev[0] == b) n->bb[b1].prev[0] = prevart_b;
1166
    else if (n->bb[b1].prev[1] == b) n->bb[b1].prev[1] = prevart_b;
1167 879 markom
    else assert (0);
1168
  }
1169
 
1170
  /* Relink back to start of the loop */
1171
  /* Set predecessor's successor */
1172
  if (n->bb[prevb].next[0] == b) n->bb[prevb].next[0] = b;
1173
  else if (n->bb[prevb].next[1] == b) n->bb[prevb].next[1] = b;
1174
  else assert (0);
1175
 
1176
  /* Set predecessor */
1177
  if (n->bb[b].prev[0] == b) n->bb[b].prev[0] = prevb;
1178
  else if (n->bb[b].prev[1] == b) n->bb[b].prev[1] = prevb;
1179
  else assert (0);
1180
 
1181
  //print_cuc_bb (n, "unroll2");
1182
 
1183
  /* Relocate backward references to current instance and forward references
1184
     to previous one */
1185
  relocate_bb (&n->bb[b], b, b, prevb);
1186
 
1187
  /* Relocate all other blocks to point to latest prevart_b */
1188
  for (i = 0; i < f->num_bb; i++)
1189
    if (i != b) relocate_bb (&n->bb[i], b, prevart_b, prevart_b);
1190
 
1191
  return n;
1192
}
1193
 
1194
/* Preroll loop b preroll times and return new function. Original
1195
   function is unmodified. */
1196
static cuc_func *preroll_loop (cuc_func *f, int b, int preroll)
1197
{
1198
  int b1, t, i, j, prevb, prevart_b;
1199
  cuc_func *n = dup_func (f);
1200
  cuc_bb *ob = &f->bb[b];
1201
  cuc_insn *ii;
1202
 
1203
  assert (preroll > 1);
1204
  //printf ("preroll BB%i x %i (num_bb %i)\n", b, preroll, n->num_bb);
1205
  preroll--;
1206
  assert (n->num_bb + preroll * 2 < MAX_BB);
1207
 
1208
  prevb = b;
1209
  prevart_b = b;
1210
  /* Duplicate the BB */
1211
  for (t = 0; t < preroll; t++) {
1212
    cuc_bb *pb = &n->bb[prevart_b];
1213
    /* Add new block and set links */
1214
    b1 = n->num_bb++;
1215
    cpy_bb (&n->bb[b1], ob);
1216
    /* Only one should be in loop, so we remove any INLOOP flags from duplicates */
1217
    n->bb[b1].type &= ~(BB_END | BB_INLOOP);
1218
 
1219
    /* Set predecessor's successor */
1220
    if (n->bb[prevb].next[0] == b) {
1221
      n->bb[prevb].next[0] = b1;
1222
      if (pb->next[0] < 0) pb->next[0] = b1 + 1;
1223
      else pb->next[1] = b1 + 1;
1224
      n->bb[b1].next[1] = b1 + 1;
1225
    } else if (n->bb[prevb].next[1] == b) {
1226
      if (pb->next[0] < 0) pb->next[0] = b1 + 1;
1227
      else pb->next[1] = b1 + 1;
1228
      n->bb[b1].next[0] = b1 + 1;
1229
      n->bb[prevb].next[1] = b1;
1230
    } else assert (0);
1231
 
1232
    /* Set predecessor */
1233
    n->bb[b1].prev[0] = prevb;
1234
    n->bb[b1].prev[1] = -1;
1235
 
1236
    /* Relocate backward references to current instance and forward references
1237
       to previous one */
1238
    relocate_bb (&n->bb[b1], b, b1, prevb);
1239
 
1240
    /* add artificial block, just to join accesses */
1241
    b1 = n->num_bb++;
1242
    cpy_bb (&n->bb[b1], ob);
1243
    n->bb[b1].cnt = 0;
1244
 
1245
    for (i = 0; i < ob->ninsn - 1; i++) {
1246
      ii = &n->bb[b1].insn[i];
1247
      if (ob->insn[i].opt[0] & OPT_DEST) {
1248
        change_insn_type (ii, II_CMOV);
1249
        ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
1250
        ii->op[1] = REF (prevart_b, i); ii->opt[1] = OPT_REF;
1251
        ii->op[2] = REF (b1 - 1, i); ii->opt[2] = OPT_REF;
1252
 
1253
        /* Take left one, if we should have finished the first iteration*/
1254
        if (pb->insn[pb->ninsn - 1].type & IT_BRANCH) {
1255
          ii->op[3] = pb->insn[pb->ninsn - 1].op[1]; ii->opt[3] = pb->insn[pb->ninsn - 1].opt[1];
1256
        } else {
1257
          assert (pb->insn[pb->ninsn - 1].type & IT_COND);
1258
          ii->op[3] = REF (prevart_b, pb->ninsn - 1); ii->opt[3] = OPT_REF;
1259
        }
1260
        ii->dep = NULL;
1261
        ii->type = 0;
1262
      } else {
1263
        change_insn_type (ii, II_NOP);
1264
      }
1265
    }
1266
 
1267
    /* Add sfor instruction at the end, prioritizing flags */
1268
    ii = &n->bb[b1].insn[ob->ninsn - 1];
1269
    change_insn_type (ii, II_SFOR);
1270
    ii->op[0] = FLAG_REG; ii->opt[0] = OPT_REGISTER | OPT_DEST;
1271
    if (pb->insn[pb->ninsn - 1].type & IT_BRANCH) {
1272
      ii->op[1] = pb->insn[pb->ninsn - 1].op[1];
1273
      ii->opt[1] = pb->insn[pb->ninsn - 1].opt[1];
1274
    } else {
1275
      ii->op[1] = REF (prevart_b, pb->ninsn - 1);
1276
      ii->opt[1] = OPT_REF;
1277
    }
1278
    if (n->bb[b1 - 1].insn[pb->ninsn - 1].type & IT_BRANCH) {
1279
      ii->op[2] = n->bb[b1 - 1].insn[pb->ninsn - 1].op[1];
1280
      ii->opt[2] = n->bb[b1 - 1].insn[pb->ninsn - 1].opt[1];
1281
    } else {
1282
      ii->op[2] = REF (b1 - 1, pb->ninsn - 1);
1283
      ii->opt[2] = OPT_REF;
1284
    }
1285
    ii->opt[3] = OPT_NONE;
1286
    ii->type = IT_COND;
1287
 
1288
    /* Only one should be in loop, so we remove any INLOOP flags from duplicates */
1289
    n->bb[b1].type &= ~(BB_END | BB_INLOOP);
1290
    n->bb[b1].prev[0] = prevart_b;
1291
    n->bb[b1].prev[1] = b1 - 1;
1292
    n->bb[b1].next[0] = ob->next[0] == b ? ob->next[1] : ob->next[0];
1293
    n->bb[b1].next[1] = -1;
1294
 
1295
    prevb = b1 - 1;
1296
    prevart_b = b1;
1297
  }
1298
  if (ob->type & BB_END) {
1299
    n->bb[prevart_b].type |= BB_END;
1300
    n->bb[b].type &= ~BB_END;
1301
  }
1302
 
1303
  //print_cuc_bb (n, "preroll1");
1304
  /* repair BB after loop, to point back to latest artificial BB */
1305
  b1 = n->bb[prevart_b].next[0];
1306
  if (b1 >= 0) {
1307 897 markom
    if (n->bb[b1].prev[0] == b) n->bb[b1].prev[0] = prevart_b;
1308
    else if (n->bb[b1].prev[1] == b) n->bb[b1].prev[1] = prevart_b;
1309 879 markom
    else assert (0);
1310
  }
1311
 
1312
  /* Relink to itself */
1313
  /* Set predecessor's successor */
1314
  if (n->bb[prevb].next[0] == b) n->bb[prevb].next[0] = prevb;
1315
  else if (n->bb[prevb].next[1] == b) n->bb[prevb].next[1] = prevb;
1316
  else assert (0);
1317
  n->bb[prevb].prev[1] = prevb;
1318
 
1319
  if (n->bb[b].prev[0] == b) {
1320
    n->bb[b].prev[0] = n->bb[b].prev[1];
1321
    n->bb[b].prev[1] = -1;
1322
  } else if (n->bb[b].prev[1] == b) {
1323
    n->bb[b].prev[1] = -1;
1324
  }
1325
 
1326
  //print_cuc_bb (n, "preroll2");
1327
 
1328
  /* Relocate backward references to current instance and forward references
1329
     to previous one */
1330
  relocate_bb (&n->bb[b], b, b, prevb);
1331
 
1332
  /* Relocate all other blocks to point to latest prevart_b */
1333
  for (i = 0; i < f->num_bb; i++)
1334
    if (i != b) relocate_bb (&n->bb[i], b, prevart_b, prevart_b);
1335
 
1336
  return n;
1337
}
1338
 
1339
/* Unroll loop b unroll times and return new function. Original
1340
   function is unmodified. */
1341
cuc_func *preunroll_loop (cuc_func *f, int b, int preroll, int unroll, char *bb_filename)
1342
{
1343
  int b1, i;
1344
  cuc_func *n, *t;
1345
  int *counts;
1346
  int *bb_reloc;
1347
 
1348
  if (preroll > 1) {
1349
    t = preroll_loop (f, b, preroll);
1350
    b1 = t->num_bb - 2;
1351
    if (unroll > 1) {
1352
      //print_cuc_bb (t, "preunroll1");
1353
      n = unroll_loop (t, b1, unroll);
1354
      free_func (t);
1355
    } else n = t;
1356
  } else {
1357
    b1 = b;
1358 897 markom
    if (unroll > 1) n = unroll_loop (f, b1, unroll);
1359
    else return dup_func (f);
1360 879 markom
  }
1361
 
1362 897 markom
  /* Assign new counts to functions */
1363 879 markom
  assert (counts = (int *)malloc (sizeof (int) * (preroll - 1 + unroll)));
1364
  count_bb_seq (n, b, bb_filename, counts, preroll, unroll);
1365
  for (i = 0; i < preroll - 1 + unroll; i++) {
1366
    if (i == 0) b1 = b;
1367
    else b1 = f->num_bb + (i - 1) * 2;
1368
    n->bb[b1].cnt = counts[i];
1369
  }
1370
 
1371
  //print_cuc_bb (n, "preunroll");
1372
  free (counts);
1373
  return n;
1374
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.