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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_69/] [or1ksim/] [cuc/] [bb.c] - Blame information for rev 924

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

powered by: WebSVN 2.1.0

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