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