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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_64/] [or1ksim/] [cuc/] [insn.c] - Blame information for rev 927

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

powered by: WebSVN 2.1.0

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