15. Toolof genpeep
The detail of define_peepholepattern refers to Overview – about define_peephole,this tool won’t handle define_peephole2 pattern which is processed by toolsgenemit, genoutput and genrecog.
353 int
354 main (int argc, char **argv) ingenpeep.c
355 {
356 rtx desc;
357
358 max_opno= -1;
359
360 progname= "genpeep";
361
362 if (argc <= 1)
363 fatal ("no input file name");
364
365 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
366 return (FATAL_EXIT_CODE);
367
368 printf ("/* Generated automatically by the program `genpeep'\n\
369 from the machine description file`md'. */\n\n");
370
371 printf ("#include \"config.h\"\n");
372 printf ("#include \"system.h\"\n");
373 printf ("#include \"coretypes.h\"\n");
374 printf ("#include \"tm.h\"\n");
375 printf ("#include \"insn-config.h\"\n");
376 printf ("#include \"rtl.h\"\n");
377 printf ("#include \"tm_p.h\"\n");
378 printf ("#include \"regs.h\"\n");
379 printf ("#include \"output.h\"\n");
380 printf ("#include \"real.h\"\n");
381 printf ("#include \"recog.h\"\n");
382 printf ("#include \"except.h\"\n\n");
383 printf ("#include \"function.h\"\n\n");
384
385 printf ("#ifdef HAVE_peephole\n");
386 printf ("extern rtx peep_operand[];\n\n");
387 printf ("#define operands peep_operand\n\n");
388
389 printf ("rtx\npeephole (rtx ins1)\n{\n");
390 printf (" rtx insn ATTRIBUTE_UNUSED, xATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;\n\n");
391
392 /* Early out: no peepholes for insns followedby barriers. */
393 printf (" if (NEXT_INSN(ins1)\n");
394 printf (" &&GET_CODE (NEXT_INSN (ins1)) == BARRIER)\n");
395 printf (" return0;\n\n");
396
397 /* Read the machine description. */
398
399 while (1)
400 {
401 int line_no, rtx_number = 0;
402
403 desc = read_md_rtx (&line_no,&rtx_number);
404 if (desc == NULL)
405 break;
406
407 if (GET_CODE (desc) == DEFINE_PEEPHOLE)
408 {
409 gen_peephole (desc);
410 insn_code_number++;
411 }
412 if (GET_CODE (desc) == DEFINE_INSN
413 || GET_CODE (desc) == DEFINE_EXPAND
414 || GET_CODE (desc) == DEFINE_SPLIT
415 || GET_CODE (desc) == DEFINE_PEEPHOLE2)
416 {
417 insn_code_number++;
418 }
419 }
420
421 printf (" return0;\n}\n\n");
422
423 if (max_opno== -1)
424 max_opno= 1;
425
426 printf ("rtx peep_operand[%d];\n", max_opno + 1);
427 printf ("#endif\n");
428
429 fflush (stdout);
430 return (ferror (stdout) != 0 ?FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
431 }
Till line 399, we can see following output fragment.
/* Generated automatically by theprogram `genpeep'
from the machine description file`md'. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "insn-config.h"
#include "rtl.h"
#include "tm_p.h"
#include "regs.h"
#include "output.h"
#include "real.h"
#include "recog.h"
#include "except.h"
#include "function.h"
#ifdef HAVE_peephole
extern rtx peep_operand[];
#define operands peep_operand
rtx
peephole (rtx ins1)
{
rtx insn ATTRIBUTE_UNUSED, x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;
if (NEXT_INSN (ins1)
&& GET_CODE (NEXT_INSN (ins1)) ==BARRIER)
return 0;
gen_peephole继续把该模式输出到这个peephole函数中。
61 static void
62 gen_peephole (rtx peep) ingenpeep.c
63 {
64 int ninsns = XVECLEN (peep, 0);
65 int i;
66
67 n_operands= 0;
68
69 printf (" insn =ins1;\n");
70
71 for(i = 0; i < ninsns; i++)
72 {
73 if (i > 0)
74 {
75 printf (" do { insn =NEXT_INSN (insn);\n");
76 printf (" if (insn ==0) goto L%d; }\n",
77 insn_code_number);
78 printf (" while (GET_CODE(insn) == NOTE\n");
79 printf ("\t || (GET_CODE(insn) == INSN\n");
80 printf ("\t &&(GET_CODE (PATTERN (insn)) == USE\n");
81 printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n");
82
83 printf (" if (GET_CODE(insn) == CODE_LABEL\n\
84 || GET_CODE (insn) ==BARRIER)\n goto L%d;\n",
85 insn_code_number);
86 }
87
88 printf (" pat = PATTERN(insn);\n");
89
90 /* Walk the insn's pattern, remembering at alltimes the path
91 down to the walking point. */
92
93 match_rtx (XVECEXP (peep, 0, i), NULL, insn_code_number);
94 }
95
96 /* We get this far if the pattern matches.
97 Now test the extra condition. */
98
99 if (XSTR (peep, 1) && XSTR (peep, 1)[0])
100 printf (" if (! (%s)) gotoL%d;\n",
101 XSTR (peep, 1), insn_code_number);
102
103 /* If that matches, construct new pattern andput it in the first insn.
104 This new pattern will never be matched.
105 It exists only so that insn-extract can getthe operands back.
106 So use a simple regular form: a PARALLELcontaining a vector
107 of all the operands. */
108
109 printf (" PATTERN (ins1) =gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands);
110
111 /* Record this define_peephole's insn code inthe insn,
112 as if it had been recognized to matchthis. */
113 printf (" INSN_CODE (ins1) = %d;\n",
114 insn_code_number);
115
116 /* Delete the remaining insns. */
117 if (ninsns > 1)
118 printf (" delete_for_peephole (NEXT_INSN (ins1), insn);\n");
119
120 /* See reload1.c for insertion of NOTE whichguarantees that this
121 cannot be zero. */
122 printf (" return NEXT_INSN(insn);\n");
123
124 printf (" L%d:\n\n", insn_code_number);
125 }
Then if the architecture (for i386 system, no define_peephole isdefined) contains define_peephole, till line 93, before invoking match_rtx, wecan get peepholefunction as following.
rtx
peephole (rtx ins1)
{
rtx insn ATTRIBUTE_UNUSED, x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;
if (NEXT_INSN (ins1)
&& GET_CODE (NEXT_INSN (ins1)) ==BARRIER)
return 0;
insn = ins1;
do { insn = NEXT_INSN (insn);
if (insn == 0) gotoL’insn-code-num`; }
while (GET_CODE (insn) == NOTE
|| (GET_CODE (insn) == INSN
&& (GET_CODE(PATTERN (insn)) == USE
|| GET_CODE (PATTERN(insn)) == CLOBBER)));
if (GET_CODE (insn) == CODE_LABEL
|| GET_CODE (insn)== BARRIER)
goto L’insn-code-num`;
pat = PATTERN (insn);
For the example we see in Overview –about define_peephole, the first child of the rtx object is following rtxobject, which will be the first parameter of match_rtx.
[(set(reg:SI 15) (plus:SI (reg:SI 15) (const_int 4)))
(set(match_operand:DF 0 "register_operand" "=f")
(match_operand:DF 1"register_operand" "ad"))]
It is parallel containing two instructions.
In the output peephole, insn is the rtx object generated by emit_insn, PATTERN willretrieve the rtx object of define_insn from the instruction.
127 static void
128 match_rtx (rtx x, struct link *path, intfail_label) in genpeep.c
129 {
130 RTX_CODE code;
131 int i;
132 int len;
133 constchar *fmt;
134 struct link link;
135
136 if (x == 0)
137 return;
138
139
140 code = GET_CODE (x);
141
142 switch (code)
143 {
144 case MATCH_OPERAND:
145 if (XINT (x, 0) > max_opno)
146 max_opno= XINT (x, 0);
147 if (XINT (x, 0) >= n_operands)
148 n_operands= 1 + XINT (x, 0);
149
150 printf (" x = ");
151 print_path (path);
152 printf (";\n");
153
154 printf (" operands[%d] =x;\n", XINT (x, 0));
155 if (XSTR (x, 1) && XSTR (x, 1)[0])
156 printf (" if (! %s (x,%smode)) goto L%d;\n",
157 XSTR(x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
158 return;
159
160 case MATCH_DUP:
161 case MATCH_PAR_DUP:
162 printf (" x = ");
163 print_path (path);
164 printf (";\n");
165
166 printf (" if (!rtx_equal_p(operands[%d], x)) goto L%d;\n",
167 XINT (x, 0), fail_label);
168 return;
169
170 case MATCH_OP_DUP:
171 printf (" x = ");
172 print_path (path);
173 printf (";\n");
174
175 printf (" if (GET_CODE(operands[%d]) != GET_CODE (x)\n", XINT (x, 0));
176 printf (" || GET_MODE(operands[%d]) != GET_MODE (x)) goto L%d;\n",
177 XINT (x, 0), fail_label);
178 printf (" operands[%d] =x;\n", XINT (x, 0));
179 link.next = path;
180 link.vecelt = -1;
181 for(i = 0; i < XVECLEN (x, 1); i++)
182 {
183 link.pos = i;
184 match_rtx (XVECEXP (x, 1, i), &link,fail_label);
185 }
186 return;
187
188 case MATCH_OPERATOR:
189 if (XINT (x, 0) > max_opno)
190 max_opno= XINT (x, 0);
191 if (XINT (x, 0) >= n_operands)
192 n_operands= 1 + XINT (x, 0);
193
194 printf (" x = ");
195 print_path (path);
196 printf (";\n");
197
198 printf (" operands[%d] =x;\n", XINT (x, 0));
199 if (XSTR (x, 1) && XSTR (x, 1)[0])
200 printf (" if (! %s (x,%smode)) goto L%d;\n",
201 XSTR (x, 1), GET_MODE_NAME(GET_MODE (x)), fail_label);
202 link.next = path;
203 link.vecelt = -1;
204 for(i = 0; i < XVECLEN (x, 2); i++)
205 {
206 link.pos = i;
207 match_rtx (XVECEXP (x, 2, i), &link,fail_label);
208 }
209 return;
210
211 case MATCH_PARALLEL:
212 if (XINT (x, 0) > max_opno)
213 max_opno= XINT (x, 0);
214 if (XINT (x, 0) >= n_operands)
215 n_operands= 1 + XINT (x, 0);
216
217 printf (" x = ");
218 print_path (path);
219 printf (";\n");
220
221 printf (" if (GET_CODE (x)!= PARALLEL) goto L%d;\n", fail_label);
222 printf (" operands[%d] =x;\n", XINT (x, 0));
223 if (XSTR (x, 1) && XSTR (x, 1)[0])
224 printf (" if (! %s (x,%smode)) goto L%d;\n",
225 XSTR(x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
226 link.next = path;
227 link.pos = 0;
228 for(i = 0; i < XVECLEN (x, 2); i++)
229 {
230 link.vecelt = i;
231 match_rtx (XVECEXP (x, 2, i), &link,fail_label);
232 }
233 return;
234
235 case ADDRESS:
236 match_rtx (XEXP (x, 0),path, fail_label);
237 return;
238
239 default:
240 break;
241 }
242
243 printf (" x = ");
244 print_path (path);
245 printf (";\n");
246
247 printf (" if (GET_CODE (x)!= ");
248 print_code (code);
249 printf (") goto L%d;\n",fail_label);
250
251 if (GET_MODE (x) != VOIDmode)
252 {
253 printf (" if (GET_MODE (x)!= %smode) goto L%d;\n",
254 GET_MODE_NAME (GET_MODE (x)),fail_label);
255 }
256
257 link.next = path;
258 link.vecelt = -1;
259 fmt = GET_RTX_FORMAT (code);
260 len = GET_RTX_LENGTH (code);
261 for(i = 0; i < len; i++)
262 {
263 link.pos = i;
264 if (fmt[i] == 'e' || fmt[i] =='u')
265 match_rtx (XEXP (x, i),&link, fail_label);
266 else if (fmt[i] == 'E')
267 {
268 int j;
269 printf (" if (XVECLEN (x,%d) != %d) goto L%d;\n",
270 i, XVECLEN (x, i),fail_label);
271 for(j = 0; j < XVECLEN (x, i); j++)
272 {
273 link.vecelt = j;
274 match_rtx (XVECEXP (x, i, j), &link,fail_label);
275 }
276 }
277 else if (fmt[i] == 'i')
278 {
279 /* Makesure that at run time `x' is the RTX we want to test. */
280 if (i != 0)
281 {
282 printf (" x = ");
283 print_path (path);
284 printf (";\n");
285 }
286
287 printf (" if (XINT (x, %d)!= %d) goto L%d;\n",
288 i, XINT (x, i), fail_label);
289 }
290 else if (fmt[i] == 'w')
291 {
292 /* Make sure that at run time `x' is the RTXwe want to test. */
293 if (i != 0)
294 {
295 printf (" x = ");
296 print_path (path);
297 printf (";\n");
298 }
299
300 printf (" if (XWINT (x, %d)!= ", i);
301 printf (HOST_WIDE_INT_PRINT_DEC, XWINT (x, i));
302 printf (") goto L%d;\n", fail_label);
303 }
304 else if (fmt[i] == 's')
305 {
306 /* Make sure that at run time `x' is the RTXwe want to test. */
307 if (i != 0)
308 {
309 printf (" x = ");
310 print_path (path);
311 printf (";\n");
312 }
313
314 printf (" if (strcmp (XSTR(x, %d), \"%s\")) goto L%d;\n",
315 i, XSTR (x, i),fail_label);
316 }
317 }
318 }
324 static void
325 print_path (struct link *path) in genpeep.c
326 {
327 if (path == 0)
328 printf ("pat");
329 else if (path->vecelt >= 0)
330 {
331 printf ("XVECEXP (");
332 print_path (path->next);
333 printf (", %d, %d)", path->pos, path->vecelt);
334 }
335 else
336 {
337 printf ("XEXP (");
338 print_path (path->next);
339 printf (", %d)", path->pos);
340 }
341 }
For instructions, peephole output as following.
1 rtx
2 peephole (rtx ins1)
3 {
4 rtx insnATTRIBUTE_UNUSED, x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;
5
6 if(NEXT_INSN (ins1)
7 && GET_CODE (NEXT_INSN (ins1)) == BARRIER)
8 return0;
9
10 insn = ins1;
11 do { insn = NEXT_INSN(insn);
12 if (insn == 0) goto L`insn-code-num`; }
13 while (GET_CODE (insn)== NOTE
14 || (GET_CODE (insn) ==INSN
15 && (GET_CODE (PATTERN (insn)) == USE
16 || GET_CODE (PATTERN (insn)) == CLOBBER)));
17
18 if (GET_CODE (insn) ==CODE_LABEL
19 || GET_CODE (insn) == BARRIER)
20 goto L`insn-code-num`;
21
22 pat = PATTERN (insn); // first insn
23 x = pat;
24 if (GET_CODE (x) !=SET) goto L`insn-code-num`; // set
25 if (GET_CODE (x) != REG)goto L`insn-code-num`; // reg:SI 15
26 if (GET_MODE (x) !=SImode) goto L`insn-code-num`;
27 x = XEXP (pat, 0);
28 if (XINT (x, 0) != 15)goto L`insn-code-num`;
29 if (GET_CODE (x)!= PLUS) goto L`insn-code-num`; //plus
30 if (GET_MODE (x) !=SImode) goto L`insn-code-num`;
31 if (GET_CODE (x) != REG)goto L`insn-code-num`; // reg:SI 15
32 if (GET_MODE (x) !=SImode) goto L`insn-code-num`;
33 x = XEXP (XEXP(pat,1), 0);
34 if (XINT (x, 0) != 15)goto L`insn-code-num`;
35 if (GET_CODE(x) !=CONST_INT) goto L`insn-code-num`; //const_int
36 x = XEXP (XEXP(pat,1), 1);
37 if (XWINT (x, 0) != 4)goto L`insn-code-num`;
38
39 do { insn = NEXT_INSN(insn); // second insn
40 if (insn == 0) goto L`insn-code-num`; }
41 while (GET_CODE (insn)== NOTE
42 || (GET_CODE (insn) ==INSN
43 && (GET_CODE (PATTERN (insn)) == USE
44 || GET_CODE (PATTERN (insn)) == CLOBBER)));
45
46 if (GET_CODE (insn) ==CODE_LABEL
47 || GET_CODE (insn) == BARRIER)
48 goto L`insn-code-num`;
49
50 pat = PATTERN (insn);
51 x = pat;
52 if (GET_CODE (x) !=SET) goto L`insn-code-num`; // set
53 x = XEXP (pat, 0);
54 operands [0] = x;
55 if (!match_operand (x,DFmode)) goto L`insn-code-num`; //match_operand 0
56 x = XEXP (pat, 1);
57 operands [1] = x;
58 if (!match_operand (x,DFmode)) goto L`insn-code-num`; //match_operand 1
59 if (FP_REG_P(operands[0]) && ! FP_REG_P (operands[1])) goto L`insn-code-num`;
60 // out of match_rtx
61 PATTERN (ins1) =gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (2, operands));
62 INSN_CODE (ins1) =`insn-code-num`;
63 delete_for_peephole(NEXT_INSN (ins1), insn);
64 return NEXT_INSN(insn);
65 L`insn-code-num`:
66 return 0;
67 }
68
69 rtx peep_operand[2];
70 #endif
It is interesting to see that, above, when instruction sequence ismatched, the new instruction object will be created and place the sequence. In 5. Tool of genoutput, define_peephole is assignedwith unique insn-code-number and data for assemble generation is output. Seethat at line 62 above, the new instruction object is assigned with that codenumber. This number will be the index to find out the corresponding assembleoutput template.