OSDN Git Service

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