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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_52/] [or1ksim/] [cuc/] [insn.c] - Blame information for rev 1765

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 1308 phoenix
 
25 1350 nogj
#include "config.h"
26
 
27
#ifdef HAVE_INTTYPES_H
28
#include <inttypes.h>
29
#endif
30
 
31
#include "port.h"
32
#include "arch.h"
33 1308 phoenix
#include "abstract.h"
34 897 markom
#include "sim-config.h"
35 879 markom
#include "cuc.h"
36
#include "insn.h"
37
 
38
/* Table of known instructions.  Watch out for indexes I_*! */
39
const cuc_known_insn known[II_LAST + 1] = {
40
{"add", 1, "assign \1 = \2 + \3;"},
41
{"sub", 0, "assign \1 = \2 - \3;"},
42
{"and", 1, "assign \1 = \2 & \3;"},
43
{"or",  1, "assign \1 = \2 | \3;"},
44
{"xor", 1, "assign \1 = \2 ^ \3;"},
45
{"mul", 1, "assign \1 = \2 * \3;"},
46
 
47
{"srl", 0, "assign \1 = \2 >> \3;"},
48
{"sll", 0, "assign \1 = \2 << \3;"},
49
{"sra", 0, "assign \1 = ({32{\2[31]}} << (6'd32-{1'b0, \3}))\n\
50
                 | \2 >> \3;"},
51
 
52 926 markom
{"lb",  0, "always @(posedge clk)"},
53
{"lh",  0, "always @(posedge clk)"},
54
{"lw",  0, "always @(posedge clk)"},
55 879 markom
{"sb",  0, "/* mem8[\2] = \1 */"},
56
{"sh",  0, "/* mem16[\2] = \1 */"},
57
{"sw",  0, "/* mem32[\2] = \1 */"},
58
 
59
{"sfeq", 1, "assign \1 = \2 == \3;"},
60
{"sfne", 1, "assign \1 = \2 != \3;"},
61
{"sfle", 0, "assign \1 = \2 <= \3;"},
62
{"sflt", 0, "assign \1 = \2 < \3;"},
63 905 markom
{"sfge", 0, "assign \1 = \2 >= \3;"},
64 879 markom
{"sfgt", 0, "assign \1 = \2 > \3;"},
65
{"bf",  0, ""},
66
 
67
{"lrbb", 0,"always @(posedge clk or posedge rst)"},
68
{"cmov", 0,"assign \1 = \4 ? \2 : \3;"},
69 926 markom
{"reg", 0, "always @(posedge clk)"},
70 879 markom
 
71 937 markom
{"nop", 1, ""},
72 917 markom
{"call", 0, "/* function call */"}};
73 879 markom
 
74
/* Find known instruction and attach them to insn */
75
void change_insn_type (cuc_insn *i, int index)
76
{
77
  int j;
78
  assert (index >= 0 && index <= II_LAST);
79
  i->index = index;
80
  if (i->index == II_NOP) {
81
    for (j = 0; j < MAX_OPERANDS; j++) i->opt[j] = OPT_NONE;
82
    i->type = 0;
83
    i->dep = NULL;
84 937 markom
    i->disasm[0] = '\0';
85 879 markom
  }
86
}
87
 
88
/* Returns instruction name */
89
const char *cuc_insn_name (cuc_insn *ii) {
90
  if (ii->index < 0 || ii->index > II_LAST) return "???";
91
  else return known[ii->index].name;
92
}
93 883 markom
 
94 897 markom
/* Prints out instructions */
95 1062 markom
void print_insns (int bb, cuc_insn *insn, int ninsn, int verbose)
96 897 markom
{
97
  int i, j;
98
  for (i = 0; i < ninsn; i++) {
99 1062 markom
    char tmp[10];
100 897 markom
    dep_list *l = insn[i].dep;
101 1062 markom
    sprintf (tmp, "[%x_%x]", bb, i);
102
    PRINTF ("%-8s%c %-4s ", tmp, insn[i].index >= 0 ? ':' : '?', cuc_insn_name (&insn[i]));
103 897 markom
    if (verbose) {
104 1308 phoenix
      PRINTF ("%-20s insn = %08lx, index = %i, type = %04x ",
105 897 markom
                      insn[i].disasm, insn[i].insn, insn[i].index, insn[i].type);
106 997 markom
    } else PRINTF ("type = %04x ", insn[i].type);
107 897 markom
    for (j = 0; j < MAX_OPERANDS; j++) {
108 997 markom
      if (insn[i].opt[j] & OPT_DEST) PRINTF ("*");
109 897 markom
      switch (insn[i].opt[j] & ~OPT_DEST) {
110 1308 phoenix
        case OPT_NONE:
111
          break;
112
        case OPT_CONST:
113
          if (insn[i].type & IT_COND && (insn[i].index == II_CMOV
114
                                                    || insn[i].index == II_ADD))
115
            PRINTF ("%lx, ", insn[i].op[j]);
116
          else
117
            PRINTF ("0x%08lx, ", insn[i].op[j]);
118
          break;
119
        case OPT_JUMP:
120
          PRINTF ("J%lx, ", insn[i].op[j]);
121
          break;
122
        case OPT_REGISTER:
123
          PRINTF ("r%li, ", insn[i].op[j]);
124
          break;
125
        case OPT_REF:
126
          PRINTF ("[%lx_%lx], ", REF_BB(insn[i].op[j]), REF_I(insn[i].op[j]));
127
          break;
128
        case OPT_BB:
129
          PRINTF ("BB ");
130
          print_bb_num (insn[i].op[j]);
131
          PRINTF (", ");
132
          break;
133
        case OPT_LRBB:
134
          PRINTF ("LRBB, ");
135
          break;
136 897 markom
        default:
137 1062 markom
          fprintf (stderr, "Invalid operand type %s(%x_%x) = %x\n",
138 897 markom
                         cuc_insn_name (&insn[i]), i, j, insn[i].opt[j]);
139
          assert (0);
140
      }
141
    }
142
    if (l) {
143 997 markom
      PRINTF ("\n\tdep:");
144 897 markom
      while (l) {
145 1308 phoenix
        PRINTF (" [%lx_%lx],", REF_BB (l->ref), REF_I (l->ref));
146 897 markom
        l = l->next;
147
      }
148
    }
149 997 markom
    PRINTF ("\n");
150 897 markom
  }
151
}
152
 
153
void add_dep (dep_list **list, int dep)
154
{
155
  dep_list *ndep;
156
  dep_list **tmp = list;
157
 
158
  while (*tmp) {
159
    if ((*tmp)->ref == dep) return; /* already there */
160
    tmp = &((*tmp)->next);
161
  }
162
  ndep = (dep_list *)malloc (sizeof (dep_list));
163
  ndep->ref = dep;
164
  ndep->next = NULL;
165
  *tmp = ndep;
166
}
167
 
168
void dispose_list (dep_list **list)
169
{
170
  while (*list) {
171
    dep_list *tmp = *list;
172
    *list = tmp->next;
173
    free (tmp);
174
  }
175
}
176
 
177
void add_data_dep (cuc_func *f)
178
{
179
  int b, i, j;
180
  for (b = 0; b < f->num_bb; b++) {
181
    cuc_insn *insn = f->bb[b].insn;
182
    for (i = 0; i < f->bb[b].ninsn; i++)
183
      for (j = 0; j < MAX_OPERANDS; j++) {
184
        fflush (stdout);
185
        if (insn[i].opt[j] & OPT_REF) {
186
          /* Copy list from predecessor */
187
          dep_list *l = f->INSN(insn[i].op[j]).dep;
188
          while (l) {
189
            add_dep (&insn[i].dep, l->ref);
190
            l = l->next;
191
          }
192
          /* add predecessor */
193
          add_dep (&insn[i].dep, insn[i].op[j]);
194
        }
195
      }
196
  }
197
}
198
 
199 953 markom
/* Inserts n nops before insn 'ref' */
200
void insert_insns (cuc_func *f, int ref, int n)
201
{
202
  int b1, i, j;
203
  int b = REF_BB(ref);
204
  int ins = REF_I(ref);
205
 
206
  assert (b < f->num_bb);
207
  assert (ins <= f->bb[b].ninsn);
208
  assert (f->bb[b].ninsn + n < MAX_INSNS);
209 996 markom
  if (cuc_debug >= 8) print_cuc_bb (f, "PREINSERT");
210 953 markom
  f->bb[b].insn = (cuc_insn *) realloc (f->bb[b].insn,
211
                                        (f->bb[b].ninsn + n) * sizeof (cuc_insn));
212
 
213
  /* Set up relocations */
214
  for (i = 0; i < f->bb[b].ninsn; i++)
215
    if (i < ins) reloc[i] = i;
216
    else reloc[i] = i + n;
217
 
218
  /* Move instructions, based on relocations */
219
  for (i = f->bb[b].ninsn - 1; i >= 0; i--) f->bb[b].insn[reloc[i]] = f->bb[b].insn[i];
220
  for (i = 0; i < n; i++) change_insn_type (&f->bb[b].insn[ins + i], II_NOP);
221
 
222
  f->bb[b].ninsn += n;
223
  for (b1 = 0; b1 < f->num_bb; b1++) {
224
    dep_list *d = f->bb[b1].mdep;
225
    while (d) {
226
      if (REF_BB (d->ref) == b && REF_I (d->ref) >= ins)
227
        d->ref = REF (b, REF_I (d->ref) + n);
228
      d = d->next;
229
    }
230
    for (i = 0; i < f->bb[b1].ninsn; i++) {
231
      d = f->bb[b1].insn[i].dep;
232
      while (d) {
233
        if (REF_BB (d->ref) == b && REF_I (d->ref) >= ins)
234
          d->ref = REF (b, REF_I (d->ref) + n);
235
        d = d->next;
236
      }
237
      for (j = 0; j < MAX_OPERANDS; j++)
238
        if (f->bb[b1].insn[i].opt[j] & OPT_REF && REF_BB (f->bb[b1].insn[i].op[j]) == b
239
         && REF_I (f->bb[b1].insn[i].op[j]) >= ins)
240
          f->bb[b1].insn[i].op[j] = REF (b, REF_I (f->bb[b1].insn[i].op[j]) + n);
241
    }
242
  }
243
  for (i = 0; i < f->nmsched; i++)
244
    if (REF_BB(f->msched[i]) == b) f->msched[i] = REF (b, reloc[REF_I (f->msched[i])]);
245 996 markom
  if (cuc_debug >= 8) print_cuc_bb (f, "POSTINSERT");
246 953 markom
  cuc_check (f);
247
}
248
 
249 897 markom
/* returns nonzero, if instruction was simplified */
250
int apply_edge_condition (cuc_insn *ii)
251
{
252
  unsigned int c = ii->op[2];
253
 
254 931 markom
  switch (ii->index) {
255
  case II_AND:
256 897 markom
    if (ii->opt[2] & OPT_CONST && c == 0) {
257
      change_insn_type (ii, II_ADD);
258
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
259
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
260
      return 1;
261 932 markom
    } else if (ii->opt[2] & OPT_CONST && c == 0xffffffff) {
262
      change_insn_type (ii, II_ADD);
263
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
264
      return 1;
265 931 markom
    } else break;
266
  case II_OR:
267 932 markom
    if (ii->opt[2] & OPT_CONST && c == 0x0) {
268 897 markom
      change_insn_type (ii, II_ADD);
269
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
270
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
271
      return 1;
272 932 markom
    } else if (ii->opt[2] & OPT_CONST && c == 0xffffffff) {
273
      change_insn_type (ii, II_ADD);
274
      ii->op[1] = 0xffffffff; ii->opt[1] = OPT_CONST;
275
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
276
      return 1;
277 931 markom
    } else break;
278
  case II_SUB:
279 897 markom
    if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) {
280
      change_insn_type (ii, II_ADD);
281
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
282
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
283
      return 1;
284 931 markom
    } else break;
285
  case II_MUL:
286 897 markom
    if (ii->opt[2] & OPT_CONST && c == 0) {
287
      change_insn_type (ii, II_ADD);
288
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
289
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
290
      return 1;
291
    } else
292
    if (ii->opt[2] & OPT_CONST && c == 1) {
293
      change_insn_type (ii, II_ADD);
294
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
295
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
296
      return 1;
297
    } else
298
    if (ii->opt[2] & OPT_CONST && c == 0xffffffff) {
299
      change_insn_type (ii, II_SUB);
300
      ii->op[2] = ii->op[1]; ii->opt[2] = ii->opt[1];
301
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
302
      return 1;
303 931 markom
    } else break;
304
  case II_SRL:
305 897 markom
    if (ii->opt[2] & OPT_CONST && c == 0) {
306
      change_insn_type (ii, II_ADD);
307
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
308
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
309
      return 1;
310
    } else if (ii->opt[2] & OPT_CONST && c >= 32) {
311
      change_insn_type (ii, II_ADD);
312
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
313
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
314
      return 1;
315 931 markom
    } else break;
316
  case II_SLL:
317 897 markom
    if (ii->opt[2] & OPT_CONST && c == 0) {
318
      change_insn_type (ii, II_ADD);
319
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
320
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
321
      return 1;
322
    } else if (ii->opt[2] & OPT_CONST && c >= 32) {
323
      change_insn_type (ii, II_ADD);
324
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
325
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
326
      return 1;
327 931 markom
    } else break;
328
  case II_SRA:
329 897 markom
    if (ii->opt[2] & OPT_CONST && c == 0) {
330
      change_insn_type (ii, II_ADD);
331
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
332
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
333
      return 1;
334 931 markom
    } else break;
335
  case II_SFEQ:
336
    if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST) {
337
      change_insn_type (ii, II_ADD);
338
      ii->op[1] = ii->op[1] == ii->op[2]; ii->opt[1] = OPT_CONST;
339
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
340
      return 1;
341
    } else break;
342
  case II_SFNE:
343
    if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST) {
344
      change_insn_type (ii, II_ADD);
345
      ii->op[1] = ii->op[1] != ii->op[2]; ii->opt[1] = OPT_CONST;
346
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
347
      return 1;
348
    } else break;
349
  case II_SFLE:
350
    if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST) {
351
      change_insn_type (ii, II_ADD);
352
      ii->op[1] = ii->op[1] <= ii->op[2]; ii->opt[1] = OPT_CONST;
353
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
354
      return 1;
355 973 markom
    } else if (ii->opt[2] && OPT_CONST && ii->op[2] == 0) {
356
      change_insn_type (ii, II_SFEQ);
357 931 markom
    } else break;
358
  case II_SFLT:
359
    if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST) {
360
      change_insn_type (ii, II_ADD);
361
      ii->op[1] = ii->op[1] < ii->op[2]; ii->opt[1] = OPT_CONST;
362
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
363
      return 1;
364 973 markom
    } else if (ii->opt[2] && OPT_CONST && ii->op[2] == 0) {
365
      change_insn_type (ii, II_ADD);
366
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
367
    } break;
368 931 markom
  case II_SFGE:
369
    if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST) {
370
      change_insn_type (ii, II_ADD);
371
      ii->op[1] = ii->op[1] >= ii->op[2]; ii->opt[1] = OPT_CONST;
372
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
373
      return 1;
374 973 markom
    } else if (ii->opt[2] && OPT_CONST && ii->op[2] == 0) {
375
      change_insn_type (ii, II_ADD);
376
      ii->op[1] = 1; ii->opt[1] = OPT_CONST;
377 931 markom
    } else break;
378
  case II_SFGT:
379
    if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST) {
380
      change_insn_type (ii, II_ADD);
381
      ii->op[1] = ii->op[1] > ii->op[2]; ii->opt[1] = OPT_CONST;
382
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
383
      return 1;
384 973 markom
    } else if (ii->opt[2] && OPT_CONST && ii->op[2] == 0) {
385
      change_insn_type (ii, II_SFNE);
386 931 markom
    } else break;
387
  case II_CMOV:
388 897 markom
    if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) {
389
      change_insn_type (ii, II_ADD);
390
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
391
      ii->opt[3] = OPT_NONE;
392
      return 1;
393
    }
394 905 markom
    if (ii->opt[3] & OPT_CONST) {
395
      change_insn_type (ii, II_ADD);
396
      if (ii->op[3]) {
397
        ii->op[2] = 0; ii->opt[2] = OPT_CONST;
398
      } else {
399
        ii->op[1] = 0; ii->opt[1] = OPT_CONST;
400
      }
401
      ii->opt[3] = OPT_NONE;
402
      return 1;
403
    }
404 927 markom
    if (ii->type & IT_COND) {
405
      if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST) {
406
        if (ii->op[1] && !ii->op[2]) {
407
          change_insn_type (ii, II_ADD);
408
          ii->op[1] = ii->op[3]; ii->opt[1] = ii->opt[3];
409
          ii->op[2] = 0; ii->opt[2] = OPT_CONST;
410
          ii->opt[3] = OPT_NONE;
411
          return 1;
412
        }
413
        if (ii->op[1] && ii->op[2]) {
414
          change_insn_type (ii, II_ADD);
415
          ii->op[1] = 1; ii->opt[1] = OPT_CONST;
416
          ii->op[2] = 0; ii->opt[2] = OPT_CONST;
417
          ii->opt[3] = OPT_NONE;
418
          return 1;
419
        }
420
        if (!ii->op[1] && !ii->op[2]) {
421
          change_insn_type (ii, II_ADD);
422
          ii->op[1] = 0; ii->opt[1] = OPT_CONST;
423
          ii->op[2] = 0; ii->opt[2] = OPT_CONST;
424
          ii->opt[3] = OPT_NONE;
425 930 markom
          return 1;
426 927 markom
        }
427
      }
428 931 markom
      if (ii->op[1] == ii->op[3] && ii->opt[1] == ii->opt[3]) {
429
        ii->op[1] = 1; ii->opt[1] = OPT_CONST;
430
        return 1;
431
      }
432
      if (ii->op[2] == ii->op[3] && ii->opt[2] == ii->opt[3]) {
433
        ii->op[2] = 0; ii->opt[2] = OPT_CONST;
434
        return 1;
435
      }
436 927 markom
    }
437 931 markom
    break;
438 897 markom
  }
439
  return 0;
440
}
441
 
442 902 markom
/* First primary input */
443
static unsigned long tmp_op, tmp_opt;
444
 
445
/* Recursive function that searches for primary inputs;
446
   returns 0 if cmov can be replaced by add */
447
static int cmov_needed (cuc_func *f, int ref)
448
{
449
  cuc_insn *ii = &f->INSN(ref);
450
  int j;
451
 
452 903 markom
  cucdebug (4, " %x", ref);
453 902 markom
  /* mark visited, if already marked, we have a loop, ignore */
454
  if (ii->tmp) return 0;
455
  ii->tmp = 1;
456
 
457
  /* handle normal movs separately */
458 917 markom
  if (ii->index == II_ADD && !(ii->type & IT_VOLATILE)
459 902 markom
    && ii->opt[2] == OPT_CONST && ii->op[2] == 0) {
460
    if (ii->opt[1] == OPT_REF) {
461
      if (cmov_needed (f, ii->op[1])) {
462
        ii->tmp = 0;
463
        return 1;
464
      }
465
    } else {
466
      if (tmp_opt == OPT_NONE) {
467
        tmp_op = ii->op[1];
468
        tmp_opt = ii->opt[1];
469
      } else if (tmp_opt != ii->opt[1] || tmp_op != ii->op[1]) {
470
        ii->tmp = 0;
471
        return 1;
472
      }
473
    }
474
    ii->tmp = 0;
475
    return 0;
476
  }
477
 
478
  /* Is this instruction CMOV? no => add to primary inputs */
479 1308 phoenix
  if ((ii->index != II_CMOV) || (ii->type & IT_VOLATILE)) {
480 902 markom
    if (tmp_opt == OPT_NONE) {
481
      tmp_op = ref;
482
      tmp_opt = OPT_REF;
483
      ii->tmp = 0;
484
      return 0;
485
    } else if (tmp_opt != OPT_REF || tmp_op != ref) {
486
      ii->tmp = 0;
487
      return 1;
488 917 markom
    } else {
489
      ii->tmp = 0;
490
      return 0;
491 902 markom
    }
492 1308 phoenix
  }
493 902 markom
 
494
  for (j = 1; j < 3; j++) {
495 903 markom
    cucdebug (4, "(%x:%i)", ref, j);
496 902 markom
    if (ii->opt[j] == OPT_REF) {
497
      if (cmov_needed (f, ii->op[j])) {
498
        ii->tmp = 0;
499
        return 1;
500
      }
501
    } else {
502
      if (tmp_opt == OPT_NONE) {
503
        tmp_op = ii->op[j];
504
        tmp_opt = ii->opt[j];
505
      } else if (tmp_opt != ii->opt[j] || tmp_op != ii->op[j]) {
506
        ii->tmp = 0;
507
        return 1;
508
      }
509
    }
510
  }
511
 
512
  ii->tmp = 0;
513
  return 0;
514
}
515
 
516
/* Search and optimize complex cmov assignments */
517 931 markom
int optimize_cmovs (cuc_func *f)
518 902 markom
{
519 931 markom
  int modified = 0;
520 1308 phoenix
  int b, i;
521 902 markom
 
522
  /* Mark all instructions unvisited */
523
  for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD))
524
    for (i = 0; i < f->bb[b].ninsn; i++) f->bb[b].insn[i].tmp = 0;
525
 
526
  for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD)) {
527
    for (i = 0; i < f->bb[b].ninsn; i++) {
528
      cuc_insn *ii = &f->bb[b].insn[i];
529
      if (ii->index == II_CMOV && !(ii->type & IT_VOLATILE)) {
530
        tmp_opt = OPT_NONE;
531 903 markom
        cucdebug (4, "\n");
532 902 markom
        if (!cmov_needed (f, REF(b, i))) {
533
          assert (tmp_opt != OPT_NONE);
534
          change_insn_type (ii, II_ADD);
535
          ii->op[1] = tmp_op; ii->opt[1] = tmp_opt;
536
          ii->op[2] = 0; ii->opt[2] = OPT_CONST;
537
          ii->opt[3] = OPT_NONE;
538 931 markom
          modified = 1;
539 902 markom
        }
540
      }
541
    }
542
  }
543 931 markom
  return modified;
544 902 markom
}
545
 
546 930 markom
/* returns number of instructions, using instruction ref */
547
static int insn_uses (cuc_func *f, int ref)
548
{
549
  int b, i, j;
550
  int cnt = 0;
551
  for (b = 0; b < f->num_bb; b++)
552
    for (i = 0; i < f->bb[b].ninsn; i++)
553
      for (j = 0; j < MAX_OPERANDS; j++)
554
        if (f->bb[b].insn[i].opt[j] & OPT_REF && f->bb[b].insn[i].op[j] == ref) cnt++;
555
  return cnt;
556
}
557
 
558
/* handles some common CMOV, CMOV-CMOV cases;
559
   returns nonzero if anything optimized */
560
static int optimize_cmov_more (cuc_func *f, int ref)
561
{
562
  int t = 0;
563
  cuc_insn *ii = &f->INSN(ref);
564
  assert (ii->index == II_CMOV);
565
 
566
  /* In case of x = cmov x, y; or x = cmov y, x; we have
567
     asynchroneous loop -> remove it */
568
  if ((ii->opt[1] & OPT_REF) && ii->op[1] == ref) t = 1;
569
  if ((ii->opt[2] & OPT_REF) && ii->op[2] == ref) t = 2;
570
  if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) t = 2;
571
  if (t) {
572
    change_insn_type (ii, II_ADD);
573
    cucdebug (2, "%8x:cmov     %i\n", ref, t);
574
    ii->opt[t] = OPT_CONST;
575
    ii->op[t] = 0;
576
    ii->opt[3] = OPT_NONE;
577
    return 1;
578
  }
579
  if (!(ii->type & IT_COND)) {
580
    for (t = 1; t <= 2; t++) {
581
      /*   cmov L, X, Y, C1
582
           cmov Z, L, Y, C2
583
         can be replaced with simpler:
584
           cmov L, C1, C2, C2
585
           cmov Z, X, Y, L */
586
      if (ii->opt[t] == OPT_REF && f->INSN(ii->op[t]).index == II_CMOV) {
587
        int r = ii->op[t];
588
        unsigned long x, xt, y, yt;
589
        cuc_insn *prev = &f->INSN(r);
590
        cuc_check (f);
591
        cucdebug (3, "%x-%x\n", ref, r);
592
        assert (!(prev->type & IT_COND));
593
        if (prev->op[3 - t] != ii->op[3 - t] || prev->opt[3 - t] != ii->opt[3 - t]
594
         || insn_uses (f, r) > 1) continue;
595
        cucdebug (3, "%x-%x cmov more\n", ref, r);
596
        prev->type |= IT_COND;
597
        x = prev->op[t]; xt = prev->opt[t];
598
        y = prev->op[3 - t]; yt = prev->opt[3 - t];
599
        prev->op[t] = ii->op[3]; prev->opt[t] = ii->opt[3];     /* C2 */
600
        ii->op[3] = r; ii->opt[3] = OPT_REF;                    /* L */
601
        prev->op[3 - t] = prev->op[3]; prev->opt[3 - t] = prev->opt[3]; /* C1 */
602
        prev->op[3] = prev->op[t]; prev->opt[3] = prev->opt[t]; /* C2 */
603
        ii->op[t] = x; ii->opt[t] = xt;                         /* X */
604
        ii->op[3 - t] = y; ii->opt[3 - t] = yt;                 /* Y */
605
        prev->op[0] = -1; prev->opt[0] = OPT_REGISTER | OPT_DEST;
606
        cuc_check (f);
607
        return 1;
608
      }
609
    }
610
  }
611
 
612 938 markom
  if (ii->opt[3] & OPT_REF) {
613 930 markom
    cuc_insn *prev = &f->INSN(ii->op[3]);
614
    assert (prev->type & IT_COND);
615
    if (prev->index == II_CMOV) {
616 931 markom
      /* negated conditional:
617
           cmov x, 0, 1, y
618
           cmov z, a, b, x
619
         is replaced by
620
           cmov z, b, a, y */
621
      if (prev->opt[1] & OPT_CONST && prev->opt[2] & OPT_CONST
622
       && !prev->op[1] && prev->op[2]) {
623
        unsigned long t;
624
        t = ii->op[1]; ii->op[1] = ii->op[2]; ii->op[2] = t;
625
        t = ii->opt[1]; ii->opt[1] = ii->opt[2]; ii->opt[2] = t;
626
        ii->op[3] = prev->op[3]; ii->opt[3] = prev->opt[3];
627
      }
628 930 markom
    } else if (prev->index == II_ADD) {
629 931 markom
      /*   add x, y, 0
630
           cmov z, a, b, x
631
        is replaced by
632
           cmov z, a, b, y */
633 930 markom
      if (prev->opt[2] & OPT_CONST && prev->op[2] == 0) {
634
        ii->op[3] = prev->op[1]; ii->opt[3] = prev->opt[1];
635
        return 1;
636
      }
637
    }
638
  }
639 1046 markom
 
640
  /* Check if both choices can be pushed through */
641 1047 markom
  if (ii->opt[1] & OPT_REF && ii->opt[2] & OPT_REF
642
    /* Usually doesn't make sense to move conditionals though => more area */
643
    && !(ii->type & IT_COND)) {
644 1046 markom
    cuc_insn *a, *b;
645
    a = &f->INSN(ii->op[1]);
646
    b = &f->INSN(ii->op[2]);
647
    if (a->index == b->index && !(a->type & IT_VOLATILE) && !(b->type & IT_VOLATILE)) {
648
      int diff = -1;
649
      int i;
650
      for (i = 0; i < MAX_OPERANDS; i++)
651
        if (a->opt[i] != b->opt[i] || !(a->op[i] == b->op[i] || a->opt[i] & OPT_REGISTER)) {
652
          if (diff == -1) diff = i; else diff = -2;
653
        }
654
      /* If diff == -1, it will be eliminated by CSE */
655
      if (diff >= 0) {
656
        cuc_insn tmp, cmov;
657
        int ref2 = REF (REF_BB (ref), REF_I (ref) + 1);
658
        insert_insns (f, ref, 1);
659
        a = &f->INSN(f->INSN(ref2).op[1]);
660
        b = &f->INSN(f->INSN(ref2).op[2]);
661 1308 phoenix
        cucdebug (4, "ref = %x %lx %lx\n", ref, f->INSN(ref2).op[1],
662
                  f->INSN(ref2).op[2]);
663 1046 markom
        if (cuc_debug >= 7) {
664
          print_cuc_bb (f, "AAA");
665
          cuc_check (f);
666
        }
667
        tmp = *a;
668
        cmov = f->INSN(ref2);
669
        tmp.op[diff] = ref; tmp.opt[diff] = OPT_REF;
670 1062 markom
        cmov.op[0] = -1; cmov.opt[0] = OPT_REGISTER | OPT_DEST;
671 1046 markom
        cmov.op[1] = a->op[diff]; cmov.opt[1] = a->opt[diff];
672
        cmov.op[2] = b->op[diff]; cmov.opt[2] = b->opt[diff];
673
        change_insn_type (&cmov, II_CMOV);
674
        cmov.type &= ~IT_COND;
675 1308 phoenix
        cucdebug (4, "ref2 = %x %lx %lx\n", ref2, cmov.op[1], cmov.op[2]);
676 1046 markom
        if (cmov.opt[1] & OPT_REF && cmov.opt[2] & OPT_REF
677
         && f->INSN(cmov.op[1]).type & IT_COND) {
678
          assert (f->INSN(cmov.op[2]).type & IT_COND);
679
          cmov.type |= IT_COND;
680
        }
681
        f->INSN(ref) = cmov;
682
        f->INSN(ref2) = tmp;
683
        if (cuc_debug >= 6) print_cuc_bb (f, "BBB");
684
        cuc_check (f);
685 1059 markom
        return 1;
686 1046 markom
      }
687
    }
688
  }
689 930 markom
  return 0;
690
}
691
 
692 897 markom
/* Optimizes dataflow tree */
693 931 markom
int optimize_tree (cuc_func *f)
694 897 markom
{
695
  int b, i, j;
696
  int modified;
697 931 markom
  int gmodified = 0;
698 897 markom
 
699
  do {
700
    modified = 0;
701 930 markom
    if (cuc_debug) cuc_check (f);
702 897 markom
    for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD)) {
703
      for (i = 0; i < f->bb[b].ninsn; i++) {
704
        cuc_insn *ii = &f->bb[b].insn[i];
705
        /* We tend to have the third parameter const if instruction is cumutative */
706 929 markom
        if ((ii->opt[1] & OPT_CONST) && !(ii->opt[2] & OPT_CONST)) {
707
          int cond = ii->index == II_SFEQ || ii->index == II_SFNE
708
                  || ii->index == II_SFLT || ii->index == II_SFLE
709
                  || ii->index == II_SFGT || ii->index == II_SFGE;
710
          if (known[ii->index].comutative || cond) {
711
            unsigned long t = ii->opt[1];
712
            ii->opt[1] = ii->opt[2];
713
            ii->opt[2] = t;
714
            t = ii->op[1];
715
            ii->op[1] = ii->op[2];
716
            ii->op[2] = t;
717
            modified = 1; cucdebug (2, "%08x:<>\n", REF(b, i));
718
            if (cond) {
719
              if (ii->index == II_SFEQ) ii->index = II_SFNE;
720
              else if (ii->index == II_SFNE) ii->index = II_SFEQ;
721
              else if (ii->index == II_SFLE) ii->index = II_SFGT;
722
              else if (ii->index == II_SFLT) ii->index = II_SFGE;
723
              else if (ii->index == II_SFGE) ii->index = II_SFLT;
724
              else if (ii->index == II_SFGT) ii->index = II_SFLE;
725
              else assert (0);
726
            }
727
          }
728 897 markom
        }
729
 
730
        /* Try to do the promotion */
731
        /* We have two consecutive expressions, containing constants,
732
         * if previous is a simple expression we can handle it simply: */
733
        for (j = 0; j < MAX_OPERANDS; j++)
734
          if (ii->opt[j] & OPT_REF) {
735
            cuc_insn *t = &f->INSN(ii->op[j]);
736
            if (f->INSN(ii->op[j]).index == II_ADD
737
             && f->INSN(ii->op[j]).opt[2] & OPT_CONST
738
             && f->INSN(ii->op[j]).op[2] == 0
739 931 markom
             && !(ii->type & IT_MEMORY && t->type & IT_MEMADD)) {
740 897 markom
            /* do not promote through add-mem, and branches */
741 1308 phoenix
              modified = 1;
742
              cucdebug (2, "%8x:promote%i %8lx %8lx\n", REF (b, i), j, ii->op[j], t->op[1]);
743
              ii->op[j] = t->op[1];
744
              ii->opt[j] = t->opt[1];
745 897 markom
            }
746
          }
747 930 markom
 
748
        /* handle some CMOV cases more deeply */
749
        if (ii->index == II_CMOV && optimize_cmov_more (f, REF (b, i))) {
750
          modified = 1;
751
          continue;
752 897 markom
        }
753
 
754
        /* Do nothing to volatile instructions */
755
        if (ii->type & IT_VOLATILE) continue;
756
 
757
        /* Check whether we can simplify the instruction */
758
        if (apply_edge_condition (ii)) {
759
          modified = 1;
760
          continue;
761
        }
762
        /* We cannot do anything more if at least one is not constant */
763
        if (!(ii->opt[2] & OPT_CONST)) continue;
764
 
765
        if (ii->opt[1] & OPT_CONST) { /* We have constant expression */
766
          unsigned long value;
767
          int ok = 1;
768
          /* Was constant expression already? */
769
          if (ii->index == II_ADD && !ii->op[2]) continue;
770
 
771
          if (ii->index == II_ADD) value = ii->op[1] + ii->op[2];
772
          else if (ii->index == II_SUB) value = ii->op[1] - ii->op[2];
773
          else if (ii->index == II_SLL) value = ii->op[1] << ii->op[2];
774
          else if (ii->index == II_SRL) value = ii->op[1] >> ii->op[2];
775
          else if (ii->index == II_MUL) value = ii->op[1] * ii->op[2];
776
          else if (ii->index == II_OR) value = ii->op[1] | ii->op[2];
777
          else if (ii->index == II_XOR) value = ii->op[1] ^ ii->op[2];
778
          else if (ii->index == II_AND) value = ii->op[1] & ii->op[2];
779
          else ok = 0;
780
          if (ok) {
781
            change_insn_type (ii, II_ADD);
782
            ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
783
            ii->op[1] = value; ii->opt[1] = OPT_CONST;
784
            ii->op[2] = 0; ii->opt[2] = OPT_CONST;
785
            modified = 1; cucdebug (2, "%8x:const\n", REF (b, i));
786
          }
787
        } else if (ii->opt[1] & OPT_REF) {
788
          cuc_insn *prev = &f->INSN(ii->op[1]);
789 930 markom
          /* Is this just a move? */
790 897 markom
          if (ii->index == II_ADD
791
           && !(ii->type & IT_MEMADD) && ii->op[2] == 0) {
792
            int b1, i1, j1;
793 1308 phoenix
            cucdebug (2, "%8x:link      %8lx: ", REF(b, i), ii->op[1]);
794 1059 markom
            if (!(prev->type & (IT_OUTPUT | IT_VOLATILE))) {
795
              assert (ii->opt[0] & OPT_DEST);
796
              prev->op[0] = ii->op[0]; prev->opt[0] = ii->opt[0];
797
              prev->type |= ii->type & IT_OUTPUT;
798
              for (b1 = 0; b1 < f->num_bb; b1++) if (!(f->bb[b1].type & BB_DEAD))
799
                for (i1 = 0; i1 < f->bb[b1].ninsn; i1++)
800
                  for (j1 = 0; j1 < MAX_OPERANDS; j1++)
801
                    if ((f->bb[b1].insn[i1].opt[j1] & OPT_REF)
802
                     && f->bb[b1].insn[i1].op[j1] == REF(b, i)) {
803
                      cucdebug (2, "%x ", REF (b1, i1));
804
                      f->bb[b1].insn[i1].op[j1] = ii->op[1];
805
                    }
806
              cucdebug (2, "\n");
807
              change_insn_type (ii, II_NOP);
808
            }
809 897 markom
          } else if (prev->opt[2] & OPT_CONST) {
810
            /* Handle some common cases */
811
            /* add - add joining */
812
            if (ii->index == II_ADD && prev->index == II_ADD) {
813
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
814
              ii->op[2] += prev->op[2];
815
              modified = 1; cucdebug (2, "%8x: add-add\n", REF(b, i));
816
            } else /* add - sub joining */
817
            if (ii->index == II_ADD && prev->index == II_SUB) {
818
              change_insn_type (&insn[i], II_SUB);
819
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
820
              ii->op[2] += prev->op[2];
821
              modified = 1; cucdebug (2, "%8x: add-sub\n", REF(b, i));
822
            } else /* sub - add joining */
823
            if (ii->index == II_SUB && prev->index == II_ADD) {
824
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
825
              ii->op[2] += prev->op[2];
826
              modified = 1; cucdebug (2, "%8x: sub-add\n", REF(b, i));
827 929 markom
            } else /* add - sfxx joining */
828
            if (prev->index == II_ADD && (
829
                ii->index == II_SFEQ || ii->index == II_SFNE
830
             || ii->index == II_SFLT || ii->index == II_SFLE
831
             || ii->index == II_SFGT || ii->index == II_SFGE)) {
832 1041 markom
              if (ii->opt[2] & OPT_CONST && ii->op[2] < 0x80000000) {
833 929 markom
                ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
834
                ii->op[2] -= prev->op[2];
835
                modified = 1; cucdebug (2, "%8x: add-sfxx\n", REF(b, i));
836
              }
837
            } else /* sub - sfxx joining */
838
            if (prev->index == II_SUB && (
839
                ii->index == II_SFEQ || ii->index == II_SFNE
840
             || ii->index == II_SFLT || ii->index == II_SFLE
841
             || ii->index == II_SFGT || ii->index == II_SFGE)) {
842 1046 markom
              if (ii->opt[2] & OPT_CONST && ii->op[2] < 0x80000000) {
843 929 markom
                ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
844
                ii->op[2] += prev->op[2];
845
                modified = 1; cucdebug (2, "%8x: sub-sfxx\n", REF(b, i));
846
              }
847 897 markom
            }
848
          }
849
        }
850
      }
851
    }
852 931 markom
    if (modified) gmodified = 1;
853 897 markom
  } while (modified);
854 931 markom
  return gmodified;
855 897 markom
}
856
 
857
/* Remove nop instructions */
858 931 markom
int remove_nops (cuc_func *f)
859 897 markom
{
860
  int b;
861 931 markom
  int modified = 0;
862 897 markom
  for (b = 0; b < f->num_bb; b++) {
863
    int c, d = 0, i, j;
864
    cuc_insn *insn = f->bb[b].insn;
865
    for (i = 0; i < f->bb[b].ninsn; i++)
866
      if (insn[i].index != II_NOP) {
867
        reloc [i] = d;
868
        insn[d++] = insn[i];
869
      } else {
870
        reloc[i] = d; /* For jumps only */
871
      }
872 931 markom
    if (f->bb[b].ninsn != d) modified = 1;
873 897 markom
    f->bb[b].ninsn = d;
874
 
875
    /* Relocate references from all basic blocks */
876
    for (c = 0; c < f->num_bb; c++)
877
      for (i = 0; i < f->bb[c].ninsn; i++) {
878
        dep_list *d = f->bb[c].insn[i].dep;
879
        for (j = 0; j < MAX_OPERANDS; j++)
880
          if ((f->bb[c].insn[i].opt[j] & OPT_REF)
881
            && REF_BB(f->bb[c].insn[i].op[j]) == b)
882
            f->bb[c].insn[i].op[j] = REF (b, reloc[REF_I (f->bb[c].insn[i].op[j])]);
883
 
884
        while (d) {
885
          if (REF_BB(d->ref) == b) d->ref = REF (b, reloc[REF_I (d->ref)]);
886
          d = d->next;
887
        }
888
      }
889
  }
890 931 markom
  return modified;
891 897 markom
}
892
 
893 932 markom
static void unmark_tree (cuc_func *f, int ref)
894
{
895
  cuc_insn *ii = &f->INSN(ref);
896 973 markom
  cucdebug (5, "%x ", ref);
897 932 markom
  if (ii->type & IT_UNUSED) {
898
    int j;
899
    ii->type &= ~IT_UNUSED;
900
    for (j = 0; j < MAX_OPERANDS; j++)
901
      if (ii->opt[j] & OPT_REF) unmark_tree (f, ii->op[j]);
902
  }
903
}
904
 
905 897 markom
/* Remove unused assignments */
906 931 markom
int remove_dead (cuc_func *f)
907 897 markom
{
908 1308 phoenix
  int b, i;
909 897 markom
  for (b = 0; b < f->num_bb; b++)
910
    for (i = 0; i < f->bb[b].ninsn; i++)
911 932 markom
      f->bb[b].insn[i].type |= IT_UNUSED;
912 897 markom
 
913 932 markom
  for (b = 0; b < f->num_bb; b++)
914
    for (i = 0; i < f->bb[b].ninsn; i++) {
915
      cuc_insn *ii = &f->bb[b].insn[i];
916
      if (ii->type & IT_VOLATILE || ii->type & IT_OUTPUT
917
       || II_IS_LOAD (ii->index) && (f->memory_order == MO_NONE || f->memory_order == MO_WEAK)
918
       || II_IS_STORE (ii->index)) {
919
        unmark_tree (f, REF (b, i));
920 973 markom
        cucdebug (5, "\n");
921 932 markom
      }
922
    }
923 897 markom
 
924
  for (b = 0; b < f->num_bb; b++)
925
    for (i = 0; i < f->bb[b].ninsn; i++)
926
      if (f->bb[b].insn[i].type & IT_UNUSED) {
927
        change_insn_type (&f->bb[b].insn[i], II_NOP);
928
      }
929
 
930 931 markom
  return remove_nops (f);
931 897 markom
}
932
 
933
/* Removes trivial register assignments */
934 931 markom
int remove_trivial_regs (cuc_func *f)
935 897 markom
{
936
  int b, i;
937 939 markom
  for (i = 0; i < MAX_REGS; i++) f->saved_regs[i] = caller_saved[i];
938 897 markom
 
939
  for (b = 0; b < f->num_bb; b++) {
940
    cuc_insn *insn = f->bb[b].insn;
941
    for (i = 0; i < f->bb[b].ninsn; i++) {
942
      if (insn[i].index == II_ADD
943
        && insn[i].opt[0] & OPT_REGISTER
944
        && insn[i].opt[1] & OPT_REGISTER && insn[i].op[0] == insn[i].op[1]
945
        && insn[i].opt[2] & OPT_CONST && insn[i].op[2] == 0) {
946
          if (insn[i].type & IT_OUTPUT) f->saved_regs[insn[i].op[0]] = 1;
947
          change_insn_type (&insn[i], II_NOP);
948
        }
949
    }
950
  }
951
  if (cuc_debug >= 2) {
952 997 markom
    PRINTF ("saved regs ");
953
    for (i = 0; i < MAX_REGS; i++) PRINTF ("%i:%i ", i, f->saved_regs[i]);
954
    PRINTF ("\n");
955 897 markom
  }
956 931 markom
  return remove_nops (f);
957 897 markom
}
958
 
959
/* Determine inputs and outputs */
960
void set_io (cuc_func *f)
961
{
962
  int b, i, j;
963
  /* Determine register usage */
964
  for (i = 0; i < MAX_REGS; i++) {
965
    f->lur[i] = -1;
966
    f->used_regs[i] = 0;
967
  }
968 902 markom
  if (cuc_debug > 5) print_cuc_bb (f, "SET_IO");
969 897 markom
  for (b = 0; b < f->num_bb; b++) {
970
    for (i = 0; i < f->bb[b].ninsn; i++)
971
      for (j = 0; j < MAX_OPERANDS; j++)
972 1308 phoenix
        if (f->bb[b].insn[i].opt[j] & OPT_REGISTER && f->bb[b].insn[i].op[j] >= 0) {
973 897 markom
          if (f->bb[b].insn[i].opt[j] & OPT_DEST) f->lur[f->bb[b].insn[i].op[j]] = REF (b, i);
974
          else f->used_regs[f->bb[b].insn[i].op[j]] = 1;
975 1308 phoenix
        }
976 897 markom
  }
977
}
978
 
979
/* relocate all accesses inside of BB b to back/fwd */
980
static void relocate_bb (cuc_bb *bb, int b, int back, int fwd)
981
{
982
  int i, j;
983
  for (i = 0; i < bb->ninsn; i++)
984
    for (j = 0; j < MAX_OPERANDS; j++)
985
      if (bb->insn[i].opt[j] & OPT_REF
986
       && REF_BB (bb->insn[i].op[j]) == b) {
987
        int t = REF_I (bb->insn[i].op[j]);
988
        if (t < i) bb->insn[i].op[j] = REF (back, t);
989
        else bb->insn[i].op[j] = REF (fwd, t);
990
      }
991
}
992
 
993
/* Latch outputs in loops */
994
void add_latches (cuc_func *f)
995
{
996
  int b, i, j;
997
 
998
  //print_cuc_bb (f, "ADD_LATCHES a");
999
  /* Cuts the tree and marks registers */
1000
  mark_cut (f);
1001
 
1002
  /* Split BBs with more than one group */
1003
  for (b = 0; b < f->num_bb; b++) expand_bb (f, b);
1004
  remove_nops (f);
1005
  //print_cuc_bb (f, "ADD_LATCHES 0");
1006
 
1007
  /* Convert accesses in BB_INLOOP type block to latched */
1008
  for (b = 0; b < f->num_bb; b++) {
1009
    int j;
1010
    for (i = 0; i < f->bb[b].ninsn; i++)
1011
      for (j = 0; j < MAX_OPERANDS; j++) if (f->bb[b].insn[i].opt[j] == OPT_REF) {
1012
        int t = f->bb[b].insn[i].op[j];
1013
        /* If we are pointing to a INLOOP block from outside, or forward
1014
           (= previous loop iteration) we must register that data */
1015
        if ((f->bb[REF_BB(t)].type & BB_INLOOP || config.cuc.no_multicycle)
1016
         && !(f->INSN(t).type & (IT_BRANCH | IT_COND))
1017
         && (REF_BB(t) != b || REF_I(t) >= i)) {
1018
          f->INSN(t).type |= IT_LATCHED;
1019
        }
1020
      }
1021
  }
1022
  //print_cuc_bb (f, "ADD_LATCHES 1");
1023
 
1024
  /* Add latches at the end of blocks as needed */
1025
  for (b = 0; b < f->num_bb; b++) {
1026
    int nreg = 0;
1027
    cuc_insn *insn;
1028
    for (i = 0; i < f->bb[b].ninsn; i++)
1029
      if (f->bb[b].insn[i].type & IT_LATCHED) nreg++;
1030
    if (nreg) {
1031
      insn = (cuc_insn *) malloc (sizeof (cuc_insn) * (f->bb[b].ninsn + nreg));
1032
      j = 0;
1033
      for (i = 0; i < f->bb[b].ninsn; i++) {
1034
        insn[i] = f->bb[b].insn[i];
1035
        if (insn[i].type & IT_LATCHED) {
1036
          cuc_insn *ii = &insn[f->bb[b].ninsn + j++];
1037
          change_insn_type (ii, II_REG);
1038
          ii->op[0] = -1; ii->opt[0] = OPT_DEST | OPT_REGISTER;
1039
          ii->op[1] = REF (b, i); ii->opt[1] = OPT_REF;
1040
          ii->opt[2] = ii->opt[3] = OPT_NONE;
1041
          ii->dep = NULL;
1042
          ii->type = IT_VOLATILE;
1043
          sprintf (ii->disasm, "reg %i_%i", b, i);
1044
        }
1045
      }
1046
      f->bb[b].ninsn += nreg;
1047
      free (f->bb[b].insn);
1048
      f->bb[b].insn = insn;
1049
    }
1050
  }
1051
  //print_cuc_bb (f, "ADD_LATCHES 2");
1052
 
1053
  /* Repair references */
1054
  for (b = 0; b < f->num_bb; b++)
1055
    for (i = 0; i < f->bb[b].ninsn; i++)
1056
      for (j = 0; j < MAX_OPERANDS; j++)
1057
        /* If destination instruction is latched, use register instead */
1058
        if (f->bb[b].insn[i].opt[j] == OPT_REF
1059
         && f->INSN(f->bb[b].insn[i].op[j]).type & IT_LATCHED) {
1060
          int b1, i1;
1061
          b1 = REF_BB (f->bb[b].insn[i].op[j]);
1062
          //cucdebug (2, "%i.%i.%i %x\n", b, i, j, f->bb[b].insn[i].op[j]);
1063
          if (b1 != b || REF_I(f->bb[b].insn[i].op[j]) >= i) {
1064
            for (i1 = f->bb[b1].ninsn - 1; i1 >= 0; i1--) {
1065
              assert (f->bb[b1].insn[i1].index == II_REG);
1066
              if (f->bb[b1].insn[i1].op[1] == f->bb[b].insn[i].op[j]) {
1067
                f->bb[b].insn[i].op[j] = REF (b1, i1);
1068
                break;
1069
              }
1070
            }
1071
          }
1072
        }
1073
}
1074
 
1075 883 markom
/* CSE -- common subexpression elimination */
1076 931 markom
int cse (cuc_func *f)
1077 883 markom
{
1078 931 markom
  int modified = 0;
1079 1308 phoenix
  int b, i, j, b1, i1, b2, i2;
1080 883 markom
  for (b1 = 0; b1 < f->num_bb; b1++)
1081 930 markom
    for (i1 = 0; i1 < f->bb[b1].ninsn; i1++) if (f->bb[b1].insn[i1].index != II_NOP
1082
       && f->bb[b1].insn[i1].index != II_LRBB && !(f->bb[b1].insn[i1].type & IT_MEMORY)
1083
       && !(f->bb[b1].insn[i1].type & IT_MEMADD))
1084 883 markom
      for (b2 = 0; b2 < f->num_bb; b2++)
1085 930 markom
        for (i2 = 0; i2 < f->bb[b2].ninsn; i2++)
1086
          if (f->bb[b2].insn[i2].index != II_NOP && f->bb[b2].insn[i2].index != II_LRBB
1087
           && !(f->bb[b2].insn[i2].type & IT_MEMORY) && !(f->bb[b2].insn[i2].type & IT_MEMADD)
1088
           && (b1 != b2 || i2 > i1)) {
1089
            cuc_insn *ii1 = &f->bb[b1].insn[i1];
1090
            cuc_insn *ii2 = &f->bb[b2].insn[i2];
1091
            int ok = 1;
1092 883 markom
 
1093 930 markom
            /* Do we have an exact match? */
1094
            if (ii1->index != ii2->index) continue;
1095
            if (ii2->type & IT_VOLATILE) continue;
1096
 
1097
            /* Check all operands also */
1098
            for (j = 0; j < MAX_OPERANDS; j++) {
1099
              if (ii1->opt[j] != ii2->opt[j]) {
1100
                ok = 0;
1101
                break;
1102
              }
1103
              if (ii1->opt[j] & OPT_DEST) continue;
1104
              if (ii1->opt[j] != OPT_NONE && ii1->op[j] != ii2->op[j]) {
1105
                ok = 0;
1106
                break;
1107
              }
1108
            }
1109
 
1110
            if (ok) {
1111
              /* remove duplicated instruction and relink the references */
1112
              cucdebug (3, "%x - %x are same\n", REF(b1, i1), REF(b2, i2));
1113
              change_insn_type (ii2, II_NOP);
1114 931 markom
              modified = 1;
1115 930 markom
              for (b = 0; b < f->num_bb; b++)
1116
                for (i = 0; i < f->bb[b].ninsn; i++)
1117
                  for (j = 0; j < MAX_OPERANDS; j++)
1118
                    if (f->bb[b].insn[i].opt[j] & OPT_REF
1119
                     && f->bb[b].insn[i].op[j] == REF (b2, i2))
1120
                      f->bb[b].insn[i].op[j] = REF (b1, i1);
1121
            }
1122
          }
1123 931 markom
  return modified;
1124 883 markom
}
1125
 
1126
static int count_cmovs (cuc_insn *ii, int match)
1127
{
1128
  int c = 0, j;
1129
  if (match & 2) {
1130
    for (j = 0; j < MAX_OPERANDS; j++)
1131
      if (ii->opt[j] & OPT_DEST) c++;
1132
  }
1133
  if (match & 1) {
1134
    for (j = 0; j < MAX_OPERANDS; j++)
1135
      if (!(ii->opt[j] & OPT_DEST) && ii->opt[j] & OPT_REF) c++;
1136
  } else {
1137
    for (j = 0; j < MAX_OPERANDS; j++)
1138
      if (!(ii->opt[j] & OPT_DEST) && ii->opt[j] != OPT_NONE) c++;
1139
  }
1140
  return c;
1141
}
1142
 
1143 897 markom
static void search_csm (int iter, cuc_func *f, cuc_shared_list *list);
1144
static cuc_shared_list *main_list;
1145 883 markom
static int *iteration;
1146
 
1147 897 markom
/* CSM -- common subexpression matching -- resource sharing
1148
   We try to match tree of instruction inside a BB with as many
1149
   matches as possible. All possibilities are collected and
1150
   options, making situation worse are removed */
1151 883 markom
void csm (cuc_func *f)
1152
{
1153
  int b, i, j;
1154
  int cnt;
1155 897 markom
  cuc_shared_list *list;
1156 883 markom
  cuc_timings timings;
1157
 
1158
  analyse_timings (f, &timings);
1159
  main_list = NULL;
1160
  for (b = 0; b < f->num_bb; b++) {
1161
    assert (iteration = (int *)malloc (sizeof (int) * f->bb[b].ninsn));
1162
    for (i = 0; i < f->bb[b].ninsn; i++) {
1163
      int cnt = 0, cntc = 0;
1164
      double size = 0., sizec = 0.;
1165
      int j2 = 0;
1166
      for (j = 0; j < f->bb[b].ninsn; j++)
1167
        if (f->bb[b].insn[i].index == f->bb[b].insn[j].index) {
1168
          int ok = 1;
1169
          for (j2 = 0; j2 < MAX_OPERANDS; j2++) if (!(f->bb[b].insn[j].opt[j2] & OPT_REF))
1170
            if (f->bb[b].insn[j].opt[j2] != f->bb[b].insn[i].opt[j2]
1171
             || f->bb[b].insn[j].op[j2] != f->bb[b].insn[i].opt[j2]) {
1172
              ok = 0;
1173
              break;
1174
            }
1175
          if (ok) {
1176
            cntc++;
1177
            sizec = sizec + insn_size (&f->bb[b].insn[j]);
1178
          } else {
1179
            cnt++;
1180
            size = size + insn_size (&f->bb[b].insn[j]);
1181
          }
1182
          iteration[j] = 0;
1183
        } else iteration[j] = -1;
1184
      if (cntc > 1) {
1185 897 markom
        assert (list = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1186 883 markom
        list->next = main_list;
1187
        list->from = NULL;
1188
        list->ref = REF (b, i);
1189
        list->cnt = cnt;
1190
        list->cmatch = 1;
1191
        list->cmovs = count_cmovs (&f->bb[b].insn[i], 3);
1192
        list->osize = sizec;
1193
        list->size = ii_size (f->bb[b].insn[i].index, 1);
1194
        main_list = list;
1195
        search_csm (0, f, list);
1196
      }
1197
      if (cnt > 1) {
1198 897 markom
        assert (list = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1199 883 markom
        list->next = main_list;
1200
        list->from = NULL;
1201
        list->ref = REF (b, i);
1202
        list->cnt = cnt + cntc;
1203
        list->cmatch = 0;
1204
        list->cmovs = count_cmovs (&f->bb[b].insn[i], 2);
1205
        list->osize = size + sizec;
1206
        list->size = ii_size (f->bb[b].insn[i].index, 0);
1207
        main_list = list;
1208
        search_csm (0, f, list);
1209
      }
1210
    }
1211
    free (iteration);
1212
  }
1213
 
1214
  for (list = main_list; list; list = list->next) list->dead = 0;
1215
  cnt = 0;
1216
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
1217
  cucdebug (1, "noptions = %i\n", cnt);
1218
 
1219
  /* Now we will check the real size of the 'improvements'; if the size
1220
     actually increases, we abandom the option */
1221
  for (list = main_list; list; list = list->next)
1222
    if (list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size >= list->osize) list->dead = 1;
1223
 
1224
  cnt = 0;
1225
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
1226
  cucdebug (1, "noptions = %i\n", cnt);
1227
 
1228
  /* Count number of instructions grouped */
1229
  for (list = main_list; list; list = list->next) {
1230 897 markom
    cuc_shared_list *l = list;
1231 883 markom
    int c = 0;
1232
    while (l) {
1233
      c++;
1234
      if (f->INSN(l->ref).type & (IT_VOLATILE | IT_MEMORY | IT_MEMADD)) list->dead = 1;
1235
      l = l->from;
1236
    }
1237
    list->ninsn = c;
1238
  }
1239
 
1240
  cnt = 0;
1241
  for (list = main_list; list; list = list->next)
1242
    if (!list->dead) cnt++;
1243
  cucdebug (1, "noptions = %i\n", cnt);
1244
 
1245
#if 1
1246
  /* We can get a lot of options here, so we will delete duplicates */
1247
  for (list = main_list; list; list = list->next) if (!list->dead) {
1248 897 markom
    cuc_shared_list *l;
1249 883 markom
    for (l = list->next; l; l = l->next) if (!l->dead) {
1250
      int ok = 1;
1251 897 markom
      cuc_shared_list *t1 = list;
1252
      cuc_shared_list *t2 = l;
1253 883 markom
      while (ok && t1 && t2) {
1254
        if (f->INSN(t1->ref).index == f->INSN(t2->ref).index) {
1255
          /* If other operands are matching, we must check for them also */
1256
          if (t1->cmatch) {
1257
            int j;
1258
            for (j = 0; j < MAX_OPERANDS; j++)
1259
              if (!(f->INSN(t1->ref).opt[j] & OPT_REF) || !(f->INSN(t2->ref).opt[j] & OPT_REF)
1260
               || f->INSN(t1->ref).opt[j] != f->INSN(t2->ref).opt[j]
1261
               || f->INSN(t1->ref).op[j] != f->INSN(t2->ref).op[j]) {
1262
                ok = 0;
1263
                break;
1264
              }
1265
          }
1266
 
1267
          /* This option is duplicate, remove */
1268
          if (ok) t1->dead = 1;
1269
        }
1270
        t1 = t1->from;
1271
        t2 = t2->from;
1272
      }
1273
    }
1274
  }
1275
  cnt = 0;
1276
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
1277
  cucdebug (1, "noptions = %i\n", cnt);
1278
#endif
1279
  /* Print out */
1280
  for (list = main_list; list; list = list->next) if (!list->dead) {
1281 897 markom
    cuc_shared_list *l = list;
1282 883 markom
    cucdebug (1, "%-4s cnt %3i ninsn %3i size %8.1f osize %8.1f cmovs %3i @",
1283
           cuc_insn_name (&f->INSN(list->ref)), list->cnt, list->ninsn,
1284
           list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size, list->osize, list->cmovs);
1285
    while (l) {
1286
      cucdebug (1, "%c%x,", l->cmatch ? '.' : '!', l->ref);
1287
      l = l->from;
1288
    }
1289
    cucdebug (1, "\n");
1290
  }
1291
 
1292
  /* Calculate estimated timings */
1293
  for (b = 0; b < f->num_bb; b++) {
1294
    cnt = 0;
1295
    for (list = main_list; list; list = list->next)
1296
      if (!list->dead && REF_BB(list->ref) == b) cnt++;
1297
 
1298
    f->bb[b].ntim = cnt;
1299
    if (!cnt) {
1300
      f->bb[b].tim = NULL;
1301
      continue;
1302
    }
1303
    assert (f->bb[b].tim = (cuc_timings *)malloc (sizeof (cuc_timings) * cnt));
1304
 
1305
    cnt = 0;
1306
    for (list = main_list; list; list = list->next) if (!list->dead && REF_BB(list->ref) == b) {
1307 897 markom
      cuc_shared_list *l = list;
1308 883 markom
      f->bb[b].tim[cnt].b = b;
1309
      f->bb[b].tim[cnt].preroll = f->bb[b].tim[cnt].unroll = 1;
1310
      f->bb[b].tim[cnt].nshared = list->ninsn;
1311 897 markom
      assert (f->bb[b].tim[cnt].shared = (cuc_shared_item *)
1312
            malloc (sizeof(cuc_shared_item) * list->ninsn));
1313
      for (i =  0; i < list->ninsn; i++, l = l->from) {
1314
        f->bb[b].tim[cnt].shared[i].ref = l->ref;
1315
        f->bb[b].tim[cnt].shared[i].cmatch = l->cmatch;
1316
      }
1317 883 markom
      f->bb[b].tim[cnt].new_time = timings.new_time + f->bb[b].cnt * (list->cnt - 1);
1318 897 markom
      f->bb[b].tim[cnt].size = timings.size +
1319
             list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size - list->osize;
1320 883 markom
      cnt++;
1321
    }
1322
  }
1323
}
1324
 
1325
/* Recursive function for searching through instruction graph */
1326 897 markom
static void search_csm (int iter, cuc_func *f, cuc_shared_list *list)
1327 883 markom
{
1328
  int b, i, j, i1;
1329 897 markom
  cuc_shared_list *l;
1330 883 markom
  b = REF_BB(list->ref);
1331
  i = REF_I(list->ref);
1332
 
1333
  for (j = 0; j < MAX_OPERANDS; j++) if (f->bb[b].insn[i].opt[j] & OPT_REF) {
1334
    int t = f->bb[b].insn[i].op[j];
1335
    int cnt = 0, cntc = 0;
1336
    double size = 0., sizec = 0.;
1337
 
1338
    /* Mark neighbours */
1339
    for (i1 = 0; i1 < f->bb[b].ninsn; i1++) {
1340
      if (iteration[i1] == iter && f->bb[b].insn[i1].opt[j] & OPT_REF) {
1341
        int t2 = f->bb[b].insn[i1].op[j];
1342
        if (f->INSN(t).index == f->INSN(t2).index && f->INSN(t2).opt[j] & OPT_REF) {
1343
          int j2;
1344
          int ok = 1;
1345
          iteration[REF_I(t2)] = iter + 1;
1346
          for (j2 = 0; j2 < MAX_OPERANDS; j2++) if (!(f->bb[b].insn[i1].opt[j2] & OPT_REF))
1347
            if (f->bb[b].insn[i1].opt[j2] != f->bb[b].insn[i].opt[j2]
1348
             || f->bb[b].insn[i1].op[j2] != f->bb[b].insn[i].opt[j2]) {
1349
              ok = 0;
1350
              break;
1351
            }
1352
          if (ok) {
1353
            cntc++;
1354
            sizec = sizec + insn_size (&f->bb[b].insn[i1]);
1355
          } else {
1356
            cnt++;
1357
            size = size + insn_size (&f->bb[b].insn[i1]);
1358
          }
1359
        }
1360
      }
1361
    }
1362
 
1363
    if (cntc > 1) {
1364 897 markom
      assert (l = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1365 883 markom
      l->next = main_list;
1366
      main_list = l;
1367
      l->from = list;
1368
      l->ref = t;
1369
      l->cnt = cnt;
1370
      l->cmatch = 1;
1371
      l->cmovs = list->cmovs + count_cmovs (&f->bb[b].insn[i], 1) - 1;
1372
      l->size = list->size + ii_size (f->bb[b].insn[i].index, 1);
1373
      l->osize = sizec;
1374
      search_csm (iter + 1, f, l);
1375
    }
1376
    if (cnt > 1) {
1377 897 markom
      assert (l = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1378 883 markom
      l->next = main_list;
1379
      main_list = l;
1380
      l->from = list;
1381
      l->ref = t;
1382
      l->cnt = cnt + cntc;
1383
      l->cmatch = 0;
1384
      l->osize = size + sizec;
1385
      l->cmovs = list->cmovs + count_cmovs (&f->bb[b].insn[i], 0) - 1;
1386
      l->size = list->size + ii_size (f->bb[b].insn[i].index, 0);
1387
      search_csm (iter + 1, f, l);
1388
    }
1389
 
1390
    /* Unmark them back */
1391
    for (i1 = 0; i1 < f->bb[b].ninsn; i1++) if (iteration[i1] > iter) iteration[i1] = -1;
1392
  }
1393
}
1394
 
1395 897 markom
/* Displays shared instructions */
1396
void print_shared (cuc_func *rf, cuc_shared_item *shared, int nshared)
1397
{
1398
  int i, first = 1;
1399
  for (i = 0; i < nshared; i++) {
1400 997 markom
    PRINTF ("%s%s%s", first ? "" : "-", cuc_insn_name (&rf->INSN(shared[i].ref)),
1401 897 markom
                    shared[i].cmatch ? "!" : "");
1402
    first = 0;
1403
  }
1404
}
1405
 
1406
/* Common subexpression matching -- resource sharing, generation pass
1407
 
1408
   Situation here is much simpler than with analysis -- we know the instruction sequence
1409
   we are going to share, but we are going to do this on whole function, not just one BB.
1410
   We can find sequence in reference function, as pointed from "shared" */
1411
void csm_gen (cuc_func *f, cuc_func *rf, cuc_shared_item *shared, int nshared)
1412
{
1413 1308 phoenix
  int b, i, cnt = 0;
1414 897 markom
#warning   some code here (2)
1415 997 markom
  PRINTF ("Replacing: ");
1416 897 markom
  print_shared (rf, shared, nshared);
1417
 
1418
  for (b = 0; b < f->num_bb; b++)
1419
    for (i = 0; i < f->bb[b].ninsn; i++) {
1420
    }
1421
 
1422 997 markom
  PRINTF ("\nFound %i matches.\n", cnt);
1423 897 markom
}
1424
 

powered by: WebSVN 2.1.0

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