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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [or1ksim/] [cuc/] [insn.c] - Blame information for rev 146

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* insn.c -- OpenRISC Custom Unit Compiler, instruction support
2
 
3
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
 
30
/* System includes */
31
#include <stdlib.h>
32
#include <assert.h>
33
 
34
/* Package includes */
35
#include "insn.h"
36
#include "sim-config.h"
37
 
38
 
39
/* Table of known instructions.  Watch out for indexes I_*! */
40
const cuc_known_insn known[II_LAST + 1] = {
41
  {"add", 1, "assign \1 = \2 + \3;"},
42
  {"sub", 0, "assign \1 = \2 - \3;"},
43
  {"and", 1, "assign \1 = \2 & \3;"},
44
  {"or", 1, "assign \1 = \2 | \3;"},
45
  {"xor", 1, "assign \1 = \2 ^ \3;"},
46
  {"mul", 1, "assign \1 = \2 * \3;"},
47
 
48
  {"srl", 0, "assign \1 = \2 >> \3;"},
49
  {"sll", 0, "assign \1 = \2 << \3;"},
50
  {"sra", 0, "assign \1 = ({32{\2[31]}} << (6'd32-{1'b0, \3}))\n\
51
                 | \2 >> \3;"},
52
 
53
  {"lb", 0, "always @(posedge clk)"},
54
  {"lh", 0, "always @(posedge clk)"},
55
  {"lw", 0, "always @(posedge clk)"},
56
  {"sb", 0, "/* mem8[\2] = \1 */"},
57
  {"sh", 0, "/* mem16[\2] = \1 */"},
58
  {"sw", 0, "/* mem32[\2] = \1 */"},
59
 
60
  {"sfeq", 1, "assign \1 = \2 == \3;"},
61
  {"sfne", 1, "assign \1 = \2 != \3;"},
62
  {"sfle", 0, "assign \1 = \2 <= \3;"},
63
  {"sflt", 0, "assign \1 = \2 < \3;"},
64
  {"sfge", 0, "assign \1 = \2 >= \3;"},
65
  {"sfgt", 0, "assign \1 = \2 > \3;"},
66
  {"bf", 0, ""},
67
 
68
  {"lrbb", 0, "always @(posedge clk or posedge rst)"},
69
  {"cmov", 0, "assign \1 = \4 ? \2 : \3;"},
70
  {"reg", 0, "always @(posedge clk)"},
71
 
72
  {"nop", 1, ""},
73
  {"call", 0, "/* function call */"}
74
};
75
 
76
/* Find known instruction and attach them to insn */
77
void
78
change_insn_type (cuc_insn * i, int index)
79
{
80
  int j;
81
  assert (index >= 0 && index <= II_LAST);
82
  i->index = index;
83
  if (i->index == II_NOP)
84
    {
85
      for (j = 0; j < MAX_OPERANDS; j++)
86
        i->opt[j] = OPT_NONE;
87
      i->type = 0;
88
      i->dep = NULL;
89
      i->disasm[0] = '\0';
90
    }
91
}
92
 
93
/* Returns instruction name */
94
const char *
95
cuc_insn_name (cuc_insn * ii)
96
{
97
  if (ii->index < 0 || ii->index > II_LAST)
98
    return "???";
99
  else
100
    return known[ii->index].name;
101
}
102
 
103
/* Prints out instructions */
104
void
105
print_insns (int bb, cuc_insn * insn, int ninsn, int verbose)
106
{
107
  int i, j;
108
  for (i = 0; i < ninsn; i++)
109
    {
110
      char tmp[10];
111
      dep_list *l = insn[i].dep;
112
      sprintf (tmp, "[%x_%x]", bb, i);
113
      PRINTF ("%-8s%c %-4s ", tmp, insn[i].index >= 0 ? ':' : '?',
114
              cuc_insn_name (&insn[i]));
115
      if (verbose)
116
        {
117
          PRINTF ("%-20s insn = %08lx, index = %i, type = %04x ",
118
                  insn[i].disasm, insn[i].insn, insn[i].index, insn[i].type);
119
        }
120
      else
121
        PRINTF ("type = %04x ", insn[i].type);
122
      for (j = 0; j < MAX_OPERANDS; j++)
123
        {
124
          if (insn[i].opt[j] & OPT_DEST)
125
            PRINTF ("*");
126
          switch (insn[i].opt[j] & ~OPT_DEST)
127
            {
128
            case OPT_NONE:
129
              break;
130
            case OPT_CONST:
131
              if (insn[i].type & IT_COND && (insn[i].index == II_CMOV
132
                                             || insn[i].index == II_ADD))
133
                PRINTF ("%lx, ", insn[i].op[j]);
134
              else
135
                PRINTF ("0x%08lx, ", insn[i].op[j]);
136
              break;
137
            case OPT_JUMP:
138
              PRINTF ("J%lx, ", insn[i].op[j]);
139
              break;
140
            case OPT_REGISTER:
141
              PRINTF ("r%li, ", insn[i].op[j]);
142
              break;
143
            case OPT_REF:
144
              PRINTF ("[%lx_%lx], ", REF_BB (insn[i].op[j]),
145
                      REF_I (insn[i].op[j]));
146
              break;
147
            case OPT_BB:
148
              PRINTF ("BB ");
149
              print_bb_num (insn[i].op[j]);
150
              PRINTF (", ");
151
              break;
152
            case OPT_LRBB:
153
              PRINTF ("LRBB, ");
154
              break;
155
            default:
156
              fprintf (stderr, "Invalid operand type %s(%x_%x) = %x\n",
157
                       cuc_insn_name (&insn[i]), i, j, insn[i].opt[j]);
158
              assert (0);
159
            }
160
        }
161
      if (l)
162
        {
163
          PRINTF ("\n\tdep:");
164
          while (l)
165
            {
166
              PRINTF (" [%lx_%lx],", REF_BB (l->ref), REF_I (l->ref));
167
              l = l->next;
168
            }
169
        }
170
      PRINTF ("\n");
171
    }
172
}
173
 
174
void
175
add_dep (dep_list ** list, int dep)
176
{
177
  dep_list *ndep;
178
  dep_list **tmp = list;
179
 
180
  while (*tmp)
181
    {
182
      if ((*tmp)->ref == dep)
183
        return;                 /* already there */
184
      tmp = &((*tmp)->next);
185
    }
186
  ndep = (dep_list *) malloc (sizeof (dep_list));
187
  ndep->ref = dep;
188
  ndep->next = NULL;
189
  *tmp = ndep;
190
}
191
 
192
void
193
dispose_list (dep_list ** list)
194
{
195
  while (*list)
196
    {
197
      dep_list *tmp = *list;
198
      *list = tmp->next;
199
      free (tmp);
200
    }
201
}
202
 
203
void
204
add_data_dep (cuc_func * f)
205
{
206
  int b, i, j;
207
  for (b = 0; b < f->num_bb; b++)
208
    {
209
      cuc_insn *insn = f->bb[b].insn;
210
      for (i = 0; i < f->bb[b].ninsn; i++)
211
        for (j = 0; j < MAX_OPERANDS; j++)
212
          {
213
            fflush (stdout);
214
            if (insn[i].opt[j] & OPT_REF)
215
              {
216
                /* Copy list from predecessor */
217
                dep_list *l = f->INSN (insn[i].op[j]).dep;
218
                while (l)
219
                  {
220
                    add_dep (&insn[i].dep, l->ref);
221
                    l = l->next;
222
                  }
223
                /* add predecessor */
224
                add_dep (&insn[i].dep, insn[i].op[j]);
225
              }
226
          }
227
    }
228
}
229
 
230
/* Inserts n nops before insn 'ref' */
231
void
232
insert_insns (cuc_func * f, int ref, int n)
233
{
234
  int b1, i, j;
235
  int b = REF_BB (ref);
236
  int ins = REF_I (ref);
237
 
238
  assert (b < f->num_bb);
239
  assert (ins <= f->bb[b].ninsn);
240
  assert (f->bb[b].ninsn + n < MAX_INSNS);
241
  if (cuc_debug >= 8)
242
    print_cuc_bb (f, "PREINSERT");
243
  f->bb[b].insn = (cuc_insn *) realloc (f->bb[b].insn,
244
                                        (f->bb[b].ninsn +
245
                                         n) * sizeof (cuc_insn));
246
 
247
  /* Set up relocations */
248
  for (i = 0; i < f->bb[b].ninsn; i++)
249
    if (i < ins)
250
      reloc[i] = i;
251
    else
252
      reloc[i] = i + n;
253
 
254
  /* Move instructions, based on relocations */
255
  for (i = f->bb[b].ninsn - 1; i >= 0; i--)
256
    f->bb[b].insn[reloc[i]] = f->bb[b].insn[i];
257
  for (i = 0; i < n; i++)
258
    change_insn_type (&f->bb[b].insn[ins + i], II_NOP);
259
 
260
  f->bb[b].ninsn += n;
261
  for (b1 = 0; b1 < f->num_bb; b1++)
262
    {
263
      dep_list *d = f->bb[b1].mdep;
264
      while (d)
265
        {
266
          if (REF_BB (d->ref) == b && REF_I (d->ref) >= ins)
267
            d->ref = REF (b, REF_I (d->ref) + n);
268
          d = d->next;
269
        }
270
      for (i = 0; i < f->bb[b1].ninsn; i++)
271
        {
272
          d = f->bb[b1].insn[i].dep;
273
          while (d)
274
            {
275
              if (REF_BB (d->ref) == b && REF_I (d->ref) >= ins)
276
                d->ref = REF (b, REF_I (d->ref) + n);
277
              d = d->next;
278
            }
279
          for (j = 0; j < MAX_OPERANDS; j++)
280
            if (f->bb[b1].insn[i].opt[j] & OPT_REF
281
                && REF_BB (f->bb[b1].insn[i].op[j]) == b
282
                && REF_I (f->bb[b1].insn[i].op[j]) >= ins)
283
              f->bb[b1].insn[i].op[j] =
284
                REF (b, REF_I (f->bb[b1].insn[i].op[j]) + n);
285
        }
286
    }
287
  for (i = 0; i < f->nmsched; i++)
288
    if (REF_BB (f->msched[i]) == b)
289
      f->msched[i] = REF (b, reloc[REF_I (f->msched[i])]);
290
  if (cuc_debug >= 8)
291
    print_cuc_bb (f, "POSTINSERT");
292
  cuc_check (f);
293
}
294
 
295
/* returns nonzero, if instruction was simplified */
296
int
297
apply_edge_condition (cuc_insn * ii)
298
{
299
  unsigned int c = ii->op[2];
300
 
301
  switch (ii->index)
302
    {
303
    case II_AND:
304
      if (ii->opt[2] & OPT_CONST && c == 0)
305
        {
306
          change_insn_type (ii, II_ADD);
307
          ii->op[1] = 0;
308
          ii->opt[1] = OPT_CONST;
309
          ii->op[2] = 0;
310
          ii->opt[2] = OPT_CONST;
311
          return 1;
312
        }
313
      else if (ii->opt[2] & OPT_CONST && c == 0xffffffff)
314
        {
315
          change_insn_type (ii, II_ADD);
316
          ii->op[2] = 0;
317
          ii->opt[2] = OPT_CONST;
318
          return 1;
319
        }
320
      else
321
        break;
322
    case II_OR:
323
      if (ii->opt[2] & OPT_CONST && c == 0x0)
324
        {
325
          change_insn_type (ii, II_ADD);
326
          ii->op[1] = c;
327
          ii->opt[1] = OPT_CONST;
328
          ii->op[2] = 0;
329
          ii->opt[2] = OPT_CONST;
330
          return 1;
331
        }
332
      else if (ii->opt[2] & OPT_CONST && c == 0xffffffff)
333
        {
334
          change_insn_type (ii, II_ADD);
335
          ii->op[1] = 0xffffffff;
336
          ii->opt[1] = OPT_CONST;
337
          ii->op[2] = 0;
338
          ii->opt[2] = OPT_CONST;
339
          return 1;
340
        }
341
      else
342
        break;
343
    case II_SUB:
344
      if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2])
345
        {
346
          change_insn_type (ii, II_ADD);
347
          ii->op[1] = 0;
348
          ii->opt[1] = OPT_CONST;
349
          ii->op[2] = 0;
350
          ii->opt[2] = OPT_CONST;
351
          return 1;
352
        }
353
      else
354
        break;
355
    case II_MUL:
356
      if (ii->opt[2] & OPT_CONST && c == 0)
357
        {
358
          change_insn_type (ii, II_ADD);
359
          ii->op[1] = 0;
360
          ii->opt[1] = OPT_CONST;
361
          ii->op[2] = 0;
362
          ii->opt[2] = OPT_CONST;
363
          return 1;
364
        }
365
      else if (ii->opt[2] & OPT_CONST && c == 1)
366
        {
367
          change_insn_type (ii, II_ADD);
368
          ii->op[1] = c;
369
          ii->opt[1] = OPT_CONST;
370
          ii->op[2] = 0;
371
          ii->opt[2] = OPT_CONST;
372
          return 1;
373
        }
374
      else if (ii->opt[2] & OPT_CONST && c == 0xffffffff)
375
        {
376
          change_insn_type (ii, II_SUB);
377
          ii->op[2] = ii->op[1];
378
          ii->opt[2] = ii->opt[1];
379
          ii->op[1] = 0;
380
          ii->opt[1] = OPT_CONST;
381
          return 1;
382
        }
383
      else
384
        break;
385
    case II_SRL:
386
      if (ii->opt[2] & OPT_CONST && c == 0)
387
        {
388
          change_insn_type (ii, II_ADD);
389
          ii->op[1] = c;
390
          ii->opt[1] = OPT_CONST;
391
          ii->op[2] = 0;
392
          ii->opt[2] = OPT_CONST;
393
          return 1;
394
        }
395
      else if (ii->opt[2] & OPT_CONST && c >= 32)
396
        {
397
          change_insn_type (ii, II_ADD);
398
          ii->op[1] = 0;
399
          ii->opt[1] = OPT_CONST;
400
          ii->op[2] = 0;
401
          ii->opt[2] = OPT_CONST;
402
          return 1;
403
        }
404
      else
405
        break;
406
    case II_SLL:
407
      if (ii->opt[2] & OPT_CONST && c == 0)
408
        {
409
          change_insn_type (ii, II_ADD);
410
          ii->op[1] = c;
411
          ii->opt[1] = OPT_CONST;
412
          ii->op[2] = 0;
413
          ii->opt[2] = OPT_CONST;
414
          return 1;
415
        }
416
      else if (ii->opt[2] & OPT_CONST && c >= 32)
417
        {
418
          change_insn_type (ii, II_ADD);
419
          ii->op[1] = 0;
420
          ii->opt[1] = OPT_CONST;
421
          ii->op[2] = 0;
422
          ii->opt[2] = OPT_CONST;
423
          return 1;
424
        }
425
      else
426
        break;
427
    case II_SRA:
428
      if (ii->opt[2] & OPT_CONST && c == 0)
429
        {
430
          change_insn_type (ii, II_ADD);
431
          ii->op[1] = c;
432
          ii->opt[1] = OPT_CONST;
433
          ii->op[2] = 0;
434
          ii->opt[2] = OPT_CONST;
435
          return 1;
436
        }
437
      else
438
        break;
439
    case II_SFEQ:
440
      if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST)
441
        {
442
          change_insn_type (ii, II_ADD);
443
          ii->op[1] = ii->op[1] == ii->op[2];
444
          ii->opt[1] = OPT_CONST;
445
          ii->op[2] = 0;
446
          ii->opt[2] = OPT_CONST;
447
          return 1;
448
        }
449
      else
450
        break;
451
    case II_SFNE:
452
      if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST)
453
        {
454
          change_insn_type (ii, II_ADD);
455
          ii->op[1] = ii->op[1] != ii->op[2];
456
          ii->opt[1] = OPT_CONST;
457
          ii->op[2] = 0;
458
          ii->opt[2] = OPT_CONST;
459
          return 1;
460
        }
461
      else
462
        break;
463
    case II_SFLE:
464
      if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST)
465
        {
466
          change_insn_type (ii, II_ADD);
467
          ii->op[1] = ii->op[1] <= ii->op[2];
468
          ii->opt[1] = OPT_CONST;
469
          ii->op[2] = 0;
470
          ii->opt[2] = OPT_CONST;
471
          return 1;
472
        }
473
      else if (ii->opt[2] && OPT_CONST && ii->op[2] == 0)
474
        {
475
          change_insn_type (ii, II_SFEQ);
476
        }
477
      else
478
        break;
479
    case II_SFLT:
480
      if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST)
481
        {
482
          change_insn_type (ii, II_ADD);
483
          ii->op[1] = ii->op[1] < ii->op[2];
484
          ii->opt[1] = OPT_CONST;
485
          ii->op[2] = 0;
486
          ii->opt[2] = OPT_CONST;
487
          return 1;
488
        }
489
      else if (ii->opt[2] && OPT_CONST && ii->op[2] == 0)
490
        {
491
          change_insn_type (ii, II_ADD);
492
          ii->op[1] = 0;
493
          ii->opt[1] = OPT_CONST;
494
        }
495
      break;
496
    case II_SFGE:
497
      if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST)
498
        {
499
          change_insn_type (ii, II_ADD);
500
          ii->op[1] = ii->op[1] >= ii->op[2];
501
          ii->opt[1] = OPT_CONST;
502
          ii->op[2] = 0;
503
          ii->opt[2] = OPT_CONST;
504
          return 1;
505
        }
506
      else if (ii->opt[2] && OPT_CONST && ii->op[2] == 0)
507
        {
508
          change_insn_type (ii, II_ADD);
509
          ii->op[1] = 1;
510
          ii->opt[1] = OPT_CONST;
511
        }
512
      else
513
        break;
514
    case II_SFGT:
515
      if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST)
516
        {
517
          change_insn_type (ii, II_ADD);
518
          ii->op[1] = ii->op[1] > ii->op[2];
519
          ii->opt[1] = OPT_CONST;
520
          ii->op[2] = 0;
521
          ii->opt[2] = OPT_CONST;
522
          return 1;
523
        }
524
      else if (ii->opt[2] && OPT_CONST && ii->op[2] == 0)
525
        {
526
          change_insn_type (ii, II_SFNE);
527
        }
528
      else
529
        break;
530
    case II_CMOV:
531
      if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2])
532
        {
533
          change_insn_type (ii, II_ADD);
534
          ii->op[2] = 0;
535
          ii->opt[2] = OPT_CONST;
536
          ii->opt[3] = OPT_NONE;
537
          return 1;
538
        }
539
      if (ii->opt[3] & OPT_CONST)
540
        {
541
          change_insn_type (ii, II_ADD);
542
          if (ii->op[3])
543
            {
544
              ii->op[2] = 0;
545
              ii->opt[2] = OPT_CONST;
546
            }
547
          else
548
            {
549
              ii->op[1] = 0;
550
              ii->opt[1] = OPT_CONST;
551
            }
552
          ii->opt[3] = OPT_NONE;
553
          return 1;
554
        }
555
      if (ii->type & IT_COND)
556
        {
557
          if (ii->opt[1] & OPT_CONST && ii->opt[2] & OPT_CONST)
558
            {
559
              if (ii->op[1] && !ii->op[2])
560
                {
561
                  change_insn_type (ii, II_ADD);
562
                  ii->op[1] = ii->op[3];
563
                  ii->opt[1] = ii->opt[3];
564
                  ii->op[2] = 0;
565
                  ii->opt[2] = OPT_CONST;
566
                  ii->opt[3] = OPT_NONE;
567
                  return 1;
568
                }
569
              if (ii->op[1] && ii->op[2])
570
                {
571
                  change_insn_type (ii, II_ADD);
572
                  ii->op[1] = 1;
573
                  ii->opt[1] = OPT_CONST;
574
                  ii->op[2] = 0;
575
                  ii->opt[2] = OPT_CONST;
576
                  ii->opt[3] = OPT_NONE;
577
                  return 1;
578
                }
579
              if (!ii->op[1] && !ii->op[2])
580
                {
581
                  change_insn_type (ii, II_ADD);
582
                  ii->op[1] = 0;
583
                  ii->opt[1] = OPT_CONST;
584
                  ii->op[2] = 0;
585
                  ii->opt[2] = OPT_CONST;
586
                  ii->opt[3] = OPT_NONE;
587
                  return 1;
588
                }
589
            }
590
          if (ii->op[1] == ii->op[3] && ii->opt[1] == ii->opt[3])
591
            {
592
              ii->op[1] = 1;
593
              ii->opt[1] = OPT_CONST;
594
              return 1;
595
            }
596
          if (ii->op[2] == ii->op[3] && ii->opt[2] == ii->opt[3])
597
            {
598
              ii->op[2] = 0;
599
              ii->opt[2] = OPT_CONST;
600
              return 1;
601
            }
602
        }
603
      break;
604
    }
605
  return 0;
606
}
607
 
608
/* First primary input */
609
static unsigned long tmp_op, tmp_opt;
610
 
611
/* Recursive function that searches for primary inputs;
612
   returns 0 if cmov can be replaced by add */
613
static int
614
cmov_needed (cuc_func * f, int ref)
615
{
616
  cuc_insn *ii = &f->INSN (ref);
617
  int j;
618
 
619
  cucdebug (4, " %x", ref);
620
  /* mark visited, if already marked, we have a loop, ignore */
621
  if (ii->tmp)
622
    return 0;
623
  ii->tmp = 1;
624
 
625
  /* handle normal movs separately */
626
  if (ii->index == II_ADD && !(ii->type & IT_VOLATILE)
627
      && ii->opt[2] == OPT_CONST && ii->op[2] == 0)
628
    {
629
      if (ii->opt[1] == OPT_REF)
630
        {
631
          if (cmov_needed (f, ii->op[1]))
632
            {
633
              ii->tmp = 0;
634
              return 1;
635
            }
636
        }
637
      else
638
        {
639
          if (tmp_opt == OPT_NONE)
640
            {
641
              tmp_op = ii->op[1];
642
              tmp_opt = ii->opt[1];
643
            }
644
          else if (tmp_opt != ii->opt[1] || tmp_op != ii->op[1])
645
            {
646
              ii->tmp = 0;
647
              return 1;
648
            }
649
        }
650
      ii->tmp = 0;
651
      return 0;
652
    }
653
 
654
  /* Is this instruction CMOV? no => add to primary inputs */
655
  if ((ii->index != II_CMOV) || (ii->type & IT_VOLATILE))
656
    {
657
      if (tmp_opt == OPT_NONE)
658
        {
659
          tmp_op = ref;
660
          tmp_opt = OPT_REF;
661
          ii->tmp = 0;
662
          return 0;
663
        }
664
      else if (tmp_opt != OPT_REF || tmp_op != ref)
665
        {
666
          ii->tmp = 0;
667
          return 1;
668
        }
669
      else
670
        {
671
          ii->tmp = 0;
672
          return 0;
673
        }
674
    }
675
 
676
  for (j = 1; j < 3; j++)
677
    {
678
      cucdebug (4, "(%x:%i)", ref, j);
679
      if (ii->opt[j] == OPT_REF)
680
        {
681
          if (cmov_needed (f, ii->op[j]))
682
            {
683
              ii->tmp = 0;
684
              return 1;
685
            }
686
        }
687
      else
688
        {
689
          if (tmp_opt == OPT_NONE)
690
            {
691
              tmp_op = ii->op[j];
692
              tmp_opt = ii->opt[j];
693
            }
694
          else if (tmp_opt != ii->opt[j] || tmp_op != ii->op[j])
695
            {
696
              ii->tmp = 0;
697
              return 1;
698
            }
699
        }
700
    }
701
 
702
  ii->tmp = 0;
703
  return 0;
704
}
705
 
706
/* Search and optimize complex cmov assignments */
707
int
708
optimize_cmovs (cuc_func * f)
709
{
710
  int modified = 0;
711
  int b, i;
712
 
713
  /* Mark all instructions unvisited */
714
  for (b = 0; b < f->num_bb; b++)
715
    if (!(f->bb[b].type & BB_DEAD))
716
      for (i = 0; i < f->bb[b].ninsn; i++)
717
        f->bb[b].insn[i].tmp = 0;
718
 
719
  for (b = 0; b < f->num_bb; b++)
720
    if (!(f->bb[b].type & BB_DEAD))
721
      {
722
        for (i = 0; i < f->bb[b].ninsn; i++)
723
          {
724
            cuc_insn *ii = &f->bb[b].insn[i];
725
            if (ii->index == II_CMOV && !(ii->type & IT_VOLATILE))
726
              {
727
                tmp_opt = OPT_NONE;
728
                cucdebug (4, "\n");
729
                if (!cmov_needed (f, REF (b, i)))
730
                  {
731
                    assert (tmp_opt != OPT_NONE);
732
                    change_insn_type (ii, II_ADD);
733
                    ii->op[1] = tmp_op;
734
                    ii->opt[1] = tmp_opt;
735
                    ii->op[2] = 0;
736
                    ii->opt[2] = OPT_CONST;
737
                    ii->opt[3] = OPT_NONE;
738
                    modified = 1;
739
                  }
740
              }
741
          }
742
      }
743
  return modified;
744
}
745
 
746
/* returns number of instructions, using instruction ref */
747
static int
748
insn_uses (cuc_func * f, int ref)
749
{
750
  int b, i, j;
751
  int cnt = 0;
752
  for (b = 0; b < f->num_bb; b++)
753
    for (i = 0; i < f->bb[b].ninsn; i++)
754
      for (j = 0; j < MAX_OPERANDS; j++)
755
        if (f->bb[b].insn[i].opt[j] & OPT_REF
756
            && f->bb[b].insn[i].op[j] == ref)
757
          cnt++;
758
  return cnt;
759
}
760
 
761
/* handles some common CMOV, CMOV-CMOV cases;
762
   returns nonzero if anything optimized */
763
static int
764
optimize_cmov_more (cuc_func * f, int ref)
765
{
766
  int t = 0;
767
  cuc_insn *ii = &f->INSN (ref);
768
  assert (ii->index == II_CMOV);
769
 
770
  /* In case of x = cmov x, y; or x = cmov y, x; we have
771
     asynchroneous loop -> remove it */
772
  if ((ii->opt[1] & OPT_REF) && ii->op[1] == ref)
773
    t = 1;
774
  if ((ii->opt[2] & OPT_REF) && ii->op[2] == ref)
775
    t = 2;
776
  if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2])
777
    t = 2;
778
  if (t)
779
    {
780
      change_insn_type (ii, II_ADD);
781
      cucdebug (2, "%8x:cmov     %i\n", ref, t);
782
      ii->opt[t] = OPT_CONST;
783
      ii->op[t] = 0;
784
      ii->opt[3] = OPT_NONE;
785
      return 1;
786
    }
787
  if (!(ii->type & IT_COND))
788
    {
789
      for (t = 1; t <= 2; t++)
790
        {
791
          /*   cmov L, X, Y, C1
792
             cmov Z, L, Y, C2
793
             can be replaced with simpler:
794
             cmov L, C1, C2, C2
795
             cmov Z, X, Y, L */
796
          if (ii->opt[t] == OPT_REF && f->INSN (ii->op[t]).index == II_CMOV)
797
            {
798
              int r = ii->op[t];
799
              unsigned long x, xt, y, yt;
800
              cuc_insn *prev = &f->INSN (r);
801
              cuc_check (f);
802
              cucdebug (3, "%x-%x\n", ref, r);
803
              assert (!(prev->type & IT_COND));
804
              if (prev->op[3 - t] != ii->op[3 - t]
805
                  || prev->opt[3 - t] != ii->opt[3 - t]
806
                  || insn_uses (f, r) > 1)
807
                continue;
808
              cucdebug (3, "%x-%x cmov more\n", ref, r);
809
              prev->type |= IT_COND;
810
              x = prev->op[t];
811
              xt = prev->opt[t];
812
              y = prev->op[3 - t];
813
              yt = prev->opt[3 - t];
814
              prev->op[t] = ii->op[3];
815
              prev->opt[t] = ii->opt[3];        /* C2 */
816
              ii->op[3] = r;
817
              ii->opt[3] = OPT_REF;     /* L */
818
              prev->op[3 - t] = prev->op[3];
819
              prev->opt[3 - t] = prev->opt[3];  /* C1 */
820
              prev->op[3] = prev->op[t];
821
              prev->opt[3] = prev->opt[t];      /* C2 */
822
              ii->op[t] = x;
823
              ii->opt[t] = xt;  /* X */
824
              ii->op[3 - t] = y;
825
              ii->opt[3 - t] = yt;      /* Y */
826
              prev->op[0] = -1;
827
              prev->opt[0] = OPT_REGISTER | OPT_DEST;
828
              cuc_check (f);
829
              return 1;
830
            }
831
        }
832
    }
833
 
834
  if (ii->opt[3] & OPT_REF)
835
    {
836
      cuc_insn *prev = &f->INSN (ii->op[3]);
837
      assert (prev->type & IT_COND);
838
      if (prev->index == II_CMOV)
839
        {
840
          /* negated conditional:
841
             cmov x, 0, 1, y
842
             cmov z, a, b, x
843
             is replaced by
844
             cmov z, b, a, y */
845
          if (prev->opt[1] & OPT_CONST && prev->opt[2] & OPT_CONST
846
              && !prev->op[1] && prev->op[2])
847
            {
848
              unsigned long t;
849
              t = ii->op[1];
850
              ii->op[1] = ii->op[2];
851
              ii->op[2] = t;
852
              t = ii->opt[1];
853
              ii->opt[1] = ii->opt[2];
854
              ii->opt[2] = t;
855
              ii->op[3] = prev->op[3];
856
              ii->opt[3] = prev->opt[3];
857
            }
858
        }
859
      else if (prev->index == II_ADD)
860
        {
861
          /*   add x, y, 0
862
             cmov z, a, b, x
863
             is replaced by
864
             cmov z, a, b, y */
865
          if (prev->opt[2] & OPT_CONST && prev->op[2] == 0)
866
            {
867
              ii->op[3] = prev->op[1];
868
              ii->opt[3] = prev->opt[1];
869
              return 1;
870
            }
871
        }
872
    }
873
 
874
  /* Check if both choices can be pushed through */
875
  if (ii->opt[1] & OPT_REF && ii->opt[2] & OPT_REF
876
      /* Usually doesn't make sense to move conditionals though => more area */
877
      && !(ii->type & IT_COND))
878
    {
879
      cuc_insn *a, *b;
880
      a = &f->INSN (ii->op[1]);
881
      b = &f->INSN (ii->op[2]);
882
      if (a->index == b->index && !(a->type & IT_VOLATILE)
883
          && !(b->type & IT_VOLATILE))
884
        {
885
          int diff = -1;
886
          int i;
887
          for (i = 0; i < MAX_OPERANDS; i++)
888
            if (a->opt[i] != b->opt[i]
889
                || !(a->op[i] == b->op[i] || a->opt[i] & OPT_REGISTER))
890
              {
891
                if (diff == -1)
892
                  diff = i;
893
                else
894
                  diff = -2;
895
              }
896
          /* If diff == -1, it will be eliminated by CSE */
897
          if (diff >= 0)
898
            {
899
              cuc_insn tmp, cmov;
900
              int ref2 = REF (REF_BB (ref), REF_I (ref) + 1);
901
              insert_insns (f, ref, 1);
902
              a = &f->INSN (f->INSN (ref2).op[1]);
903
              b = &f->INSN (f->INSN (ref2).op[2]);
904
              cucdebug (4, "ref = %x %lx %lx\n", ref, f->INSN (ref2).op[1],
905
                        f->INSN (ref2).op[2]);
906
              if (cuc_debug >= 7)
907
                {
908
                  print_cuc_bb (f, "AAA");
909
                  cuc_check (f);
910
                }
911
              tmp = *a;
912
              cmov = f->INSN (ref2);
913
              tmp.op[diff] = ref;
914
              tmp.opt[diff] = OPT_REF;
915
              cmov.op[0] = -1;
916
              cmov.opt[0] = OPT_REGISTER | OPT_DEST;
917
              cmov.op[1] = a->op[diff];
918
              cmov.opt[1] = a->opt[diff];
919
              cmov.op[2] = b->op[diff];
920
              cmov.opt[2] = b->opt[diff];
921
              change_insn_type (&cmov, II_CMOV);
922
              cmov.type &= ~IT_COND;
923
              cucdebug (4, "ref2 = %x %lx %lx\n", ref2, cmov.op[1],
924
                        cmov.op[2]);
925
              if (cmov.opt[1] & OPT_REF && cmov.opt[2] & OPT_REF
926
                  && f->INSN (cmov.op[1]).type & IT_COND)
927
                {
928
                  assert (f->INSN (cmov.op[2]).type & IT_COND);
929
                  cmov.type |= IT_COND;
930
                }
931
              f->INSN (ref) = cmov;
932
              f->INSN (ref2) = tmp;
933
              if (cuc_debug >= 6)
934
                print_cuc_bb (f, "BBB");
935
              cuc_check (f);
936
              return 1;
937
            }
938
        }
939
    }
940
  return 0;
941
}
942
 
943
/* Optimizes dataflow tree */
944
int
945
optimize_tree (cuc_func * f)
946
{
947
  int b, i, j;
948
  int modified;
949
  int gmodified = 0;
950
 
951
  do
952
    {
953
      modified = 0;
954
      if (cuc_debug)
955
        cuc_check (f);
956
      for (b = 0; b < f->num_bb; b++)
957
        if (!(f->bb[b].type & BB_DEAD))
958
          {
959
            for (i = 0; i < f->bb[b].ninsn; i++)
960
              {
961
                cuc_insn *ii = &f->bb[b].insn[i];
962
                /* We tend to have the third parameter const if instruction is cumutative */
963
                if ((ii->opt[1] & OPT_CONST) && !(ii->opt[2] & OPT_CONST))
964
                  {
965
                    int cond = ii->index == II_SFEQ || ii->index == II_SFNE
966
                      || ii->index == II_SFLT || ii->index == II_SFLE
967
                      || ii->index == II_SFGT || ii->index == II_SFGE;
968
                    if (known[ii->index].comutative || cond)
969
                      {
970
                        unsigned long t = ii->opt[1];
971
                        ii->opt[1] = ii->opt[2];
972
                        ii->opt[2] = t;
973
                        t = ii->op[1];
974
                        ii->op[1] = ii->op[2];
975
                        ii->op[2] = t;
976
                        modified = 1;
977
                        cucdebug (2, "%08x:<>\n", REF (b, i));
978
                        if (cond)
979
                          {
980
                            if (ii->index == II_SFEQ)
981
                              ii->index = II_SFNE;
982
                            else if (ii->index == II_SFNE)
983
                              ii->index = II_SFEQ;
984
                            else if (ii->index == II_SFLE)
985
                              ii->index = II_SFGT;
986
                            else if (ii->index == II_SFLT)
987
                              ii->index = II_SFGE;
988
                            else if (ii->index == II_SFGE)
989
                              ii->index = II_SFLT;
990
                            else if (ii->index == II_SFGT)
991
                              ii->index = II_SFLE;
992
                            else
993
                              assert (0);
994
                          }
995
                      }
996
                  }
997
 
998
                /* Try to do the promotion */
999
                /* We have two consecutive expressions, containing constants,
1000
                 * if previous is a simple expression we can handle it simply: */
1001
                for (j = 0; j < MAX_OPERANDS; j++)
1002
                  if (ii->opt[j] & OPT_REF)
1003
                    {
1004
                      cuc_insn *t = &f->INSN (ii->op[j]);
1005
                      if (f->INSN (ii->op[j]).index == II_ADD
1006
                          && f->INSN (ii->op[j]).opt[2] & OPT_CONST
1007
                          && f->INSN (ii->op[j]).op[2] == 0
1008
                          && !(ii->type & IT_MEMORY && t->type & IT_MEMADD))
1009
                        {
1010
                          /* do not promote through add-mem, and branches */
1011
                          modified = 1;
1012
                          cucdebug (2, "%8x:promote%i %8lx %8lx\n",
1013
                                    REF (b, i), j, ii->op[j], t->op[1]);
1014
                          ii->op[j] = t->op[1];
1015
                          ii->opt[j] = t->opt[1];
1016
                        }
1017
                    }
1018
 
1019
                /* handle some CMOV cases more deeply */
1020
                if (ii->index == II_CMOV
1021
                    && optimize_cmov_more (f, REF (b, i)))
1022
                  {
1023
                    modified = 1;
1024
                    continue;
1025
                  }
1026
 
1027
                /* Do nothing to volatile instructions */
1028
                if (ii->type & IT_VOLATILE)
1029
                  continue;
1030
 
1031
                /* Check whether we can simplify the instruction */
1032
                if (apply_edge_condition (ii))
1033
                  {
1034
                    modified = 1;
1035
                    continue;
1036
                  }
1037
                /* We cannot do anything more if at least one is not constant */
1038
                if (!(ii->opt[2] & OPT_CONST))
1039
                  continue;
1040
 
1041
                if (ii->opt[1] & OPT_CONST)
1042
                  {             /* We have constant expression */
1043
                    unsigned long value;
1044
                    int ok = 1;
1045
                    /* Was constant expression already? */
1046
                    if (ii->index == II_ADD && !ii->op[2])
1047
                      continue;
1048
 
1049
                    if (ii->index == II_ADD)
1050
                      value = ii->op[1] + ii->op[2];
1051
                    else if (ii->index == II_SUB)
1052
                      value = ii->op[1] - ii->op[2];
1053
                    else if (ii->index == II_SLL)
1054
                      value = ii->op[1] << ii->op[2];
1055
                    else if (ii->index == II_SRL)
1056
                      value = ii->op[1] >> ii->op[2];
1057
                    else if (ii->index == II_MUL)
1058
                      value = ii->op[1] * ii->op[2];
1059
                    else if (ii->index == II_OR)
1060
                      value = ii->op[1] | ii->op[2];
1061
                    else if (ii->index == II_XOR)
1062
                      value = ii->op[1] ^ ii->op[2];
1063
                    else if (ii->index == II_AND)
1064
                      value = ii->op[1] & ii->op[2];
1065
                    else
1066
                      ok = 0;
1067
                    if (ok)
1068
                      {
1069
                        change_insn_type (ii, II_ADD);
1070
                        ii->op[0] = -1;
1071
                        ii->opt[0] = OPT_REGISTER | OPT_DEST;
1072
                        ii->op[1] = value;
1073
                        ii->opt[1] = OPT_CONST;
1074
                        ii->op[2] = 0;
1075
                        ii->opt[2] = OPT_CONST;
1076
                        modified = 1;
1077
                        cucdebug (2, "%8x:const\n", REF (b, i));
1078
                      }
1079
                  }
1080
                else if (ii->opt[1] & OPT_REF)
1081
                  {
1082
                    cuc_insn *prev = &f->INSN (ii->op[1]);
1083
                    /* Is this just a move? */
1084
                    if (ii->index == II_ADD
1085
                        && !(ii->type & IT_MEMADD) && ii->op[2] == 0)
1086
                      {
1087
                        int b1, i1, j1;
1088
                        cucdebug (2, "%8x:link      %8lx: ", REF (b, i),
1089
                                  ii->op[1]);
1090
                        if (!(prev->type & (IT_OUTPUT | IT_VOLATILE)))
1091
                          {
1092
                            assert (ii->opt[0] & OPT_DEST);
1093
                            prev->op[0] = ii->op[0];
1094
                            prev->opt[0] = ii->opt[0];
1095
                            prev->type |= ii->type & IT_OUTPUT;
1096
                            for (b1 = 0; b1 < f->num_bb; b1++)
1097
                              if (!(f->bb[b1].type & BB_DEAD))
1098
                                for (i1 = 0; i1 < f->bb[b1].ninsn; i1++)
1099
                                  for (j1 = 0; j1 < MAX_OPERANDS; j1++)
1100
                                    if ((f->bb[b1].insn[i1].opt[j1] & OPT_REF)
1101
                                        && f->bb[b1].insn[i1].op[j1] ==
1102
                                        REF (b, i))
1103
                                      {
1104
                                        cucdebug (2, "%x ", REF (b1, i1));
1105
                                        f->bb[b1].insn[i1].op[j1] = ii->op[1];
1106
                                      }
1107
                            cucdebug (2, "\n");
1108
                            change_insn_type (ii, II_NOP);
1109
                          }
1110
                      }
1111
                    else if (prev->opt[2] & OPT_CONST)
1112
                      {
1113
                        /* Handle some common cases */
1114
                        /* add - add joining */
1115
                        if (ii->index == II_ADD && prev->index == II_ADD)
1116
                          {
1117
                            ii->op[1] = prev->op[1];
1118
                            ii->opt[1] = prev->opt[1];
1119
                            ii->op[2] += prev->op[2];
1120
                            modified = 1;
1121
                            cucdebug (2, "%8x: add-add\n", REF (b, i));
1122
                          }
1123
                        else /* add - sub joining */ if (ii->index == II_ADD
1124
                                                         && prev->index ==
1125
                                                         II_SUB)
1126
                          {
1127
                            change_insn_type (&insn[i], II_SUB);
1128
                            ii->op[1] = prev->op[1];
1129
                            ii->opt[1] = prev->opt[1];
1130
                            ii->op[2] += prev->op[2];
1131
                            modified = 1;
1132
                            cucdebug (2, "%8x: add-sub\n", REF (b, i));
1133
                          }
1134
                        else /* sub - add joining */ if (ii->index == II_SUB
1135
                                                         && prev->index ==
1136
                                                         II_ADD)
1137
                          {
1138
                            ii->op[1] = prev->op[1];
1139
                            ii->opt[1] = prev->opt[1];
1140
                            ii->op[2] += prev->op[2];
1141
                            modified = 1;
1142
                            cucdebug (2, "%8x: sub-add\n", REF (b, i));
1143
                          }
1144
                        else /* add - sfxx joining */ if (prev->index ==
1145
                                                          II_ADD && (
1146
                                                                       ii->
1147
                                                                       index
1148
                                                                       ==
1149
                                                                       II_SFEQ
1150
                                                                       || ii->
1151
                                                                       index
1152
                                                                       ==
1153
                                                                       II_SFNE
1154
                                                                       || ii->
1155
                                                                       index
1156
                                                                       ==
1157
                                                                       II_SFLT
1158
                                                                       || ii->
1159
                                                                       index
1160
                                                                       ==
1161
                                                                       II_SFLE
1162
                                                                       || ii->
1163
                                                                       index
1164
                                                                       ==
1165
                                                                       II_SFGT
1166
                                                                       || ii->
1167
                                                                       index
1168
                                                                       ==
1169
                                                                       II_SFGE))
1170
                          {
1171
                            if (ii->opt[2] & OPT_CONST
1172
                                && ii->op[2] < 0x80000000)
1173
                              {
1174
                                ii->op[1] = prev->op[1];
1175
                                ii->opt[1] = prev->opt[1];
1176
                                ii->op[2] -= prev->op[2];
1177
                                modified = 1;
1178
                                cucdebug (2, "%8x: add-sfxx\n", REF (b, i));
1179
                              }
1180
                          }
1181
                        else /* sub - sfxx joining */ if (prev->index ==
1182
                                                          II_SUB && (
1183
                                                                       ii->
1184
                                                                       index
1185
                                                                       ==
1186
                                                                       II_SFEQ
1187
                                                                       || ii->
1188
                                                                       index
1189
                                                                       ==
1190
                                                                       II_SFNE
1191
                                                                       || ii->
1192
                                                                       index
1193
                                                                       ==
1194
                                                                       II_SFLT
1195
                                                                       || ii->
1196
                                                                       index
1197
                                                                       ==
1198
                                                                       II_SFLE
1199
                                                                       || ii->
1200
                                                                       index
1201
                                                                       ==
1202
                                                                       II_SFGT
1203
                                                                       || ii->
1204
                                                                       index
1205
                                                                       ==
1206
                                                                       II_SFGE))
1207
                          {
1208
                            if (ii->opt[2] & OPT_CONST
1209
                                && ii->op[2] < 0x80000000)
1210
                              {
1211
                                ii->op[1] = prev->op[1];
1212
                                ii->opt[1] = prev->opt[1];
1213
                                ii->op[2] += prev->op[2];
1214
                                modified = 1;
1215
                                cucdebug (2, "%8x: sub-sfxx\n", REF (b, i));
1216
                              }
1217
                          }
1218
                      }
1219
                  }
1220
              }
1221
          }
1222
      if (modified)
1223
        gmodified = 1;
1224
    }
1225
  while (modified);
1226
  return gmodified;
1227
}
1228
 
1229
/* Remove nop instructions */
1230
int
1231
remove_nops (cuc_func * f)
1232
{
1233
  int b;
1234
  int modified = 0;
1235
  for (b = 0; b < f->num_bb; b++)
1236
    {
1237
      int c, d = 0, i, j;
1238
      cuc_insn *insn = f->bb[b].insn;
1239
      for (i = 0; i < f->bb[b].ninsn; i++)
1240
        if (insn[i].index != II_NOP)
1241
          {
1242
            reloc[i] = d;
1243
            insn[d++] = insn[i];
1244
          }
1245
        else
1246
          {
1247
            reloc[i] = d;       /* For jumps only */
1248
          }
1249
      if (f->bb[b].ninsn != d)
1250
        modified = 1;
1251
      f->bb[b].ninsn = d;
1252
 
1253
      /* Relocate references from all basic blocks */
1254
      for (c = 0; c < f->num_bb; c++)
1255
        for (i = 0; i < f->bb[c].ninsn; i++)
1256
          {
1257
            dep_list *d = f->bb[c].insn[i].dep;
1258
            for (j = 0; j < MAX_OPERANDS; j++)
1259
              if ((f->bb[c].insn[i].opt[j] & OPT_REF)
1260
                  && REF_BB (f->bb[c].insn[i].op[j]) == b)
1261
                f->bb[c].insn[i].op[j] =
1262
                  REF (b, reloc[REF_I (f->bb[c].insn[i].op[j])]);
1263
 
1264
            while (d)
1265
              {
1266
                if (REF_BB (d->ref) == b)
1267
                  d->ref = REF (b, reloc[REF_I (d->ref)]);
1268
                d = d->next;
1269
              }
1270
          }
1271
    }
1272
  return modified;
1273
}
1274
 
1275
static void
1276
unmark_tree (cuc_func * f, int ref)
1277
{
1278
  cuc_insn *ii = &f->INSN (ref);
1279
  cucdebug (5, "%x ", ref);
1280
  if (ii->type & IT_UNUSED)
1281
    {
1282
      int j;
1283
      ii->type &= ~IT_UNUSED;
1284
      for (j = 0; j < MAX_OPERANDS; j++)
1285
        if (ii->opt[j] & OPT_REF)
1286
          unmark_tree (f, ii->op[j]);
1287
    }
1288
}
1289
 
1290
/* Remove unused assignments */
1291
int
1292
remove_dead (cuc_func * f)
1293
{
1294
  int b, i;
1295
  for (b = 0; b < f->num_bb; b++)
1296
    for (i = 0; i < f->bb[b].ninsn; i++)
1297
      f->bb[b].insn[i].type |= IT_UNUSED;
1298
 
1299
  for (b = 0; b < f->num_bb; b++)
1300
    for (i = 0; i < f->bb[b].ninsn; i++)
1301
      {
1302
        cuc_insn *ii = &f->bb[b].insn[i];
1303
        if (ii->type & IT_VOLATILE || ii->type & IT_OUTPUT
1304
            || (II_IS_LOAD (ii->index)
1305
                && (f->memory_order == MO_NONE || f->memory_order == MO_WEAK))
1306
            || II_IS_STORE (ii->index))
1307
          {
1308
            unmark_tree (f, REF (b, i));
1309
            cucdebug (5, "\n");
1310
          }
1311
      }
1312
 
1313
  for (b = 0; b < f->num_bb; b++)
1314
    for (i = 0; i < f->bb[b].ninsn; i++)
1315
      if (f->bb[b].insn[i].type & IT_UNUSED)
1316
        {
1317
          change_insn_type (&f->bb[b].insn[i], II_NOP);
1318
        }
1319
 
1320
  return remove_nops (f);
1321
}
1322
 
1323
/* Removes trivial register assignments */
1324
int
1325
remove_trivial_regs (cuc_func * f)
1326
{
1327
  int b, i;
1328
  for (i = 0; i < MAX_REGS; i++)
1329
    f->saved_regs[i] = caller_saved[i];
1330
 
1331
  for (b = 0; b < f->num_bb; b++)
1332
    {
1333
      cuc_insn *insn = f->bb[b].insn;
1334
      for (i = 0; i < f->bb[b].ninsn; i++)
1335
        {
1336
          if (insn[i].index == II_ADD
1337
              && insn[i].opt[0] & OPT_REGISTER
1338
              && insn[i].opt[1] & OPT_REGISTER
1339
              && insn[i].op[0] == insn[i].op[1] && insn[i].opt[2] & OPT_CONST
1340
              && insn[i].op[2] == 0)
1341
            {
1342
              if (insn[i].type & IT_OUTPUT)
1343
                f->saved_regs[insn[i].op[0]] = 1;
1344
              change_insn_type (&insn[i], II_NOP);
1345
            }
1346
        }
1347
    }
1348
  if (cuc_debug >= 2)
1349
    {
1350
      PRINTF ("saved regs ");
1351
      for (i = 0; i < MAX_REGS; i++)
1352
        PRINTF ("%i:%i ", i, f->saved_regs[i]);
1353
      PRINTF ("\n");
1354
    }
1355
  return remove_nops (f);
1356
}
1357
 
1358
/* Determine inputs and outputs */
1359
void
1360
set_io (cuc_func * f)
1361
{
1362
  int b, i, j;
1363
  /* Determine register usage */
1364
  for (i = 0; i < MAX_REGS; i++)
1365
    {
1366
      f->lur[i] = -1;
1367
      f->used_regs[i] = 0;
1368
    }
1369
  if (cuc_debug > 5)
1370
    print_cuc_bb (f, "SET_IO");
1371
  for (b = 0; b < f->num_bb; b++)
1372
    {
1373
      for (i = 0; i < f->bb[b].ninsn; i++)
1374
        for (j = 0; j < MAX_OPERANDS; j++)
1375
          if (f->bb[b].insn[i].opt[j] & OPT_REGISTER
1376
              && f->bb[b].insn[i].op[j] >= 0)
1377
            {
1378
              if (f->bb[b].insn[i].opt[j] & OPT_DEST)
1379
                f->lur[f->bb[b].insn[i].op[j]] = REF (b, i);
1380
              else
1381
                f->used_regs[f->bb[b].insn[i].op[j]] = 1;
1382
            }
1383
    }
1384
}
1385
 
1386
/* relocate all accesses inside of BB b to back/fwd */
1387
#if 0
1388
static void
1389
relocate_bb (cuc_bb * bb, int b, int back, int fwd)
1390
{
1391
  int i, j;
1392
  for (i = 0; i < bb->ninsn; i++)
1393
    for (j = 0; j < MAX_OPERANDS; j++)
1394
      if (bb->insn[i].opt[j] & OPT_REF && REF_BB (bb->insn[i].op[j]) == b)
1395
        {
1396
          int t = REF_I (bb->insn[i].op[j]);
1397
          if (t < i)
1398
            bb->insn[i].op[j] = REF (back, t);
1399
          else
1400
            bb->insn[i].op[j] = REF (fwd, t);
1401
        }
1402
}
1403
#endif
1404
 
1405
/* Latch outputs in loops */
1406
void
1407
add_latches (cuc_func * f)
1408
{
1409
  int b, i, j;
1410
 
1411
  //print_cuc_bb (f, "ADD_LATCHES a");
1412
  /* Cuts the tree and marks registers */
1413
  mark_cut (f);
1414
 
1415
  /* Split BBs with more than one group */
1416
  for (b = 0; b < f->num_bb; b++)
1417
    expand_bb (f, b);
1418
  remove_nops (f);
1419
  //print_cuc_bb (f, "ADD_LATCHES 0");
1420
 
1421
  /* Convert accesses in BB_INLOOP type block to latched */
1422
  for (b = 0; b < f->num_bb; b++)
1423
    {
1424
      int j;
1425
      for (i = 0; i < f->bb[b].ninsn; i++)
1426
        for (j = 0; j < MAX_OPERANDS; j++)
1427
          if (f->bb[b].insn[i].opt[j] == OPT_REF)
1428
            {
1429
              int t = f->bb[b].insn[i].op[j];
1430
              /* If we are pointing to a INLOOP block from outside, or forward
1431
                 (= previous loop iteration) we must register that data */
1432
              if ((f->bb[REF_BB (t)].type & BB_INLOOP
1433
                   || config.cuc.no_multicycle)
1434
                  && !(f->INSN (t).type & (IT_BRANCH | IT_COND))
1435
                  && (REF_BB (t) != b || REF_I (t) >= i))
1436
                {
1437
                  f->INSN (t).type |= IT_LATCHED;
1438
                }
1439
            }
1440
    }
1441
  //print_cuc_bb (f, "ADD_LATCHES 1");
1442
 
1443
  /* Add latches at the end of blocks as needed */
1444
  for (b = 0; b < f->num_bb; b++)
1445
    {
1446
      int nreg = 0;
1447
      cuc_insn *insn;
1448
      for (i = 0; i < f->bb[b].ninsn; i++)
1449
        if (f->bb[b].insn[i].type & IT_LATCHED)
1450
          nreg++;
1451
      if (nreg)
1452
        {
1453
          insn =
1454
            (cuc_insn *) malloc (sizeof (cuc_insn) * (f->bb[b].ninsn + nreg));
1455
          j = 0;
1456
          for (i = 0; i < f->bb[b].ninsn; i++)
1457
            {
1458
              insn[i] = f->bb[b].insn[i];
1459
              if (insn[i].type & IT_LATCHED)
1460
                {
1461
                  cuc_insn *ii = &insn[f->bb[b].ninsn + j++];
1462
                  change_insn_type (ii, II_REG);
1463
                  ii->op[0] = -1;
1464
                  ii->opt[0] = OPT_DEST | OPT_REGISTER;
1465
                  ii->op[1] = REF (b, i);
1466
                  ii->opt[1] = OPT_REF;
1467
                  ii->opt[2] = ii->opt[3] = OPT_NONE;
1468
                  ii->dep = NULL;
1469
                  ii->type = IT_VOLATILE;
1470
                  sprintf (ii->disasm, "reg %i_%i", b, i);
1471
                }
1472
            }
1473
          f->bb[b].ninsn += nreg;
1474
          free (f->bb[b].insn);
1475
          f->bb[b].insn = insn;
1476
        }
1477
    }
1478
  //print_cuc_bb (f, "ADD_LATCHES 2");
1479
 
1480
  /* Repair references */
1481
  for (b = 0; b < f->num_bb; b++)
1482
    for (i = 0; i < f->bb[b].ninsn; i++)
1483
      for (j = 0; j < MAX_OPERANDS; j++)
1484
        /* If destination instruction is latched, use register instead */
1485
        if (f->bb[b].insn[i].opt[j] == OPT_REF
1486
            && f->INSN (f->bb[b].insn[i].op[j]).type & IT_LATCHED)
1487
          {
1488
            int b1, i1;
1489
            b1 = REF_BB (f->bb[b].insn[i].op[j]);
1490
            //cucdebug (2, "%i.%i.%i %x\n", b, i, j, f->bb[b].insn[i].op[j]);
1491
            if (b1 != b || REF_I (f->bb[b].insn[i].op[j]) >= i)
1492
              {
1493
                for (i1 = f->bb[b1].ninsn - 1; i1 >= 0; i1--)
1494
                  {
1495
                    assert (f->bb[b1].insn[i1].index == II_REG);
1496
                    if (f->bb[b1].insn[i1].op[1] == f->bb[b].insn[i].op[j])
1497
                      {
1498
                        f->bb[b].insn[i].op[j] = REF (b1, i1);
1499
                        break;
1500
                      }
1501
                  }
1502
              }
1503
          }
1504
}
1505
 
1506
/* CSE -- common subexpression elimination */
1507
int
1508
cse (cuc_func * f)
1509
{
1510
  int modified = 0;
1511
  int b, i, j, b1, i1, b2, i2;
1512
  for (b1 = 0; b1 < f->num_bb; b1++)
1513
    for (i1 = 0; i1 < f->bb[b1].ninsn; i1++)
1514
      if (f->bb[b1].insn[i1].index != II_NOP
1515
          && f->bb[b1].insn[i1].index != II_LRBB
1516
          && !(f->bb[b1].insn[i1].type & IT_MEMORY)
1517
          && !(f->bb[b1].insn[i1].type & IT_MEMADD))
1518
        for (b2 = 0; b2 < f->num_bb; b2++)
1519
          for (i2 = 0; i2 < f->bb[b2].ninsn; i2++)
1520
            if (f->bb[b2].insn[i2].index != II_NOP
1521
                && f->bb[b2].insn[i2].index != II_LRBB
1522
                && !(f->bb[b2].insn[i2].type & IT_MEMORY)
1523
                && !(f->bb[b2].insn[i2].type & IT_MEMADD) && (b1 != b2
1524
                                                              || i2 > i1))
1525
              {
1526
                cuc_insn *ii1 = &f->bb[b1].insn[i1];
1527
                cuc_insn *ii2 = &f->bb[b2].insn[i2];
1528
                int ok = 1;
1529
 
1530
                /* Do we have an exact match? */
1531
                if (ii1->index != ii2->index)
1532
                  continue;
1533
                if (ii2->type & IT_VOLATILE)
1534
                  continue;
1535
 
1536
                /* Check all operands also */
1537
                for (j = 0; j < MAX_OPERANDS; j++)
1538
                  {
1539
                    if (ii1->opt[j] != ii2->opt[j])
1540
                      {
1541
                        ok = 0;
1542
                        break;
1543
                      }
1544
                    if (ii1->opt[j] & OPT_DEST)
1545
                      continue;
1546
                    if (ii1->opt[j] != OPT_NONE && ii1->op[j] != ii2->op[j])
1547
                      {
1548
                        ok = 0;
1549
                        break;
1550
                      }
1551
                  }
1552
 
1553
                if (ok)
1554
                  {
1555
                    /* remove duplicated instruction and relink the references */
1556
                    cucdebug (3, "%x - %x are same\n", REF (b1, i1),
1557
                              REF (b2, i2));
1558
                    change_insn_type (ii2, II_NOP);
1559
                    modified = 1;
1560
                    for (b = 0; b < f->num_bb; b++)
1561
                      for (i = 0; i < f->bb[b].ninsn; i++)
1562
                        for (j = 0; j < MAX_OPERANDS; j++)
1563
                          if (f->bb[b].insn[i].opt[j] & OPT_REF
1564
                              && f->bb[b].insn[i].op[j] == REF (b2, i2))
1565
                            f->bb[b].insn[i].op[j] = REF (b1, i1);
1566
                  }
1567
              }
1568
  return modified;
1569
}
1570
 
1571
static int
1572
count_cmovs (cuc_insn * ii, int match)
1573
{
1574
  int c = 0, j;
1575
  if (match & 2)
1576
    {
1577
      for (j = 0; j < MAX_OPERANDS; j++)
1578
        if (ii->opt[j] & OPT_DEST)
1579
          c++;
1580
    }
1581
  if (match & 1)
1582
    {
1583
      for (j = 0; j < MAX_OPERANDS; j++)
1584
        if (!(ii->opt[j] & OPT_DEST) && ii->opt[j] & OPT_REF)
1585
          c++;
1586
    }
1587
  else
1588
    {
1589
      for (j = 0; j < MAX_OPERANDS; j++)
1590
        if (!(ii->opt[j] & OPT_DEST) && ii->opt[j] != OPT_NONE)
1591
          c++;
1592
    }
1593
  return c;
1594
}
1595
 
1596
static void search_csm (int iter, cuc_func * f, cuc_shared_list * list);
1597
static cuc_shared_list *main_list;
1598
static int *iteration;
1599
 
1600
/* CSM -- common subexpression matching -- resource sharing
1601
   We try to match tree of instruction inside a BB with as many
1602
   matches as possible. All possibilities are collected and
1603
   options, making situation worse are removed */
1604
void
1605
csm (cuc_func * f)
1606
{
1607
  int b, i, j;
1608
  int cnt;
1609
  cuc_shared_list *list;
1610
  cuc_timings timings;
1611
 
1612
  analyse_timings (f, &timings);
1613
  main_list = NULL;
1614
  for (b = 0; b < f->num_bb; b++)
1615
    {
1616
      assert (iteration = (int *) malloc (sizeof (int) * f->bb[b].ninsn));
1617
      for (i = 0; i < f->bb[b].ninsn; i++)
1618
        {
1619
          int cnt = 0, cntc = 0;
1620
          double size = 0., sizec = 0.;
1621
          int j2 = 0;
1622
          for (j = 0; j < f->bb[b].ninsn; j++)
1623
            if (f->bb[b].insn[i].index == f->bb[b].insn[j].index)
1624
              {
1625
                int ok = 1;
1626
                for (j2 = 0; j2 < MAX_OPERANDS; j2++)
1627
                  if (!(f->bb[b].insn[j].opt[j2] & OPT_REF))
1628
                    if (f->bb[b].insn[j].opt[j2] != f->bb[b].insn[i].opt[j2]
1629
                        || f->bb[b].insn[j].op[j2] !=
1630
                        f->bb[b].insn[i].opt[j2])
1631
                      {
1632
                        ok = 0;
1633
                        break;
1634
                      }
1635
                if (ok)
1636
                  {
1637
                    cntc++;
1638
                    sizec = sizec + insn_size (&f->bb[b].insn[j]);
1639
                  }
1640
                else
1641
                  {
1642
                    cnt++;
1643
                    size = size + insn_size (&f->bb[b].insn[j]);
1644
                  }
1645
                iteration[j] = 0;
1646
              }
1647
            else
1648
              iteration[j] = -1;
1649
          if (cntc > 1)
1650
            {
1651
              assert (list =
1652
                      (cuc_shared_list *) malloc (sizeof (cuc_shared_list)));
1653
              list->next = main_list;
1654
              list->from = NULL;
1655
              list->ref = REF (b, i);
1656
              list->cnt = cnt;
1657
              list->cmatch = 1;
1658
              list->cmovs = count_cmovs (&f->bb[b].insn[i], 3);
1659
              list->osize = sizec;
1660
              list->size = ii_size (f->bb[b].insn[i].index, 1);
1661
              main_list = list;
1662
              search_csm (0, f, list);
1663
            }
1664
          if (cnt > 1)
1665
            {
1666
              assert (list =
1667
                      (cuc_shared_list *) malloc (sizeof (cuc_shared_list)));
1668
              list->next = main_list;
1669
              list->from = NULL;
1670
              list->ref = REF (b, i);
1671
              list->cnt = cnt + cntc;
1672
              list->cmatch = 0;
1673
              list->cmovs = count_cmovs (&f->bb[b].insn[i], 2);
1674
              list->osize = size + sizec;
1675
              list->size = ii_size (f->bb[b].insn[i].index, 0);
1676
              main_list = list;
1677
              search_csm (0, f, list);
1678
            }
1679
        }
1680
      free (iteration);
1681
    }
1682
 
1683
  for (list = main_list; list; list = list->next)
1684
    list->dead = 0;
1685
  cnt = 0;
1686
  for (list = main_list; list; list = list->next)
1687
    if (!list->dead)
1688
      cnt++;
1689
  cucdebug (1, "noptions = %i\n", cnt);
1690
 
1691
  /* Now we will check the real size of the 'improvements'; if the size
1692
     actually increases, we abandom the option */
1693
  for (list = main_list; list; list = list->next)
1694
    if (list->cmovs * ii_size (II_CMOV, 0) * (list->cnt - 1) + list->size >=
1695
        list->osize)
1696
      list->dead = 1;
1697
 
1698
  cnt = 0;
1699
  for (list = main_list; list; list = list->next)
1700
    if (!list->dead)
1701
      cnt++;
1702
  cucdebug (1, "noptions = %i\n", cnt);
1703
 
1704
  /* Count number of instructions grouped */
1705
  for (list = main_list; list; list = list->next)
1706
    {
1707
      cuc_shared_list *l = list;
1708
      int c = 0;
1709
      while (l)
1710
        {
1711
          c++;
1712
          if (f->INSN (l->ref).type & (IT_VOLATILE | IT_MEMORY | IT_MEMADD))
1713
            list->dead = 1;
1714
          l = l->from;
1715
        }
1716
      list->ninsn = c;
1717
    }
1718
 
1719
  cnt = 0;
1720
  for (list = main_list; list; list = list->next)
1721
    if (!list->dead)
1722
      cnt++;
1723
  cucdebug (1, "noptions = %i\n", cnt);
1724
 
1725
#if 1
1726
  /* We can get a lot of options here, so we will delete duplicates */
1727
  for (list = main_list; list; list = list->next)
1728
    if (!list->dead)
1729
      {
1730
        cuc_shared_list *l;
1731
        for (l = list->next; l; l = l->next)
1732
          if (!l->dead)
1733
            {
1734
              int ok = 1;
1735
              cuc_shared_list *t1 = list;
1736
              cuc_shared_list *t2 = l;
1737
              while (ok && t1 && t2)
1738
                {
1739
                  if (f->INSN (t1->ref).index == f->INSN (t2->ref).index)
1740
                    {
1741
                      /* If other operands are matching, we must check for them also */
1742
                      if (t1->cmatch)
1743
                        {
1744
                          int j;
1745
                          for (j = 0; j < MAX_OPERANDS; j++)
1746
                            if (!(f->INSN (t1->ref).opt[j] & OPT_REF)
1747
                                || !(f->INSN (t2->ref).opt[j] & OPT_REF)
1748
                                || f->INSN (t1->ref).opt[j] !=
1749
                                f->INSN (t2->ref).opt[j]
1750
                                || f->INSN (t1->ref).op[j] !=
1751
                                f->INSN (t2->ref).op[j])
1752
                              {
1753
                                ok = 0;
1754
                                break;
1755
                              }
1756
                        }
1757
 
1758
                      /* This option is duplicate, remove */
1759
                      if (ok)
1760
                        t1->dead = 1;
1761
                    }
1762
                  t1 = t1->from;
1763
                  t2 = t2->from;
1764
                }
1765
            }
1766
      }
1767
  cnt = 0;
1768
  for (list = main_list; list; list = list->next)
1769
    if (!list->dead)
1770
      cnt++;
1771
  cucdebug (1, "noptions = %i\n", cnt);
1772
#endif
1773
  /* Print out */
1774
  for (list = main_list; list; list = list->next)
1775
    if (!list->dead)
1776
      {
1777
        cuc_shared_list *l = list;
1778
        cucdebug (1,
1779
                  "%-4s cnt %3i ninsn %3i size %8.1f osize %8.1f cmovs %3i @",
1780
                  cuc_insn_name (&f->INSN (list->ref)), list->cnt,
1781
                  list->ninsn, list->cmovs * ii_size (II_CMOV,
1782
                                                      0) * (list->cnt - 1) +
1783
                  list->size, list->osize, list->cmovs);
1784
        while (l)
1785
          {
1786
            cucdebug (1, "%c%x,", l->cmatch ? '.' : '!', l->ref);
1787
            l = l->from;
1788
          }
1789
        cucdebug (1, "\n");
1790
      }
1791
 
1792
  /* Calculate estimated timings */
1793
  for (b = 0; b < f->num_bb; b++)
1794
    {
1795
      cnt = 0;
1796
      for (list = main_list; list; list = list->next)
1797
        if (!list->dead && REF_BB (list->ref) == b)
1798
          cnt++;
1799
 
1800
      f->bb[b].ntim = cnt;
1801
      if (!cnt)
1802
        {
1803
          f->bb[b].tim = NULL;
1804
          continue;
1805
        }
1806
      assert (f->bb[b].tim =
1807
              (cuc_timings *) malloc (sizeof (cuc_timings) * cnt));
1808
 
1809
      cnt = 0;
1810
      for (list = main_list; list; list = list->next)
1811
        if (!list->dead && REF_BB (list->ref) == b)
1812
          {
1813
            cuc_shared_list *l = list;
1814
            f->bb[b].tim[cnt].b = b;
1815
            f->bb[b].tim[cnt].preroll = f->bb[b].tim[cnt].unroll = 1;
1816
            f->bb[b].tim[cnt].nshared = list->ninsn;
1817
            assert (f->bb[b].tim[cnt].shared = (cuc_shared_item *)
1818
                    malloc (sizeof (cuc_shared_item) * list->ninsn));
1819
            for (i = 0; i < list->ninsn; i++, l = l->from)
1820
              {
1821
                f->bb[b].tim[cnt].shared[i].ref = l->ref;
1822
                f->bb[b].tim[cnt].shared[i].cmatch = l->cmatch;
1823
              }
1824
            f->bb[b].tim[cnt].new_time =
1825
              timings.new_time + f->bb[b].cnt * (list->cnt - 1);
1826
            f->bb[b].tim[cnt].size =
1827
              timings.size + list->cmovs * ii_size (II_CMOV,
1828
                                                    0) * (list->cnt - 1) +
1829
              list->size - list->osize;
1830
            cnt++;
1831
          }
1832
    }
1833
}
1834
 
1835
/* Recursive function for searching through instruction graph */
1836
static void
1837
search_csm (int iter, cuc_func * f, cuc_shared_list * list)
1838
{
1839
  int b, i, j, i1;
1840
  cuc_shared_list *l;
1841
  b = REF_BB (list->ref);
1842
  i = REF_I (list->ref);
1843
 
1844
  for (j = 0; j < MAX_OPERANDS; j++)
1845
    if (f->bb[b].insn[i].opt[j] & OPT_REF)
1846
      {
1847
        int t = f->bb[b].insn[i].op[j];
1848
        int cnt = 0, cntc = 0;
1849
        double size = 0., sizec = 0.;
1850
 
1851
        /* Mark neighbours */
1852
        for (i1 = 0; i1 < f->bb[b].ninsn; i1++)
1853
          {
1854
            if (iteration[i1] == iter && f->bb[b].insn[i1].opt[j] & OPT_REF)
1855
              {
1856
                int t2 = f->bb[b].insn[i1].op[j];
1857
                if (f->INSN (t).index == f->INSN (t2).index
1858
                    && f->INSN (t2).opt[j] & OPT_REF)
1859
                  {
1860
                    int j2;
1861
                    int ok = 1;
1862
                    iteration[REF_I (t2)] = iter + 1;
1863
                    for (j2 = 0; j2 < MAX_OPERANDS; j2++)
1864
                      if (!(f->bb[b].insn[i1].opt[j2] & OPT_REF))
1865
                        if (f->bb[b].insn[i1].opt[j2] !=
1866
                            f->bb[b].insn[i].opt[j2]
1867
                            || f->bb[b].insn[i1].op[j2] !=
1868
                            f->bb[b].insn[i].opt[j2])
1869
                          {
1870
                            ok = 0;
1871
                            break;
1872
                          }
1873
                    if (ok)
1874
                      {
1875
                        cntc++;
1876
                        sizec = sizec + insn_size (&f->bb[b].insn[i1]);
1877
                      }
1878
                    else
1879
                      {
1880
                        cnt++;
1881
                        size = size + insn_size (&f->bb[b].insn[i1]);
1882
                      }
1883
                  }
1884
              }
1885
          }
1886
 
1887
        if (cntc > 1)
1888
          {
1889
            assert (l =
1890
                    (cuc_shared_list *) malloc (sizeof (cuc_shared_list)));
1891
            l->next = main_list;
1892
            main_list = l;
1893
            l->from = list;
1894
            l->ref = t;
1895
            l->cnt = cnt;
1896
            l->cmatch = 1;
1897
            l->cmovs = list->cmovs + count_cmovs (&f->bb[b].insn[i], 1) - 1;
1898
            l->size = list->size + ii_size (f->bb[b].insn[i].index, 1);
1899
            l->osize = sizec;
1900
            search_csm (iter + 1, f, l);
1901
          }
1902
        if (cnt > 1)
1903
          {
1904
            assert (l =
1905
                    (cuc_shared_list *) malloc (sizeof (cuc_shared_list)));
1906
            l->next = main_list;
1907
            main_list = l;
1908
            l->from = list;
1909
            l->ref = t;
1910
            l->cnt = cnt + cntc;
1911
            l->cmatch = 0;
1912
            l->osize = size + sizec;
1913
            l->cmovs = list->cmovs + count_cmovs (&f->bb[b].insn[i], 0) - 1;
1914
            l->size = list->size + ii_size (f->bb[b].insn[i].index, 0);
1915
            search_csm (iter + 1, f, l);
1916
          }
1917
 
1918
        /* Unmark them back */
1919
        for (i1 = 0; i1 < f->bb[b].ninsn; i1++)
1920
          if (iteration[i1] > iter)
1921
            iteration[i1] = -1;
1922
      }
1923
}
1924
 
1925
/* Displays shared instructions */
1926
void
1927
print_shared (cuc_func * rf, cuc_shared_item * shared, int nshared)
1928
{
1929
  int i, first = 1;
1930
  for (i = 0; i < nshared; i++)
1931
    {
1932
      PRINTF ("%s%s%s", first ? "" : "-",
1933
              cuc_insn_name (&rf->INSN (shared[i].ref)),
1934
              shared[i].cmatch ? "!" : "");
1935
      first = 0;
1936
    }
1937
}
1938
 
1939
/* Common subexpression matching -- resource sharing, generation pass
1940
 
1941
   Situation here is much simpler than with analysis -- we know the instruction sequence
1942
   we are going to share, but we are going to do this on whole function, not just one BB.
1943
   We can find sequence in reference function, as pointed from "shared" */
1944
void
1945
csm_gen (cuc_func * f, cuc_func * rf, cuc_shared_item * shared, int nshared)
1946
{
1947
  int b, i, cnt = 0;
1948
  /* FIXME: some code here (2) */
1949
  PRINTF ("Replacing: ");
1950
  print_shared (rf, shared, nshared);
1951
 
1952
  for (b = 0; b < f->num_bb; b++)
1953
    for (i = 0; i < f->bb[b].ninsn; i++)
1954
      {
1955
      }
1956
 
1957
  PRINTF ("\nFound %i matches.\n", cnt);
1958
}

powered by: WebSVN 2.1.0

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