source: trunk/third/gcc/genpeep.c @ 11288

Revision 11288, 12.1 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11287, which included commits to RCS files with non-trunk default branches.
Line 
1/* Generate code from machine description to perform peephole optimizations.
2   Copyright (C) 1987, 1989, 1992, 1997 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING.  If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.  */
20
21
22#include <stdio.h>
23#include "hconfig.h"
24#include "rtl.h"
25#include "obstack.h"
26
27static struct obstack obstack;
28struct obstack *rtl_obstack = &obstack;
29
30#define obstack_chunk_alloc xmalloc
31#define obstack_chunk_free free
32
33extern void free ();
34extern rtx read_rtx ();
35
36/* While tree-walking an instruction pattern, we keep a chain
37   of these `struct link's to record how to get down to the
38   current position.  In each one, POS is the operand number,
39   and if the operand is a vector VEC is the element number.
40   VEC is -1 if the operand is not a vector.  */
41
42struct link
43{
44  struct link *next;
45  int pos;
46  int vecelt;
47};
48
49char *xmalloc ();
50static void match_rtx ();
51static void fatal ();
52void fancy_abort ();
53
54static int max_opno;
55
56/* Number of operands used in current peephole definition.  */
57
58static int n_operands;
59
60/* Peephole optimizations get insn codes just like insn patterns.
61   Count them so we know the code of the define_peephole we are handling.  */
62
63static int insn_code_number = 0;
64
65static void print_path ();
66static void print_code ();
67
68static void
69gen_peephole (peep)
70     rtx peep;
71{
72  int ninsns = XVECLEN (peep, 0);
73  int i;
74
75  n_operands = 0;
76
77  printf ("  insn = ins1;\n");
78#if 0
79  printf ("  want_jump = 0;\n");
80#endif
81
82  for (i = 0; i < ninsns; i++)
83    {
84      if (i > 0)
85        {
86          printf ("  do { insn = NEXT_INSN (insn);\n");
87          printf ("       if (insn == 0) goto L%d; }\n",
88                  insn_code_number);
89          printf ("  while (GET_CODE (insn) == NOTE\n");
90          printf ("\t || (GET_CODE (insn) == INSN\n");
91          printf ("\t     && (GET_CODE (PATTERN (insn)) == USE\n");
92          printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n");
93
94          printf ("  if (GET_CODE (insn) == CODE_LABEL\n\
95      || GET_CODE (insn) == BARRIER)\n    goto L%d;\n",
96                  insn_code_number);
97        }
98
99#if 0
100      printf ("  if (GET_CODE (insn) == JUMP_INSN)\n");
101      printf ("    want_jump = JUMP_LABEL (insn);\n");
102#endif
103
104      printf ("  pat = PATTERN (insn);\n");
105
106      /* Walk the insn's pattern, remembering at all times the path
107         down to the walking point.  */
108
109      match_rtx (XVECEXP (peep, 0, i), NULL_PTR, insn_code_number);
110    }
111
112  /* We get this far if the pattern matches.
113     Now test the extra condition.  */
114
115  if (XSTR (peep, 1) && XSTR (peep, 1)[0])
116    printf ("  if (! (%s)) goto L%d;\n",
117            XSTR (peep, 1), insn_code_number);
118
119  /* If that matches, construct new pattern and put it in the first insn.
120     This new pattern will never be matched.
121     It exists only so that insn-extract can get the operands back.
122     So use a simple regular form: a PARALLEL containing a vector
123     of all the operands.  */
124
125  printf ("  PATTERN (ins1) = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands);
126
127#if 0
128  printf ("  if (want_jump && GET_CODE (ins1) != JUMP_INSN)\n");
129  printf ("    {\n");
130  printf ("      rtx insn2 = emit_jump_insn_before (PATTERN (ins1), ins1);\n");
131  printf ("      delete_insn (ins1);\n");
132  printf ("      ins1 = ins2;\n");
133  printf ("    }\n");
134#endif
135
136  /* Record this define_peephole's insn code in the insn,
137     as if it had been recognized to match this.  */
138  printf ("  INSN_CODE (ins1) = %d;\n",
139          insn_code_number);
140
141  /* Delete the remaining insns.  */
142  if (ninsns > 1)
143    printf ("  delete_for_peephole (NEXT_INSN (ins1), insn);\n");
144
145  /* See reload1.c for insertion of NOTE which guarantees that this
146     cannot be zero.  */
147  printf ("  return NEXT_INSN (insn);\n");
148
149  printf (" L%d:\n\n", insn_code_number);
150}
151
152static void
153match_rtx (x, path, fail_label)
154     rtx x;
155     struct link *path;
156     int fail_label;
157{
158  register RTX_CODE code;
159  register int i;
160  register int len;
161  register char *fmt;
162  struct link link;
163
164  if (x == 0)
165    return;
166
167
168  code = GET_CODE (x);
169
170  switch (code)
171    {
172    case MATCH_OPERAND:
173      if (XINT (x, 0) > max_opno)
174        max_opno = XINT (x, 0);
175      if (XINT (x, 0) >= n_operands)
176        n_operands = 1 + XINT (x, 0);
177
178      printf ("  x = ");
179      print_path (path);
180      printf (";\n");
181
182      printf ("  operands[%d] = x;\n", XINT (x, 0));
183      if (XSTR (x, 1) && XSTR (x, 1)[0])
184        printf ("  if (! %s (x, %smode)) goto L%d;\n",
185                XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
186      return;
187
188    case MATCH_DUP:
189    case MATCH_PAR_DUP:
190      printf ("  x = ");
191      print_path (path);
192      printf (";\n");
193
194      printf ("  if (!rtx_equal_p (operands[%d], x)) goto L%d;\n",
195              XINT (x, 0), fail_label);
196      return;
197
198    case MATCH_OP_DUP:
199      printf ("  x = ");
200      print_path (path);
201      printf (";\n");
202
203      printf ("  if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0));
204      printf ("      || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n",
205              XINT (x, 0), fail_label);
206      printf ("  operands[%d] = x;\n", XINT (x, 0));
207      link.next = path;
208      link.vecelt = -1;
209      for (i = 0; i < XVECLEN (x, 1); i++)
210        {
211          link.pos = i;
212          match_rtx (XVECEXP (x, 1, i), &link, fail_label);
213        }
214      return;
215
216    case MATCH_OPERATOR:
217      if (XINT (x, 0) > max_opno)
218        max_opno = XINT (x, 0);
219      if (XINT (x, 0) >= n_operands)
220        n_operands = 1 + XINT (x, 0);
221
222      printf ("  x = ");
223      print_path (path);
224      printf (";\n");
225
226      printf ("  operands[%d] = x;\n", XINT (x, 0));
227      if (XSTR (x, 1) && XSTR (x, 1)[0])
228        printf ("  if (! %s (x, %smode)) goto L%d;\n",
229                XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
230      link.next = path;
231      link.vecelt = -1;
232      for (i = 0; i < XVECLEN (x, 2); i++)
233        {
234          link.pos = i;
235          match_rtx (XVECEXP (x, 2, i), &link, fail_label);
236        }
237      return;
238
239    case MATCH_PARALLEL:
240      if (XINT (x, 0) > max_opno)
241        max_opno = XINT (x, 0);
242      if (XINT (x, 0) >= n_operands)
243        n_operands = 1 + XINT (x, 0);
244
245      printf ("  x = ");
246      print_path (path);
247      printf (";\n");
248
249      printf ("  if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label);
250      printf ("  operands[%d] = x;\n", XINT (x, 0));
251      if (XSTR (x, 1) && XSTR (x, 1)[0])
252        printf ("  if (! %s (x, %smode)) goto L%d;\n",
253                XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
254      link.next = path;
255      link.pos = 0;
256      for (i = 0; i < XVECLEN (x, 2); i++)
257        {
258          link.vecelt = i;
259          match_rtx (XVECEXP (x, 2, i), &link, fail_label);
260        }
261      return;
262
263    case ADDRESS:
264      match_rtx (XEXP (x, 0), path, fail_label);
265      return;
266     
267    default:
268      break;
269    }
270
271  printf ("  x = ");
272  print_path (path);
273  printf (";\n");
274
275  printf ("  if (GET_CODE (x) != ");
276  print_code (code);
277  printf (") goto L%d;\n", fail_label);
278
279  if (GET_MODE (x) != VOIDmode)
280    {
281      printf ("  if (GET_MODE (x) != %smode) goto L%d;\n",
282              GET_MODE_NAME (GET_MODE (x)), fail_label);
283    }
284
285  link.next = path;
286  link.vecelt = -1;
287  fmt = GET_RTX_FORMAT (code);
288  len = GET_RTX_LENGTH (code);
289  for (i = 0; i < len; i++)
290    {
291      link.pos = i;
292      if (fmt[i] == 'e' || fmt[i] == 'u')
293        match_rtx (XEXP (x, i), &link, fail_label);
294      else if (fmt[i] == 'E')
295        {
296          int j;
297          printf ("  if (XVECLEN (x, %d) != %d) goto L%d;\n",
298                  i, XVECLEN (x, i), fail_label);
299          for (j = 0; j < XVECLEN (x, i); j++)
300            {
301              link.vecelt = j;
302              match_rtx (XVECEXP (x, i, j), &link, fail_label);
303            }
304        }
305      else if (fmt[i] == 'i')
306        {
307          /* Make sure that at run time `x' is the RTX we want to test.  */
308          if (i != 0)
309            {
310              printf ("  x = ");
311              print_path (path);
312              printf (";\n");
313            }
314
315          printf ("  if (XINT (x, %d) != %d) goto L%d;\n",
316                  i, XINT (x, i), fail_label);
317        }
318      else if (fmt[i] == 'w')
319        {
320          /* Make sure that at run time `x' is the RTX we want to test.  */
321          if (i != 0)
322            {
323              printf ("  x = ");
324              print_path (path);
325              printf (";\n");
326            }
327
328#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
329          printf ("  if (XWINT (x, %d) != %d) goto L%d;\n",
330                  i, XWINT (x, i), fail_label);
331#else
332          printf ("  if (XWINT (x, %d) != %ld) goto L%d;\n",
333                  i, XWINT (x, i), fail_label);
334#endif
335        }
336      else if (fmt[i] == 's')
337        {
338          /* Make sure that at run time `x' is the RTX we want to test.  */
339          if (i != 0)
340            {
341              printf ("  x = ");
342              print_path (path);
343              printf (";\n");
344            }
345
346          printf ("  if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
347                  i, XSTR (x, i), fail_label);
348        }
349    }
350}
351
352/* Given a PATH, representing a path down the instruction's
353   pattern from the root to a certain point, output code to
354   evaluate to the rtx at that point.  */
355
356static void
357print_path (path)
358     struct link *path;
359{
360  if (path == 0)
361    printf ("pat");
362  else if (path->vecelt >= 0)
363    {
364      printf ("XVECEXP (");
365      print_path (path->next);
366      printf (", %d, %d)", path->pos, path->vecelt);
367    }
368  else
369    {
370      printf ("XEXP (");
371      print_path (path->next);
372      printf (", %d)", path->pos);
373    }
374}
375
376static void
377print_code (code)
378     RTX_CODE code;
379{
380  register char *p1;
381  for (p1 = GET_RTX_NAME (code); *p1; p1++)
382    {
383      if (*p1 >= 'a' && *p1 <= 'z')
384        putchar (*p1 + 'A' - 'a');
385      else
386        putchar (*p1);
387    }
388}
389
390char *
391xmalloc (size)
392     unsigned size;
393{
394  register char *val = (char *) malloc (size);
395
396  if (val == 0)
397    fatal ("virtual memory exhausted");
398  return val;
399}
400
401char *
402xrealloc (ptr, size)
403     char *ptr;
404     unsigned size;
405{
406  char *result = (char *) realloc (ptr, size);
407  if (!result)
408    fatal ("virtual memory exhausted");
409  return result;
410}
411
412static void
413fatal (s, a1, a2)
414     char *s;
415{
416  fprintf (stderr, "genpeep: ");
417  fprintf (stderr, s, a1, a2);
418  fprintf (stderr, "\n");
419  exit (FATAL_EXIT_CODE);
420}
421
422/* More 'friendly' abort that prints the line and file.
423   config.h can #define abort fancy_abort if you like that sort of thing.  */
424
425void
426fancy_abort ()
427{
428  fatal ("Internal gcc abort.");
429}
430
431int
432main (argc, argv)
433     int argc;
434     char **argv;
435{
436  rtx desc;
437  FILE *infile;
438  register int c;
439
440  max_opno = -1;
441
442  obstack_init (rtl_obstack);
443
444  if (argc <= 1)
445    fatal ("No input file name.");
446
447  infile = fopen (argv[1], "r");
448  if (infile == 0)
449    {
450      perror (argv[1]);
451      exit (FATAL_EXIT_CODE);
452    }
453
454  init_rtl ();
455
456  printf ("/* Generated automatically by the program `genpeep'\n\
457from the machine description file `md'.  */\n\n");
458
459  printf ("#include \"config.h\"\n");
460  printf ("#include <stdio.h>\n");
461  printf ("#include \"rtl.h\"\n");
462  printf ("#include \"regs.h\"\n");
463  printf ("#include \"output.h\"\n");
464  printf ("#include \"real.h\"\n\n");
465
466  printf ("extern rtx peep_operand[];\n\n");
467  printf ("#define operands peep_operand\n\n");
468
469  printf ("rtx\npeephole (ins1)\n     rtx ins1;\n{\n");
470  printf ("  rtx insn, x, pat;\n");
471  printf ("  int i;\n\n");
472
473  /* Early out: no peepholes for insns followed by barriers.  */
474  printf ("  if (NEXT_INSN (ins1)\n");
475  printf ("      && GET_CODE (NEXT_INSN (ins1)) == BARRIER)\n");
476  printf ("    return 0;\n\n");
477
478  /* Read the machine description.  */
479
480  while (1)
481    {
482      c = read_skip_spaces (infile);
483      if (c == EOF)
484        break;
485      ungetc (c, infile);
486
487      desc = read_rtx (infile);
488      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
489        {
490          gen_peephole (desc);
491          insn_code_number++;
492        }
493      if (GET_CODE (desc) == DEFINE_INSN
494          || GET_CODE (desc) == DEFINE_EXPAND
495          || GET_CODE (desc) == DEFINE_SPLIT)
496        {
497          insn_code_number++;
498        }
499    }
500
501  printf ("  return 0;\n}\n\n");
502
503  if (max_opno == -1)
504    max_opno = 1;
505
506  printf ("rtx peep_operand[%d];\n", max_opno + 1);
507
508  fflush (stdout);
509  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
510  /* NOTREACHED */
511  return 0;
512}
Note: See TracBrowser for help on using the repository browser.