Merge branch 'vendor/LESS'
[dragonfly.git] / contrib / gcc-4.1 / gcc / sched-vis.c
1 /* Instruction scheduling pass.
2    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000, 2002, 2003, 2004, 2005 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 2, 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 COPYING.  If not, write to the Free
21 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA.  */
23 \f
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "toplev.h"
29 #include "rtl.h"
30 #include "tm_p.h"
31 #include "regs.h"
32 #include "hard-reg-set.h"
33 #include "basic-block.h"
34 #include "insn-attr.h"
35 #include "real.h"
36 #include "sched-int.h"
37 #include "target.h"
38
39 #ifdef INSN_SCHEDULING
40
41 static char *safe_concat (char *, char *, const char *);
42 static void print_exp (char *, rtx, int);
43 static void print_value (char *, rtx, int);
44 static void print_pattern (char *, rtx, int);
45
46 #define BUF_LEN 2048
47
48 static char *
49 safe_concat (char *buf, char *cur, const char *str)
50 {
51   char *end = buf + BUF_LEN - 2;        /* Leave room for null.  */
52   int c;
53
54   if (cur > end)
55     {
56       *end = '\0';
57       return end;
58     }
59
60   while (cur < end && (c = *str++) != '\0')
61     *cur++ = c;
62
63   *cur = '\0';
64   return cur;
65 }
66
67 /* This recognizes rtx, I classified as expressions.  These are always
68    represent some action on values or results of other expression, that
69    may be stored in objects representing values.  */
70
71 static void
72 print_exp (char *buf, rtx x, int verbose)
73 {
74   char tmp[BUF_LEN];
75   const char *st[4];
76   char *cur = buf;
77   const char *fun = (char *) 0;
78   const char *sep;
79   rtx op[4];
80   int i;
81
82   for (i = 0; i < 4; i++)
83     {
84       st[i] = (char *) 0;
85       op[i] = NULL_RTX;
86     }
87
88   switch (GET_CODE (x))
89     {
90     case PLUS:
91       op[0] = XEXP (x, 0);
92       if (GET_CODE (XEXP (x, 1)) == CONST_INT
93           && INTVAL (XEXP (x, 1)) < 0)
94         {
95           st[1] = "-";
96           op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
97         }
98       else
99         {
100           st[1] = "+";
101           op[1] = XEXP (x, 1);
102         }
103       break;
104     case LO_SUM:
105       op[0] = XEXP (x, 0);
106       st[1] = "+low(";
107       op[1] = XEXP (x, 1);
108       st[2] = ")";
109       break;
110     case MINUS:
111       op[0] = XEXP (x, 0);
112       st[1] = "-";
113       op[1] = XEXP (x, 1);
114       break;
115     case COMPARE:
116       fun = "cmp";
117       op[0] = XEXP (x, 0);
118       op[1] = XEXP (x, 1);
119       break;
120     case NEG:
121       st[0] = "-";
122       op[0] = XEXP (x, 0);
123       break;
124     case MULT:
125       op[0] = XEXP (x, 0);
126       st[1] = "*";
127       op[1] = XEXP (x, 1);
128       break;
129     case DIV:
130       op[0] = XEXP (x, 0);
131       st[1] = "/";
132       op[1] = XEXP (x, 1);
133       break;
134     case UDIV:
135       fun = "udiv";
136       op[0] = XEXP (x, 0);
137       op[1] = XEXP (x, 1);
138       break;
139     case MOD:
140       op[0] = XEXP (x, 0);
141       st[1] = "%";
142       op[1] = XEXP (x, 1);
143       break;
144     case UMOD:
145       fun = "umod";
146       op[0] = XEXP (x, 0);
147       op[1] = XEXP (x, 1);
148       break;
149     case SMIN:
150       fun = "smin";
151       op[0] = XEXP (x, 0);
152       op[1] = XEXP (x, 1);
153       break;
154     case SMAX:
155       fun = "smax";
156       op[0] = XEXP (x, 0);
157       op[1] = XEXP (x, 1);
158       break;
159     case UMIN:
160       fun = "umin";
161       op[0] = XEXP (x, 0);
162       op[1] = XEXP (x, 1);
163       break;
164     case UMAX:
165       fun = "umax";
166       op[0] = XEXP (x, 0);
167       op[1] = XEXP (x, 1);
168       break;
169     case NOT:
170       st[0] = "!";
171       op[0] = XEXP (x, 0);
172       break;
173     case AND:
174       op[0] = XEXP (x, 0);
175       st[1] = "&";
176       op[1] = XEXP (x, 1);
177       break;
178     case IOR:
179       op[0] = XEXP (x, 0);
180       st[1] = "|";
181       op[1] = XEXP (x, 1);
182       break;
183     case XOR:
184       op[0] = XEXP (x, 0);
185       st[1] = "^";
186       op[1] = XEXP (x, 1);
187       break;
188     case ASHIFT:
189       op[0] = XEXP (x, 0);
190       st[1] = "<<";
191       op[1] = XEXP (x, 1);
192       break;
193     case LSHIFTRT:
194       op[0] = XEXP (x, 0);
195       st[1] = " 0>>";
196       op[1] = XEXP (x, 1);
197       break;
198     case ASHIFTRT:
199       op[0] = XEXP (x, 0);
200       st[1] = ">>";
201       op[1] = XEXP (x, 1);
202       break;
203     case ROTATE:
204       op[0] = XEXP (x, 0);
205       st[1] = "<-<";
206       op[1] = XEXP (x, 1);
207       break;
208     case ROTATERT:
209       op[0] = XEXP (x, 0);
210       st[1] = ">->";
211       op[1] = XEXP (x, 1);
212       break;
213     case ABS:
214       fun = "abs";
215       op[0] = XEXP (x, 0);
216       break;
217     case SQRT:
218       fun = "sqrt";
219       op[0] = XEXP (x, 0);
220       break;
221     case FFS:
222       fun = "ffs";
223       op[0] = XEXP (x, 0);
224       break;
225     case EQ:
226       op[0] = XEXP (x, 0);
227       st[1] = "==";
228       op[1] = XEXP (x, 1);
229       break;
230     case NE:
231       op[0] = XEXP (x, 0);
232       st[1] = "!=";
233       op[1] = XEXP (x, 1);
234       break;
235     case GT:
236       op[0] = XEXP (x, 0);
237       st[1] = ">";
238       op[1] = XEXP (x, 1);
239       break;
240     case GTU:
241       fun = "gtu";
242       op[0] = XEXP (x, 0);
243       op[1] = XEXP (x, 1);
244       break;
245     case LT:
246       op[0] = XEXP (x, 0);
247       st[1] = "<";
248       op[1] = XEXP (x, 1);
249       break;
250     case LTU:
251       fun = "ltu";
252       op[0] = XEXP (x, 0);
253       op[1] = XEXP (x, 1);
254       break;
255     case GE:
256       op[0] = XEXP (x, 0);
257       st[1] = ">=";
258       op[1] = XEXP (x, 1);
259       break;
260     case GEU:
261       fun = "geu";
262       op[0] = XEXP (x, 0);
263       op[1] = XEXP (x, 1);
264       break;
265     case LE:
266       op[0] = XEXP (x, 0);
267       st[1] = "<=";
268       op[1] = XEXP (x, 1);
269       break;
270     case LEU:
271       fun = "leu";
272       op[0] = XEXP (x, 0);
273       op[1] = XEXP (x, 1);
274       break;
275     case SIGN_EXTRACT:
276       fun = (verbose) ? "sign_extract" : "sxt";
277       op[0] = XEXP (x, 0);
278       op[1] = XEXP (x, 1);
279       op[2] = XEXP (x, 2);
280       break;
281     case ZERO_EXTRACT:
282       fun = (verbose) ? "zero_extract" : "zxt";
283       op[0] = XEXP (x, 0);
284       op[1] = XEXP (x, 1);
285       op[2] = XEXP (x, 2);
286       break;
287     case SIGN_EXTEND:
288       fun = (verbose) ? "sign_extend" : "sxn";
289       op[0] = XEXP (x, 0);
290       break;
291     case ZERO_EXTEND:
292       fun = (verbose) ? "zero_extend" : "zxn";
293       op[0] = XEXP (x, 0);
294       break;
295     case FLOAT_EXTEND:
296       fun = (verbose) ? "float_extend" : "fxn";
297       op[0] = XEXP (x, 0);
298       break;
299     case TRUNCATE:
300       fun = (verbose) ? "trunc" : "trn";
301       op[0] = XEXP (x, 0);
302       break;
303     case FLOAT_TRUNCATE:
304       fun = (verbose) ? "float_trunc" : "ftr";
305       op[0] = XEXP (x, 0);
306       break;
307     case FLOAT:
308       fun = (verbose) ? "float" : "flt";
309       op[0] = XEXP (x, 0);
310       break;
311     case UNSIGNED_FLOAT:
312       fun = (verbose) ? "uns_float" : "ufl";
313       op[0] = XEXP (x, 0);
314       break;
315     case FIX:
316       fun = "fix";
317       op[0] = XEXP (x, 0);
318       break;
319     case UNSIGNED_FIX:
320       fun = (verbose) ? "uns_fix" : "ufx";
321       op[0] = XEXP (x, 0);
322       break;
323     case PRE_DEC:
324       st[0] = "--";
325       op[0] = XEXP (x, 0);
326       break;
327     case PRE_INC:
328       st[0] = "++";
329       op[0] = XEXP (x, 0);
330       break;
331     case POST_DEC:
332       op[0] = XEXP (x, 0);
333       st[1] = "--";
334       break;
335     case POST_INC:
336       op[0] = XEXP (x, 0);
337       st[1] = "++";
338       break;
339     case CALL:
340       st[0] = "call ";
341       op[0] = XEXP (x, 0);
342       if (verbose)
343         {
344           st[1] = " argc:";
345           op[1] = XEXP (x, 1);
346         }
347       break;
348     case IF_THEN_ELSE:
349       st[0] = "{(";
350       op[0] = XEXP (x, 0);
351       st[1] = ")?";
352       op[1] = XEXP (x, 1);
353       st[2] = ":";
354       op[2] = XEXP (x, 2);
355       st[3] = "}";
356       break;
357     case TRAP_IF:
358       fun = "trap_if";
359       op[0] = TRAP_CONDITION (x);
360       break;
361     case PREFETCH:
362       fun = "prefetch";
363       op[0] = XEXP (x, 0);
364       op[1] = XEXP (x, 1);
365       op[2] = XEXP (x, 2);
366       break;
367     case UNSPEC:
368     case UNSPEC_VOLATILE:
369       {
370         cur = safe_concat (buf, cur, "unspec");
371         if (GET_CODE (x) == UNSPEC_VOLATILE)
372           cur = safe_concat (buf, cur, "/v");
373         cur = safe_concat (buf, cur, "[");
374         sep = "";
375         for (i = 0; i < XVECLEN (x, 0); i++)
376           {
377             print_pattern (tmp, XVECEXP (x, 0, i), verbose);
378             cur = safe_concat (buf, cur, sep);
379             cur = safe_concat (buf, cur, tmp);
380             sep = ",";
381           }
382         cur = safe_concat (buf, cur, "] ");
383         sprintf (tmp, "%d", XINT (x, 1));
384         cur = safe_concat (buf, cur, tmp);
385       }
386       break;
387     default:
388       /* If (verbose) debug_rtx (x);  */
389       st[0] = GET_RTX_NAME (GET_CODE (x));
390       break;
391     }
392
393   /* Print this as a function?  */
394   if (fun)
395     {
396       cur = safe_concat (buf, cur, fun);
397       cur = safe_concat (buf, cur, "(");
398     }
399
400   for (i = 0; i < 4; i++)
401     {
402       if (st[i])
403         cur = safe_concat (buf, cur, st[i]);
404
405       if (op[i])
406         {
407           if (fun && i != 0)
408             cur = safe_concat (buf, cur, ",");
409
410           print_value (tmp, op[i], verbose);
411           cur = safe_concat (buf, cur, tmp);
412         }
413     }
414
415   if (fun)
416     cur = safe_concat (buf, cur, ")");
417 }               /* print_exp */
418
419 /* Prints rtxes, I customarily classified as values.  They're constants,
420    registers, labels, symbols and memory accesses.  */
421
422 static void
423 print_value (char *buf, rtx x, int verbose)
424 {
425   char t[BUF_LEN];
426   char *cur = buf;
427
428   switch (GET_CODE (x))
429     {
430     case CONST_INT:
431       sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
432       cur = safe_concat (buf, cur, t);
433       break;
434     case CONST_DOUBLE:
435       if (FLOAT_MODE_P (GET_MODE (x)))
436         real_to_decimal (t, CONST_DOUBLE_REAL_VALUE (x), sizeof (t), 0, 1);
437       else
438         sprintf (t, "<0x%lx,0x%lx>", (long) CONST_DOUBLE_LOW (x), (long) CONST_DOUBLE_HIGH (x));
439       cur = safe_concat (buf, cur, t);
440       break;
441     case CONST_STRING:
442       cur = safe_concat (buf, cur, "\"");
443       cur = safe_concat (buf, cur, XSTR (x, 0));
444       cur = safe_concat (buf, cur, "\"");
445       break;
446     case SYMBOL_REF:
447       cur = safe_concat (buf, cur, "`");
448       cur = safe_concat (buf, cur, XSTR (x, 0));
449       cur = safe_concat (buf, cur, "'");
450       break;
451     case LABEL_REF:
452       sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
453       cur = safe_concat (buf, cur, t);
454       break;
455     case CONST:
456       print_value (t, XEXP (x, 0), verbose);
457       cur = safe_concat (buf, cur, "const(");
458       cur = safe_concat (buf, cur, t);
459       cur = safe_concat (buf, cur, ")");
460       break;
461     case HIGH:
462       print_value (t, XEXP (x, 0), verbose);
463       cur = safe_concat (buf, cur, "high(");
464       cur = safe_concat (buf, cur, t);
465       cur = safe_concat (buf, cur, ")");
466       break;
467     case REG:
468       if (REGNO (x) < FIRST_PSEUDO_REGISTER)
469         {
470           int c = reg_names[REGNO (x)][0];
471           if (ISDIGIT (c))
472             cur = safe_concat (buf, cur, "%");
473
474           cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
475         }
476       else
477         {
478           sprintf (t, "r%d", REGNO (x));
479           cur = safe_concat (buf, cur, t);
480         }
481       break;
482     case SUBREG:
483       print_value (t, SUBREG_REG (x), verbose);
484       cur = safe_concat (buf, cur, t);
485       sprintf (t, "#%d", SUBREG_BYTE (x));
486       cur = safe_concat (buf, cur, t);
487       break;
488     case SCRATCH:
489       cur = safe_concat (buf, cur, "scratch");
490       break;
491     case CC0:
492       cur = safe_concat (buf, cur, "cc0");
493       break;
494     case PC:
495       cur = safe_concat (buf, cur, "pc");
496       break;
497     case MEM:
498       print_value (t, XEXP (x, 0), verbose);
499       cur = safe_concat (buf, cur, "[");
500       cur = safe_concat (buf, cur, t);
501       cur = safe_concat (buf, cur, "]");
502       break;
503     default:
504       print_exp (t, x, verbose);
505       cur = safe_concat (buf, cur, t);
506       break;
507     }
508 }                               /* print_value */
509
510 /* The next step in insn detalization, its pattern recognition.  */
511
512 static void
513 print_pattern (char *buf, rtx x, int verbose)
514 {
515   char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
516
517   switch (GET_CODE (x))
518     {
519     case SET:
520       print_value (t1, SET_DEST (x), verbose);
521       print_value (t2, SET_SRC (x), verbose);
522       sprintf (buf, "%s=%s", t1, t2);
523       break;
524     case RETURN:
525       sprintf (buf, "return");
526       break;
527     case CALL:
528       print_exp (buf, x, verbose);
529       break;
530     case CLOBBER:
531       print_value (t1, XEXP (x, 0), verbose);
532       sprintf (buf, "clobber %s", t1);
533       break;
534     case USE:
535       print_value (t1, XEXP (x, 0), verbose);
536       sprintf (buf, "use %s", t1);
537       break;
538     case COND_EXEC:
539       if (GET_CODE (COND_EXEC_TEST (x)) == NE
540           && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
541         print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
542       else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
543                && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
544         {
545           t1[0] = '!';
546           print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
547         }
548       else
549         print_value (t1, COND_EXEC_TEST (x), verbose);
550       print_pattern (t2, COND_EXEC_CODE (x), verbose);
551       sprintf (buf, "(%s) %s", t1, t2);
552       break;
553     case PARALLEL:
554       {
555         int i;
556
557         sprintf (t1, "{");
558         for (i = 0; i < XVECLEN (x, 0); i++)
559           {
560             print_pattern (t2, XVECEXP (x, 0, i), verbose);
561             sprintf (t3, "%s%s;", t1, t2);
562             strcpy (t1, t3);
563           }
564         sprintf (buf, "%s}", t1);
565       }
566       break;
567     case SEQUENCE:
568       /* Should never see SEQUENCE codes until after reorg.  */
569       gcc_unreachable ();
570     case ASM_INPUT:
571       sprintf (buf, "asm {%s}", XSTR (x, 0));
572       break;
573     case ADDR_VEC:
574       break;
575     case ADDR_DIFF_VEC:
576       print_value (buf, XEXP (x, 0), verbose);
577       break;
578     case TRAP_IF:
579       print_value (t1, TRAP_CONDITION (x), verbose);
580       sprintf (buf, "trap_if %s", t1);
581       break;
582     case UNSPEC:
583       {
584         int i;
585
586         sprintf (t1, "unspec{");
587         for (i = 0; i < XVECLEN (x, 0); i++)
588           {
589             print_pattern (t2, XVECEXP (x, 0, i), verbose);
590             sprintf (t3, "%s%s;", t1, t2);
591             strcpy (t1, t3);
592           }
593         sprintf (buf, "%s}", t1);
594       }
595       break;
596     case UNSPEC_VOLATILE:
597       {
598         int i;
599
600         sprintf (t1, "unspec/v{");
601         for (i = 0; i < XVECLEN (x, 0); i++)
602           {
603             print_pattern (t2, XVECEXP (x, 0, i), verbose);
604             sprintf (t3, "%s%s;", t1, t2);
605             strcpy (t1, t3);
606           }
607         sprintf (buf, "%s}", t1);
608       }
609       break;
610     default:
611       print_value (buf, x, verbose);
612     }
613 }                               /* print_pattern */
614
615 /* This is the main function in rtl visualization mechanism. It
616    accepts an rtx and tries to recognize it as an insn, then prints it
617    properly in human readable form, resembling assembler mnemonics.
618    For every insn it prints its UID and BB the insn belongs too.
619    (Probably the last "option" should be extended somehow, since it
620    depends now on sched.c inner variables ...)  */
621
622 void
623 print_insn (char *buf, rtx x, int verbose)
624 {
625   char t[BUF_LEN];
626   rtx insn = x;
627
628   switch (GET_CODE (x))
629     {
630     case INSN:
631       print_pattern (t, PATTERN (x), verbose);
632       if (verbose)
633         sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
634                  t);
635       else
636         sprintf (buf, "%-4d %s", INSN_UID (x), t);
637       break;
638     case JUMP_INSN:
639       print_pattern (t, PATTERN (x), verbose);
640       if (verbose)
641         sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
642                  t);
643       else
644         sprintf (buf, "%-4d %s", INSN_UID (x), t);
645       break;
646     case CALL_INSN:
647       x = PATTERN (insn);
648       if (GET_CODE (x) == PARALLEL)
649         {
650           x = XVECEXP (x, 0, 0);
651           print_pattern (t, x, verbose);
652         }
653       else
654         strcpy (t, "call <...>");
655       if (verbose)
656         sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
657       else
658         sprintf (buf, "%-4d %s", INSN_UID (insn), t);
659       break;
660     case CODE_LABEL:
661       sprintf (buf, "L%d:", INSN_UID (x));
662       break;
663     case BARRIER:
664       sprintf (buf, "i% 4d: barrier", INSN_UID (x));
665       break;
666     case NOTE:
667       if (NOTE_LINE_NUMBER (x) > 0)
668         {
669           expanded_location xloc;
670           NOTE_EXPANDED_LOCATION (xloc, x);
671           sprintf (buf, "%4d note \"%s\" %d", INSN_UID (x),
672                    xloc.file, xloc.line);
673         }
674       else
675         sprintf (buf, "%4d %s", INSN_UID (x),
676                  GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x)));
677       break;
678     default:
679       if (verbose)
680         {
681           sprintf (buf, "Not an INSN at all\n");
682           debug_rtx (x);
683         }
684       else
685         sprintf (buf, "i%-4d  <What?>", INSN_UID (x));
686     }
687 }                               /* print_insn */
688
689 #endif