gcc50: Disconnect from buildworld.
[dragonfly.git] / contrib / gcc-5.0 / gcc / genpeep.c
1 /* Generate code from machine description to perform peephole optimizations.
2    Copyright (C) 1987-2015 Free Software Foundation, Inc.
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 gen_peephole (rtx, int);
50 static void match_rtx (rtx, struct link *, int);
51 static void print_path (struct link *);
52 static void print_code (RTX_CODE);
53 \f
54 static void
55 gen_peephole (rtx peep, int insn_code_number)
56 {
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");
69           printf ("       if (insn == 0) goto L%d; }\n",
70                   insn_code_number);
71           printf ("  while (NOTE_P (insn)\n");
72           printf ("\t || (NONJUMP_INSN_P (insn)\n");
73           printf ("\t     && (GET_CODE (PATTERN (insn)) == USE\n");
74           printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n");
75
76           printf ("  if (LABEL_P (insn)\n\
77       || BARRIER_P (insn))\n    goto L%d;\n",
78                   insn_code_number);
79         }
80
81       printf ("  pat = PATTERN (insn);\n");
82
83       /* Walk the insn's pattern, remembering at all times the path
84          down to the walking point.  */
85
86       match_rtx (XVECEXP (peep, 0, i), NULL, insn_code_number);
87     }
88
89   /* We get this far if the pattern matches.
90      Now test the extra condition.  */
91
92   if (XSTR (peep, 1) && XSTR (peep, 1)[0])
93     printf ("  if (! (%s)) goto L%d;\n",
94             XSTR (peep, 1), insn_code_number);
95
96   /* If that matches, construct new pattern and put it in the first insn.
97      This new pattern will never be matched.
98      It exists only so that insn-extract can get the operands back.
99      So use a simple regular form: a PARALLEL containing a vector
100      of all the operands.  */
101
102   printf ("  PATTERN (ins1) = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands);
103
104   /* Record this define_peephole's insn code in the insn,
105      as if it had been recognized to match this.  */
106   printf ("  INSN_CODE (ins1) = %d;\n",
107           insn_code_number);
108
109   /* Delete the remaining insns.  */
110   if (ninsns > 1)
111     printf ("  delete_for_peephole (NEXT_INSN (ins1), insn);\n");
112
113   /* See reload1.c for insertion of NOTE which guarantees that this
114      cannot be zero.  */
115   printf ("  return NEXT_INSN (insn);\n");
116
117   printf (" L%d:\n\n", insn_code_number);
118 }
119 \f
120 static void
121 match_rtx (rtx x, struct link *path, int fail_label)
122 {
123   RTX_CODE code;
124   int i;
125   int len;
126   const char *fmt;
127   struct link link;
128
129   if (x == 0)
130     return;
131
132
133   code = GET_CODE (x);
134
135   switch (code)
136     {
137     case MATCH_OPERAND:
138       if (XINT (x, 0) > max_opno)
139         max_opno = XINT (x, 0);
140       if (XINT (x, 0) >= n_operands)
141         n_operands = 1 + XINT (x, 0);
142
143       printf ("  x = ");
144       print_path (path);
145       printf (";\n");
146
147       printf ("  operands[%d] = x;\n", XINT (x, 0));
148       if (XSTR (x, 1) && XSTR (x, 1)[0])
149         printf ("  if (! %s (x, %smode)) goto L%d;\n",
150                 XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
151       return;
152
153     case MATCH_DUP:
154     case MATCH_PAR_DUP:
155       printf ("  x = ");
156       print_path (path);
157       printf (";\n");
158
159       printf ("  if (!rtx_equal_p (operands[%d], x)) goto L%d;\n",
160               XINT (x, 0), fail_label);
161       return;
162
163     case MATCH_OP_DUP:
164       printf ("  x = ");
165       print_path (path);
166       printf (";\n");
167
168       printf ("  if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0));
169       printf ("      || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n",
170               XINT (x, 0), fail_label);
171       printf ("  operands[%d] = x;\n", XINT (x, 0));
172       link.next = path;
173       link.vecelt = -1;
174       for (i = 0; i < XVECLEN (x, 1); i++)
175         {
176           link.pos = i;
177           match_rtx (XVECEXP (x, 1, i), &link, fail_label);
178         }
179       return;
180
181     case MATCH_OPERATOR:
182       if (XINT (x, 0) > max_opno)
183         max_opno = XINT (x, 0);
184       if (XINT (x, 0) >= n_operands)
185         n_operands = 1 + XINT (x, 0);
186
187       printf ("  x = ");
188       print_path (path);
189       printf (";\n");
190
191       printf ("  operands[%d] = x;\n", XINT (x, 0));
192       if (XSTR (x, 1) && XSTR (x, 1)[0])
193         printf ("  if (! %s (x, %smode)) goto L%d;\n",
194                 XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
195       link.next = path;
196       link.vecelt = -1;
197       for (i = 0; i < XVECLEN (x, 2); i++)
198         {
199           link.pos = i;
200           match_rtx (XVECEXP (x, 2, i), &link, fail_label);
201         }
202       return;
203
204     case MATCH_PARALLEL:
205       if (XINT (x, 0) > max_opno)
206         max_opno = XINT (x, 0);
207       if (XINT (x, 0) >= n_operands)
208         n_operands = 1 + XINT (x, 0);
209
210       printf ("  x = ");
211       print_path (path);
212       printf (";\n");
213
214       printf ("  if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label);
215       printf ("  operands[%d] = x;\n", XINT (x, 0));
216       if (XSTR (x, 1) && XSTR (x, 1)[0])
217         printf ("  if (! %s (x, %smode)) goto L%d;\n",
218                 XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
219       link.next = path;
220       link.pos = 0;
221       for (i = 0; i < XVECLEN (x, 2); i++)
222         {
223           link.vecelt = i;
224           match_rtx (XVECEXP (x, 2, i), &link, fail_label);
225         }
226       return;
227
228     default:
229       break;
230     }
231
232   printf ("  x = ");
233   print_path (path);
234   printf (";\n");
235
236   printf ("  if (GET_CODE (x) != ");
237   print_code (code);
238   printf (") goto L%d;\n", fail_label);
239
240   if (GET_MODE (x) != VOIDmode)
241     {
242       printf ("  if (GET_MODE (x) != %smode) goto L%d;\n",
243               GET_MODE_NAME (GET_MODE (x)), fail_label);
244     }
245
246   link.next = path;
247   link.vecelt = -1;
248   fmt = GET_RTX_FORMAT (code);
249   len = GET_RTX_LENGTH (code);
250   for (i = 0; i < len; i++)
251     {
252       link.pos = i;
253       if (fmt[i] == 'e' || fmt[i] == 'u')
254         match_rtx (XEXP (x, i), &link, fail_label);
255       else if (fmt[i] == 'E')
256         {
257           int j;
258           printf ("  if (XVECLEN (x, %d) != %d) goto L%d;\n",
259                   i, XVECLEN (x, i), fail_label);
260           for (j = 0; j < XVECLEN (x, i); j++)
261             {
262               link.vecelt = j;
263               match_rtx (XVECEXP (x, i, j), &link, fail_label);
264             }
265         }
266       else if (fmt[i] == 'i')
267         {
268           /* Make sure that at run time `x' is the RTX we want to test.  */
269           if (i != 0)
270             {
271               printf ("  x = ");
272               print_path (path);
273               printf (";\n");
274             }
275
276           printf ("  if (XINT (x, %d) != %d) goto L%d;\n",
277                   i, XINT (x, i), fail_label);
278         }
279       else if (fmt[i] == 'w')
280         {
281           /* Make sure that at run time `x' is the RTX we want to test.  */
282           if (i != 0)
283             {
284               printf ("  x = ");
285               print_path (path);
286               printf (";\n");
287             }
288
289           printf ("  if (XWINT (x, %d) != ", i);
290           printf (HOST_WIDE_INT_PRINT_DEC, XWINT (x, i));
291           printf (") goto L%d;\n", fail_label);
292         }
293       else if (fmt[i] == 's')
294         {
295           /* Make sure that at run time `x' is the RTX we want to test.  */
296           if (i != 0)
297             {
298               printf ("  x = ");
299               print_path (path);
300               printf (";\n");
301             }
302
303           printf ("  if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
304                   i, XSTR (x, i), fail_label);
305         }
306     }
307 }
308
309 /* Given a PATH, representing a path down the instruction's
310    pattern from the root to a certain point, output code to
311    evaluate to the rtx at that point.  */
312
313 static void
314 print_path (struct link *path)
315 {
316   if (path == 0)
317     printf ("pat");
318   else if (path->vecelt >= 0)
319     {
320       printf ("XVECEXP (");
321       print_path (path->next);
322       printf (", %d, %d)", path->pos, path->vecelt);
323     }
324   else
325     {
326       printf ("XEXP (");
327       print_path (path->next);
328       printf (", %d)", path->pos);
329     }
330 }
331 \f
332 static void
333 print_code (RTX_CODE code)
334 {
335   const char *p1;
336   for (p1 = GET_RTX_NAME (code); *p1; p1++)
337     putchar (TOUPPER (*p1));
338 }
339
340 extern int main (int, char **);
341
342 int
343 main (int argc, char **argv)
344 {
345   rtx desc;
346
347   max_opno = -1;
348
349   progname = "genpeep";
350
351   if (!init_rtx_reader_args (argc, argv))
352     return (FATAL_EXIT_CODE);
353
354   printf ("/* Generated automatically by the program `genpeep'\n\
355 from the machine description file `md'.  */\n\n");
356
357   printf ("#include \"config.h\"\n");
358   printf ("#include \"system.h\"\n");
359   printf ("#include \"coretypes.h\"\n");
360   printf ("#include \"tm.h\"\n");
361   printf ("#include \"insn-config.h\"\n");
362   printf ("#include \"hash-set.h\"\n");
363   printf ("#include \"machmode.h\"\n");
364   printf ("#include \"vec.h\"\n");
365   printf ("#include \"double-int.h\"\n");
366   printf ("#include \"input.h\"\n");
367   printf ("#include \"alias.h\"\n");
368   printf ("#include \"symtab.h\"\n");
369   printf ("#include \"wide-int.h\"\n");
370   printf ("#include \"inchash.h\"\n");
371   printf ("#include \"tree.h\"\n");
372   printf ("#include \"varasm.h\"\n");
373   printf ("#include \"stor-layout.h\"\n");
374   printf ("#include \"calls.h\"\n");
375   printf ("#include \"rtl.h\"\n");
376   printf ("#include \"tm_p.h\"\n");
377   printf ("#include \"regs.h\"\n");
378   printf ("#include \"output.h\"\n");
379   printf ("#include \"recog.h\"\n");
380   printf ("#include \"except.h\"\n");
381   printf ("#include \"function.h\"\n");
382   printf ("#include \"diagnostic-core.h\"\n");
383   printf ("#include \"flags.h\"\n");
384   printf ("#include \"tm-constrs.h\"\n\n");
385
386   printf ("#ifdef HAVE_peephole\n");
387   printf ("extern rtx peep_operand[];\n\n");
388   printf ("#define operands peep_operand\n\n");
389
390   printf ("rtx_insn *\npeephole (rtx_insn *ins1)\n{\n");
391   printf ("  rtx_insn *insn ATTRIBUTE_UNUSED;\n");
392   printf ("  rtx x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;\n\n");
393
394   /* Early out: no peepholes for insns followed by barriers.  */
395   printf ("  if (NEXT_INSN (ins1)\n");
396   printf ("      && BARRIER_P (NEXT_INSN (ins1)))\n");
397   printf ("    return 0;\n\n");
398
399   /* Read the machine description.  */
400
401   while (1)
402     {
403       int line_no;
404       int insn_code_number;
405
406       desc = read_md_rtx (&line_no, &insn_code_number);
407       if (desc == NULL)
408         break;
409
410       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
411         gen_peephole (desc, insn_code_number);
412     }
413
414   printf ("  return 0;\n}\n\n");
415
416   if (max_opno == -1)
417     max_opno = 1;
418
419   printf ("rtx peep_operand[%d];\n", max_opno + 1);
420   printf ("#endif\n");
421
422   fflush (stdout);
423   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
424 }