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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_36/] [or1ksim/] [cuc/] [bb.c] - Blame information for rev 1045

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

powered by: WebSVN 2.1.0

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