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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc2/] [or1ksim/] [cuc/] [insn.c] - Blame information for rev 1778

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 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 1557 nogj
       || (II_IS_LOAD (ii->index) && (f->memory_order == MO_NONE || f->memory_order == MO_WEAK))
918 932 markom
       || 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 1557 nogj
#if 0
981 897 markom
static void relocate_bb (cuc_bb *bb, int b, int back, int fwd)
982
{
983
  int i, j;
984
  for (i = 0; i < bb->ninsn; i++)
985
    for (j = 0; j < MAX_OPERANDS; j++)
986
      if (bb->insn[i].opt[j] & OPT_REF
987
       && REF_BB (bb->insn[i].op[j]) == b) {
988
        int t = REF_I (bb->insn[i].op[j]);
989
        if (t < i) bb->insn[i].op[j] = REF (back, t);
990
        else bb->insn[i].op[j] = REF (fwd, t);
991
      }
992
}
993 1557 nogj
#endif
994 897 markom
 
995
/* Latch outputs in loops */
996
void add_latches (cuc_func *f)
997
{
998
  int b, i, j;
999
 
1000
  //print_cuc_bb (f, "ADD_LATCHES a");
1001
  /* Cuts the tree and marks registers */
1002
  mark_cut (f);
1003
 
1004
  /* Split BBs with more than one group */
1005
  for (b = 0; b < f->num_bb; b++) expand_bb (f, b);
1006
  remove_nops (f);
1007
  //print_cuc_bb (f, "ADD_LATCHES 0");
1008
 
1009
  /* Convert accesses in BB_INLOOP type block to latched */
1010
  for (b = 0; b < f->num_bb; b++) {
1011
    int j;
1012
    for (i = 0; i < f->bb[b].ninsn; i++)
1013
      for (j = 0; j < MAX_OPERANDS; j++) if (f->bb[b].insn[i].opt[j] == OPT_REF) {
1014
        int t = f->bb[b].insn[i].op[j];
1015
        /* If we are pointing to a INLOOP block from outside, or forward
1016
           (= previous loop iteration) we must register that data */
1017
        if ((f->bb[REF_BB(t)].type & BB_INLOOP || config.cuc.no_multicycle)
1018
         && !(f->INSN(t).type & (IT_BRANCH | IT_COND))
1019
         && (REF_BB(t) != b || REF_I(t) >= i)) {
1020
          f->INSN(t).type |= IT_LATCHED;
1021
        }
1022
      }
1023
  }
1024
  //print_cuc_bb (f, "ADD_LATCHES 1");
1025
 
1026
  /* Add latches at the end of blocks as needed */
1027
  for (b = 0; b < f->num_bb; b++) {
1028
    int nreg = 0;
1029
    cuc_insn *insn;
1030
    for (i = 0; i < f->bb[b].ninsn; i++)
1031
      if (f->bb[b].insn[i].type & IT_LATCHED) nreg++;
1032
    if (nreg) {
1033
      insn = (cuc_insn *) malloc (sizeof (cuc_insn) * (f->bb[b].ninsn + nreg));
1034
      j = 0;
1035
      for (i = 0; i < f->bb[b].ninsn; i++) {
1036
        insn[i] = f->bb[b].insn[i];
1037
        if (insn[i].type & IT_LATCHED) {
1038
          cuc_insn *ii = &insn[f->bb[b].ninsn + j++];
1039
          change_insn_type (ii, II_REG);
1040
          ii->op[0] = -1; ii->opt[0] = OPT_DEST | OPT_REGISTER;
1041
          ii->op[1] = REF (b, i); ii->opt[1] = OPT_REF;
1042
          ii->opt[2] = ii->opt[3] = OPT_NONE;
1043
          ii->dep = NULL;
1044
          ii->type = IT_VOLATILE;
1045
          sprintf (ii->disasm, "reg %i_%i", b, i);
1046
        }
1047
      }
1048
      f->bb[b].ninsn += nreg;
1049
      free (f->bb[b].insn);
1050
      f->bb[b].insn = insn;
1051
    }
1052
  }
1053
  //print_cuc_bb (f, "ADD_LATCHES 2");
1054
 
1055
  /* Repair references */
1056
  for (b = 0; b < f->num_bb; b++)
1057
    for (i = 0; i < f->bb[b].ninsn; i++)
1058
      for (j = 0; j < MAX_OPERANDS; j++)
1059
        /* If destination instruction is latched, use register instead */
1060
        if (f->bb[b].insn[i].opt[j] == OPT_REF
1061
         && f->INSN(f->bb[b].insn[i].op[j]).type & IT_LATCHED) {
1062
          int b1, i1;
1063
          b1 = REF_BB (f->bb[b].insn[i].op[j]);
1064
          //cucdebug (2, "%i.%i.%i %x\n", b, i, j, f->bb[b].insn[i].op[j]);
1065
          if (b1 != b || REF_I(f->bb[b].insn[i].op[j]) >= i) {
1066
            for (i1 = f->bb[b1].ninsn - 1; i1 >= 0; i1--) {
1067
              assert (f->bb[b1].insn[i1].index == II_REG);
1068
              if (f->bb[b1].insn[i1].op[1] == f->bb[b].insn[i].op[j]) {
1069
                f->bb[b].insn[i].op[j] = REF (b1, i1);
1070
                break;
1071
              }
1072
            }
1073
          }
1074
        }
1075
}
1076
 
1077 883 markom
/* CSE -- common subexpression elimination */
1078 931 markom
int cse (cuc_func *f)
1079 883 markom
{
1080 931 markom
  int modified = 0;
1081 1308 phoenix
  int b, i, j, b1, i1, b2, i2;
1082 883 markom
  for (b1 = 0; b1 < f->num_bb; b1++)
1083 930 markom
    for (i1 = 0; i1 < f->bb[b1].ninsn; i1++) if (f->bb[b1].insn[i1].index != II_NOP
1084
       && f->bb[b1].insn[i1].index != II_LRBB && !(f->bb[b1].insn[i1].type & IT_MEMORY)
1085
       && !(f->bb[b1].insn[i1].type & IT_MEMADD))
1086 883 markom
      for (b2 = 0; b2 < f->num_bb; b2++)
1087 930 markom
        for (i2 = 0; i2 < f->bb[b2].ninsn; i2++)
1088
          if (f->bb[b2].insn[i2].index != II_NOP && f->bb[b2].insn[i2].index != II_LRBB
1089
           && !(f->bb[b2].insn[i2].type & IT_MEMORY) && !(f->bb[b2].insn[i2].type & IT_MEMADD)
1090
           && (b1 != b2 || i2 > i1)) {
1091
            cuc_insn *ii1 = &f->bb[b1].insn[i1];
1092
            cuc_insn *ii2 = &f->bb[b2].insn[i2];
1093
            int ok = 1;
1094 883 markom
 
1095 930 markom
            /* Do we have an exact match? */
1096
            if (ii1->index != ii2->index) continue;
1097
            if (ii2->type & IT_VOLATILE) continue;
1098
 
1099
            /* Check all operands also */
1100
            for (j = 0; j < MAX_OPERANDS; j++) {
1101
              if (ii1->opt[j] != ii2->opt[j]) {
1102
                ok = 0;
1103
                break;
1104
              }
1105
              if (ii1->opt[j] & OPT_DEST) continue;
1106
              if (ii1->opt[j] != OPT_NONE && ii1->op[j] != ii2->op[j]) {
1107
                ok = 0;
1108
                break;
1109
              }
1110
            }
1111
 
1112
            if (ok) {
1113
              /* remove duplicated instruction and relink the references */
1114
              cucdebug (3, "%x - %x are same\n", REF(b1, i1), REF(b2, i2));
1115
              change_insn_type (ii2, II_NOP);
1116 931 markom
              modified = 1;
1117 930 markom
              for (b = 0; b < f->num_bb; b++)
1118
                for (i = 0; i < f->bb[b].ninsn; i++)
1119
                  for (j = 0; j < MAX_OPERANDS; j++)
1120
                    if (f->bb[b].insn[i].opt[j] & OPT_REF
1121
                     && f->bb[b].insn[i].op[j] == REF (b2, i2))
1122
                      f->bb[b].insn[i].op[j] = REF (b1, i1);
1123
            }
1124
          }
1125 931 markom
  return modified;
1126 883 markom
}
1127
 
1128
static int count_cmovs (cuc_insn *ii, int match)
1129
{
1130
  int c = 0, j;
1131
  if (match & 2) {
1132
    for (j = 0; j < MAX_OPERANDS; j++)
1133
      if (ii->opt[j] & OPT_DEST) c++;
1134
  }
1135
  if (match & 1) {
1136
    for (j = 0; j < MAX_OPERANDS; j++)
1137
      if (!(ii->opt[j] & OPT_DEST) && ii->opt[j] & OPT_REF) c++;
1138
  } else {
1139
    for (j = 0; j < MAX_OPERANDS; j++)
1140
      if (!(ii->opt[j] & OPT_DEST) && ii->opt[j] != OPT_NONE) c++;
1141
  }
1142
  return c;
1143
}
1144
 
1145 897 markom
static void search_csm (int iter, cuc_func *f, cuc_shared_list *list);
1146
static cuc_shared_list *main_list;
1147 883 markom
static int *iteration;
1148
 
1149 897 markom
/* CSM -- common subexpression matching -- resource sharing
1150
   We try to match tree of instruction inside a BB with as many
1151
   matches as possible. All possibilities are collected and
1152
   options, making situation worse are removed */
1153 883 markom
void csm (cuc_func *f)
1154
{
1155
  int b, i, j;
1156
  int cnt;
1157 897 markom
  cuc_shared_list *list;
1158 883 markom
  cuc_timings timings;
1159
 
1160
  analyse_timings (f, &timings);
1161
  main_list = NULL;
1162
  for (b = 0; b < f->num_bb; b++) {
1163
    assert (iteration = (int *)malloc (sizeof (int) * f->bb[b].ninsn));
1164
    for (i = 0; i < f->bb[b].ninsn; i++) {
1165
      int cnt = 0, cntc = 0;
1166
      double size = 0., sizec = 0.;
1167
      int j2 = 0;
1168
      for (j = 0; j < f->bb[b].ninsn; j++)
1169
        if (f->bb[b].insn[i].index == f->bb[b].insn[j].index) {
1170
          int ok = 1;
1171
          for (j2 = 0; j2 < MAX_OPERANDS; j2++) if (!(f->bb[b].insn[j].opt[j2] & OPT_REF))
1172
            if (f->bb[b].insn[j].opt[j2] != f->bb[b].insn[i].opt[j2]
1173
             || f->bb[b].insn[j].op[j2] != f->bb[b].insn[i].opt[j2]) {
1174
              ok = 0;
1175
              break;
1176
            }
1177
          if (ok) {
1178
            cntc++;
1179
            sizec = sizec + insn_size (&f->bb[b].insn[j]);
1180
          } else {
1181
            cnt++;
1182
            size = size + insn_size (&f->bb[b].insn[j]);
1183
          }
1184
          iteration[j] = 0;
1185
        } else iteration[j] = -1;
1186
      if (cntc > 1) {
1187 897 markom
        assert (list = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1188 883 markom
        list->next = main_list;
1189
        list->from = NULL;
1190
        list->ref = REF (b, i);
1191
        list->cnt = cnt;
1192
        list->cmatch = 1;
1193
        list->cmovs = count_cmovs (&f->bb[b].insn[i], 3);
1194
        list->osize = sizec;
1195
        list->size = ii_size (f->bb[b].insn[i].index, 1);
1196
        main_list = list;
1197
        search_csm (0, f, list);
1198
      }
1199
      if (cnt > 1) {
1200 897 markom
        assert (list = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1201 883 markom
        list->next = main_list;
1202
        list->from = NULL;
1203
        list->ref = REF (b, i);
1204
        list->cnt = cnt + cntc;
1205
        list->cmatch = 0;
1206
        list->cmovs = count_cmovs (&f->bb[b].insn[i], 2);
1207
        list->osize = size + sizec;
1208
        list->size = ii_size (f->bb[b].insn[i].index, 0);
1209
        main_list = list;
1210
        search_csm (0, f, list);
1211
      }
1212
    }
1213
    free (iteration);
1214
  }
1215
 
1216
  for (list = main_list; list; list = list->next) list->dead = 0;
1217
  cnt = 0;
1218
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
1219
  cucdebug (1, "noptions = %i\n", cnt);
1220
 
1221
  /* Now we will check the real size of the 'improvements'; if the size
1222
     actually increases, we abandom the option */
1223
  for (list = main_list; list; list = list->next)
1224
    if (list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size >= list->osize) list->dead = 1;
1225
 
1226
  cnt = 0;
1227
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
1228
  cucdebug (1, "noptions = %i\n", cnt);
1229
 
1230
  /* Count number of instructions grouped */
1231
  for (list = main_list; list; list = list->next) {
1232 897 markom
    cuc_shared_list *l = list;
1233 883 markom
    int c = 0;
1234
    while (l) {
1235
      c++;
1236
      if (f->INSN(l->ref).type & (IT_VOLATILE | IT_MEMORY | IT_MEMADD)) list->dead = 1;
1237
      l = l->from;
1238
    }
1239
    list->ninsn = c;
1240
  }
1241
 
1242
  cnt = 0;
1243
  for (list = main_list; list; list = list->next)
1244
    if (!list->dead) cnt++;
1245
  cucdebug (1, "noptions = %i\n", cnt);
1246
 
1247
#if 1
1248
  /* We can get a lot of options here, so we will delete duplicates */
1249
  for (list = main_list; list; list = list->next) if (!list->dead) {
1250 897 markom
    cuc_shared_list *l;
1251 883 markom
    for (l = list->next; l; l = l->next) if (!l->dead) {
1252
      int ok = 1;
1253 897 markom
      cuc_shared_list *t1 = list;
1254
      cuc_shared_list *t2 = l;
1255 883 markom
      while (ok && t1 && t2) {
1256
        if (f->INSN(t1->ref).index == f->INSN(t2->ref).index) {
1257
          /* If other operands are matching, we must check for them also */
1258
          if (t1->cmatch) {
1259
            int j;
1260
            for (j = 0; j < MAX_OPERANDS; j++)
1261
              if (!(f->INSN(t1->ref).opt[j] & OPT_REF) || !(f->INSN(t2->ref).opt[j] & OPT_REF)
1262
               || f->INSN(t1->ref).opt[j] != f->INSN(t2->ref).opt[j]
1263
               || f->INSN(t1->ref).op[j] != f->INSN(t2->ref).op[j]) {
1264
                ok = 0;
1265
                break;
1266
              }
1267
          }
1268
 
1269
          /* This option is duplicate, remove */
1270
          if (ok) t1->dead = 1;
1271
        }
1272
        t1 = t1->from;
1273
        t2 = t2->from;
1274
      }
1275
    }
1276
  }
1277
  cnt = 0;
1278
  for (list = main_list; list; list = list->next) if (!list->dead) cnt++;
1279
  cucdebug (1, "noptions = %i\n", cnt);
1280
#endif
1281
  /* Print out */
1282
  for (list = main_list; list; list = list->next) if (!list->dead) {
1283 897 markom
    cuc_shared_list *l = list;
1284 883 markom
    cucdebug (1, "%-4s cnt %3i ninsn %3i size %8.1f osize %8.1f cmovs %3i @",
1285
           cuc_insn_name (&f->INSN(list->ref)), list->cnt, list->ninsn,
1286
           list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size, list->osize, list->cmovs);
1287
    while (l) {
1288
      cucdebug (1, "%c%x,", l->cmatch ? '.' : '!', l->ref);
1289
      l = l->from;
1290
    }
1291
    cucdebug (1, "\n");
1292
  }
1293
 
1294
  /* Calculate estimated timings */
1295
  for (b = 0; b < f->num_bb; b++) {
1296
    cnt = 0;
1297
    for (list = main_list; list; list = list->next)
1298
      if (!list->dead && REF_BB(list->ref) == b) cnt++;
1299
 
1300
    f->bb[b].ntim = cnt;
1301
    if (!cnt) {
1302
      f->bb[b].tim = NULL;
1303
      continue;
1304
    }
1305
    assert (f->bb[b].tim = (cuc_timings *)malloc (sizeof (cuc_timings) * cnt));
1306
 
1307
    cnt = 0;
1308
    for (list = main_list; list; list = list->next) if (!list->dead && REF_BB(list->ref) == b) {
1309 897 markom
      cuc_shared_list *l = list;
1310 883 markom
      f->bb[b].tim[cnt].b = b;
1311
      f->bb[b].tim[cnt].preroll = f->bb[b].tim[cnt].unroll = 1;
1312
      f->bb[b].tim[cnt].nshared = list->ninsn;
1313 897 markom
      assert (f->bb[b].tim[cnt].shared = (cuc_shared_item *)
1314
            malloc (sizeof(cuc_shared_item) * list->ninsn));
1315
      for (i =  0; i < list->ninsn; i++, l = l->from) {
1316
        f->bb[b].tim[cnt].shared[i].ref = l->ref;
1317
        f->bb[b].tim[cnt].shared[i].cmatch = l->cmatch;
1318
      }
1319 883 markom
      f->bb[b].tim[cnt].new_time = timings.new_time + f->bb[b].cnt * (list->cnt - 1);
1320 897 markom
      f->bb[b].tim[cnt].size = timings.size +
1321
             list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size - list->osize;
1322 883 markom
      cnt++;
1323
    }
1324
  }
1325
}
1326
 
1327
/* Recursive function for searching through instruction graph */
1328 897 markom
static void search_csm (int iter, cuc_func *f, cuc_shared_list *list)
1329 883 markom
{
1330
  int b, i, j, i1;
1331 897 markom
  cuc_shared_list *l;
1332 883 markom
  b = REF_BB(list->ref);
1333
  i = REF_I(list->ref);
1334
 
1335
  for (j = 0; j < MAX_OPERANDS; j++) if (f->bb[b].insn[i].opt[j] & OPT_REF) {
1336
    int t = f->bb[b].insn[i].op[j];
1337
    int cnt = 0, cntc = 0;
1338
    double size = 0., sizec = 0.;
1339
 
1340
    /* Mark neighbours */
1341
    for (i1 = 0; i1 < f->bb[b].ninsn; i1++) {
1342
      if (iteration[i1] == iter && f->bb[b].insn[i1].opt[j] & OPT_REF) {
1343
        int t2 = f->bb[b].insn[i1].op[j];
1344
        if (f->INSN(t).index == f->INSN(t2).index && f->INSN(t2).opt[j] & OPT_REF) {
1345
          int j2;
1346
          int ok = 1;
1347
          iteration[REF_I(t2)] = iter + 1;
1348
          for (j2 = 0; j2 < MAX_OPERANDS; j2++) if (!(f->bb[b].insn[i1].opt[j2] & OPT_REF))
1349
            if (f->bb[b].insn[i1].opt[j2] != f->bb[b].insn[i].opt[j2]
1350
             || f->bb[b].insn[i1].op[j2] != f->bb[b].insn[i].opt[j2]) {
1351
              ok = 0;
1352
              break;
1353
            }
1354
          if (ok) {
1355
            cntc++;
1356
            sizec = sizec + insn_size (&f->bb[b].insn[i1]);
1357
          } else {
1358
            cnt++;
1359
            size = size + insn_size (&f->bb[b].insn[i1]);
1360
          }
1361
        }
1362
      }
1363
    }
1364
 
1365
    if (cntc > 1) {
1366 897 markom
      assert (l = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1367 883 markom
      l->next = main_list;
1368
      main_list = l;
1369
      l->from = list;
1370
      l->ref = t;
1371
      l->cnt = cnt;
1372
      l->cmatch = 1;
1373
      l->cmovs = list->cmovs + count_cmovs (&f->bb[b].insn[i], 1) - 1;
1374
      l->size = list->size + ii_size (f->bb[b].insn[i].index, 1);
1375
      l->osize = sizec;
1376
      search_csm (iter + 1, f, l);
1377
    }
1378
    if (cnt > 1) {
1379 897 markom
      assert (l = (cuc_shared_list *)malloc (sizeof (cuc_shared_list)));
1380 883 markom
      l->next = main_list;
1381
      main_list = l;
1382
      l->from = list;
1383
      l->ref = t;
1384
      l->cnt = cnt + cntc;
1385
      l->cmatch = 0;
1386
      l->osize = size + sizec;
1387
      l->cmovs = list->cmovs + count_cmovs (&f->bb[b].insn[i], 0) - 1;
1388
      l->size = list->size + ii_size (f->bb[b].insn[i].index, 0);
1389
      search_csm (iter + 1, f, l);
1390
    }
1391
 
1392
    /* Unmark them back */
1393
    for (i1 = 0; i1 < f->bb[b].ninsn; i1++) if (iteration[i1] > iter) iteration[i1] = -1;
1394
  }
1395
}
1396
 
1397 897 markom
/* Displays shared instructions */
1398
void print_shared (cuc_func *rf, cuc_shared_item *shared, int nshared)
1399
{
1400
  int i, first = 1;
1401
  for (i = 0; i < nshared; i++) {
1402 997 markom
    PRINTF ("%s%s%s", first ? "" : "-", cuc_insn_name (&rf->INSN(shared[i].ref)),
1403 897 markom
                    shared[i].cmatch ? "!" : "");
1404
    first = 0;
1405
  }
1406
}
1407
 
1408
/* Common subexpression matching -- resource sharing, generation pass
1409
 
1410
   Situation here is much simpler than with analysis -- we know the instruction sequence
1411
   we are going to share, but we are going to do this on whole function, not just one BB.
1412
   We can find sequence in reference function, as pointed from "shared" */
1413
void csm_gen (cuc_func *f, cuc_func *rf, cuc_shared_item *shared, int nshared)
1414
{
1415 1308 phoenix
  int b, i, cnt = 0;
1416 1557 nogj
  /* FIXME: some code here (2) */
1417 997 markom
  PRINTF ("Replacing: ");
1418 897 markom
  print_shared (rf, shared, nshared);
1419
 
1420
  for (b = 0; b < f->num_bb; b++)
1421
    for (i = 0; i < f->bb[b].ninsn; i++) {
1422
    }
1423
 
1424 997 markom
  PRINTF ("\nFound %i matches.\n", cnt);
1425 897 markom
}
1426
 

powered by: WebSVN 2.1.0

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