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

Subversion Repositories or1k

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

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

powered by: WebSVN 2.1.0

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