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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_65/] [or1ksim/] [cuc/] [bb.c] - Blame information for rev 931

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

powered by: WebSVN 2.1.0

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