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