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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_39/] [or1ksim/] [cuc/] [insn.c] - Blame information for rev 917

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

powered by: WebSVN 2.1.0

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