|
|
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 "config.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 ();
1.1.1.2 ! root 33: extern rtx read_rtx ();
1.1 root 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), 0, 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: printf (" x = ");
190: print_path (path);
191: printf (";\n");
192:
193: printf (" if (!rtx_equal_p (operands[%d], x)) goto L%d;\n",
194: XINT (x, 0), fail_label);
195: return;
196:
197: case MATCH_OP_DUP:
198: printf (" x = ");
199: print_path (path);
200: printf (";\n");
201:
202: printf (" if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0));
203: printf (" || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n",
204: XINT (x, 0), fail_label);
205: printf (" operands[%d] = x;\n", XINT (x, 0));
206: link.next = path;
207: link.vecelt = -1;
208: for (i = 0; i < XVECLEN (x, 1); i++)
209: {
210: link.pos = i;
211: match_rtx (XVECEXP (x, 1, i), &link, fail_label);
212: }
213: return;
214:
215: case MATCH_OPERATOR:
216: if (XINT (x, 0) > max_opno)
217: max_opno = XINT (x, 0);
218: if (XINT (x, 0) >= n_operands)
219: n_operands = 1 + XINT (x, 0);
220:
221: printf (" x = ");
222: print_path (path);
223: printf (";\n");
224:
225: printf (" operands[%d] = x;\n", XINT (x, 0));
226: if (XSTR (x, 1) && XSTR (x, 1)[0])
227: printf (" if (! %s (x, %smode)) goto L%d;\n",
228: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
229: link.next = path;
230: link.vecelt = -1;
231: for (i = 0; i < XVECLEN (x, 2); i++)
232: {
233: link.pos = i;
234: match_rtx (XVECEXP (x, 2, i), &link, fail_label);
235: }
236: return;
237:
238: case MATCH_PARALLEL:
239: if (XINT (x, 0) > max_opno)
240: max_opno = XINT (x, 0);
241: if (XINT (x, 0) >= n_operands)
242: n_operands = 1 + XINT (x, 0);
243:
244: printf (" x = ");
245: print_path (path);
246: printf (";\n");
247:
248: printf (" if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label);
249: printf (" operands[%d] = x;\n", XINT (x, 0));
250: if (XSTR (x, 1) && XSTR (x, 1)[0])
251: printf (" if (! %s (x, %smode)) goto L%d;\n",
252: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
253: link.next = path;
254: link.pos = 0;
255: for (i = 0; i < XVECLEN (x, 2); i++)
256: {
257: link.vecelt = i;
258: match_rtx (XVECEXP (x, 2, i), &link, fail_label);
259: }
260: return;
261:
262: case ADDRESS:
263: match_rtx (XEXP (x, 0), path, fail_label);
264: return;
265: }
266:
267: printf (" x = ");
268: print_path (path);
269: printf (";\n");
270:
271: printf (" if (GET_CODE (x) != ");
272: print_code (code);
273: printf (") goto L%d;\n", fail_label);
274:
275: if (GET_MODE (x) != VOIDmode)
276: {
277: printf (" if (GET_MODE (x) != %smode) goto L%d;\n",
278: GET_MODE_NAME (GET_MODE (x)), fail_label);
279: }
280:
281: link.next = path;
282: link.vecelt = -1;
283: fmt = GET_RTX_FORMAT (code);
284: len = GET_RTX_LENGTH (code);
285: for (i = 0; i < len; i++)
286: {
287: link.pos = i;
288: if (fmt[i] == 'e' || fmt[i] == 'u')
289: match_rtx (XEXP (x, i), &link, fail_label);
290: else if (fmt[i] == 'E')
291: {
292: int j;
293: printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n",
294: i, XVECLEN (x, i), fail_label);
295: for (j = 0; j < XVECLEN (x, i); j++)
296: {
297: link.vecelt = j;
298: match_rtx (XVECEXP (x, i, j), &link, fail_label);
299: }
300: }
301: else if (fmt[i] == 'i')
302: {
303: /* Make sure that at run time `x' is the RTX we want to test. */
304: if (i != 0)
305: {
306: printf (" x = ");
307: print_path (path);
308: printf (";\n");
309: }
310:
311: printf (" if (XINT (x, %d) != %d) goto L%d;\n",
312: i, XINT (x, i), fail_label);
313: }
314: else if (fmt[i] == 's')
315: {
316: /* Make sure that at run time `x' is the RTX we want to test. */
317: if (i != 0)
318: {
319: printf (" x = ");
320: print_path (path);
321: printf (";\n");
322: }
323:
324: printf (" if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
325: i, XSTR (x, i), fail_label);
326: }
327: }
328: }
329:
330: /* Given a PATH, representing a path down the instruction's
331: pattern from the root to a certain point, output code to
332: evaluate to the rtx at that point. */
333:
334: static void
335: print_path (path)
336: struct link *path;
337: {
338: if (path == 0)
339: printf ("pat");
340: else if (path->vecelt >= 0)
341: {
342: printf ("XVECEXP (");
343: print_path (path->next);
344: printf (", %d, %d)", path->pos, path->vecelt);
345: }
346: else
347: {
348: printf ("XEXP (");
349: print_path (path->next);
350: printf (", %d)", path->pos);
351: }
352: }
353:
354: static void
355: print_code (code)
356: RTX_CODE code;
357: {
358: register char *p1;
359: for (p1 = GET_RTX_NAME (code); *p1; p1++)
360: {
361: if (*p1 >= 'a' && *p1 <= 'z')
362: putchar (*p1 + 'A' - 'a');
363: else
364: putchar (*p1);
365: }
366: }
367:
368: char *
369: xmalloc (size)
370: unsigned size;
371: {
372: register char *val = (char *) malloc (size);
373:
374: if (val == 0)
375: fatal ("virtual memory exhausted");
376: return val;
377: }
378:
379: char *
380: xrealloc (ptr, size)
381: char *ptr;
382: unsigned size;
383: {
384: char *result = (char *) realloc (ptr, size);
385: if (!result)
386: fatal ("virtual memory exhausted");
387: return result;
388: }
389:
390: static void
391: fatal (s, a1, a2)
392: char *s;
393: {
394: fprintf (stderr, "genpeep: ");
395: fprintf (stderr, s, a1, a2);
396: fprintf (stderr, "\n");
397: exit (FATAL_EXIT_CODE);
398: }
399:
400: /* More 'friendly' abort that prints the line and file.
401: config.h can #define abort fancy_abort if you like that sort of thing. */
402:
403: void
404: fancy_abort ()
405: {
406: fatal ("Internal gcc abort.");
407: }
408:
409: int
410: main (argc, argv)
411: int argc;
412: char **argv;
413: {
414: rtx desc;
415: FILE *infile;
416: register int c;
417:
418: max_opno = -1;
419:
420: obstack_init (rtl_obstack);
421:
422: if (argc <= 1)
423: fatal ("No input file name.");
424:
425: infile = fopen (argv[1], "r");
426: if (infile == 0)
427: {
428: perror (argv[1]);
429: exit (FATAL_EXIT_CODE);
430: }
431:
432: init_rtl ();
433:
434: printf ("/* Generated automatically by the program `genpeep'\n\
435: from the machine description file `md'. */\n\n");
436:
437: printf ("#include \"config.h\"\n");
438: printf ("#include \"rtl.h\"\n");
439: printf ("#include \"regs.h\"\n");
440: printf ("#include \"output.h\"\n");
441: printf ("#include \"real.h\"\n\n");
442:
443: printf ("extern rtx peep_operand[];\n\n");
444: printf ("#define operands peep_operand\n\n");
445:
446: printf ("rtx\npeephole (ins1)\n rtx ins1;\n{\n");
447: printf (" rtx insn, x, pat;\n");
448: printf (" int i;\n\n");
449:
450: /* Early out: no peepholes for insns followed by barriers. */
451: printf (" if (NEXT_INSN (ins1)\n");
452: printf (" && GET_CODE (NEXT_INSN (ins1)) == BARRIER)\n");
453: printf (" return 0;\n\n");
454:
455: /* Read the machine description. */
456:
457: while (1)
458: {
459: c = read_skip_spaces (infile);
460: if (c == EOF)
461: break;
462: ungetc (c, infile);
463:
464: desc = read_rtx (infile);
465: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
466: {
467: gen_peephole (desc);
468: insn_code_number++;
469: }
470: if (GET_CODE (desc) == DEFINE_INSN
471: || GET_CODE (desc) == DEFINE_EXPAND
472: || GET_CODE (desc) == DEFINE_SPLIT)
473: {
474: insn_code_number++;
475: }
476: }
477:
478: printf (" return 0;\n}\n\n");
479:
480: if (max_opno == -1)
481: max_opno = 1;
482:
483: printf ("rtx peep_operand[%d];\n", max_opno + 1);
484:
485: fflush (stdout);
486: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
487: /* NOTREACHED */
488: return 0;
489: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.