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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_37/] [or1ksim/] [cuc/] [insn.c] - Blame information for rev 928

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 879 markom
/* insn.c -- OpenRISC Custom Unit Compiler, instruction support
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 879 markom
#include "cuc.h"
26
#include "insn.h"
27
 
28
/* Table of known instructions.  Watch out for indexes I_*! */
29
const cuc_known_insn known[II_LAST + 1] = {
30
{"add", 1, "assign \1 = \2 + \3;"},
31
{"sub", 0, "assign \1 = \2 - \3;"},
32
{"and", 1, "assign \1 = \2 & \3;"},
33
{"or",  1, "assign \1 = \2 | \3;"},
34
{"xor", 1, "assign \1 = \2 ^ \3;"},
35
{"mul", 1, "assign \1 = \2 * \3;"},
36
 
37
{"srl", 0, "assign \1 = \2 >> \3;"},
38
{"sll", 0, "assign \1 = \2 << \3;"},
39
{"sra", 0, "assign \1 = ({32{\2[31]}} << (6'd32-{1'b0, \3}))\n\
40
                 | \2 >> \3;"},
41
 
42 926 markom
{"lb",  0, "always @(posedge clk)"},
43
{"lh",  0, "always @(posedge clk)"},
44
{"lw",  0, "always @(posedge clk)"},
45 879 markom
{"sb",  0, "/* mem8[\2] = \1 */"},
46
{"sh",  0, "/* mem16[\2] = \1 */"},
47
{"sw",  0, "/* mem32[\2] = \1 */"},
48
 
49
{"sfeq", 1, "assign \1 = \2 == \3;"},
50
{"sfne", 1, "assign \1 = \2 != \3;"},
51
{"sfle", 0, "assign \1 = \2 <= \3;"},
52
{"sflt", 0, "assign \1 = \2 < \3;"},
53 905 markom
{"sfge", 0, "assign \1 = \2 >= \3;"},
54 879 markom
{"sfgt", 0, "assign \1 = \2 > \3;"},
55
{"bf",  0, ""},
56
 
57
{"lrbb", 0,"always @(posedge clk or posedge rst)"},
58
{"cmov", 0,"assign \1 = \4 ? \2 : \3;"},
59 926 markom
{"reg", 0, "always @(posedge clk)"},
60 879 markom
 
61 917 markom
{"nop", 0, NULL},
62
{"call", 0, "/* function call */"}};
63 879 markom
 
64
/* Find known instruction and attach them to insn */
65
void change_insn_type (cuc_insn *i, int index)
66
{
67
  int j;
68
  assert (index >= 0 && index <= II_LAST);
69
  i->index = index;
70
  if (i->index == II_NOP) {
71
    for (j = 0; j < MAX_OPERANDS; j++) i->opt[j] = OPT_NONE;
72
    i->type = 0;
73
    i->dep = NULL;
74
  }
75
}
76
 
77
/* Returns instruction name */
78
const char *cuc_insn_name (cuc_insn *ii) {
79
  if (ii->index < 0 || ii->index > II_LAST) return "???";
80
  else return known[ii->index].name;
81
}
82 883 markom
 
83 897 markom
/* Prints out instructions */
84
void print_insns (cuc_insn *insn, int ninsn, int verbose)
85
{
86
  int i, j;
87
  for (i = 0; i < ninsn; i++) {
88
    dep_list *l = insn[i].dep;
89
    printf ("%4x%c %-4s ", i, insn[i].index >= 0 ? ':' : '?', cuc_insn_name (&insn[i]));
90
    if (verbose) {
91
      printf ("%-20s insn = %08x, index = %i, type = %04x ",
92
                      insn[i].disasm, insn[i].insn, insn[i].index, insn[i].type);
93
    } else printf ("type = %04x ", insn[i].type);
94
    for (j = 0; j < MAX_OPERANDS; j++) {
95
      if (insn[i].opt[j] & OPT_DEST) printf ("*");
96
      switch (insn[i].opt[j] & ~OPT_DEST) {
97
        case OPT_NONE: break;
98
        case OPT_CONST: printf ("0x%08x, ", insn[i].op[j]); break;
99
        case OPT_JUMP: printf ("J%x ", insn[i].op[j]); break;
100
        case OPT_REGISTER: printf ("r%i, ", insn[i].op[j]); break;
101
        case OPT_REF: printf ("[%x.%x], ", REF_BB(insn[i].op[j]), REF_I(insn[i].op[j])); break;
102 925 markom
        case OPT_BB: printf ("BB "); print_bb_num (insn[i].op[j]); printf (", "); break;
103 897 markom
        case OPT_LRBB: printf ("LRBB, "); break;
104
        default:
105
          fprintf (stderr, "Invalid operand type %s(%x.%x) = %x\n",
106
                         cuc_insn_name (&insn[i]), i, j, insn[i].opt[j]);
107
          assert (0);
108
      }
109
    }
110
    if (l) {
111
      printf ("\n\tdep:");
112
      while (l) {
113
        printf (" [%x.%x],", REF_BB (l->ref), REF_I (l->ref));
114
        l = l->next;
115
      }
116
    }
117
    printf ("\n");
118
  }
119
}
120
 
121
void add_dep (dep_list **list, int dep)
122
{
123
  dep_list *ndep;
124
  dep_list **tmp = list;
125
 
126
  while (*tmp) {
127
    if ((*tmp)->ref == dep) return; /* already there */
128
    tmp = &((*tmp)->next);
129
  }
130
  ndep = (dep_list *)malloc (sizeof (dep_list));
131
  ndep->ref = dep;
132
  ndep->next = NULL;
133
  *tmp = ndep;
134
}
135
 
136
void dispose_list (dep_list **list)
137
{
138
  while (*list) {
139
    dep_list *tmp = *list;
140
    *list = tmp->next;
141
    free (tmp);
142
  }
143
}
144
 
145
void add_data_dep (cuc_func *f)
146
{
147
  int b, i, j;
148
  dep_list *tmp;
149
  for (b = 0; b < f->num_bb; b++) {
150
    cuc_insn *insn = f->bb[b].insn;
151
    for (i = 0; i < f->bb[b].ninsn; i++)
152
      for (j = 0; j < MAX_OPERANDS; j++) {
153
        fflush (stdout);
154
        if (insn[i].opt[j] & OPT_REF) {
155
          /* Copy list from predecessor */
156
          dep_list *l = f->INSN(insn[i].op[j]).dep;
157
          while (l) {
158
            add_dep (&insn[i].dep, l->ref);
159
            l = l->next;
160
          }
161
          /* add predecessor */
162
          add_dep (&insn[i].dep, insn[i].op[j]);
163
        }
164
      }
165
  }
166
}
167
 
168
/* returns nonzero, if instruction was simplified */
169
int apply_edge_condition (cuc_insn *ii)
170
{
171
  unsigned int c = ii->op[2];
172
 
173
  if (ii->index == II_AND) {
174
    if (ii->opt[2] & OPT_CONST && c == 0) {
175
      change_insn_type (ii, II_ADD);
176
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
177
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
178
      return 1;
179
    }
180
  } else if (ii->index == II_OR) {
181
    if (ii->opt[2] & OPT_CONST && c == 0xffffffff) {
182
      change_insn_type (ii, II_ADD);
183
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
184
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
185
      return 1;
186
    }
187
  } else if (ii->index == II_SUB) {
188
    if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) {
189
      change_insn_type (ii, II_ADD);
190
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
191
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
192
      return 1;
193
    }
194
  } else if (ii->index == II_MUL) {
195
    if (ii->opt[2] & OPT_CONST && c == 0) {
196
      change_insn_type (ii, II_ADD);
197
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
198
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
199
      return 1;
200
    } else
201
    if (ii->opt[2] & OPT_CONST && c == 1) {
202
      change_insn_type (ii, II_ADD);
203
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
204
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
205
      return 1;
206
    } else
207
    if (ii->opt[2] & OPT_CONST && c == 0xffffffff) {
208
      change_insn_type (ii, II_SUB);
209
      ii->op[2] = ii->op[1]; ii->opt[2] = ii->opt[1];
210
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
211
      return 1;
212
    }
213
  } else if (ii->index == II_SRL) {
214
    if (ii->opt[2] & OPT_CONST && c == 0) {
215
      change_insn_type (ii, II_ADD);
216
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
217
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
218
      return 1;
219
    } else if (ii->opt[2] & OPT_CONST && c >= 32) {
220
      change_insn_type (ii, II_ADD);
221
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
222
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
223
      return 1;
224
    }
225
  } else if (ii->index == II_SLL) {
226
    if (ii->opt[2] & OPT_CONST && c == 0) {
227
      change_insn_type (ii, II_ADD);
228
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
229
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
230
      return 1;
231
    } else if (ii->opt[2] & OPT_CONST && c >= 32) {
232
      change_insn_type (ii, II_ADD);
233
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
234
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
235
      return 1;
236
    }
237
  } else if (ii->index == II_SRA) {
238
    if (ii->opt[2] & OPT_CONST && c == 0) {
239
      change_insn_type (ii, II_ADD);
240
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
241
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
242
      return 1;
243
    }
244
  } else if (ii->index == II_CMOV) {
245
    if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) {
246
      change_insn_type (ii, II_ADD);
247
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
248
      ii->opt[3] = OPT_NONE;
249
      return 1;
250
    }
251 905 markom
    if (ii->opt[3] & OPT_CONST) {
252
      change_insn_type (ii, II_ADD);
253
      if (ii->op[3]) {
254
        ii->op[2] = 0; ii->opt[2] = OPT_CONST;
255
      } else {
256
        ii->op[1] = 0; ii->opt[1] = OPT_CONST;
257
      }
258
      ii->opt[3] = OPT_NONE;
259
      return 1;
260
    }
261 927 markom
    if (ii->type & IT_COND) {
262
      if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST) {
263
        if (ii->op[1] && !ii->op[2]) {
264
          change_insn_type (ii, II_ADD);
265
          ii->op[1] = ii->op[3]; ii->opt[1] = ii->opt[3];
266
          ii->op[2] = 0; ii->opt[2] = OPT_CONST;
267
          ii->opt[3] = OPT_NONE;
268
          return 1;
269
        }
270
        if (ii->op[1] && ii->op[2]) {
271
          change_insn_type (ii, II_ADD);
272
          ii->op[1] = 1; ii->opt[1] = OPT_CONST;
273
          ii->op[2] = 0; ii->opt[2] = OPT_CONST;
274
          ii->opt[3] = OPT_NONE;
275
          return 1;
276
        }
277
        if (!ii->op[1] && !ii->op[2]) {
278
          change_insn_type (ii, II_ADD);
279
          ii->op[1] = 0; ii->opt[1] = OPT_CONST;
280
          ii->op[2] = 0; ii->opt[2] = OPT_CONST;
281
          ii->opt[3] = OPT_NONE;
282
          return 0;
283
        }
284
      }
285
    }
286 897 markom
  }
287
  return 0;
288
}
289
 
290 902 markom
/* First primary input */
291
static unsigned long tmp_op, tmp_opt;
292
 
293
/* Recursive function that searches for primary inputs;
294
   returns 0 if cmov can be replaced by add */
295
static int cmov_needed (cuc_func *f, int ref)
296
{
297
  cuc_insn *ii = &f->INSN(ref);
298
  int j;
299
 
300 903 markom
  cucdebug (4, " %x", ref);
301 902 markom
  /* mark visited, if already marked, we have a loop, ignore */
302
  if (ii->tmp) return 0;
303
  ii->tmp = 1;
304
 
305
  /* handle normal movs separately */
306 917 markom
  if (ii->index == II_ADD && !(ii->type & IT_VOLATILE)
307 902 markom
    && ii->opt[2] == OPT_CONST && ii->op[2] == 0) {
308
    if (ii->opt[1] == OPT_REF) {
309
      if (cmov_needed (f, ii->op[1])) {
310
        ii->tmp = 0;
311
        return 1;
312
      }
313
    } else {
314
      if (tmp_opt == OPT_NONE) {
315
        tmp_op = ii->op[1];
316
        tmp_opt = ii->opt[1];
317
      } else if (tmp_opt != ii->opt[1] || tmp_op != ii->op[1]) {
318
        ii->tmp = 0;
319
        return 1;
320
      }
321
    }
322
    ii->tmp = 0;
323
    return 0;
324
  }
325
 
326
  /* Is this instruction CMOV? no => add to primary inputs */
327
  if (ii->index != II_CMOV || ii->type & IT_VOLATILE)
328
    if (tmp_opt == OPT_NONE) {
329
      tmp_op = ref;
330
      tmp_opt = OPT_REF;
331
      ii->tmp = 0;
332
      return 0;
333
    } else if (tmp_opt != OPT_REF || tmp_op != ref) {
334
      ii->tmp = 0;
335
      return 1;
336 917 markom
    } else {
337
      ii->tmp = 0;
338
      return 0;
339 902 markom
    }
340
 
341
  for (j = 1; j < 3; j++) {
342 903 markom
    cucdebug (4, "(%x:%i)", ref, j);
343 902 markom
    if (ii->opt[j] == OPT_REF) {
344
      if (cmov_needed (f, ii->op[j])) {
345
        ii->tmp = 0;
346
        return 1;
347
      }
348
    } else {
349
      if (tmp_opt == OPT_NONE) {
350
        tmp_op = ii->op[j];
351
        tmp_opt = ii->opt[j];
352
      } else if (tmp_opt != ii->opt[j] || tmp_op != ii->op[j]) {
353
        ii->tmp = 0;
354
        return 1;
355
      }
356
    }
357
  }
358
 
359
  ii->tmp = 0;
360
  return 0;
361
}
362
 
363
/* Search and optimize complex cmov assignments */
364
void optimize_cmovs (cuc_func *f)
365
{
366
  int b, i, j;
367
 
368
  /* Mark all instructions unvisited */
369
  for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD))
370
    for (i = 0; i < f->bb[b].ninsn; i++) f->bb[b].insn[i].tmp = 0;
371
 
372
  for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD)) {
373
    for (i = 0; i < f->bb[b].ninsn; i++) {
374
      cuc_insn *ii = &f->bb[b].insn[i];
375
      if (ii->index == II_CMOV && !(ii->type & IT_VOLATILE)) {
376
        tmp_opt = OPT_NONE;
377 903 markom
        cucdebug (4, "\n");
378 902 markom
        if (!cmov_needed (f, REF(b, i))) {
379
          assert (tmp_opt != OPT_NONE);
380
          change_insn_type (ii, II_ADD);
381
          ii->op[1] = tmp_op; ii->opt[1] = tmp_opt;
382
          ii->op[2] = 0; ii->opt[2] = OPT_CONST;
383
          ii->opt[3] = OPT_NONE;
384
        }
385
      }
386
    }
387
  }
388
}
389
 
390 897 markom
/* Optimizes dataflow tree */
391
void optimize_tree (cuc_func *f)
392
{
393
  int b, i, j;
394
  int modified;
395
 
396
  do {
397
    modified = 0;
398
    for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD)) {
399
      for (i = 0; i < f->bb[b].ninsn; i++) {
400
        cuc_insn *ii = &f->bb[b].insn[i];
401
        /* We tend to have the third parameter const if instruction is cumutative */
402
        if ((ii->opt[1] & OPT_CONST) && !(ii->opt[2] & OPT_CONST)
403
            && known[ii->index].comutative) {
404
          unsigned long t = ii->opt[1];
405
          ii->opt[1] = ii->opt[2];
406
          ii->opt[2] = t;
407
          t = ii->op[1];
408
          ii->op[1] = ii->op[2];
409
          ii->op[2] = t;
410
          modified = 1; cucdebug (2, "%08x:<>\n", REF(b, i));
411
        }
412
 
413
        /* Try to do the promotion */
414
        /* We have two consecutive expressions, containing constants,
415
         * if previous is a simple expression we can handle it simply: */
416
        for (j = 0; j < MAX_OPERANDS; j++)
417
          if (ii->opt[j] & OPT_REF) {
418
            cuc_insn *t = &f->INSN(ii->op[j]);
419
            if (f->INSN(ii->op[j]).index == II_ADD
420
             && f->INSN(ii->op[j]).opt[2] & OPT_CONST
421
             && f->INSN(ii->op[j]).op[2] == 0
422
             && !(ii->type & IT_MEMORY && t->type & IT_MEMADD)
423
             && !(ii->type & IT_BRANCH) && !(t->type & IT_COND)) {
424
            /* do not promote through add-mem, and branches */
425
              modified = 1; cucdebug (2, "%8x:promote%i %8x %8x\n", REF (b, i), j, ii->op[j], t->op[1]);
426
              ii->op[j] = t->op[1]; ii->opt[j] = t->opt[1];
427
            }
428
          }
429
 
430
        /* In case of x = cmov x, y; or x = cmov y, x; we have
431
           asynchroneous loop -> remove it */
432
        if (ii->index == II_CMOV) {
433
          int f = 0;
434
          if ((ii->opt[1] & OPT_REF) && ii->op[1] == REF (b, i)) f = 1;
435
          if ((ii->opt[2] & OPT_REF) && ii->op[2] == REF (b, i)) f = 2;
436
          if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) f = 2;
437
          if (f) {
438
            change_insn_type (ii, II_ADD);
439
            cucdebug (2, "%8x:cmov     %i\n", REF(b, i), f);
440
            ii->opt[f] = OPT_CONST;
441
            ii->op[f] = 0;
442
            ii->opt[3] = OPT_NONE;
443
            modified = 1;
444
            continue;
445
          }
446
        }
447
 
448
        /* Do nothing to volatile instructions */
449
        if (ii->type & IT_VOLATILE) continue;
450
 
451
        /* Check whether we can simplify the instruction */
452
        if (apply_edge_condition (ii)) {
453
          modified = 1;
454
          continue;
455
        }
456
        /* We cannot do anything more if at least one is not constant */
457
        if (!(ii->opt[2] & OPT_CONST)) continue;
458
 
459
        if (ii->opt[1] & OPT_CONST) { /* We have constant expression */
460
          unsigned long value;
461
          int ok = 1;
462
          /* Was constant expression already? */
463
          if (ii->index == II_ADD && !ii->op[2]) continue;
464
 
465
          if (ii->index == II_ADD) value = ii->op[1] + ii->op[2];
466
          else if (ii->index == II_SUB) value = ii->op[1] - ii->op[2];
467
          else if (ii->index == II_SLL) value = ii->op[1] << ii->op[2];
468
          else if (ii->index == II_SRL) value = ii->op[1] >> ii->op[2];
469
          else if (ii->index == II_MUL) value = ii->op[1] * ii->op[2];
470
          else if (ii->index == II_OR) value = ii->op[1] | ii->op[2];
471
          else if (ii->index == II_XOR) value = ii->op[1] ^ ii->op[2];
472
          else if (ii->index == II_AND) value = ii->op[1] & ii->op[2];
473
          else ok = 0;
474
          if (ok) {
475
            change_insn_type (ii, II_ADD);
476
            ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
477
            ii->op[1] = value; ii->opt[1] = OPT_CONST;
478
            ii->op[2] = 0; ii->opt[2] = OPT_CONST;
479
            modified = 1; cucdebug (2, "%8x:const\n", REF (b, i));
480
          }
481
        } else if (ii->opt[1] & OPT_REF) {
482
          cuc_insn *prev = &f->INSN(ii->op[1]);
483
          /* Is this just a link? */
484
          if (ii->index == II_ADD
485
           && !(ii->type & IT_MEMADD) && ii->op[2] == 0) {
486
            int b1, i1, j1;
487
            cucdebug (2, "%8x:link      %8x: ", REF(b, i), ii->op[1]);
488
            for (b1 = 0; b1 < f->num_bb; b1++) if (!(f->bb[b1].type & BB_DEAD))
489
              for (i1 = 0; i1 < f->bb[b1].ninsn; i1++)
490
                for (j1 = 0; j1 < MAX_OPERANDS; j1++)
491
                  if ((f->bb[b1].insn[i1].opt[j1] & OPT_REF)
492
                   && f->bb[b1].insn[i1].op[j1] == REF(b, i)) {
493
                    cucdebug (2, "%x ", REF (b1, i1));
494
                    f->bb[b1].insn[i1].op[j1] = ii->op[1];
495
                  }
496
            cucdebug (2, "\n");
497
            change_insn_type (ii, II_NOP);
498
          } else if (prev->opt[2] & OPT_CONST) {
499
            /* Handle some common cases */
500
            /* add - add joining */
501
            if (ii->index == II_ADD && prev->index == II_ADD) {
502
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
503
              ii->op[2] += prev->op[2];
504
              modified = 1; cucdebug (2, "%8x: add-add\n", REF(b, i));
505
            } else /* add - sub joining */
506
            if (ii->index == II_ADD && prev->index == II_SUB) {
507
              change_insn_type (&insn[i], II_SUB);
508
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
509
              ii->op[2] += prev->op[2];
510
              modified = 1; cucdebug (2, "%8x: add-sub\n", REF(b, i));
511
            } else /* sub - add joining */
512
            if (ii->index == II_SUB && prev->index == II_ADD) {
513
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
514
              ii->op[2] += prev->op[2];
515
              modified = 1; cucdebug (2, "%8x: sub-add\n", REF(b, i));
516
            }
517
          }
518
        }
519
      }
520
    }
521
  } while (modified);
522
}
523
 
524
/* Remove nop instructions */
525
void remove_nops (cuc_func *f)
526
{
527
  int b;
528
  for (b = 0; b < f->num_bb; b++) {
529
    int c, d = 0, i, j;
530
    cuc_insn *insn = f->bb[b].insn;
531
    for (i = 0; i < f->bb[b].ninsn; i++)
532
      if (insn[i].index != II_NOP) {
533
        reloc [i] = d;
534
        insn[d++] = insn[i];
535
      } else {
536
        reloc[i] = d; /* For jumps only */
537
      }
538
    f->bb[b].ninsn = d;
539
 
540
    /* Relocate references from all basic blocks */
541
    for (c = 0; c < f->num_bb; c++)
542
      for (i = 0; i < f->bb[c].ninsn; i++) {
543
        dep_list *d = f->bb[c].insn[i].dep;
544
        for (j = 0; j < MAX_OPERANDS; j++)
545
          if ((f->bb[c].insn[i].opt[j] & OPT_REF)
546
            && REF_BB(f->bb[c].insn[i].op[j]) == b)
547
            f->bb[c].insn[i].op[j] = REF (b, reloc[REF_I (f->bb[c].insn[i].op[j])]);
548
 
549
        while (d) {
550
          if (REF_BB(d->ref) == b) d->ref = REF (b, reloc[REF_I (d->ref)]);
551
          d = d->next;
552
        }
553
      }
554
  }
555
}
556
 
557
/* Remove unused assignments */
558
void remove_dead (cuc_func *f)
559
{
560
  int b, i, j;
561
  for (b = 0; b < f->num_bb; b++)
562
    for (i = 0; i < f->bb[b].ninsn; i++)
563
      if (!(f->bb[b].insn[i].type & (IT_VOLATILE | IT_OUTPUT)))
564
        f->bb[b].insn[i].type |= IT_UNUSED;
565
 
566
  for (b = 0; b < f->num_bb; b++) {
567
    for (i = 0; i < f->bb[b].ninsn; i++)
568
      for (j = 0; j < MAX_OPERANDS; j++)
569
        if (f->bb[b].insn[i].opt[j] & OPT_REF) {
570
          f->INSN(f->bb[b].insn[i].op[j]).type &= ~IT_UNUSED;
571
        }
572
  }
573
 
574
  for (b = 0; b < f->num_bb; b++)
575
    for (i = 0; i < f->bb[b].ninsn; i++)
576
      if (f->bb[b].insn[i].type & IT_UNUSED) {
577
        change_insn_type (&f->bb[b].insn[i], II_NOP);
578
      }
579
 
580
  remove_nops (f);
581
}
582
 
583
/* Removes trivial register assignments */
584
void remove_trivial_regs (cuc_func *f)
585
{
586
  int b, i;
587
  for (i = 0; i < MAX_REGS; i++) f->saved_regs[i] = call_saved[i];
588
 
589
  for (b = 0; b < f->num_bb; b++) {
590
    cuc_insn *insn = f->bb[b].insn;
591
    for (i = 0; i < f->bb[b].ninsn; i++) {
592
      if (insn[i].index == II_ADD
593
        && insn[i].opt[0] & OPT_REGISTER
594
        && insn[i].opt[1] & OPT_REGISTER && insn[i].op[0] == insn[i].op[1]
595
        && insn[i].opt[2] & OPT_CONST && insn[i].op[2] == 0) {
596
          if (insn[i].type & IT_OUTPUT) f->saved_regs[insn[i].op[0]] = 1;
597
          change_insn_type (&insn[i], II_NOP);
598
        }
599
    }
600
  }
601
  if (cuc_debug >= 2) {
602
    printf ("saved regs ");
603
    for (i = 0; i < MAX_REGS; i++) printf ("%i:%i ", i, f->saved_regs[i]);
604
    printf ("\n");
605
  }
606
  remove_nops (f);
607
}
608
 
609
/* Determine inputs and outputs */
610
void set_io (cuc_func *f)
611
{
612
  int b, i, j;
613
  /* Determine register usage */
614
  for (i = 0; i < MAX_REGS; i++) {
615
    f->lur[i] = -1;
616
    f->used_regs[i] = 0;
617
  }
618 902 markom
  if (cuc_debug > 5) print_cuc_bb (f, "SET_IO");
619 897 markom
  for (b = 0; b < f->num_bb; b++) {
620
    for (i = 0; i < f->bb[b].ninsn; i++)
621
      for (j = 0; j < MAX_OPERANDS; j++)
622
        if (f->bb[b].insn[i].opt[j] & OPT_REGISTER && f->bb[b].insn[i].op[j] >= 0)
623
          if (f->bb[b].insn[i].opt[j] & OPT_DEST) f->lur[f->bb[b].insn[i].op[j]] = REF (b, i);
624
          else f->used_regs[f->bb[b].insn[i].op[j]] = 1;
625
  }
626
}
627
 
628
/* relocate all accesses inside of BB b to back/fwd */
629
static void relocate_bb (cuc_bb *bb, int b, int back, int fwd)
630
{
631
  int i, j;
632
  for (i = 0; i < bb->ninsn; i++)
633
    for (j = 0; j < MAX_OPERANDS; j++)
634
      if (bb->insn[i].opt[j] & OPT_REF
635
       && REF_BB (bb->insn[i].op[j]) == b) {
636
        int t = REF_I (bb->insn[i].op[j]);
637
        if (t < i) bb->insn[i].op[j] = REF (back, t);
638
        else bb->insn[i].op[j] = REF (fwd, t);
639
      }
640
}
641
 
642
/* Latch outputs in loops */
643
void add_latches (cuc_func *f)
644
{
645
  int b, i, j;
646
 
647
  //print_cuc_bb (f, "ADD_LATCHES a");
648
  /* Cuts the tree and marks registers */
649
  mark_cut (f);
650
 
651
  /* Split BBs with more than one group */
652
  for (b = 0; b < f->num_bb; b++) expand_bb (f, b);
653
  remove_nops (f);
654
  //print_cuc_bb (f, "ADD_LATCHES 0");
655
 
656
  /* Convert accesses in BB_INLOOP type block to latched */
657
  for (b = 0; b < f->num_bb; b++) {
658
    int j;
659
    for (i = 0; i < f->bb[b].ninsn; i++)
660
      for (j = 0; j < MAX_OPERANDS; j++) if (f->bb[b].insn[i].opt[j] == OPT_REF) {
661
        int t = f->bb[b].insn[i].op[j];
662
        /* If we are pointing to a INLOOP block from outside, or forward
663
           (= previous loop iteration) we must register that data */
664
        if ((f->bb[REF_BB(t)].type & BB_INLOOP || config.cuc.no_multicycle)
665
         && !(f->INSN(t).type & (IT_BRANCH | IT_COND))
666
         && (REF_BB(t) != b || REF_I(t) >= i)) {
667
          f->INSN(t).type |= IT_LATCHED;
668
        }
669
      }
670
  }
671
  //print_cuc_bb (f, "ADD_LATCHES 1");
672
 
673
  /* Add latches at the end of blocks as needed */
674
  for (b = 0; b < f->num_bb; b++) {
675
    int nreg = 0;
676
    cuc_insn *insn;
677
    for (i = 0; i < f->bb[b].ninsn; i++)
678
      if (f->bb[b].insn[i].type & IT_LATCHED) nreg++;
679
    if (nreg) {
680
      insn = (cuc_insn *) malloc (sizeof (cuc_insn) * (f->bb[b].ninsn + nreg));
681
      j = 0;
682
      for (i = 0; i < f->bb[b].ninsn; i++) {
683
        insn[i] = f->bb[b].insn[i];
684
        if (insn[i].type & IT_LATCHED) {
685
          cuc_insn *ii = &insn[f->bb[b].ninsn + j++];
686
          change_insn_type (ii, II_REG);
687
          ii->op[0] = -1; ii->opt[0] = OPT_DEST | OPT_REGISTER;
688
          ii->op[1] = REF (b, i); ii->opt[1] = OPT_REF;
689
          ii->opt[2] = ii->opt[3] = OPT_NONE;
690
          ii->dep = NULL;
691
          ii->type = IT_VOLATILE;
692
          sprintf (ii->disasm, "reg %i_%i", b, i);
693
        }
694
      }
695
      f->bb[b].ninsn += nreg;
696
      free (f->bb[b].insn);
697
      f->bb[b].insn = insn;
698
    }
699
  }
700
  //print_cuc_bb (f, "ADD_LATCHES 2");
701
 
702
  /* Repair references */
703
  for (b = 0; b < f->num_bb; b++)
704
    for (i = 0; i < f->bb[b].ninsn; i++)
705
      for (j = 0; j < MAX_OPERANDS; j++)
706
        /* If destination instruction is latched, use register instead */
707
        if (f->bb[b].insn[i].opt[j] == OPT_REF
708
         && f->INSN(f->bb[b].insn[i].op[j]).type & IT_LATCHED) {
709
          int b1, i1;
710
          b1 = REF_BB (f->bb[b].insn[i].op[j]);
711
          //cucdebug (2, "%i.%i.%i %x\n", b, i, j, f->bb[b].insn[i].op[j]);
712
          if (b1 != b || REF_I(f->bb[b].insn[i].op[j]) >= i) {
713
            for (i1 = f->bb[b1].ninsn - 1; i1 >= 0; i1--) {
714
              assert (f->bb[b1].insn[i1].index == II_REG);
715
              if (f->bb[b1].insn[i1].op[1] == f->bb[b].insn[i].op[j]) {
716
                f->bb[b].insn[i].op[j] = REF (b1, i1);
717
                break;
718
              }
719
            }
720
          }
721
        }
722
}
723
 
724 883 markom
/* CSE -- common subexpression elimination */
725
void cse (cuc_func *f)
726
{
727
  int b, i, j, b1, i1, b2, i2, j2;
728
  for (b1 = 0; b1 < f->num_bb; b1++)
729
    for (i1 = 0; i1 < f->bb[b1].ninsn; i1++)
730
      for (b2 = 0; b2 < f->num_bb; b2++)
731
        for (i2 = 0; i2 < f->bb[b2].ninsn; i2++) {
732
          cuc_insn *ii1 = &f->bb[b1].insn[i1];
733
          cuc_insn *ii2 = &f->bb[b2].insn[i2];
734
 
735
          /* Do we have an exact match? */
736
          if (ii1->index == ii2->index) continue;
737
          if (ii1->type & IT_VOLATILE) continue;
738
 
739
          if (ii1->op[1] != ii2->op[1] || ii1->opt[1] != ii2->opt[1]) continue;
740
          if (ii1->op[2] != ii2->op[2] || ii1->opt[2] != ii2->opt[2]) continue;
741
          if (ii1->opt[3] != ii2->opt[3]) continue;
742
          if (ii1->opt[3] != OPT_NONE && ii1->op[3] != ii2->op[3]) continue;
743
 
744
          /* Check if we drive outputs? */
745
          if ((ii1->opt[0] & OPT_REGISTER) && ii1->op[0] >= 0)
746
            if ((ii2->opt[0] & OPT_REGISTER) && ii2->op[0] >= 0) continue;
747
            else ii2->op[0] = ii1->op[0];
748
 
749
          /* remove duplicated instruction and relink the references */
750
          change_insn_type (ii2, II_NOP);
751
          for (b = 0; b < f->num_bb; b++)
752
            for (i = 0; i < f->bb[b].ninsn; i++)
753
              for (j = 0; j < MAX_OPERANDS; j++)
754
                if (f->bb[b].insn[i].opt[j] & OPT_REF && f->bb[b].insn[i].op[j] == REF (b2, i2))
755
                  f->bb[b].insn[i].op[j] = REF (b1, i1);
756
        }
757
}
758
 
759
static int count_cmovs (cuc_insn *ii, int match)
760
{
761
  int c = 0, j;
762
  if (match & 2) {
763
    for (j = 0; j < MAX_OPERANDS; j++)
764
      if (ii->opt[j] & OPT_DEST) c++;
765
  }
766
  if (match & 1) {
767
    for (j = 0; j < MAX_OPERANDS; j++)
768
      if (!(ii->opt[j] & OPT_DEST) && ii->opt[j] & OPT_REF) c++;
769
  } else {
770
    for (j = 0; j < MAX_OPERANDS; j++)
771
      if (!(ii->opt[j] & OPT_DEST) && ii->opt[j] != OPT_NONE) c++;
772
  }
773
  return c;
774
}
775
 
776 897 markom
static void search_csm (int iter, cuc_func *f, cuc_shared_list *list);
777
static cuc_shared_list *main_list;
778 883 markom
static int *iteration;
779
 
780 897 markom
/* CSM -- common subexpression matching -- resource sharing
781
   We try to match tree of instruction inside a BB with as many
782
   matches as possible. All possibilities are collected and
783
   options, making situation worse are removed */
784 883 markom
void csm (cuc_func *f)
785
{
786
  int b, i, j;
787
  int cnt;
788 897 markom
  cuc_shared_list *list;
789 883 markom
  cuc_timings timings;
790
 
791
  analyse_timings (f, &timings);
792
  main_list = NULL;
793
  for (b = 0; b < f->num_bb; b++) {
794
    assert (iteration = (int *)malloc (sizeof (int) * f->bb[b].ninsn));
795
    for (i = 0; i < f->bb[b].ninsn; i++) {
796
      int cnt = 0, cntc = 0;
797
      double size = 0., sizec = 0.;
798
      int j2 = 0;
799
      for (j = 0; j < f->bb[b].ninsn; j++)
800
        if (f->bb[b].insn[i].index == f->bb[b].insn[j].index) {
801
          int ok = 1;
802
          for (j2 = 0; j2 < MAX_OPERANDS; j2++) if (!(f->bb[b].insn[j].opt[j2] & OPT_REF))
803
            if (f->bb[b].insn[j].opt[j2] != f->bb[b].insn[i].opt[j2]
804
             || f->bb[b].insn[j].op[j2] != f->bb[b].insn[i].opt[j2]) {
805
              ok = 0;
806
              break;
807
            }
808
          if (ok) {
809
            cntc++;
810
            sizec = sizec + insn_size (&f->bb[b].insn[j]);
811
          } else {
812
            cnt++;
813
            size = size + insn_size (&f->bb[b].insn[j]);
814
          }
815
          iteration[j] = 0;
816
        } else iteration[j] = -1;
817
      if (cntc > 1) {
818 897 markom
        assert (list = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
819 883 markom
        list->next = main_list;
820
        list->from = NULL;
821
        list->ref = REF (b, i);
822
        list->cnt = cnt;
823
        list->cmatch = 1;
824
        list->cmovs = count_cmovs (&f->bb[b].insn[i], 3);
825
        list->osize = sizec;
826
        list->size = ii_size (f->bb[b].insn[i].index, 1);
827
        main_list = list;
828
        search_csm (0, f, list);
829
      }
830
      if (cnt > 1) {
831 897 markom
        assert (list = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
832 883 markom
        list->next = main_list;
833
        list->from = NULL;
834
        list->ref = REF (b, i);
835
        list->cnt = cnt + cntc;
836
        list->cmatch = 0;
837
        list->cmovs = count_cmovs (&f->bb[b].insn[i], 2);
838
        list->osize = size + sizec;
839
        list->size = ii_size (f->bb[b].insn[i].index, 0);
840
        main_list = list;
841
        search_csm (0, f, list);
842
      }
843
    }
844
    free (iteration);
845
  }
846
 
847
  for (list = main_list; list; list = list->next) list->dead = 0;
848
  cnt = 0;
849
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
850
  cucdebug (1, "noptions = %i\n", cnt);
851
 
852
  /* Now we will check the real size of the 'improvements'; if the size
853
     actually increases, we abandom the option */
854
  for (list = main_list; list; list = list->next)
855
    if (list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size >= list->osize) list->dead = 1;
856
 
857
  cnt = 0;
858
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
859
  cucdebug (1, "noptions = %i\n", cnt);
860
 
861
  /* Count number of instructions grouped */
862
  for (list = main_list; list; list = list->next) {
863 897 markom
    cuc_shared_list *l = list;
864 883 markom
    int c = 0;
865
    while (l) {
866
      c++;
867
      if (f->INSN(l->ref).type & (IT_VOLATILE | IT_MEMORY | IT_MEMADD)) list->dead = 1;
868
      l = l->from;
869
    }
870
    list->ninsn = c;
871
  }
872
 
873
  cnt = 0;
874
  for (list = main_list; list; list = list->next)
875
    if (!list->dead) cnt++;
876
  cucdebug (1, "noptions = %i\n", cnt);
877
 
878
#if 1
879
  /* We can get a lot of options here, so we will delete duplicates */
880
  for (list = main_list; list; list = list->next) if (!list->dead) {
881 897 markom
    cuc_shared_list *l;
882 883 markom
    for (l = list->next; l; l = l->next) if (!l->dead) {
883
      int ok = 1;
884 897 markom
      cuc_shared_list *t1 = list;
885
      cuc_shared_list *t2 = l;
886 883 markom
      while (ok && t1 && t2) {
887
        if (f->INSN(t1->ref).index == f->INSN(t2->ref).index) {
888
          /* If other operands are matching, we must check for them also */
889
          if (t1->cmatch) {
890
            int j;
891
            for (j = 0; j < MAX_OPERANDS; j++)
892
              if (!(f->INSN(t1->ref).opt[j] & OPT_REF) || !(f->INSN(t2->ref).opt[j] & OPT_REF)
893
               || f->INSN(t1->ref).opt[j] != f->INSN(t2->ref).opt[j]
894
               || f->INSN(t1->ref).op[j] != f->INSN(t2->ref).op[j]) {
895
                ok = 0;
896
                break;
897
              }
898
          }
899
 
900
          /* This option is duplicate, remove */
901
          if (ok) t1->dead = 1;
902
        }
903
        t1 = t1->from;
904
        t2 = t2->from;
905
      }
906
    }
907
  }
908
  cnt = 0;
909
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
910
  cucdebug (1, "noptions = %i\n", cnt);
911
#endif
912
  /* Print out */
913
  for (list = main_list; list; list = list->next) if (!list->dead) {
914 897 markom
    cuc_shared_list *l = list;
915 883 markom
    cucdebug (1, "%-4s cnt %3i ninsn %3i size %8.1f osize %8.1f cmovs %3i @",
916
           cuc_insn_name (&f->INSN(list->ref)), list->cnt, list->ninsn,
917
           list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size, list->osize, list->cmovs);
918
    while (l) {
919
      cucdebug (1, "%c%x,", l->cmatch ? '.' : '!', l->ref);
920
      l = l->from;
921
    }
922
    cucdebug (1, "\n");
923
  }
924
 
925
  /* Calculate estimated timings */
926
  for (b = 0; b < f->num_bb; b++) {
927
    cnt = 0;
928
    for (list = main_list; list; list = list->next)
929
      if (!list->dead && REF_BB(list->ref) == b) cnt++;
930
 
931
    f->bb[b].ntim = cnt;
932
    if (!cnt) {
933
      f->bb[b].tim = NULL;
934
      continue;
935
    }
936
    assert (f->bb[b].tim = (cuc_timings *)malloc (sizeof (cuc_timings) * cnt));
937
 
938
    cnt = 0;
939
    for (list = main_list; list; list = list->next) if (!list->dead && REF_BB(list->ref) == b) {
940 897 markom
      cuc_shared_list *l = list;
941 883 markom
      f->bb[b].tim[cnt].b = b;
942
      f->bb[b].tim[cnt].preroll = f->bb[b].tim[cnt].unroll = 1;
943
      f->bb[b].tim[cnt].nshared = list->ninsn;
944 897 markom
      assert (f->bb[b].tim[cnt].shared = (cuc_shared_item *)
945
            malloc (sizeof(cuc_shared_item) * list->ninsn));
946
      for (i =  0; i < list->ninsn; i++, l = l->from) {
947
        f->bb[b].tim[cnt].shared[i].ref = l->ref;
948
        f->bb[b].tim[cnt].shared[i].cmatch = l->cmatch;
949
      }
950 883 markom
      f->bb[b].tim[cnt].new_time = timings.new_time + f->bb[b].cnt * (list->cnt - 1);
951 897 markom
      f->bb[b].tim[cnt].size = timings.size +
952
             list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size - list->osize;
953 883 markom
      cnt++;
954
    }
955
  }
956
}
957
 
958
/* Recursive function for searching through instruction graph */
959 897 markom
static void search_csm (int iter, cuc_func *f, cuc_shared_list *list)
960 883 markom
{
961
  int b, i, j, i1;
962 897 markom
  cuc_shared_list *l;
963 883 markom
  b = REF_BB(list->ref);
964
  i = REF_I(list->ref);
965
 
966
  for (j = 0; j < MAX_OPERANDS; j++) if (f->bb[b].insn[i].opt[j] & OPT_REF) {
967
    int t = f->bb[b].insn[i].op[j];
968
    int cnt = 0, cntc = 0;
969
    double size = 0., sizec = 0.;
970
 
971
    /* Mark neighbours */
972
    for (i1 = 0; i1 < f->bb[b].ninsn; i1++) {
973
      if (iteration[i1] == iter && f->bb[b].insn[i1].opt[j] & OPT_REF) {
974
        int t2 = f->bb[b].insn[i1].op[j];
975
        if (f->INSN(t).index == f->INSN(t2).index && f->INSN(t2).opt[j] & OPT_REF) {
976
          int j2;
977
          int ok = 1;
978
          iteration[REF_I(t2)] = iter + 1;
979
          for (j2 = 0; j2 < MAX_OPERANDS; j2++) if (!(f->bb[b].insn[i1].opt[j2] & OPT_REF))
980
            if (f->bb[b].insn[i1].opt[j2] != f->bb[b].insn[i].opt[j2]
981
             || f->bb[b].insn[i1].op[j2] != f->bb[b].insn[i].opt[j2]) {
982
              ok = 0;
983
              break;
984
            }
985
          if (ok) {
986
            cntc++;
987
            sizec = sizec + insn_size (&f->bb[b].insn[i1]);
988
          } else {
989
            cnt++;
990
            size = size + insn_size (&f->bb[b].insn[i1]);
991
          }
992
        }
993
      }
994
    }
995
 
996
    if (cntc > 1) {
997 897 markom
      assert (l = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
998 883 markom
      l->next = main_list;
999
      main_list = l;
1000
      l->from = list;
1001
      l->ref = t;
1002
      l->cnt = cnt;
1003
      l->cmatch = 1;
1004
      l->cmovs = list->cmovs + count_cmovs (&f->bb[b].insn[i], 1) - 1;
1005
      l->size = list->size + ii_size (f->bb[b].insn[i].index, 1);
1006
      l->osize = sizec;
1007
      search_csm (iter + 1, f, l);
1008
    }
1009
    if (cnt > 1) {
1010 897 markom
      assert (l = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1011 883 markom
      l->next = main_list;
1012
      main_list = l;
1013
      l->from = list;
1014
      l->ref = t;
1015
      l->cnt = cnt + cntc;
1016
      l->cmatch = 0;
1017
      l->osize = size + sizec;
1018
      l->cmovs = list->cmovs + count_cmovs (&f->bb[b].insn[i], 0) - 1;
1019
      l->size = list->size + ii_size (f->bb[b].insn[i].index, 0);
1020
      search_csm (iter + 1, f, l);
1021
    }
1022
 
1023
    /* Unmark them back */
1024
    for (i1 = 0; i1 < f->bb[b].ninsn; i1++) if (iteration[i1] > iter) iteration[i1] = -1;
1025
  }
1026
}
1027
 
1028 897 markom
/* Displays shared instructions */
1029
void print_shared (cuc_func *rf, cuc_shared_item *shared, int nshared)
1030
{
1031
  int i, first = 1;
1032
  for (i = 0; i < nshared; i++) {
1033 906 markom
    printf ("%s%s%s", first ? "" : "-", cuc_insn_name (&rf->INSN(shared[i].ref)),
1034 897 markom
                    shared[i].cmatch ? "!" : "");
1035
    first = 0;
1036
  }
1037
}
1038
 
1039
/* Common subexpression matching -- resource sharing, generation pass
1040
 
1041
   Situation here is much simpler than with analysis -- we know the instruction sequence
1042
   we are going to share, but we are going to do this on whole function, not just one BB.
1043
   We can find sequence in reference function, as pointed from "shared" */
1044
void csm_gen (cuc_func *f, cuc_func *rf, cuc_shared_item *shared, int nshared)
1045
{
1046
  int b, i, j, cnt = 0;
1047
#warning   some code here (2)
1048
  printf ("Replacing: ");
1049
  print_shared (rf, shared, nshared);
1050
 
1051
  for (b = 0; b < f->num_bb; b++)
1052
    for (i = 0; i < f->bb[b].ninsn; i++) {
1053
    }
1054
 
1055
  printf ("\nFound %i matches.\n", cnt);
1056
}
1057
 

powered by: WebSVN 2.1.0

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