|
|
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 ();
33:
34: /* While tree-walking an instruction pattern, we keep a chain
35: of these `struct link's to record how to get down to the
36: current position. In each one, POS is the operand number,
37: and if the operand is a vector VEC is the element number.
38: VEC is -1 if the operand is not a vector. */
39:
40: struct link
41: {
42: struct link *next;
43: int pos;
44: int vecelt;
45: };
46:
47: char *xmalloc ();
48: static void match_rtx ();
49: static void gen_exp ();
50: static void fatal ();
51: void fancy_abort ();
52:
53: static int max_opno;
54:
55: /* Number of operands used in current peephole definition. */
56:
57: static int n_operands;
58:
59: /* Peephole optimizations get insn codes just like insn patterns.
60: Count them so we know the code of the define_peephole we are handling. */
61:
62: static int insn_code_number = 0;
63:
64: static void print_path ();
65: static void print_code ();
66:
67: static void
68: gen_peephole (peep)
69: rtx peep;
70: {
71: int ninsns = XVECLEN (peep, 0);
72: int i;
73:
74: n_operands = 0;
75:
76: printf (" insn = ins1;\n");
77: #if 0
78: printf (" want_jump = 0;\n");
79: #endif
80:
81: for (i = 0; i < ninsns; i++)
82: {
83: if (i > 0)
84: {
85: printf (" do { insn = NEXT_INSN (insn);\n");
86: printf (" if (insn == 0) goto L%d; }\n",
87: insn_code_number);
88: printf (" while (GET_CODE (insn) == NOTE\n");
89: printf ("\t || (GET_CODE (insn) == INSN\n");
90: printf ("\t && (GET_CODE (PATTERN (insn)) == USE\n");
91: printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n");
92:
93: printf (" if (GET_CODE (insn) == CODE_LABEL\n\
94: || GET_CODE (insn) == BARRIER)\n goto L%d;\n",
95: insn_code_number);
96: }
97:
98: #if 0
99: printf (" if (GET_CODE (insn) == JUMP_INSN)\n");
100: printf (" want_jump = JUMP_LABEL (insn);\n");
101: #endif
102:
103: printf (" pat = PATTERN (insn);\n");
104:
105: /* Walk the insn's pattern, remembering at all times the path
106: down to the walking point. */
107:
108: match_rtx (XVECEXP (peep, 0, i), 0, insn_code_number);
109: }
110:
111: /* We get this far if the pattern matches.
112: Now test the extra condition. */
113:
114: if (XSTR (peep, 1) && XSTR (peep, 1)[0])
115: printf (" if (! (%s)) goto L%d;\n",
116: XSTR (peep, 1), insn_code_number);
117:
118: /* If that matches, construct new pattern and put it in the first insn.
119: This new pattern will never be matched.
120: It exists only so that insn-extract can get the operands back.
121: So use a simple regular form: a PARALLEL containing a vector
122: of all the operands. */
123:
124: printf (" PATTERN (ins1) = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands);
125:
126: #if 0
127: printf (" if (want_jump && GET_CODE (ins1) != JUMP_INSN)\n");
128: printf (" {\n");
129: printf (" rtx insn2 = emit_jump_insn_before (PATTERN (ins1), ins1);\n");
130: printf (" delete_insn (ins1);\n");
131: printf (" ins1 = ins2;\n");
132: printf (" }\n");
133: #endif
134:
135: /* Record this define_peephole's insn code in the insn,
136: as if it had been recognized to match this. */
137: printf (" INSN_CODE (ins1) = %d;\n",
138: insn_code_number);
139:
140: /* Delete the remaining insns. */
141: if (ninsns > 1)
142: printf (" delete_for_peephole (NEXT_INSN (ins1), insn);\n");
143:
144: /* See reload1.c for insertion of NOTE which guarantees that this
145: cannot be zero. */
146: printf (" return NEXT_INSN (insn);\n");
147:
148: printf (" L%d:\n\n", insn_code_number);
149: }
150:
151: static void
152: match_rtx (x, path, fail_label)
153: rtx x;
154: struct link *path;
155: int fail_label;
156: {
157: register RTX_CODE code;
158: register int i;
159: register int len;
160: register char *fmt;
161: struct link link;
162:
163: if (x == 0)
164: return;
165:
166:
167: code = GET_CODE (x);
168:
169: switch (code)
170: {
171: case MATCH_OPERAND:
172: if (XINT (x, 0) > max_opno)
173: max_opno = XINT (x, 0);
174: if (XINT (x, 0) >= n_operands)
175: n_operands = 1 + XINT (x, 0);
176:
177: printf (" x = ");
178: print_path (path);
179: printf (";\n");
180:
181: printf (" operands[%d] = x;\n", XINT (x, 0));
182: if (XSTR (x, 1) && XSTR (x, 1)[0])
183: printf (" if (! %s (x, %smode)) goto L%d;\n",
184: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
185: return;
186:
187: case MATCH_DUP:
188: printf (" x = ");
189: print_path (path);
190: printf (";\n");
191:
192: printf (" if (!rtx_equal_p (operands[%d], x)) goto L%d;\n",
193: XINT (x, 0), fail_label);
194: return;
195:
196: case MATCH_OP_DUP:
197: printf (" x = ");
198: print_path (path);
199: printf (";\n");
200:
201: printf (" if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0));
202: printf (" || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n",
203: XINT (x, 0), fail_label);
204: printf (" operands[%d] = x;\n", XINT (x, 0));
205: link.next = path;
206: link.vecelt = -1;
207: for (i = 0; i < XVECLEN (x, 1); i++)
208: {
209: link.pos = i;
210: match_rtx (XVECEXP (x, 1, i), &link, fail_label);
211: }
212: return;
213:
214: case MATCH_OPERATOR:
215: if (XINT (x, 0) > max_opno)
216: max_opno = XINT (x, 0);
217: if (XINT (x, 0) >= n_operands)
218: n_operands = 1 + XINT (x, 0);
219:
220: printf (" x = ");
221: print_path (path);
222: printf (";\n");
223:
224: printf (" operands[%d] = x;\n", XINT (x, 0));
225: if (XSTR (x, 1) && XSTR (x, 1)[0])
226: printf (" if (! %s (x, %smode)) goto L%d;\n",
227: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
228: link.next = path;
229: link.vecelt = -1;
230: for (i = 0; i < XVECLEN (x, 2); i++)
231: {
232: link.pos = i;
233: match_rtx (XVECEXP (x, 2, i), &link, fail_label);
234: }
235: return;
236:
237: case MATCH_PARALLEL:
238: if (XINT (x, 0) > max_opno)
239: max_opno = XINT (x, 0);
240: if (XINT (x, 0) >= n_operands)
241: n_operands = 1 + XINT (x, 0);
242:
243: printf (" x = ");
244: print_path (path);
245: printf (";\n");
246:
247: printf (" if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label);
248: printf (" operands[%d] = x;\n", XINT (x, 0));
249: if (XSTR (x, 1) && XSTR (x, 1)[0])
250: printf (" if (! %s (x, %smode)) goto L%d;\n",
251: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
252: link.next = path;
253: link.pos = 0;
254: for (i = 0; i < XVECLEN (x, 2); i++)
255: {
256: link.vecelt = i;
257: match_rtx (XVECEXP (x, 2, i), &link, fail_label);
258: }
259: return;
260:
261: case ADDRESS:
262: match_rtx (XEXP (x, 0), path, fail_label);
263: return;
264: }
265:
266: printf (" x = ");
267: print_path (path);
268: printf (";\n");
269:
270: printf (" if (GET_CODE (x) != ");
271: print_code (code);
272: printf (") goto L%d;\n", fail_label);
273:
274: if (GET_MODE (x) != VOIDmode)
275: {
276: printf (" if (GET_MODE (x) != %smode) goto L%d;\n",
277: GET_MODE_NAME (GET_MODE (x)), fail_label);
278: }
279:
280: link.next = path;
281: link.vecelt = -1;
282: fmt = GET_RTX_FORMAT (code);
283: len = GET_RTX_LENGTH (code);
284: for (i = 0; i < len; i++)
285: {
286: link.pos = i;
287: if (fmt[i] == 'e' || fmt[i] == 'u')
288: match_rtx (XEXP (x, i), &link, fail_label);
289: else if (fmt[i] == 'E')
290: {
291: int j;
292: printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n",
293: i, XVECLEN (x, i), fail_label);
294: for (j = 0; j < XVECLEN (x, i); j++)
295: {
296: link.vecelt = j;
297: match_rtx (XVECEXP (x, i, j), &link, fail_label);
298: }
299: }
300: else if (fmt[i] == 'i')
301: {
302: /* Make sure that at run time `x' is the RTX we want to test. */
303: if (i != 0)
304: {
305: printf (" x = ");
306: print_path (path);
307: printf (";\n");
308: }
309:
310: printf (" if (XINT (x, %d) != %d) goto L%d;\n",
311: i, XINT (x, i), fail_label);
312: }
313: else if (fmt[i] == 's')
314: {
315: /* Make sure that at run time `x' is the RTX we want to test. */
316: if (i != 0)
317: {
318: printf (" x = ");
319: print_path (path);
320: printf (";\n");
321: }
322:
323: printf (" if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
324: i, XSTR (x, i), fail_label);
325: }
326: }
327: }
328:
329: /* Given a PATH, representing a path down the instruction's
330: pattern from the root to a certain point, output code to
331: evaluate to the rtx at that point. */
332:
333: static void
334: print_path (path)
335: struct link *path;
336: {
337: if (path == 0)
338: printf ("pat");
339: else if (path->vecelt >= 0)
340: {
341: printf ("XVECEXP (");
342: print_path (path->next);
343: printf (", %d, %d)", path->pos, path->vecelt);
344: }
345: else
346: {
347: printf ("XEXP (");
348: print_path (path->next);
349: printf (", %d)", path->pos);
350: }
351: }
352:
353: static void
354: print_code (code)
355: RTX_CODE code;
356: {
357: register char *p1;
358: for (p1 = GET_RTX_NAME (code); *p1; p1++)
359: {
360: if (*p1 >= 'a' && *p1 <= 'z')
361: putchar (*p1 + 'A' - 'a');
362: else
363: putchar (*p1);
364: }
365: }
366:
367: char *
368: xmalloc (size)
369: unsigned size;
370: {
371: register char *val = (char *) malloc (size);
372:
373: if (val == 0)
374: fatal ("virtual memory exhausted");
375: return val;
376: }
377:
378: char *
379: xrealloc (ptr, size)
380: char *ptr;
381: unsigned size;
382: {
383: char *result = (char *) realloc (ptr, size);
384: if (!result)
385: fatal ("virtual memory exhausted");
386: return result;
387: }
388:
389: static void
390: fatal (s, a1, a2)
391: char *s;
392: {
393: fprintf (stderr, "genpeep: ");
394: fprintf (stderr, s, a1, a2);
395: fprintf (stderr, "\n");
396: exit (FATAL_EXIT_CODE);
397: }
398:
399: /* More 'friendly' abort that prints the line and file.
400: config.h can #define abort fancy_abort if you like that sort of thing. */
401:
402: void
403: fancy_abort ()
404: {
405: fatal ("Internal gcc abort.");
406: }
407:
408: int
409: main (argc, argv)
410: int argc;
411: char **argv;
412: {
413: rtx desc;
414: FILE *infile;
415: extern rtx read_rtx ();
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.