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

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