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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_50/] [or1ksim/] [cuc/] [bb.c] - Blame information for rev 905

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

powered by: WebSVN 2.1.0

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