|
|
1.1 root 1: /* Generate code from machine description to perform peephole optimizations.
2: Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20:
21: #include <stdio.h>
22: #include "hconfig.h"
23: #include "rtl.h"
24: #include "obstack.h"
25:
26: static struct obstack obstack;
27: struct obstack *rtl_obstack = &obstack;
28:
29: #define obstack_chunk_alloc xmalloc
30: #define obstack_chunk_free free
31:
32: extern void free ();
33: extern rtx read_rtx ();
34:
35: /* While tree-walking an instruction pattern, we keep a chain
36: of these `struct link's to record how to get down to the
37: current position. In each one, POS is the operand number,
38: and if the operand is a vector VEC is the element number.
39: VEC is -1 if the operand is not a vector. */
40:
41: struct link
42: {
43: struct link *next;
44: int pos;
45: int vecelt;
46: };
47:
48: char *xmalloc ();
49: static void match_rtx ();
50: static void gen_exp ();
51: static void fatal ();
52: void fancy_abort ();
53:
54: static int max_opno;
55:
56: /* Number of operands used in current peephole definition. */
57:
58: static 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:
63: static int insn_code_number = 0;
64:
65: static void print_path ();
66: static void print_code ();
67:
68: static void
69: gen_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:
152: static void
153: match_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:
268: printf (" x = ");
269: print_path (path);
270: printf (";\n");
271:
272: printf (" if (GET_CODE (x) != ");
273: print_code (code);
274: printf (") goto L%d;\n", fail_label);
275:
276: if (GET_MODE (x) != VOIDmode)
277: {
278: printf (" if (GET_MODE (x) != %smode) goto L%d;\n",
279: GET_MODE_NAME (GET_MODE (x)), fail_label);
280: }
281:
282: link.next = path;
283: link.vecelt = -1;
284: fmt = GET_RTX_FORMAT (code);
285: len = GET_RTX_LENGTH (code);
286: for (i = 0; i < len; i++)
287: {
288: link.pos = i;
289: if (fmt[i] == 'e' || fmt[i] == 'u')
290: match_rtx (XEXP (x, i), &link, fail_label);
291: else if (fmt[i] == 'E')
292: {
293: int j;
294: printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n",
295: i, XVECLEN (x, i), fail_label);
296: for (j = 0; j < XVECLEN (x, i); j++)
297: {
298: link.vecelt = j;
299: match_rtx (XVECEXP (x, i, j), &link, fail_label);
300: }
301: }
302: else if (fmt[i] == 'i')
303: {
304: /* Make sure that at run time `x' is the RTX we want to test. */
305: if (i != 0)
306: {
307: printf (" x = ");
308: print_path (path);
309: printf (";\n");
310: }
311:
312: printf (" if (XINT (x, %d) != %d) goto L%d;\n",
313: i, XINT (x, i), fail_label);
314: }
315: else if (fmt[i] == 'w')
316: {
317: /* Make sure that at run time `x' is the RTX we want to test. */
318: if (i != 0)
319: {
320: printf (" x = ");
321: print_path (path);
322: printf (";\n");
323: }
324:
325: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
326: printf (" if (XWINT (x, %d) != %d) goto L%d;\n",
327: i, XWINT (x, i), fail_label);
328: #else
329: printf (" if (XWINT (x, %d) != %ld) goto L%d;\n",
330: i, XWINT (x, i), fail_label);
331: #endif
332: }
333: else if (fmt[i] == 's')
334: {
335: /* Make sure that at run time `x' is the RTX we want to test. */
336: if (i != 0)
337: {
338: printf (" x = ");
339: print_path (path);
340: printf (";\n");
341: }
342:
343: printf (" if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
344: i, XSTR (x, i), fail_label);
345: }
346: }
347: }
348:
349: /* Given a PATH, representing a path down the instruction's
350: pattern from the root to a certain point, output code to
351: evaluate to the rtx at that point. */
352:
353: static void
354: print_path (path)
355: struct link *path;
356: {
357: if (path == 0)
358: printf ("pat");
359: else if (path->vecelt >= 0)
360: {
361: printf ("XVECEXP (");
362: print_path (path->next);
363: printf (", %d, %d)", path->pos, path->vecelt);
364: }
365: else
366: {
367: printf ("XEXP (");
368: print_path (path->next);
369: printf (", %d)", path->pos);
370: }
371: }
372:
373: static void
374: print_code (code)
375: RTX_CODE code;
376: {
377: register char *p1;
378: for (p1 = GET_RTX_NAME (code); *p1; p1++)
379: {
380: if (*p1 >= 'a' && *p1 <= 'z')
381: putchar (*p1 + 'A' - 'a');
382: else
383: putchar (*p1);
384: }
385: }
386:
387: char *
388: xmalloc (size)
389: unsigned size;
390: {
391: register char *val = (char *) malloc (size);
392:
393: if (val == 0)
394: fatal ("virtual memory exhausted");
395: return val;
396: }
397:
398: char *
399: xrealloc (ptr, size)
400: char *ptr;
401: unsigned size;
402: {
403: char *result = (char *) realloc (ptr, size);
404: if (!result)
405: fatal ("virtual memory exhausted");
406: return result;
407: }
408:
409: static void
410: fatal (s, a1, a2)
411: char *s;
412: {
413: fprintf (stderr, "genpeep: ");
414: fprintf (stderr, s, a1, a2);
415: fprintf (stderr, "\n");
416: exit (FATAL_EXIT_CODE);
417: }
418:
419: /* More 'friendly' abort that prints the line and file.
420: config.h can #define abort fancy_abort if you like that sort of thing. */
421:
422: void
423: fancy_abort ()
424: {
425: fatal ("Internal gcc abort.");
426: }
427:
428: int
429: main (argc, argv)
430: int argc;
431: char **argv;
432: {
433: rtx desc;
434: FILE *infile;
435: register int c;
436:
437: max_opno = -1;
438:
439: obstack_init (rtl_obstack);
440:
441: if (argc <= 1)
442: fatal ("No input file name.");
443:
444: infile = fopen (argv[1], "r");
445: if (infile == 0)
446: {
447: perror (argv[1]);
448: exit (FATAL_EXIT_CODE);
449: }
450:
451: init_rtl ();
452:
453: printf ("/* Generated automatically by the program `genpeep'\n\
454: from the machine description file `md'. */\n\n");
455:
456: printf ("#include \"config.h\"\n");
457: printf ("#include \"rtl.h\"\n");
458: printf ("#include \"regs.h\"\n");
459: printf ("#include \"output.h\"\n");
460: printf ("#include \"real.h\"\n\n");
461:
462: printf ("extern rtx peep_operand[];\n\n");
463: printf ("#define operands peep_operand\n\n");
464:
465: printf ("rtx\npeephole (ins1)\n rtx ins1;\n{\n");
466: printf (" rtx insn, x, pat;\n");
467: printf (" int i;\n\n");
468:
469: /* Early out: no peepholes for insns followed by barriers. */
470: printf (" if (NEXT_INSN (ins1)\n");
471: printf (" && GET_CODE (NEXT_INSN (ins1)) == BARRIER)\n");
472: printf (" return 0;\n\n");
473:
474: /* Read the machine description. */
475:
476: while (1)
477: {
478: c = read_skip_spaces (infile);
479: if (c == EOF)
480: break;
481: ungetc (c, infile);
482:
483: desc = read_rtx (infile);
484: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
485: {
486: gen_peephole (desc);
487: insn_code_number++;
488: }
489: if (GET_CODE (desc) == DEFINE_INSN
490: || GET_CODE (desc) == DEFINE_EXPAND
491: || GET_CODE (desc) == DEFINE_SPLIT)
492: {
493: insn_code_number++;
494: }
495: }
496:
497: printf (" return 0;\n}\n\n");
498:
499: if (max_opno == -1)
500: max_opno = 1;
501:
502: printf ("rtx peep_operand[%d];\n", max_opno + 1);
503:
504: fflush (stdout);
505: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
506: /* NOTREACHED */
507: return 0;
508: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.