|
|
1.1 root 1: /* Generate code from machine description to perform peephole optimizations.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: #include <stdio.h>
23: #include "config.h"
24: #include "rtl.h"
25: #include "obstack.h"
26:
27: struct obstack obstack;
28: struct obstack *rtl_obstack = &obstack;
29:
30: #define obstack_chunk_alloc xmalloc
31: #define obstack_chunk_free free
32: extern int xmalloc ();
33: extern void free ();
34:
35: void match_rtx ();
36: void gen_exp ();
37: void fatal ();
38:
39:
40: int max_opno;
41:
42: /* While tree-walking an instruction pattern, we keep a chain
43: of these `struct link's to record how to get down to the
44: current position. In each one, POS is the operand number,
45: and if the operand is a vector VEC is the element number.
46: VEC is -1 if the operand is not a vector. */
47:
48: struct link
49: {
50: struct link *next;
51: int pos;
52: int vecelt;
53: };
54:
55: /* Number of operands used in current peephole definition. */
56:
57: 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: int insn_code_number = 0;
63:
64: void print_path ();
65: void print_code ();
66:
67: 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:
78: for (i = 0; i < ninsns; i++)
79: {
80: if (i > 0)
81: {
82: printf (" do { insn = NEXT_INSN (insn);\n");
83: printf (" if (insn == 0) goto L%d; }\n",
84: insn_code_number);
85: printf (" while (GET_CODE (insn) == NOTE);\n");
86: }
87:
88: printf (" if (GET_CODE (insn) == CODE_LABEL) goto L%d;\n",
89: insn_code_number);
90:
91: printf (" pat = PATTERN (insn);\n");
92: /* Walk the insn's pattern, remembering at all times the path
93: down to the walking point. */
94:
95: match_rtx (XVECEXP (peep, 0, i), 0, insn_code_number);
96: }
97:
98: /* We get this far if the pattern matches.
99: Now test the extra condition. */
100:
101: if (XSTR (peep, 1) && XSTR (peep, 1)[0])
102: printf (" if (! (%s)) goto L%d;\n",
103: XSTR (peep, 1), insn_code_number);
104:
105: /* If that matches, construct new pattern and put it in the first insn.
106: This new pattern will never be matched.
107: It exists only so that insn-extract can get the operands back.
108: So use a simple regular form: a PARALLEL containing a vector
109: of all the operands. */
110:
111: printf (" PATTERN (ins1) = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands);
112: printf (" insn = ins1;\n");
113:
114: /* Make sure that labels referred to by the insns
115: don't get deleted because of their counts' going to zero. */
116: printf (" for (i = 0; i < %d; i++)\n", n_operands);
117: printf (" if (GET_CODE (operands[i]) == CODE_LABEL)\n");
118: printf (" LABEL_NUSES (operands[i])++;\n");
119:
120: /* Record this define_peephole's insn code in the insn,
121: as if it had been recognized to match this. */
122: printf (" INSN_CODE (insn) = %d;\n",
123: insn_code_number);
124:
125: /* Delete the remaining insns. */
126: for (i = 1; i < ninsns; i++)
127: {
128: printf (" do insn = NEXT_INSN (insn);\n");
129: printf (" while (GET_CODE (insn) == NOTE);\n");
130: printf (" delete_insn (insn);\n");
131: }
132:
133: printf (" return 1;\n");
134:
135: printf (" L%d:\n\n", insn_code_number);
136: }
137:
138: void
139: match_rtx (x, path, fail_label)
140: rtx x;
141: struct link *path;
142: int fail_label;
143: {
144: register RTX_CODE code;
145: register int i;
146: register int len;
147: register char *fmt;
148: struct link link;
149:
150: if (x == 0)
151: return;
152:
153:
154: code = GET_CODE (x);
155:
156: switch (code)
157: {
158: case MATCH_OPERAND:
159: if (XINT (x, 0) > max_opno)
160: max_opno = XINT (x, 0);
161: if (XINT (x, 0) >= n_operands)
162: n_operands = 1 + XINT (x, 0);
163:
164: printf (" x = ");
165: print_path (path);
166: printf (";\n");
167:
168: printf (" operands[%d] = x;\n", XINT (x, 0));
169: if (XSTR (x, 1) && XSTR (x, 1)[0])
170: printf (" if (! %s (x, %smode)) goto L%d;\n",
171: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
172: return;
173:
174: case MATCH_DUP:
175: printf (" x = ");
176: print_path (path);
177: printf (";\n");
178:
179: printf (" if (!rtx_equal_p (operands[%d], x)) goto L%d;\n",
180: XINT (x, 0), fail_label);
181: return;
182:
183: case ADDRESS:
184: match_rtx (XEXP (x, 0), path, fail_label);
185: return;
186: }
187:
188: printf (" x = ");
189: print_path (path);
190: printf (";\n");
191:
192: printf (" if (GET_CODE (x) != ");
193: print_code (code);
194: printf (") goto L%d;\n", fail_label);
195:
196: if (GET_MODE (x) != VOIDmode)
197: {
198: printf (" if (GET_MODE (x) != %smode) goto L%d;\n",
199: GET_MODE_NAME (GET_MODE (x)), fail_label);
200: }
201:
202: link.next = path;
203: link.vecelt = -1;
204: fmt = GET_RTX_FORMAT (code);
205: len = GET_RTX_LENGTH (code);
206: for (i = 0; i < len; i++)
207: {
208: link.pos = i;
209: if (fmt[i] == 'e' || fmt[i] == 'u')
210: match_rtx (XEXP (x, i), &link, fail_label);
211: else if (fmt[i] == 'E')
212: {
213: int j;
214: printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n",
215: i, XVECLEN (x, i), fail_label);
216: for (j = XVECLEN (x, i) - 1; j >= 0; j--)
217: {
218: link.vecelt = j;
219: match_rtx (XVECEXP (x, i, j), &link, fail_label);
220: }
221: }
222: else if (fmt[i] == 'i')
223: {
224: /* Make sure that at run time `x' is the RTX we want to test. */
225: if (i != 0)
226: {
227: printf (" x = ");
228: print_path (path);
229: printf (";\n");
230: }
231:
232: printf (" if (XINT (x, %d) != %d) goto L%d;\n",
233: i, XINT (x, i), fail_label);
234: }
235: else if (fmt[i] == 's')
236: {
237: /* Make sure that at run time `x' is the RTX we want to test. */
238: if (i != 0)
239: {
240: printf (" x = ");
241: print_path (path);
242: printf (";\n");
243: }
244:
245: printf (" if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
246: i, XSTR (x, i), fail_label);
247: }
248: }
249: }
250:
251: /* Given a PATH, representing a path down the instruction's
252: pattern from the root to a certain point, output code to
253: evaluate to the rtx at that point. */
254:
255: void
256: print_path (path)
257: struct link *path;
258: {
259: if (path == 0)
260: printf ("pat");
261: else if (path->vecelt >= 0)
262: {
263: printf ("XVECEXP (");
264: print_path (path->next);
265: printf (", %d, %d)", path->pos, path->vecelt);
266: }
267: else
268: {
269: printf ("XEXP (");
270: print_path (path->next);
271: printf (", %d)", path->pos);
272: }
273: }
274:
275: void
276: print_code (code)
277: RTX_CODE code;
278: {
279: register char *p1;
280: for (p1 = GET_RTX_NAME (code); *p1; p1++)
281: {
282: if (*p1 >= 'a' && *p1 <= 'z')
283: putchar (*p1 + 'A' - 'a');
284: else
285: putchar (*p1);
286: }
287: }
288:
289: int
290: xmalloc (size)
291: {
292: register int val = malloc (size);
293:
294: if (val == 0)
295: fatal ("virtual memory exhausted");
296: return val;
297: }
298:
299: int
300: xrealloc (ptr, size)
301: char *ptr;
302: int size;
303: {
304: int result = realloc (ptr, size);
305: if (!result)
306: fatal ("virtual memory exhausted");
307: return result;
308: }
309:
310: void
311: fatal (s, a1, a2)
312: {
313: fprintf (stderr, "genpeep: ");
314: fprintf (stderr, s, a1, a2);
315: fprintf (stderr, "\n");
316: exit (FATAL_EXIT_CODE);
317: }
318:
319: int
320: main (argc, argv)
321: int argc;
322: char **argv;
323: {
324: rtx desc;
325: FILE *infile;
326: extern rtx read_rtx ();
327: register int c, i;
328:
329: max_opno = -1;
330:
331: obstack_init (rtl_obstack);
332:
333: if (argc <= 1)
334: fatal ("No input file name.");
335:
336: infile = fopen (argv[1], "r");
337: if (infile == 0)
338: {
339: perror (argv[1]);
340: exit (FATAL_EXIT_CODE);
341: }
342:
343: init_rtl ();
344:
345: printf ("/* Generated automatically by the program `genpeep'\n\
346: from the machine description file `md'. */\n\n");
347:
348: printf ("#include \"rtl.h\"\n\n");
349: printf ("#include \"config.h\"\n\n");
350: printf ("#include \"regs.h\"\n\n");
351:
352: printf ("rtx peep_operand[];\n\n");
353: printf ("#define operands peep_operand\n\n");
354:
355: printf ("int\npeephole (ins1)\n rtx ins1;\n{\n");
356: printf (" rtx insn, x, pat;\n");
357: printf (" int i;\n");
358:
359: /* Read the machine description. */
360:
361: while (1)
362: {
363: c = read_skip_spaces (infile);
364: if (c == EOF)
365: break;
366: ungetc (c, infile);
367:
368: desc = read_rtx (infile);
369: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
370: {
371: gen_peephole (desc);
372: insn_code_number++;
373: }
374: if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
375: {
376: insn_code_number++;
377: }
378: }
379:
380: printf (" return 0;\n}\n\n");
381:
382: if (max_opno == -1)
383: max_opno = 1;
384:
385: printf ("rtx peep_operand[%d];\n", max_opno + 1);
386:
387: fflush (stdout);
388: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
389: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.