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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [genpeep.c] - Blame information for rev 758

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

Line No. Rev Author Line
1 684 jeremybenn
/* Generate code from machine description to perform peephole optimizations.
2
   Copyright (C) 1987, 1989, 1992, 1997, 1998, 1999, 2000, 2003, 2004,
3
   2007, 2010  Free Software Foundation, Inc.
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING3.  If not see
19
<http://www.gnu.org/licenses/>.  */
20
 
21
 
22
#include "bconfig.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "rtl.h"
27
#include "errors.h"
28
#include "gensupport.h"
29
 
30
 
31
/* While tree-walking an instruction pattern, we keep a chain
32
   of these `struct link's to record how to get down to the
33
   current position.  In each one, POS is the operand number,
34
   and if the operand is a vector VEC is the element number.
35
   VEC is -1 if the operand is not a vector.  */
36
 
37
struct link
38
{
39
  struct link *next;
40
  int pos;
41
  int vecelt;
42
};
43
 
44
static int max_opno;
45
 
46
/* Number of operands used in current peephole definition.  */
47
 
48
static int n_operands;
49
 
50
/* Peephole optimizations get insn codes just like insn patterns.
51
   Count them so we know the code of the define_peephole we are handling.  */
52
 
53
static int insn_code_number = 0;
54
 
55
static void gen_peephole (rtx);
56
static void match_rtx (rtx, struct link *, int);
57
static void print_path (struct link *);
58
static void print_code (RTX_CODE);
59
 
60
static void
61
gen_peephole (rtx peep)
62
{
63
  int ninsns = XVECLEN (peep, 0);
64
  int i;
65
 
66
  n_operands = 0;
67
 
68
  printf ("  insn = ins1;\n");
69
 
70
  for (i = 0; i < ninsns; i++)
71
    {
72
      if (i > 0)
73
        {
74
          printf ("  do { insn = NEXT_INSN (insn);\n");
75
          printf ("       if (insn == 0) goto L%d; }\n",
76
                  insn_code_number);
77
          printf ("  while (NOTE_P (insn)\n");
78
          printf ("\t || (NONJUMP_INSN_P (insn)\n");
79
          printf ("\t     && (GET_CODE (PATTERN (insn)) == USE\n");
80
          printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n");
81
 
82
          printf ("  if (LABEL_P (insn)\n\
83
      || BARRIER_P (insn))\n    goto L%d;\n",
84
                  insn_code_number);
85
        }
86
 
87
      printf ("  pat = PATTERN (insn);\n");
88
 
89
      /* Walk the insn's pattern, remembering at all times the path
90
         down to the walking point.  */
91
 
92
      match_rtx (XVECEXP (peep, 0, i), NULL, insn_code_number);
93
    }
94
 
95
  /* We get this far if the pattern matches.
96
     Now test the extra condition.  */
97
 
98
  if (XSTR (peep, 1) && XSTR (peep, 1)[0])
99
    printf ("  if (! (%s)) goto L%d;\n",
100
            XSTR (peep, 1), insn_code_number);
101
 
102
  /* If that matches, construct new pattern and put it in the first insn.
103
     This new pattern will never be matched.
104
     It exists only so that insn-extract can get the operands back.
105
     So use a simple regular form: a PARALLEL containing a vector
106
     of all the operands.  */
107
 
108
  printf ("  PATTERN (ins1) = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands);
109
 
110
  /* Record this define_peephole's insn code in the insn,
111
     as if it had been recognized to match this.  */
112
  printf ("  INSN_CODE (ins1) = %d;\n",
113
          insn_code_number);
114
 
115
  /* Delete the remaining insns.  */
116
  if (ninsns > 1)
117
    printf ("  delete_for_peephole (NEXT_INSN (ins1), insn);\n");
118
 
119
  /* See reload1.c for insertion of NOTE which guarantees that this
120
     cannot be zero.  */
121
  printf ("  return NEXT_INSN (insn);\n");
122
 
123
  printf (" L%d:\n\n", insn_code_number);
124
}
125
 
126
static void
127
match_rtx (rtx x, struct link *path, int fail_label)
128
{
129
  RTX_CODE code;
130
  int i;
131
  int len;
132
  const char *fmt;
133
  struct link link;
134
 
135
  if (x == 0)
136
    return;
137
 
138
 
139
  code = GET_CODE (x);
140
 
141
  switch (code)
142
    {
143
    case MATCH_OPERAND:
144
      if (XINT (x, 0) > max_opno)
145
        max_opno = XINT (x, 0);
146
      if (XINT (x, 0) >= n_operands)
147
        n_operands = 1 + XINT (x, 0);
148
 
149
      printf ("  x = ");
150
      print_path (path);
151
      printf (";\n");
152
 
153
      printf ("  operands[%d] = x;\n", XINT (x, 0));
154
      if (XSTR (x, 1) && XSTR (x, 1)[0])
155
        printf ("  if (! %s (x, %smode)) goto L%d;\n",
156
                XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
157
      return;
158
 
159
    case MATCH_DUP:
160
    case MATCH_PAR_DUP:
161
      printf ("  x = ");
162
      print_path (path);
163
      printf (";\n");
164
 
165
      printf ("  if (!rtx_equal_p (operands[%d], x)) goto L%d;\n",
166
              XINT (x, 0), fail_label);
167
      return;
168
 
169
    case MATCH_OP_DUP:
170
      printf ("  x = ");
171
      print_path (path);
172
      printf (";\n");
173
 
174
      printf ("  if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0));
175
      printf ("      || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n",
176
              XINT (x, 0), fail_label);
177
      printf ("  operands[%d] = x;\n", XINT (x, 0));
178
      link.next = path;
179
      link.vecelt = -1;
180
      for (i = 0; i < XVECLEN (x, 1); i++)
181
        {
182
          link.pos = i;
183
          match_rtx (XVECEXP (x, 1, i), &link, fail_label);
184
        }
185
      return;
186
 
187
    case MATCH_OPERATOR:
188
      if (XINT (x, 0) > max_opno)
189
        max_opno = XINT (x, 0);
190
      if (XINT (x, 0) >= n_operands)
191
        n_operands = 1 + XINT (x, 0);
192
 
193
      printf ("  x = ");
194
      print_path (path);
195
      printf (";\n");
196
 
197
      printf ("  operands[%d] = x;\n", XINT (x, 0));
198
      if (XSTR (x, 1) && XSTR (x, 1)[0])
199
        printf ("  if (! %s (x, %smode)) goto L%d;\n",
200
                XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
201
      link.next = path;
202
      link.vecelt = -1;
203
      for (i = 0; i < XVECLEN (x, 2); i++)
204
        {
205
          link.pos = i;
206
          match_rtx (XVECEXP (x, 2, i), &link, fail_label);
207
        }
208
      return;
209
 
210
    case MATCH_PARALLEL:
211
      if (XINT (x, 0) > max_opno)
212
        max_opno = XINT (x, 0);
213
      if (XINT (x, 0) >= n_operands)
214
        n_operands = 1 + XINT (x, 0);
215
 
216
      printf ("  x = ");
217
      print_path (path);
218
      printf (";\n");
219
 
220
      printf ("  if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label);
221
      printf ("  operands[%d] = x;\n", XINT (x, 0));
222
      if (XSTR (x, 1) && XSTR (x, 1)[0])
223
        printf ("  if (! %s (x, %smode)) goto L%d;\n",
224
                XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
225
      link.next = path;
226
      link.pos = 0;
227
      for (i = 0; i < XVECLEN (x, 2); i++)
228
        {
229
          link.vecelt = i;
230
          match_rtx (XVECEXP (x, 2, i), &link, fail_label);
231
        }
232
      return;
233
 
234
    case ADDRESS:
235
      match_rtx (XEXP (x, 0), path, fail_label);
236
      return;
237
 
238
    default:
239
      break;
240
    }
241
 
242
  printf ("  x = ");
243
  print_path (path);
244
  printf (";\n");
245
 
246
  printf ("  if (GET_CODE (x) != ");
247
  print_code (code);
248
  printf (") goto L%d;\n", fail_label);
249
 
250
  if (GET_MODE (x) != VOIDmode)
251
    {
252
      printf ("  if (GET_MODE (x) != %smode) goto L%d;\n",
253
              GET_MODE_NAME (GET_MODE (x)), fail_label);
254
    }
255
 
256
  link.next = path;
257
  link.vecelt = -1;
258
  fmt = GET_RTX_FORMAT (code);
259
  len = GET_RTX_LENGTH (code);
260
  for (i = 0; i < len; i++)
261
    {
262
      link.pos = i;
263
      if (fmt[i] == 'e' || fmt[i] == 'u')
264
        match_rtx (XEXP (x, i), &link, fail_label);
265
      else if (fmt[i] == 'E')
266
        {
267
          int j;
268
          printf ("  if (XVECLEN (x, %d) != %d) goto L%d;\n",
269
                  i, XVECLEN (x, i), fail_label);
270
          for (j = 0; j < XVECLEN (x, i); j++)
271
            {
272
              link.vecelt = j;
273
              match_rtx (XVECEXP (x, i, j), &link, fail_label);
274
            }
275
        }
276
      else if (fmt[i] == 'i')
277
        {
278
          /* Make sure that at run time `x' is the RTX we want to test.  */
279
          if (i != 0)
280
            {
281
              printf ("  x = ");
282
              print_path (path);
283
              printf (";\n");
284
            }
285
 
286
          printf ("  if (XINT (x, %d) != %d) goto L%d;\n",
287
                  i, XINT (x, i), fail_label);
288
        }
289
      else if (fmt[i] == 'w')
290
        {
291
          /* Make sure that at run time `x' is the RTX we want to test.  */
292
          if (i != 0)
293
            {
294
              printf ("  x = ");
295
              print_path (path);
296
              printf (";\n");
297
            }
298
 
299
          printf ("  if (XWINT (x, %d) != ", i);
300
          printf (HOST_WIDE_INT_PRINT_DEC, XWINT (x, i));
301
          printf (") goto L%d;\n", fail_label);
302
        }
303
      else if (fmt[i] == 's')
304
        {
305
          /* Make sure that at run time `x' is the RTX we want to test.  */
306
          if (i != 0)
307
            {
308
              printf ("  x = ");
309
              print_path (path);
310
              printf (";\n");
311
            }
312
 
313
          printf ("  if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
314
                  i, XSTR (x, i), fail_label);
315
        }
316
    }
317
}
318
 
319
/* Given a PATH, representing a path down the instruction's
320
   pattern from the root to a certain point, output code to
321
   evaluate to the rtx at that point.  */
322
 
323
static void
324
print_path (struct link *path)
325
{
326
  if (path == 0)
327
    printf ("pat");
328
  else if (path->vecelt >= 0)
329
    {
330
      printf ("XVECEXP (");
331
      print_path (path->next);
332
      printf (", %d, %d)", path->pos, path->vecelt);
333
    }
334
  else
335
    {
336
      printf ("XEXP (");
337
      print_path (path->next);
338
      printf (", %d)", path->pos);
339
    }
340
}
341
 
342
static void
343
print_code (RTX_CODE code)
344
{
345
  const char *p1;
346
  for (p1 = GET_RTX_NAME (code); *p1; p1++)
347
    putchar (TOUPPER(*p1));
348
}
349
 
350
extern int main (int, char **);
351
 
352
int
353
main (int argc, char **argv)
354
{
355
  rtx desc;
356
 
357
  max_opno = -1;
358
 
359
  progname = "genpeep";
360
 
361
  if (!init_rtx_reader_args (argc, argv))
362
    return (FATAL_EXIT_CODE);
363
 
364
  printf ("/* Generated automatically by the program `genpeep'\n\
365
from the machine description file `md'.  */\n\n");
366
 
367
  printf ("#include \"config.h\"\n");
368
  printf ("#include \"system.h\"\n");
369
  printf ("#include \"coretypes.h\"\n");
370
  printf ("#include \"tm.h\"\n");
371
  printf ("#include \"insn-config.h\"\n");
372
  printf ("#include \"rtl.h\"\n");
373
  printf ("#include \"tm_p.h\"\n");
374
  printf ("#include \"regs.h\"\n");
375
  printf ("#include \"output.h\"\n");
376
  printf ("#include \"recog.h\"\n");
377
  printf ("#include \"except.h\"\n");
378
  printf ("#include \"function.h\"\n");
379
  printf ("#include \"diagnostic-core.h\"\n");
380
  printf ("#include \"flags.h\"\n");
381
  printf ("#include \"tm-constrs.h\"\n\n");
382
 
383
  printf ("#ifdef HAVE_peephole\n");
384
  printf ("extern rtx peep_operand[];\n\n");
385
  printf ("#define operands peep_operand\n\n");
386
 
387
  printf ("rtx\npeephole (rtx ins1)\n{\n");
388
  printf ("  rtx insn ATTRIBUTE_UNUSED, x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;\n\n");
389
 
390
  /* Early out: no peepholes for insns followed by barriers.  */
391
  printf ("  if (NEXT_INSN (ins1)\n");
392
  printf ("      && BARRIER_P (NEXT_INSN (ins1)))\n");
393
  printf ("    return 0;\n\n");
394
 
395
  /* Read the machine description.  */
396
 
397
  while (1)
398
    {
399
      int line_no, rtx_number = 0;
400
 
401
      desc = read_md_rtx (&line_no, &rtx_number);
402
      if (desc == NULL)
403
        break;
404
 
405
       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
406
        {
407
          gen_peephole (desc);
408
          insn_code_number++;
409
        }
410
      if (GET_CODE (desc) == DEFINE_INSN
411
          || GET_CODE (desc) == DEFINE_EXPAND
412
          || GET_CODE (desc) == DEFINE_SPLIT
413
          || GET_CODE (desc) == DEFINE_PEEPHOLE2)
414
        {
415
          insn_code_number++;
416
        }
417
    }
418
 
419
  printf ("  return 0;\n}\n\n");
420
 
421
  if (max_opno == -1)
422
    max_opno = 1;
423
 
424
  printf ("rtx peep_operand[%d];\n", max_opno + 1);
425
  printf ("#endif\n");
426
 
427
  fflush (stdout);
428
  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
429
}

powered by: WebSVN 2.1.0

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