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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc2/] [or1ksim/] [cuc/] [bb.c] - Blame information for rev 997

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

powered by: WebSVN 2.1.0

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