0
|
1 /* Instruction scheduling pass.
|
|
2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
|
3 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
|
4 Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
|
|
5 and currently maintained by, Jim Wilson (wilson@cygnus.com)
|
|
6
|
|
7 This file is part of GCC.
|
|
8
|
|
9 GCC is free software; you can redistribute it and/or modify it under
|
|
10 the terms of the GNU General Public License as published by the Free
|
|
11 Software Foundation; either version 3, or (at your option) any later
|
|
12 version.
|
|
13
|
|
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
17 for more details.
|
|
18
|
|
19 You should have received a copy of the GNU General Public License
|
|
20 along with GCC; see the file COPYING3. If not see
|
|
21 <http://www.gnu.org/licenses/>. */
|
|
22
|
|
23 #include "config.h"
|
|
24 #include "system.h"
|
|
25 #include "coretypes.h"
|
|
26 #include "tm.h"
|
|
27 #include "rtl.h"
|
|
28 #include "obstack.h"
|
|
29 #include "hard-reg-set.h"
|
|
30 #include "basic-block.h"
|
|
31 #include "real.h"
|
|
32 #include "insn-attr.h"
|
|
33 #include "sched-int.h"
|
|
34 #include "tree-pass.h"
|
|
35
|
|
36 static char *safe_concat (char *, char *, const char *);
|
|
37
|
|
38 #define BUF_LEN 2048
|
|
39
|
|
40 static char *
|
|
41 safe_concat (char *buf, char *cur, const char *str)
|
|
42 {
|
|
43 char *end = buf + BUF_LEN - 2; /* Leave room for null. */
|
|
44 int c;
|
|
45
|
|
46 if (cur > end)
|
|
47 {
|
|
48 *end = '\0';
|
|
49 return end;
|
|
50 }
|
|
51
|
|
52 while (cur < end && (c = *str++) != '\0')
|
|
53 *cur++ = c;
|
|
54
|
|
55 *cur = '\0';
|
|
56 return cur;
|
|
57 }
|
|
58
|
|
59 /* This recognizes rtx, I classified as expressions. These are always
|
|
60 represent some action on values or results of other expression, that
|
|
61 may be stored in objects representing values. */
|
|
62
|
|
63 static void
|
|
64 print_exp (char *buf, const_rtx x, int verbose)
|
|
65 {
|
|
66 char tmp[BUF_LEN];
|
|
67 const char *st[4];
|
|
68 char *cur = buf;
|
|
69 const char *fun = (char *) 0;
|
|
70 const char *sep;
|
|
71 rtx op[4];
|
|
72 int i;
|
|
73
|
|
74 for (i = 0; i < 4; i++)
|
|
75 {
|
|
76 st[i] = (char *) 0;
|
|
77 op[i] = NULL_RTX;
|
|
78 }
|
|
79
|
|
80 switch (GET_CODE (x))
|
|
81 {
|
|
82 case PLUS:
|
|
83 op[0] = XEXP (x, 0);
|
|
84 if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
|
85 && INTVAL (XEXP (x, 1)) < 0)
|
|
86 {
|
|
87 st[1] = "-";
|
|
88 op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
|
|
89 }
|
|
90 else
|
|
91 {
|
|
92 st[1] = "+";
|
|
93 op[1] = XEXP (x, 1);
|
|
94 }
|
|
95 break;
|
|
96 case LO_SUM:
|
|
97 op[0] = XEXP (x, 0);
|
|
98 st[1] = "+low(";
|
|
99 op[1] = XEXP (x, 1);
|
|
100 st[2] = ")";
|
|
101 break;
|
|
102 case MINUS:
|
|
103 op[0] = XEXP (x, 0);
|
|
104 st[1] = "-";
|
|
105 op[1] = XEXP (x, 1);
|
|
106 break;
|
|
107 case COMPARE:
|
|
108 fun = "cmp";
|
|
109 op[0] = XEXP (x, 0);
|
|
110 op[1] = XEXP (x, 1);
|
|
111 break;
|
|
112 case NEG:
|
|
113 st[0] = "-";
|
|
114 op[0] = XEXP (x, 0);
|
|
115 break;
|
|
116 case MULT:
|
|
117 op[0] = XEXP (x, 0);
|
|
118 st[1] = "*";
|
|
119 op[1] = XEXP (x, 1);
|
|
120 break;
|
|
121 case DIV:
|
|
122 op[0] = XEXP (x, 0);
|
|
123 st[1] = "/";
|
|
124 op[1] = XEXP (x, 1);
|
|
125 break;
|
|
126 case UDIV:
|
|
127 fun = "udiv";
|
|
128 op[0] = XEXP (x, 0);
|
|
129 op[1] = XEXP (x, 1);
|
|
130 break;
|
|
131 case MOD:
|
|
132 op[0] = XEXP (x, 0);
|
|
133 st[1] = "%";
|
|
134 op[1] = XEXP (x, 1);
|
|
135 break;
|
|
136 case UMOD:
|
|
137 fun = "umod";
|
|
138 op[0] = XEXP (x, 0);
|
|
139 op[1] = XEXP (x, 1);
|
|
140 break;
|
|
141 case SMIN:
|
|
142 fun = "smin";
|
|
143 op[0] = XEXP (x, 0);
|
|
144 op[1] = XEXP (x, 1);
|
|
145 break;
|
|
146 case SMAX:
|
|
147 fun = "smax";
|
|
148 op[0] = XEXP (x, 0);
|
|
149 op[1] = XEXP (x, 1);
|
|
150 break;
|
|
151 case UMIN:
|
|
152 fun = "umin";
|
|
153 op[0] = XEXP (x, 0);
|
|
154 op[1] = XEXP (x, 1);
|
|
155 break;
|
|
156 case UMAX:
|
|
157 fun = "umax";
|
|
158 op[0] = XEXP (x, 0);
|
|
159 op[1] = XEXP (x, 1);
|
|
160 break;
|
|
161 case NOT:
|
|
162 st[0] = "!";
|
|
163 op[0] = XEXP (x, 0);
|
|
164 break;
|
|
165 case AND:
|
|
166 op[0] = XEXP (x, 0);
|
|
167 st[1] = "&";
|
|
168 op[1] = XEXP (x, 1);
|
|
169 break;
|
|
170 case IOR:
|
|
171 op[0] = XEXP (x, 0);
|
|
172 st[1] = "|";
|
|
173 op[1] = XEXP (x, 1);
|
|
174 break;
|
|
175 case XOR:
|
|
176 op[0] = XEXP (x, 0);
|
|
177 st[1] = "^";
|
|
178 op[1] = XEXP (x, 1);
|
|
179 break;
|
|
180 case ASHIFT:
|
|
181 op[0] = XEXP (x, 0);
|
|
182 st[1] = "<<";
|
|
183 op[1] = XEXP (x, 1);
|
|
184 break;
|
|
185 case LSHIFTRT:
|
|
186 op[0] = XEXP (x, 0);
|
|
187 st[1] = " 0>>";
|
|
188 op[1] = XEXP (x, 1);
|
|
189 break;
|
|
190 case ASHIFTRT:
|
|
191 op[0] = XEXP (x, 0);
|
|
192 st[1] = ">>";
|
|
193 op[1] = XEXP (x, 1);
|
|
194 break;
|
|
195 case ROTATE:
|
|
196 op[0] = XEXP (x, 0);
|
|
197 st[1] = "<-<";
|
|
198 op[1] = XEXP (x, 1);
|
|
199 break;
|
|
200 case ROTATERT:
|
|
201 op[0] = XEXP (x, 0);
|
|
202 st[1] = ">->";
|
|
203 op[1] = XEXP (x, 1);
|
|
204 break;
|
|
205 case ABS:
|
|
206 fun = "abs";
|
|
207 op[0] = XEXP (x, 0);
|
|
208 break;
|
|
209 case SQRT:
|
|
210 fun = "sqrt";
|
|
211 op[0] = XEXP (x, 0);
|
|
212 break;
|
|
213 case FFS:
|
|
214 fun = "ffs";
|
|
215 op[0] = XEXP (x, 0);
|
|
216 break;
|
|
217 case EQ:
|
|
218 op[0] = XEXP (x, 0);
|
|
219 st[1] = "==";
|
|
220 op[1] = XEXP (x, 1);
|
|
221 break;
|
|
222 case NE:
|
|
223 op[0] = XEXP (x, 0);
|
|
224 st[1] = "!=";
|
|
225 op[1] = XEXP (x, 1);
|
|
226 break;
|
|
227 case GT:
|
|
228 op[0] = XEXP (x, 0);
|
|
229 st[1] = ">";
|
|
230 op[1] = XEXP (x, 1);
|
|
231 break;
|
|
232 case GTU:
|
|
233 fun = "gtu";
|
|
234 op[0] = XEXP (x, 0);
|
|
235 op[1] = XEXP (x, 1);
|
|
236 break;
|
|
237 case LT:
|
|
238 op[0] = XEXP (x, 0);
|
|
239 st[1] = "<";
|
|
240 op[1] = XEXP (x, 1);
|
|
241 break;
|
|
242 case LTU:
|
|
243 fun = "ltu";
|
|
244 op[0] = XEXP (x, 0);
|
|
245 op[1] = XEXP (x, 1);
|
|
246 break;
|
|
247 case GE:
|
|
248 op[0] = XEXP (x, 0);
|
|
249 st[1] = ">=";
|
|
250 op[1] = XEXP (x, 1);
|
|
251 break;
|
|
252 case GEU:
|
|
253 fun = "geu";
|
|
254 op[0] = XEXP (x, 0);
|
|
255 op[1] = XEXP (x, 1);
|
|
256 break;
|
|
257 case LE:
|
|
258 op[0] = XEXP (x, 0);
|
|
259 st[1] = "<=";
|
|
260 op[1] = XEXP (x, 1);
|
|
261 break;
|
|
262 case LEU:
|
|
263 fun = "leu";
|
|
264 op[0] = XEXP (x, 0);
|
|
265 op[1] = XEXP (x, 1);
|
|
266 break;
|
|
267 case SIGN_EXTRACT:
|
|
268 fun = (verbose) ? "sign_extract" : "sxt";
|
|
269 op[0] = XEXP (x, 0);
|
|
270 op[1] = XEXP (x, 1);
|
|
271 op[2] = XEXP (x, 2);
|
|
272 break;
|
|
273 case ZERO_EXTRACT:
|
|
274 fun = (verbose) ? "zero_extract" : "zxt";
|
|
275 op[0] = XEXP (x, 0);
|
|
276 op[1] = XEXP (x, 1);
|
|
277 op[2] = XEXP (x, 2);
|
|
278 break;
|
|
279 case SIGN_EXTEND:
|
|
280 fun = (verbose) ? "sign_extend" : "sxn";
|
|
281 op[0] = XEXP (x, 0);
|
|
282 break;
|
|
283 case ZERO_EXTEND:
|
|
284 fun = (verbose) ? "zero_extend" : "zxn";
|
|
285 op[0] = XEXP (x, 0);
|
|
286 break;
|
|
287 case FLOAT_EXTEND:
|
|
288 fun = (verbose) ? "float_extend" : "fxn";
|
|
289 op[0] = XEXP (x, 0);
|
|
290 break;
|
|
291 case TRUNCATE:
|
|
292 fun = (verbose) ? "trunc" : "trn";
|
|
293 op[0] = XEXP (x, 0);
|
|
294 break;
|
|
295 case FLOAT_TRUNCATE:
|
|
296 fun = (verbose) ? "float_trunc" : "ftr";
|
|
297 op[0] = XEXP (x, 0);
|
|
298 break;
|
|
299 case FLOAT:
|
|
300 fun = (verbose) ? "float" : "flt";
|
|
301 op[0] = XEXP (x, 0);
|
|
302 break;
|
|
303 case UNSIGNED_FLOAT:
|
|
304 fun = (verbose) ? "uns_float" : "ufl";
|
|
305 op[0] = XEXP (x, 0);
|
|
306 break;
|
|
307 case FIX:
|
|
308 fun = "fix";
|
|
309 op[0] = XEXP (x, 0);
|
|
310 break;
|
|
311 case UNSIGNED_FIX:
|
|
312 fun = (verbose) ? "uns_fix" : "ufx";
|
|
313 op[0] = XEXP (x, 0);
|
|
314 break;
|
|
315 case PRE_DEC:
|
|
316 st[0] = "--";
|
|
317 op[0] = XEXP (x, 0);
|
|
318 break;
|
|
319 case PRE_INC:
|
|
320 st[0] = "++";
|
|
321 op[0] = XEXP (x, 0);
|
|
322 break;
|
|
323 case POST_DEC:
|
|
324 op[0] = XEXP (x, 0);
|
|
325 st[1] = "--";
|
|
326 break;
|
|
327 case POST_INC:
|
|
328 op[0] = XEXP (x, 0);
|
|
329 st[1] = "++";
|
|
330 break;
|
|
331 case PRE_MODIFY:
|
|
332 st[0] = "pre ";
|
|
333 op[0] = XEXP (XEXP (x, 1), 0);
|
|
334 st[1] = "+=";
|
|
335 op[1] = XEXP (XEXP (x, 1), 1);
|
|
336 break;
|
|
337 case POST_MODIFY:
|
|
338 st[0] = "post ";
|
|
339 op[0] = XEXP (XEXP (x, 1), 0);
|
|
340 st[1] = "+=";
|
|
341 op[1] = XEXP (XEXP (x, 1), 1);
|
|
342 break;
|
|
343 case CALL:
|
|
344 st[0] = "call ";
|
|
345 op[0] = XEXP (x, 0);
|
|
346 if (verbose)
|
|
347 {
|
|
348 st[1] = " argc:";
|
|
349 op[1] = XEXP (x, 1);
|
|
350 }
|
|
351 break;
|
|
352 case IF_THEN_ELSE:
|
|
353 st[0] = "{(";
|
|
354 op[0] = XEXP (x, 0);
|
|
355 st[1] = ")?";
|
|
356 op[1] = XEXP (x, 1);
|
|
357 st[2] = ":";
|
|
358 op[2] = XEXP (x, 2);
|
|
359 st[3] = "}";
|
|
360 break;
|
|
361 case TRAP_IF:
|
|
362 fun = "trap_if";
|
|
363 op[0] = TRAP_CONDITION (x);
|
|
364 break;
|
|
365 case PREFETCH:
|
|
366 fun = "prefetch";
|
|
367 op[0] = XEXP (x, 0);
|
|
368 op[1] = XEXP (x, 1);
|
|
369 op[2] = XEXP (x, 2);
|
|
370 break;
|
|
371 case UNSPEC:
|
|
372 case UNSPEC_VOLATILE:
|
|
373 {
|
|
374 cur = safe_concat (buf, cur, "unspec");
|
|
375 if (GET_CODE (x) == UNSPEC_VOLATILE)
|
|
376 cur = safe_concat (buf, cur, "/v");
|
|
377 cur = safe_concat (buf, cur, "[");
|
|
378 sep = "";
|
|
379 for (i = 0; i < XVECLEN (x, 0); i++)
|
|
380 {
|
|
381 print_pattern (tmp, XVECEXP (x, 0, i), verbose);
|
|
382 cur = safe_concat (buf, cur, sep);
|
|
383 cur = safe_concat (buf, cur, tmp);
|
|
384 sep = ",";
|
|
385 }
|
|
386 cur = safe_concat (buf, cur, "] ");
|
|
387 sprintf (tmp, "%d", XINT (x, 1));
|
|
388 cur = safe_concat (buf, cur, tmp);
|
|
389 }
|
|
390 break;
|
|
391 default:
|
|
392 /* If (verbose) debug_rtx (x); */
|
|
393 st[0] = GET_RTX_NAME (GET_CODE (x));
|
|
394 break;
|
|
395 }
|
|
396
|
|
397 /* Print this as a function? */
|
|
398 if (fun)
|
|
399 {
|
|
400 cur = safe_concat (buf, cur, fun);
|
|
401 cur = safe_concat (buf, cur, "(");
|
|
402 }
|
|
403
|
|
404 for (i = 0; i < 4; i++)
|
|
405 {
|
|
406 if (st[i])
|
|
407 cur = safe_concat (buf, cur, st[i]);
|
|
408
|
|
409 if (op[i])
|
|
410 {
|
|
411 if (fun && i != 0)
|
|
412 cur = safe_concat (buf, cur, ",");
|
|
413
|
|
414 print_value (tmp, op[i], verbose);
|
|
415 cur = safe_concat (buf, cur, tmp);
|
|
416 }
|
|
417 }
|
|
418
|
|
419 if (fun)
|
|
420 cur = safe_concat (buf, cur, ")");
|
|
421 } /* print_exp */
|
|
422
|
|
423 /* Prints rtxes, I customarily classified as values. They're constants,
|
|
424 registers, labels, symbols and memory accesses. */
|
|
425
|
|
426 void
|
|
427 print_value (char *buf, const_rtx x, int verbose)
|
|
428 {
|
|
429 char t[BUF_LEN];
|
|
430 char *cur = buf;
|
|
431
|
|
432 switch (GET_CODE (x))
|
|
433 {
|
|
434 case CONST_INT:
|
|
435 sprintf (t, HOST_WIDE_INT_PRINT_HEX,
|
|
436 (unsigned HOST_WIDE_INT) INTVAL (x));
|
|
437 cur = safe_concat (buf, cur, t);
|
|
438 break;
|
|
439 case CONST_DOUBLE:
|
|
440 if (FLOAT_MODE_P (GET_MODE (x)))
|
|
441 real_to_decimal (t, CONST_DOUBLE_REAL_VALUE (x), sizeof (t), 0, 1);
|
|
442 else
|
|
443 sprintf (t,
|
|
444 "<" HOST_WIDE_INT_PRINT_HEX "," HOST_WIDE_INT_PRINT_HEX ">",
|
|
445 (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
|
|
446 (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
|
|
447 cur = safe_concat (buf, cur, t);
|
|
448 break;
|
|
449 case CONST_FIXED:
|
|
450 fixed_to_decimal (t, CONST_FIXED_VALUE (x), sizeof (t));
|
|
451 cur = safe_concat (buf, cur, t);
|
|
452 break;
|
|
453 case CONST_STRING:
|
|
454 cur = safe_concat (buf, cur, "\"");
|
|
455 cur = safe_concat (buf, cur, XSTR (x, 0));
|
|
456 cur = safe_concat (buf, cur, "\"");
|
|
457 break;
|
|
458 case SYMBOL_REF:
|
|
459 cur = safe_concat (buf, cur, "`");
|
|
460 cur = safe_concat (buf, cur, XSTR (x, 0));
|
|
461 cur = safe_concat (buf, cur, "'");
|
|
462 break;
|
|
463 case LABEL_REF:
|
|
464 sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
|
|
465 cur = safe_concat (buf, cur, t);
|
|
466 break;
|
|
467 case CONST:
|
|
468 print_value (t, XEXP (x, 0), verbose);
|
|
469 cur = safe_concat (buf, cur, "const(");
|
|
470 cur = safe_concat (buf, cur, t);
|
|
471 cur = safe_concat (buf, cur, ")");
|
|
472 break;
|
|
473 case HIGH:
|
|
474 print_value (t, XEXP (x, 0), verbose);
|
|
475 cur = safe_concat (buf, cur, "high(");
|
|
476 cur = safe_concat (buf, cur, t);
|
|
477 cur = safe_concat (buf, cur, ")");
|
|
478 break;
|
|
479 case REG:
|
|
480 if (REGNO (x) < FIRST_PSEUDO_REGISTER)
|
|
481 {
|
|
482 int c = reg_names[REGNO (x)][0];
|
|
483 if (ISDIGIT (c))
|
|
484 cur = safe_concat (buf, cur, "%");
|
|
485
|
|
486 cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
|
|
487 }
|
|
488 else
|
|
489 {
|
|
490 sprintf (t, "r%d", REGNO (x));
|
|
491 cur = safe_concat (buf, cur, t);
|
|
492 }
|
|
493 if (verbose
|
|
494 #ifdef INSN_SCHEDULING
|
|
495 && !current_sched_info
|
|
496 #endif
|
|
497 )
|
|
498 {
|
|
499 sprintf (t, ":%s", GET_MODE_NAME (GET_MODE (x)));
|
|
500 cur = safe_concat (buf, cur, t);
|
|
501 }
|
|
502 break;
|
|
503 case SUBREG:
|
|
504 print_value (t, SUBREG_REG (x), verbose);
|
|
505 cur = safe_concat (buf, cur, t);
|
|
506 sprintf (t, "#%d", SUBREG_BYTE (x));
|
|
507 cur = safe_concat (buf, cur, t);
|
|
508 break;
|
|
509 case SCRATCH:
|
|
510 cur = safe_concat (buf, cur, "scratch");
|
|
511 break;
|
|
512 case CC0:
|
|
513 cur = safe_concat (buf, cur, "cc0");
|
|
514 break;
|
|
515 case PC:
|
|
516 cur = safe_concat (buf, cur, "pc");
|
|
517 break;
|
|
518 case MEM:
|
|
519 print_value (t, XEXP (x, 0), verbose);
|
|
520 cur = safe_concat (buf, cur, "[");
|
|
521 cur = safe_concat (buf, cur, t);
|
|
522 cur = safe_concat (buf, cur, "]");
|
|
523 break;
|
|
524 default:
|
|
525 print_exp (t, x, verbose);
|
|
526 cur = safe_concat (buf, cur, t);
|
|
527 break;
|
|
528 }
|
|
529 } /* print_value */
|
|
530
|
|
531 /* The next step in insn detalization, its pattern recognition. */
|
|
532
|
|
533 void
|
|
534 print_pattern (char *buf, const_rtx x, int verbose)
|
|
535 {
|
|
536 char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
|
|
537
|
|
538 switch (GET_CODE (x))
|
|
539 {
|
|
540 case SET:
|
|
541 print_value (t1, SET_DEST (x), verbose);
|
|
542 print_value (t2, SET_SRC (x), verbose);
|
|
543 sprintf (buf, "%s=%s", t1, t2);
|
|
544 break;
|
|
545 case RETURN:
|
|
546 sprintf (buf, "return");
|
|
547 break;
|
|
548 case CALL:
|
|
549 print_exp (buf, x, verbose);
|
|
550 break;
|
|
551 case CLOBBER:
|
|
552 print_value (t1, XEXP (x, 0), verbose);
|
|
553 sprintf (buf, "clobber %s", t1);
|
|
554 break;
|
|
555 case USE:
|
|
556 print_value (t1, XEXP (x, 0), verbose);
|
|
557 sprintf (buf, "use %s", t1);
|
|
558 break;
|
|
559 case COND_EXEC:
|
|
560 if (GET_CODE (COND_EXEC_TEST (x)) == NE
|
|
561 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
|
|
562 print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
|
|
563 else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
|
|
564 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
|
|
565 {
|
|
566 t1[0] = '!';
|
|
567 print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
|
|
568 }
|
|
569 else
|
|
570 print_value (t1, COND_EXEC_TEST (x), verbose);
|
|
571 print_pattern (t2, COND_EXEC_CODE (x), verbose);
|
|
572 sprintf (buf, "(%s) %s", t1, t2);
|
|
573 break;
|
|
574 case PARALLEL:
|
|
575 {
|
|
576 int i;
|
|
577
|
|
578 sprintf (t1, "{");
|
|
579 for (i = 0; i < XVECLEN (x, 0); i++)
|
|
580 {
|
|
581 print_pattern (t2, XVECEXP (x, 0, i), verbose);
|
|
582 sprintf (t3, "%s%s;", t1, t2);
|
|
583 strcpy (t1, t3);
|
|
584 }
|
|
585 sprintf (buf, "%s}", t1);
|
|
586 }
|
|
587 break;
|
|
588 case SEQUENCE:
|
|
589 /* Should never see SEQUENCE codes until after reorg. */
|
|
590 gcc_unreachable ();
|
|
591 case ASM_INPUT:
|
|
592 sprintf (buf, "asm {%s}", XSTR (x, 0));
|
|
593 break;
|
|
594 case ADDR_VEC:
|
|
595 break;
|
|
596 case ADDR_DIFF_VEC:
|
|
597 print_value (buf, XEXP (x, 0), verbose);
|
|
598 break;
|
|
599 case TRAP_IF:
|
|
600 print_value (t1, TRAP_CONDITION (x), verbose);
|
|
601 sprintf (buf, "trap_if %s", t1);
|
|
602 break;
|
|
603 case UNSPEC:
|
|
604 {
|
|
605 int i;
|
|
606
|
|
607 sprintf (t1, "unspec{");
|
|
608 for (i = 0; i < XVECLEN (x, 0); i++)
|
|
609 {
|
|
610 print_pattern (t2, XVECEXP (x, 0, i), verbose);
|
|
611 sprintf (t3, "%s%s;", t1, t2);
|
|
612 strcpy (t1, t3);
|
|
613 }
|
|
614 sprintf (buf, "%s}", t1);
|
|
615 }
|
|
616 break;
|
|
617 case UNSPEC_VOLATILE:
|
|
618 {
|
|
619 int i;
|
|
620
|
|
621 sprintf (t1, "unspec/v{");
|
|
622 for (i = 0; i < XVECLEN (x, 0); i++)
|
|
623 {
|
|
624 print_pattern (t2, XVECEXP (x, 0, i), verbose);
|
|
625 sprintf (t3, "%s%s;", t1, t2);
|
|
626 strcpy (t1, t3);
|
|
627 }
|
|
628 sprintf (buf, "%s}", t1);
|
|
629 }
|
|
630 break;
|
|
631 default:
|
|
632 print_value (buf, x, verbose);
|
|
633 }
|
|
634 } /* print_pattern */
|
|
635
|
|
636 /* This is the main function in rtl visualization mechanism. It
|
|
637 accepts an rtx and tries to recognize it as an insn, then prints it
|
|
638 properly in human readable form, resembling assembler mnemonics.
|
|
639 For every insn it prints its UID and BB the insn belongs too.
|
|
640 (Probably the last "option" should be extended somehow, since it
|
|
641 depends now on sched.c inner variables ...) */
|
|
642
|
|
643 void
|
|
644 print_insn (char *buf, const_rtx x, int verbose)
|
|
645 {
|
|
646 char t[BUF_LEN];
|
|
647 const_rtx insn = x;
|
|
648
|
|
649 switch (GET_CODE (x))
|
|
650 {
|
|
651 case INSN:
|
|
652 print_pattern (t, PATTERN (x), verbose);
|
|
653 #ifdef INSN_SCHEDULING
|
|
654 if (verbose && current_sched_info)
|
|
655 sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
|
|
656 t);
|
|
657 else
|
|
658 #endif
|
|
659 sprintf (buf, " %4d %s", INSN_UID (x), t);
|
|
660 break;
|
|
661 case JUMP_INSN:
|
|
662 print_pattern (t, PATTERN (x), verbose);
|
|
663 #ifdef INSN_SCHEDULING
|
|
664 if (verbose && current_sched_info)
|
|
665 sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
|
|
666 t);
|
|
667 else
|
|
668 #endif
|
|
669 sprintf (buf, " %4d %s", INSN_UID (x), t);
|
|
670 break;
|
|
671 case CALL_INSN:
|
|
672 x = PATTERN (insn);
|
|
673 if (GET_CODE (x) == PARALLEL)
|
|
674 {
|
|
675 x = XVECEXP (x, 0, 0);
|
|
676 print_pattern (t, x, verbose);
|
|
677 }
|
|
678 else
|
|
679 strcpy (t, "call <...>");
|
|
680 #ifdef INSN_SCHEDULING
|
|
681 if (verbose && current_sched_info)
|
|
682 sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (insn, 1), t);
|
|
683 else
|
|
684 #endif
|
|
685 sprintf (buf, " %4d %s", INSN_UID (insn), t);
|
|
686 break;
|
|
687 case CODE_LABEL:
|
|
688 sprintf (buf, "L%d:", INSN_UID (x));
|
|
689 break;
|
|
690 case BARRIER:
|
|
691 sprintf (buf, "i%4d: barrier", INSN_UID (x));
|
|
692 break;
|
|
693 case NOTE:
|
|
694 sprintf (buf, " %4d %s", INSN_UID (x),
|
|
695 GET_NOTE_INSN_NAME (NOTE_KIND (x)));
|
|
696 break;
|
|
697 default:
|
|
698 sprintf (buf, "i%4d <What %s?>", INSN_UID (x),
|
|
699 GET_RTX_NAME (GET_CODE (x)));
|
|
700 }
|
|
701 } /* print_insn */
|
|
702
|
|
703 /* Emit a slim dump of X (an insn) to the file F, including any register
|
|
704 note attached to the instruction. */
|
|
705 void
|
|
706 dump_insn_slim (FILE *f, rtx x)
|
|
707 {
|
|
708 char t[BUF_LEN + 32];
|
|
709 rtx note;
|
|
710
|
|
711 print_insn (t, x, 1);
|
|
712 fputs (t, f);
|
|
713 putc ('\n', f);
|
|
714 if (INSN_P (x) && REG_NOTES (x))
|
|
715 for (note = REG_NOTES (x); note; note = XEXP (note, 1))
|
|
716 {
|
|
717 print_value (t, XEXP (note, 0), 1);
|
|
718 fprintf (f, " %s: %s\n",
|
|
719 GET_REG_NOTE_NAME (REG_NOTE_KIND (note)), t);
|
|
720 }
|
|
721 }
|
|
722
|
|
723 /* Emit a slim dump of X (an insn) to stderr. */
|
|
724 void
|
|
725 debug_insn_slim (rtx x)
|
|
726 {
|
|
727 dump_insn_slim (stderr, x);
|
|
728 }
|
|
729
|
|
730 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
|
|
731 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
|
|
732 include more information on the basic blocks. */
|
|
733 void
|
|
734 print_rtl_slim_with_bb (FILE *f, rtx first, int flags)
|
|
735 {
|
|
736 print_rtl_slim (f, first, NULL, -1, flags);
|
|
737 }
|
|
738
|
|
739 /* Same as above, but stop at LAST or when COUNT == 0.
|
|
740 If COUNT < 0 it will stop only at LAST or NULL rtx. */
|
|
741 void
|
|
742 print_rtl_slim (FILE *f, rtx first, rtx last, int count, int flags)
|
|
743 {
|
|
744 basic_block current_bb = NULL;
|
|
745 rtx insn, tail;
|
|
746
|
|
747 tail = last ? NEXT_INSN (last) : NULL_RTX;
|
|
748 for (insn = first;
|
|
749 (insn != NULL) && (insn != tail) && (count != 0);
|
|
750 insn = NEXT_INSN (insn))
|
|
751 {
|
|
752 if ((flags & TDF_BLOCKS)
|
|
753 && (INSN_P (insn) || GET_CODE (insn) == NOTE)
|
|
754 && BLOCK_FOR_INSN (insn)
|
|
755 && !current_bb)
|
|
756 {
|
|
757 current_bb = BLOCK_FOR_INSN (insn);
|
|
758 dump_bb_info (current_bb, true, false, flags, ";; ", f);
|
|
759 }
|
|
760
|
|
761 dump_insn_slim (f, insn);
|
|
762
|
|
763 if ((flags & TDF_BLOCKS)
|
|
764 && current_bb
|
|
765 && insn == BB_END (current_bb))
|
|
766 {
|
|
767 dump_bb_info (current_bb, false, true, flags, ";; ", f);
|
|
768 current_bb = NULL;
|
|
769 }
|
|
770 if (count > 0)
|
|
771 count--;
|
|
772 }
|
|
773 }
|
|
774
|
|
775 void
|
|
776 debug_bb_slim (struct basic_block_def *bb)
|
|
777 {
|
|
778 print_rtl_slim (stderr, BB_HEAD (bb), BB_END (bb), -1, 32);
|
|
779 }
|
|
780
|
|
781 void
|
|
782 debug_bb_n_slim (int n)
|
|
783 {
|
|
784 struct basic_block_def *bb = BASIC_BLOCK (n);
|
|
785 debug_bb_slim (bb);
|
|
786 }
|
|
787
|