190075Sobrien/* Instruction scheduling pass.
290075Sobrien   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3169689Skan   1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
490075Sobrien   Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
590075Sobrien   and currently maintained by, Jim Wilson (wilson@cygnus.com)
690075Sobrien
790075SobrienThis file is part of GCC.
890075Sobrien
990075SobrienGCC is free software; you can redistribute it and/or modify it under
1090075Sobrienthe terms of the GNU General Public License as published by the Free
1190075SobrienSoftware Foundation; either version 2, or (at your option) any later
1290075Sobrienversion.
1390075Sobrien
1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1690075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1790075Sobrienfor more details.
1890075Sobrien
1990075SobrienYou should have received a copy of the GNU General Public License
2090075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
21169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22169689Skan02110-1301, USA.  */
2390075Sobrien
2490075Sobrien#include "config.h"
2590075Sobrien#include "system.h"
26132718Skan#include "coretypes.h"
27132718Skan#include "tm.h"
2890075Sobrien#include "rtl.h"
29169689Skan#include "obstack.h"
3090075Sobrien#include "hard-reg-set.h"
3190075Sobrien#include "basic-block.h"
32117395Skan#include "real.h"
3390075Sobrien#include "sched-int.h"
34169689Skan#include "tree-pass.h"
3590075Sobrien
36132718Skanstatic char *safe_concat (char *, char *, const char *);
37132718Skanstatic void print_exp (char *, rtx, int);
38132718Skanstatic void print_value (char *, rtx, int);
39132718Skanstatic void print_pattern (char *, rtx, int);
4090075Sobrien
4190075Sobrien#define BUF_LEN 2048
4290075Sobrien
4390075Sobrienstatic char *
44132718Skansafe_concat (char *buf, char *cur, const char *str)
4590075Sobrien{
4690075Sobrien  char *end = buf + BUF_LEN - 2;	/* Leave room for null.  */
4790075Sobrien  int c;
4890075Sobrien
4990075Sobrien  if (cur > end)
5090075Sobrien    {
5190075Sobrien      *end = '\0';
5290075Sobrien      return end;
5390075Sobrien    }
5490075Sobrien
5590075Sobrien  while (cur < end && (c = *str++) != '\0')
5690075Sobrien    *cur++ = c;
5790075Sobrien
5890075Sobrien  *cur = '\0';
5990075Sobrien  return cur;
6090075Sobrien}
6190075Sobrien
6290075Sobrien/* This recognizes rtx, I classified as expressions.  These are always
6390075Sobrien   represent some action on values or results of other expression, that
6490075Sobrien   may be stored in objects representing values.  */
6590075Sobrien
6690075Sobrienstatic void
67132718Skanprint_exp (char *buf, rtx x, int verbose)
6890075Sobrien{
6990075Sobrien  char tmp[BUF_LEN];
7090075Sobrien  const char *st[4];
7190075Sobrien  char *cur = buf;
7290075Sobrien  const char *fun = (char *) 0;
7390075Sobrien  const char *sep;
7490075Sobrien  rtx op[4];
7590075Sobrien  int i;
7690075Sobrien
7790075Sobrien  for (i = 0; i < 4; i++)
7890075Sobrien    {
7990075Sobrien      st[i] = (char *) 0;
8090075Sobrien      op[i] = NULL_RTX;
8190075Sobrien    }
8290075Sobrien
8390075Sobrien  switch (GET_CODE (x))
8490075Sobrien    {
8590075Sobrien    case PLUS:
8690075Sobrien      op[0] = XEXP (x, 0);
8790075Sobrien      if (GET_CODE (XEXP (x, 1)) == CONST_INT
8890075Sobrien	  && INTVAL (XEXP (x, 1)) < 0)
8990075Sobrien	{
9090075Sobrien	  st[1] = "-";
9190075Sobrien	  op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
9290075Sobrien	}
9390075Sobrien      else
9490075Sobrien	{
9590075Sobrien	  st[1] = "+";
9690075Sobrien	  op[1] = XEXP (x, 1);
9790075Sobrien	}
9890075Sobrien      break;
9990075Sobrien    case LO_SUM:
10090075Sobrien      op[0] = XEXP (x, 0);
10190075Sobrien      st[1] = "+low(";
10290075Sobrien      op[1] = XEXP (x, 1);
10390075Sobrien      st[2] = ")";
10490075Sobrien      break;
10590075Sobrien    case MINUS:
10690075Sobrien      op[0] = XEXP (x, 0);
10790075Sobrien      st[1] = "-";
10890075Sobrien      op[1] = XEXP (x, 1);
10990075Sobrien      break;
11090075Sobrien    case COMPARE:
11190075Sobrien      fun = "cmp";
11290075Sobrien      op[0] = XEXP (x, 0);
11390075Sobrien      op[1] = XEXP (x, 1);
11490075Sobrien      break;
11590075Sobrien    case NEG:
11690075Sobrien      st[0] = "-";
11790075Sobrien      op[0] = XEXP (x, 0);
11890075Sobrien      break;
11990075Sobrien    case MULT:
12090075Sobrien      op[0] = XEXP (x, 0);
12190075Sobrien      st[1] = "*";
12290075Sobrien      op[1] = XEXP (x, 1);
12390075Sobrien      break;
12490075Sobrien    case DIV:
12590075Sobrien      op[0] = XEXP (x, 0);
12690075Sobrien      st[1] = "/";
12790075Sobrien      op[1] = XEXP (x, 1);
12890075Sobrien      break;
12990075Sobrien    case UDIV:
13090075Sobrien      fun = "udiv";
13190075Sobrien      op[0] = XEXP (x, 0);
13290075Sobrien      op[1] = XEXP (x, 1);
13390075Sobrien      break;
13490075Sobrien    case MOD:
13590075Sobrien      op[0] = XEXP (x, 0);
13690075Sobrien      st[1] = "%";
13790075Sobrien      op[1] = XEXP (x, 1);
13890075Sobrien      break;
13990075Sobrien    case UMOD:
14090075Sobrien      fun = "umod";
14190075Sobrien      op[0] = XEXP (x, 0);
14290075Sobrien      op[1] = XEXP (x, 1);
14390075Sobrien      break;
14490075Sobrien    case SMIN:
14590075Sobrien      fun = "smin";
14690075Sobrien      op[0] = XEXP (x, 0);
14790075Sobrien      op[1] = XEXP (x, 1);
14890075Sobrien      break;
14990075Sobrien    case SMAX:
15090075Sobrien      fun = "smax";
15190075Sobrien      op[0] = XEXP (x, 0);
15290075Sobrien      op[1] = XEXP (x, 1);
15390075Sobrien      break;
15490075Sobrien    case UMIN:
15590075Sobrien      fun = "umin";
15690075Sobrien      op[0] = XEXP (x, 0);
15790075Sobrien      op[1] = XEXP (x, 1);
15890075Sobrien      break;
15990075Sobrien    case UMAX:
16090075Sobrien      fun = "umax";
16190075Sobrien      op[0] = XEXP (x, 0);
16290075Sobrien      op[1] = XEXP (x, 1);
16390075Sobrien      break;
16490075Sobrien    case NOT:
16590075Sobrien      st[0] = "!";
16690075Sobrien      op[0] = XEXP (x, 0);
16790075Sobrien      break;
16890075Sobrien    case AND:
16990075Sobrien      op[0] = XEXP (x, 0);
17090075Sobrien      st[1] = "&";
17190075Sobrien      op[1] = XEXP (x, 1);
17290075Sobrien      break;
17390075Sobrien    case IOR:
17490075Sobrien      op[0] = XEXP (x, 0);
17590075Sobrien      st[1] = "|";
17690075Sobrien      op[1] = XEXP (x, 1);
17790075Sobrien      break;
17890075Sobrien    case XOR:
17990075Sobrien      op[0] = XEXP (x, 0);
18090075Sobrien      st[1] = "^";
18190075Sobrien      op[1] = XEXP (x, 1);
18290075Sobrien      break;
18390075Sobrien    case ASHIFT:
18490075Sobrien      op[0] = XEXP (x, 0);
18590075Sobrien      st[1] = "<<";
18690075Sobrien      op[1] = XEXP (x, 1);
18790075Sobrien      break;
18890075Sobrien    case LSHIFTRT:
18990075Sobrien      op[0] = XEXP (x, 0);
19090075Sobrien      st[1] = " 0>>";
19190075Sobrien      op[1] = XEXP (x, 1);
19290075Sobrien      break;
19390075Sobrien    case ASHIFTRT:
19490075Sobrien      op[0] = XEXP (x, 0);
19590075Sobrien      st[1] = ">>";
19690075Sobrien      op[1] = XEXP (x, 1);
19790075Sobrien      break;
19890075Sobrien    case ROTATE:
19990075Sobrien      op[0] = XEXP (x, 0);
20090075Sobrien      st[1] = "<-<";
20190075Sobrien      op[1] = XEXP (x, 1);
20290075Sobrien      break;
20390075Sobrien    case ROTATERT:
20490075Sobrien      op[0] = XEXP (x, 0);
20590075Sobrien      st[1] = ">->";
20690075Sobrien      op[1] = XEXP (x, 1);
20790075Sobrien      break;
20890075Sobrien    case ABS:
20990075Sobrien      fun = "abs";
21090075Sobrien      op[0] = XEXP (x, 0);
21190075Sobrien      break;
21290075Sobrien    case SQRT:
21390075Sobrien      fun = "sqrt";
21490075Sobrien      op[0] = XEXP (x, 0);
21590075Sobrien      break;
21690075Sobrien    case FFS:
21790075Sobrien      fun = "ffs";
21890075Sobrien      op[0] = XEXP (x, 0);
21990075Sobrien      break;
22090075Sobrien    case EQ:
22190075Sobrien      op[0] = XEXP (x, 0);
22290075Sobrien      st[1] = "==";
22390075Sobrien      op[1] = XEXP (x, 1);
22490075Sobrien      break;
22590075Sobrien    case NE:
22690075Sobrien      op[0] = XEXP (x, 0);
22790075Sobrien      st[1] = "!=";
22890075Sobrien      op[1] = XEXP (x, 1);
22990075Sobrien      break;
23090075Sobrien    case GT:
23190075Sobrien      op[0] = XEXP (x, 0);
23290075Sobrien      st[1] = ">";
23390075Sobrien      op[1] = XEXP (x, 1);
23490075Sobrien      break;
23590075Sobrien    case GTU:
23690075Sobrien      fun = "gtu";
23790075Sobrien      op[0] = XEXP (x, 0);
23890075Sobrien      op[1] = XEXP (x, 1);
23990075Sobrien      break;
24090075Sobrien    case LT:
24190075Sobrien      op[0] = XEXP (x, 0);
24290075Sobrien      st[1] = "<";
24390075Sobrien      op[1] = XEXP (x, 1);
24490075Sobrien      break;
24590075Sobrien    case LTU:
24690075Sobrien      fun = "ltu";
24790075Sobrien      op[0] = XEXP (x, 0);
24890075Sobrien      op[1] = XEXP (x, 1);
24990075Sobrien      break;
25090075Sobrien    case GE:
25190075Sobrien      op[0] = XEXP (x, 0);
25290075Sobrien      st[1] = ">=";
25390075Sobrien      op[1] = XEXP (x, 1);
25490075Sobrien      break;
25590075Sobrien    case GEU:
25690075Sobrien      fun = "geu";
25790075Sobrien      op[0] = XEXP (x, 0);
25890075Sobrien      op[1] = XEXP (x, 1);
25990075Sobrien      break;
26090075Sobrien    case LE:
26190075Sobrien      op[0] = XEXP (x, 0);
26290075Sobrien      st[1] = "<=";
26390075Sobrien      op[1] = XEXP (x, 1);
26490075Sobrien      break;
26590075Sobrien    case LEU:
26690075Sobrien      fun = "leu";
26790075Sobrien      op[0] = XEXP (x, 0);
26890075Sobrien      op[1] = XEXP (x, 1);
26990075Sobrien      break;
27090075Sobrien    case SIGN_EXTRACT:
27190075Sobrien      fun = (verbose) ? "sign_extract" : "sxt";
27290075Sobrien      op[0] = XEXP (x, 0);
27390075Sobrien      op[1] = XEXP (x, 1);
27490075Sobrien      op[2] = XEXP (x, 2);
27590075Sobrien      break;
27690075Sobrien    case ZERO_EXTRACT:
27790075Sobrien      fun = (verbose) ? "zero_extract" : "zxt";
27890075Sobrien      op[0] = XEXP (x, 0);
27990075Sobrien      op[1] = XEXP (x, 1);
28090075Sobrien      op[2] = XEXP (x, 2);
28190075Sobrien      break;
28290075Sobrien    case SIGN_EXTEND:
28390075Sobrien      fun = (verbose) ? "sign_extend" : "sxn";
28490075Sobrien      op[0] = XEXP (x, 0);
28590075Sobrien      break;
28690075Sobrien    case ZERO_EXTEND:
28790075Sobrien      fun = (verbose) ? "zero_extend" : "zxn";
28890075Sobrien      op[0] = XEXP (x, 0);
28990075Sobrien      break;
29090075Sobrien    case FLOAT_EXTEND:
29190075Sobrien      fun = (verbose) ? "float_extend" : "fxn";
29290075Sobrien      op[0] = XEXP (x, 0);
29390075Sobrien      break;
29490075Sobrien    case TRUNCATE:
29590075Sobrien      fun = (verbose) ? "trunc" : "trn";
29690075Sobrien      op[0] = XEXP (x, 0);
29790075Sobrien      break;
29890075Sobrien    case FLOAT_TRUNCATE:
29990075Sobrien      fun = (verbose) ? "float_trunc" : "ftr";
30090075Sobrien      op[0] = XEXP (x, 0);
30190075Sobrien      break;
30290075Sobrien    case FLOAT:
30390075Sobrien      fun = (verbose) ? "float" : "flt";
30490075Sobrien      op[0] = XEXP (x, 0);
30590075Sobrien      break;
30690075Sobrien    case UNSIGNED_FLOAT:
30790075Sobrien      fun = (verbose) ? "uns_float" : "ufl";
30890075Sobrien      op[0] = XEXP (x, 0);
30990075Sobrien      break;
31090075Sobrien    case FIX:
31190075Sobrien      fun = "fix";
31290075Sobrien      op[0] = XEXP (x, 0);
31390075Sobrien      break;
31490075Sobrien    case UNSIGNED_FIX:
31590075Sobrien      fun = (verbose) ? "uns_fix" : "ufx";
31690075Sobrien      op[0] = XEXP (x, 0);
31790075Sobrien      break;
31890075Sobrien    case PRE_DEC:
31990075Sobrien      st[0] = "--";
32090075Sobrien      op[0] = XEXP (x, 0);
32190075Sobrien      break;
32290075Sobrien    case PRE_INC:
32390075Sobrien      st[0] = "++";
32490075Sobrien      op[0] = XEXP (x, 0);
32590075Sobrien      break;
32690075Sobrien    case POST_DEC:
32790075Sobrien      op[0] = XEXP (x, 0);
32890075Sobrien      st[1] = "--";
32990075Sobrien      break;
33090075Sobrien    case POST_INC:
33190075Sobrien      op[0] = XEXP (x, 0);
33290075Sobrien      st[1] = "++";
33390075Sobrien      break;
33490075Sobrien    case CALL:
33590075Sobrien      st[0] = "call ";
33690075Sobrien      op[0] = XEXP (x, 0);
33790075Sobrien      if (verbose)
33890075Sobrien	{
33990075Sobrien	  st[1] = " argc:";
34090075Sobrien	  op[1] = XEXP (x, 1);
34190075Sobrien	}
34290075Sobrien      break;
34390075Sobrien    case IF_THEN_ELSE:
34490075Sobrien      st[0] = "{(";
34590075Sobrien      op[0] = XEXP (x, 0);
34690075Sobrien      st[1] = ")?";
34790075Sobrien      op[1] = XEXP (x, 1);
34890075Sobrien      st[2] = ":";
34990075Sobrien      op[2] = XEXP (x, 2);
35090075Sobrien      st[3] = "}";
35190075Sobrien      break;
35290075Sobrien    case TRAP_IF:
35390075Sobrien      fun = "trap_if";
35490075Sobrien      op[0] = TRAP_CONDITION (x);
35590075Sobrien      break;
35690075Sobrien    case PREFETCH:
35790075Sobrien      fun = "prefetch";
35890075Sobrien      op[0] = XEXP (x, 0);
35990075Sobrien      op[1] = XEXP (x, 1);
36090075Sobrien      op[2] = XEXP (x, 2);
36190075Sobrien      break;
36290075Sobrien    case UNSPEC:
36390075Sobrien    case UNSPEC_VOLATILE:
36490075Sobrien      {
36590075Sobrien	cur = safe_concat (buf, cur, "unspec");
36690075Sobrien	if (GET_CODE (x) == UNSPEC_VOLATILE)
36790075Sobrien	  cur = safe_concat (buf, cur, "/v");
36890075Sobrien	cur = safe_concat (buf, cur, "[");
36990075Sobrien	sep = "";
37090075Sobrien	for (i = 0; i < XVECLEN (x, 0); i++)
37190075Sobrien	  {
37290075Sobrien	    print_pattern (tmp, XVECEXP (x, 0, i), verbose);
37390075Sobrien	    cur = safe_concat (buf, cur, sep);
37490075Sobrien	    cur = safe_concat (buf, cur, tmp);
37590075Sobrien	    sep = ",";
37690075Sobrien	  }
37790075Sobrien	cur = safe_concat (buf, cur, "] ");
37890075Sobrien	sprintf (tmp, "%d", XINT (x, 1));
37990075Sobrien	cur = safe_concat (buf, cur, tmp);
38090075Sobrien      }
38190075Sobrien      break;
38290075Sobrien    default:
38390075Sobrien      /* If (verbose) debug_rtx (x);  */
38490075Sobrien      st[0] = GET_RTX_NAME (GET_CODE (x));
38590075Sobrien      break;
38690075Sobrien    }
38790075Sobrien
38890075Sobrien  /* Print this as a function?  */
38990075Sobrien  if (fun)
39090075Sobrien    {
39190075Sobrien      cur = safe_concat (buf, cur, fun);
39290075Sobrien      cur = safe_concat (buf, cur, "(");
39390075Sobrien    }
39490075Sobrien
39590075Sobrien  for (i = 0; i < 4; i++)
39690075Sobrien    {
39790075Sobrien      if (st[i])
39890075Sobrien	cur = safe_concat (buf, cur, st[i]);
39990075Sobrien
40090075Sobrien      if (op[i])
40190075Sobrien	{
40290075Sobrien	  if (fun && i != 0)
40390075Sobrien	    cur = safe_concat (buf, cur, ",");
40490075Sobrien
40590075Sobrien	  print_value (tmp, op[i], verbose);
40690075Sobrien	  cur = safe_concat (buf, cur, tmp);
40790075Sobrien	}
40890075Sobrien    }
40990075Sobrien
41090075Sobrien  if (fun)
41190075Sobrien    cur = safe_concat (buf, cur, ")");
41290075Sobrien}		/* print_exp */
41390075Sobrien
414132718Skan/* Prints rtxes, I customarily classified as values.  They're constants,
41590075Sobrien   registers, labels, symbols and memory accesses.  */
41690075Sobrien
41790075Sobrienstatic void
418132718Skanprint_value (char *buf, rtx x, int verbose)
41990075Sobrien{
42090075Sobrien  char t[BUF_LEN];
42190075Sobrien  char *cur = buf;
42290075Sobrien
42390075Sobrien  switch (GET_CODE (x))
42490075Sobrien    {
42590075Sobrien    case CONST_INT:
42690075Sobrien      sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
42790075Sobrien      cur = safe_concat (buf, cur, t);
42890075Sobrien      break;
42990075Sobrien    case CONST_DOUBLE:
430117395Skan      if (FLOAT_MODE_P (GET_MODE (x)))
431117395Skan	real_to_decimal (t, CONST_DOUBLE_REAL_VALUE (x), sizeof (t), 0, 1);
432117395Skan      else
433259947Spfg	sprintf (t,
434259947Spfg		 "<" HOST_WIDE_INT_PRINT_HEX "," HOST_WIDE_INT_PRINT_HEX ">",
435259947Spfg		 (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
436259947Spfg		 (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
43790075Sobrien      cur = safe_concat (buf, cur, t);
43890075Sobrien      break;
43990075Sobrien    case CONST_STRING:
44090075Sobrien      cur = safe_concat (buf, cur, "\"");
44190075Sobrien      cur = safe_concat (buf, cur, XSTR (x, 0));
44290075Sobrien      cur = safe_concat (buf, cur, "\"");
44390075Sobrien      break;
44490075Sobrien    case SYMBOL_REF:
44590075Sobrien      cur = safe_concat (buf, cur, "`");
44690075Sobrien      cur = safe_concat (buf, cur, XSTR (x, 0));
44790075Sobrien      cur = safe_concat (buf, cur, "'");
44890075Sobrien      break;
44990075Sobrien    case LABEL_REF:
45090075Sobrien      sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
45190075Sobrien      cur = safe_concat (buf, cur, t);
45290075Sobrien      break;
45390075Sobrien    case CONST:
45490075Sobrien      print_value (t, XEXP (x, 0), verbose);
45590075Sobrien      cur = safe_concat (buf, cur, "const(");
45690075Sobrien      cur = safe_concat (buf, cur, t);
45790075Sobrien      cur = safe_concat (buf, cur, ")");
45890075Sobrien      break;
45990075Sobrien    case HIGH:
46090075Sobrien      print_value (t, XEXP (x, 0), verbose);
46190075Sobrien      cur = safe_concat (buf, cur, "high(");
46290075Sobrien      cur = safe_concat (buf, cur, t);
46390075Sobrien      cur = safe_concat (buf, cur, ")");
46490075Sobrien      break;
46590075Sobrien    case REG:
46690075Sobrien      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
46790075Sobrien	{
46890075Sobrien	  int c = reg_names[REGNO (x)][0];
46990075Sobrien	  if (ISDIGIT (c))
47090075Sobrien	    cur = safe_concat (buf, cur, "%");
47190075Sobrien
47290075Sobrien	  cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
47390075Sobrien	}
47490075Sobrien      else
47590075Sobrien	{
47690075Sobrien	  sprintf (t, "r%d", REGNO (x));
47790075Sobrien	  cur = safe_concat (buf, cur, t);
47890075Sobrien	}
479169689Skan      if (verbose
480169689Skan#ifdef INSN_SCHEDULING
481169689Skan	  && !current_sched_info
482169689Skan#endif
483169689Skan	 )
484169689Skan	{
485169689Skan	  sprintf (t, ":%s", GET_MODE_NAME (GET_MODE (x)));
486169689Skan	  cur = safe_concat (buf, cur, t);
487169689Skan	}
48890075Sobrien      break;
48990075Sobrien    case SUBREG:
49090075Sobrien      print_value (t, SUBREG_REG (x), verbose);
49190075Sobrien      cur = safe_concat (buf, cur, t);
49290075Sobrien      sprintf (t, "#%d", SUBREG_BYTE (x));
49390075Sobrien      cur = safe_concat (buf, cur, t);
49490075Sobrien      break;
49590075Sobrien    case SCRATCH:
49690075Sobrien      cur = safe_concat (buf, cur, "scratch");
49790075Sobrien      break;
49890075Sobrien    case CC0:
49990075Sobrien      cur = safe_concat (buf, cur, "cc0");
50090075Sobrien      break;
50190075Sobrien    case PC:
50290075Sobrien      cur = safe_concat (buf, cur, "pc");
50390075Sobrien      break;
50490075Sobrien    case MEM:
50590075Sobrien      print_value (t, XEXP (x, 0), verbose);
50690075Sobrien      cur = safe_concat (buf, cur, "[");
50790075Sobrien      cur = safe_concat (buf, cur, t);
50890075Sobrien      cur = safe_concat (buf, cur, "]");
50990075Sobrien      break;
51090075Sobrien    default:
51190075Sobrien      print_exp (t, x, verbose);
51290075Sobrien      cur = safe_concat (buf, cur, t);
51390075Sobrien      break;
51490075Sobrien    }
51590075Sobrien}				/* print_value */
51690075Sobrien
51790075Sobrien/* The next step in insn detalization, its pattern recognition.  */
51890075Sobrien
51990075Sobrienstatic void
520132718Skanprint_pattern (char *buf, rtx x, int verbose)
52190075Sobrien{
52290075Sobrien  char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
52390075Sobrien
52490075Sobrien  switch (GET_CODE (x))
52590075Sobrien    {
52690075Sobrien    case SET:
52790075Sobrien      print_value (t1, SET_DEST (x), verbose);
52890075Sobrien      print_value (t2, SET_SRC (x), verbose);
52990075Sobrien      sprintf (buf, "%s=%s", t1, t2);
53090075Sobrien      break;
53190075Sobrien    case RETURN:
53290075Sobrien      sprintf (buf, "return");
53390075Sobrien      break;
53490075Sobrien    case CALL:
53590075Sobrien      print_exp (buf, x, verbose);
53690075Sobrien      break;
53790075Sobrien    case CLOBBER:
53890075Sobrien      print_value (t1, XEXP (x, 0), verbose);
53990075Sobrien      sprintf (buf, "clobber %s", t1);
54090075Sobrien      break;
54190075Sobrien    case USE:
54290075Sobrien      print_value (t1, XEXP (x, 0), verbose);
54390075Sobrien      sprintf (buf, "use %s", t1);
54490075Sobrien      break;
54590075Sobrien    case COND_EXEC:
54690075Sobrien      if (GET_CODE (COND_EXEC_TEST (x)) == NE
54790075Sobrien	  && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
54890075Sobrien	print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
54990075Sobrien      else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
550117395Skan	       && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
551117395Skan	{
55290075Sobrien	  t1[0] = '!';
55390075Sobrien	  print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
55490075Sobrien	}
55590075Sobrien      else
556117395Skan	print_value (t1, COND_EXEC_TEST (x), verbose);
55790075Sobrien      print_pattern (t2, COND_EXEC_CODE (x), verbose);
55890075Sobrien      sprintf (buf, "(%s) %s", t1, t2);
55990075Sobrien      break;
56090075Sobrien    case PARALLEL:
56190075Sobrien      {
56290075Sobrien	int i;
56390075Sobrien
56490075Sobrien	sprintf (t1, "{");
56590075Sobrien	for (i = 0; i < XVECLEN (x, 0); i++)
56690075Sobrien	  {
56790075Sobrien	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
56890075Sobrien	    sprintf (t3, "%s%s;", t1, t2);
56990075Sobrien	    strcpy (t1, t3);
57090075Sobrien	  }
57190075Sobrien	sprintf (buf, "%s}", t1);
57290075Sobrien      }
57390075Sobrien      break;
57490075Sobrien    case SEQUENCE:
575117395Skan      /* Should never see SEQUENCE codes until after reorg.  */
576169689Skan      gcc_unreachable ();
57790075Sobrien    case ASM_INPUT:
57890075Sobrien      sprintf (buf, "asm {%s}", XSTR (x, 0));
57990075Sobrien      break;
58090075Sobrien    case ADDR_VEC:
58190075Sobrien      break;
58290075Sobrien    case ADDR_DIFF_VEC:
58390075Sobrien      print_value (buf, XEXP (x, 0), verbose);
58490075Sobrien      break;
58590075Sobrien    case TRAP_IF:
58690075Sobrien      print_value (t1, TRAP_CONDITION (x), verbose);
58790075Sobrien      sprintf (buf, "trap_if %s", t1);
58890075Sobrien      break;
58990075Sobrien    case UNSPEC:
59090075Sobrien      {
59190075Sobrien	int i;
59290075Sobrien
59390075Sobrien	sprintf (t1, "unspec{");
59490075Sobrien	for (i = 0; i < XVECLEN (x, 0); i++)
59590075Sobrien	  {
59690075Sobrien	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
59790075Sobrien	    sprintf (t3, "%s%s;", t1, t2);
59890075Sobrien	    strcpy (t1, t3);
59990075Sobrien	  }
60090075Sobrien	sprintf (buf, "%s}", t1);
60190075Sobrien      }
60290075Sobrien      break;
60390075Sobrien    case UNSPEC_VOLATILE:
60490075Sobrien      {
60590075Sobrien	int i;
60690075Sobrien
60790075Sobrien	sprintf (t1, "unspec/v{");
60890075Sobrien	for (i = 0; i < XVECLEN (x, 0); i++)
60990075Sobrien	  {
61090075Sobrien	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
61190075Sobrien	    sprintf (t3, "%s%s;", t1, t2);
61290075Sobrien	    strcpy (t1, t3);
61390075Sobrien	  }
61490075Sobrien	sprintf (buf, "%s}", t1);
61590075Sobrien      }
61690075Sobrien      break;
61790075Sobrien    default:
61890075Sobrien      print_value (buf, x, verbose);
61990075Sobrien    }
62090075Sobrien}				/* print_pattern */
62190075Sobrien
62290075Sobrien/* This is the main function in rtl visualization mechanism. It
62390075Sobrien   accepts an rtx and tries to recognize it as an insn, then prints it
62490075Sobrien   properly in human readable form, resembling assembler mnemonics.
62590075Sobrien   For every insn it prints its UID and BB the insn belongs too.
62690075Sobrien   (Probably the last "option" should be extended somehow, since it
62790075Sobrien   depends now on sched.c inner variables ...)  */
62890075Sobrien
629117395Skanvoid
630132718Skanprint_insn (char *buf, rtx x, int verbose)
63190075Sobrien{
63290075Sobrien  char t[BUF_LEN];
63390075Sobrien  rtx insn = x;
63490075Sobrien
63590075Sobrien  switch (GET_CODE (x))
63690075Sobrien    {
63790075Sobrien    case INSN:
63890075Sobrien      print_pattern (t, PATTERN (x), verbose);
639169689Skan#ifdef INSN_SCHEDULING
640169689Skan      if (verbose && current_sched_info)
64190075Sobrien	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
64290075Sobrien		 t);
64390075Sobrien      else
644169689Skan#endif
645169689Skan	sprintf (buf, " %4d %s", INSN_UID (x), t);
64690075Sobrien      break;
64790075Sobrien    case JUMP_INSN:
64890075Sobrien      print_pattern (t, PATTERN (x), verbose);
649169689Skan#ifdef INSN_SCHEDULING
650169689Skan      if (verbose && current_sched_info)
65190075Sobrien	sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
65290075Sobrien		 t);
65390075Sobrien      else
654169689Skan#endif
655169689Skan	sprintf (buf, " %4d %s", INSN_UID (x), t);
65690075Sobrien      break;
65790075Sobrien    case CALL_INSN:
65890075Sobrien      x = PATTERN (insn);
65990075Sobrien      if (GET_CODE (x) == PARALLEL)
66090075Sobrien	{
66190075Sobrien	  x = XVECEXP (x, 0, 0);
66290075Sobrien	  print_pattern (t, x, verbose);
66390075Sobrien	}
66490075Sobrien      else
66590075Sobrien	strcpy (t, "call <...>");
666169689Skan#ifdef INSN_SCHEDULING
667169689Skan      if (verbose && current_sched_info)
66890075Sobrien	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
66990075Sobrien      else
670169689Skan#endif
671169689Skan	sprintf (buf, " %4d %s", INSN_UID (insn), t);
67290075Sobrien      break;
67390075Sobrien    case CODE_LABEL:
67490075Sobrien      sprintf (buf, "L%d:", INSN_UID (x));
67590075Sobrien      break;
67690075Sobrien    case BARRIER:
677169689Skan      sprintf (buf, "i%4d: barrier", INSN_UID (x));
67890075Sobrien      break;
67990075Sobrien    case NOTE:
68090075Sobrien      if (NOTE_LINE_NUMBER (x) > 0)
681169689Skan	{
682169689Skan	  expanded_location xloc;
683169689Skan	  NOTE_EXPANDED_LOCATION (xloc, x);
684169689Skan	  sprintf (buf, " %4d note \"%s\" %d", INSN_UID (x),
685169689Skan		   xloc.file, xloc.line);
686169689Skan	}
68790075Sobrien      else
688169689Skan	sprintf (buf, " %4d %s", INSN_UID (x),
68990075Sobrien		 GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x)));
69090075Sobrien      break;
69190075Sobrien    default:
692169689Skan      sprintf (buf, "i%4d  <What %s?>", INSN_UID (x),
693169689Skan	       GET_RTX_NAME (GET_CODE (x)));
69490075Sobrien    }
69590075Sobrien}				/* print_insn */
69690075Sobrien
69790075Sobrien
698169689Skan/* Emit a slim dump of X (an insn) to the file F, including any register
699169689Skan   note attached to the instruction.  */
70090075Sobrienvoid
701169689Skandump_insn_slim (FILE *f, rtx x)
70290075Sobrien{
703169689Skan  char t[BUF_LEN + 32];
704169689Skan  rtx note;
70590075Sobrien
706169689Skan  print_insn (t, x, 1);
707169689Skan  fputs (t, f);
708169689Skan  putc ('\n', f);
709169689Skan  if (INSN_P (x) && REG_NOTES (x))
710169689Skan    for (note = REG_NOTES (x); note; note = XEXP (note, 1))
711169689Skan      {
712169689Skan        print_value (t, XEXP (note, 0), 1);
713169689Skan	fprintf (f, "      %s: %s\n",
714169689Skan		 GET_REG_NOTE_NAME (REG_NOTE_KIND (note)), t);
715169689Skan      }
71690075Sobrien}
71790075Sobrien
718169689Skan/* Emit a slim dump of X (an insn) to stderr.  */
71990075Sobrienvoid
720169689Skandebug_insn_slim (rtx x)
72190075Sobrien{
722169689Skan  dump_insn_slim (stderr, x);
72390075Sobrien}
72490075Sobrien
725169689Skan/* Provide a slim dump the instruction chain starting at FIRST to F, honoring
726169689Skan   the dump flags given in FLAGS.  Currently, TDF_BLOCKS and TDF_DETAILS
727169689Skan   include more information on the basic blocks.  */
72890075Sobrienvoid
729169689Skanprint_rtl_slim_with_bb (FILE *f, rtx first, int flags)
73090075Sobrien{
731169689Skan  basic_block current_bb = NULL;
732169689Skan  rtx insn;
73390075Sobrien
734169689Skan  for (insn = first; NULL != insn; insn = NEXT_INSN (insn))
73590075Sobrien    {
736169689Skan      if ((flags & TDF_BLOCKS)
737169689Skan	  && (INSN_P (insn) || GET_CODE (insn) == NOTE)
738169689Skan	  && BLOCK_FOR_INSN (insn)
739169689Skan	  && !current_bb)
740169689Skan	{
741169689Skan	  current_bb = BLOCK_FOR_INSN (insn);
742169689Skan	  dump_bb_info (current_bb, true, false, flags, ";; ", f);
743169689Skan	}
74490075Sobrien
745169689Skan      dump_insn_slim (f, insn);
74690075Sobrien
747169689Skan      if ((flags & TDF_BLOCKS)
748169689Skan	  && current_bb
749169689Skan	  && insn == BB_END (current_bb))
75090075Sobrien	{
751169689Skan	  dump_bb_info (current_bb, false, true, flags, ";; ", f);
752169689Skan	  current_bb = NULL;
75390075Sobrien	}
75490075Sobrien    }
75590075Sobrien}
75690075Sobrien
757