This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Haifa cleanup part 3: move the visualization code


This patch moves the scheduling visualization code into its own file,
sched-vis.c.  It also loses a couple more unnecessary references to basic
block numbers.

Bootstrapped on i686-linux & installed.


Bernd

	* Makefile.in (OBJS): Add sched-vis.o.
	(sched-vis.o): New rule.
	* haifa-sched.c (get_unit_last_insn): New function.
	(sched_dump, insn_unit, actual_hazard_this_instance): No longer
	static.
	(schedule_block): Call visualize_alloc and visualize_free.  Delete
	spurious return statement.
	(init_target_units, insn_print_units, get_visual_tbl_length,
	init_block_visualization, print_block_visualization, safe_concat,
	visualize_scheduled_inns, visualize_no_unit, visualize_stall_cycles,
	print_exp, print_value, print_pattern, print_insn, target_units,
	MAX_VISUAL_LINES, INSN_LEN, n_visual_lines, visual_tbl,
	n_vis_no_unit, vis_no_unit): Move scheduling visualization
	functions/variables...
	* sched-vis.c: ...here.  New file.
	(visualize_alloc, visualize_free): New functions.
	(visualize_scheduled_insns, visualize_stall_cycles,
	print_block_visualization): Lose basic block argument.  All callers
	changed.
	(visualize_scheduled_insns): Use new function get_unit_last_insn.

Index: haifa-sched.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/haifa-sched.c,v
retrieving revision 1.169
diff -u -p -r1.169 haifa-sched.c
--- haifa-sched.c	2000/12/03 12:53:48	1.169
+++ haifa-sched.c	2000/12/03 14:33:42
@@ -177,15 +177,6 @@ extern rtx *reg_known_value;
 
 #ifdef INSN_SCHEDULING
 
-/* target_units bitmask has 1 for each unit in the cpu.  It should be
-   possible to compute this variable from the machine description.
-   But currently it is computed by examining the insn list.  Since
-   this is only needed for visualization, it seems an acceptable
-   solution.  (For understanding the mapping of bits to units, see
-   definition of function_units[] in "insn-attrtab.c".)  */
-
-static int target_units = 0;
-
 /* issue_rate is the number of insns that can be scheduled in the same
    machine cycle.  It can be defined in the config/mach/mach.h file,
    otherwise we set it to 1.  */
@@ -216,7 +207,7 @@ static int nr_inter, nr_spec;
 
 /* Debugging file.  All printouts are sent to dump, which is always set,
    either to stderr, or to the dump listing file (-dRS).  */
-static FILE *sched_dump = 0;
+FILE *sched_dump = 0;
 
 /* Highest uid before scheduling.  */
 static int old_max_uid;
@@ -502,10 +493,8 @@ static void add_dependence PARAMS ((rtx,
 static void remove_dependence PARAMS ((rtx, rtx));
 static rtx find_insn_list PARAMS ((rtx, rtx));
 static void set_sched_group_p PARAMS ((rtx));
-static int insn_unit PARAMS ((rtx));
 static unsigned int blockage_range PARAMS ((int, rtx));
 static void clear_units PARAMS ((void));
-static int actual_hazard_this_instance PARAMS ((int, int, rtx, int, int));
 static void schedule_unit PARAMS ((int, rtx, int));
 static int actual_hazard PARAMS ((int, rtx, int, int));
 static int potential_hazard PARAMS ((int, rtx, int));
@@ -525,7 +514,6 @@ static void queue_insn PARAMS ((rtx, int
 static void schedule_insn PARAMS ((rtx, struct ready_list *, int));
 static void find_insn_reg_weight PARAMS ((int));
 static void schedule_block PARAMS ((int, int));
-static char *safe_concat PARAMS ((char *, char *, const char *));
 static int insn_issue_delay PARAMS ((rtx));
 static void adjust_priority PARAMS ((rtx));
 
@@ -802,18 +790,6 @@ static rtx ready_remove_first PARAMS ((s
 static void queue_to_ready PARAMS ((struct ready_list *));
 
 static void debug_ready_list PARAMS ((struct ready_list *));
-static void init_target_units PARAMS ((void));
-static void insn_print_units PARAMS ((rtx));
-static int get_visual_tbl_length PARAMS ((void));
-static void init_block_visualization PARAMS ((void));
-static void print_block_visualization PARAMS ((int, const char *));
-static void visualize_scheduled_insns PARAMS ((int, int));
-static void visualize_no_unit PARAMS ((rtx));
-static void visualize_stall_cycles PARAMS ((int, int));
-static void print_exp PARAMS ((char *, rtx, int));
-static void print_value PARAMS ((char *, rtx, int));
-static void print_pattern PARAMS ((char *, rtx, int));
-static void print_insn PARAMS ((char *, rtx, int));
 void debug_reg_vector PARAMS ((regset));
 
 static rtx move_insn1 PARAMS ((rtx, rtx));
@@ -2914,7 +2890,7 @@ find_insn_mem_list (insn, x, list, list1
    mask if the value is negative.  A function unit index is the
    non-negative encoding.  */
 
-HAIFA_INLINE static int
+HAIFA_INLINE int
 insn_unit (insn)
      rtx insn;
 {
@@ -2986,6 +2962,15 @@ static int unit_tick[FUNCTION_UNITS_SIZE
    that remain to use the unit.  */
 static int unit_n_insns[FUNCTION_UNITS_SIZE];
 
+/* Access the unit_last_insn array.  Used by the visualization code.  */
+
+rtx
+get_unit_last_insn (instance)
+     int instance;
+{
+  return unit_last_insn[instance];
+}
+
 /* Reset the function unit state to the null state.  */
 
 static void
@@ -3028,7 +3013,7 @@ insn_issue_delay (insn)
    instance INSTANCE at time CLOCK if the previous actual hazard cost
    was COST.  */
 
-HAIFA_INLINE static int
+HAIFA_INLINE int
 actual_hazard_this_instance (unit, instance, insn, clock, cost)
      int unit, instance, clock, cost;
      rtx insn;
@@ -4899,7 +4884,7 @@ queue_to_ready (ready)
 	}
 
       if (sched_verbose && stalls)
-	visualize_stall_cycles (BB_TO_BLOCK (target_bb), stalls);
+	visualize_stall_cycles (stalls);
       q_ptr = NEXT_Q_AFTER (q_ptr, stalls);
       clock_var += stalls;
     }
@@ -4923,873 +4908,6 @@ debug_ready_list (ready)
   fprintf (sched_dump, "\n");
 }
 
-/* Print names of units on which insn can/should execute, for debugging.  */
-
-static void
-insn_print_units (insn)
-     rtx insn;
-{
-  int i;
-  int unit = insn_unit (insn);
-
-  if (unit == -1)
-    fprintf (sched_dump, "none");
-  else if (unit >= 0)
-    fprintf (sched_dump, "%s", function_units[unit].name);
-  else
-    {
-      fprintf (sched_dump, "[");
-      for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
-	if (unit & 1)
-	  {
-	    fprintf (sched_dump, "%s", function_units[i].name);
-	    if (unit != 1)
-	      fprintf (sched_dump, " ");
-	  }
-      fprintf (sched_dump, "]");
-    }
-}
-
-/* MAX_VISUAL_LINES is the maximum number of lines in visualization table
-   of a basic block.  If more lines are needed, table is splitted to two.
-   n_visual_lines is the number of lines printed so far for a block.
-   visual_tbl contains the block visualization info.
-   vis_no_unit holds insns in a cycle that are not mapped to any unit.  */
-#define MAX_VISUAL_LINES 100
-#define INSN_LEN 30
-int n_visual_lines;
-char *visual_tbl;
-int n_vis_no_unit;
-rtx vis_no_unit[10];
-
-/* Finds units that are in use in this fuction.  Required only
-   for visualization.  */
-
-static void
-init_target_units ()
-{
-  rtx insn;
-  int unit;
-
-  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
-    {
-      if (! INSN_P (insn))
-	continue;
-
-      unit = insn_unit (insn);
-
-      if (unit < 0)
-	target_units |= ~unit;
-      else
-	target_units |= (1 << unit);
-    }
-}
-
-/* Return the length of the visualization table.  */
-
-static int
-get_visual_tbl_length ()
-{
-  int unit, i;
-  int n, n1;
-  char *s;
-
-  /* Compute length of one field in line.  */
-  s = (char *) alloca (INSN_LEN + 6);
-  sprintf (s, "  %33s", "uname");
-  n1 = strlen (s);
-
-  /* Compute length of one line.  */
-  n = strlen (";; ");
-  n += n1;
-  for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
-    if (function_units[unit].bitmask & target_units)
-      for (i = 0; i < function_units[unit].multiplicity; i++)
-	n += n1;
-  n += n1;
-  n += strlen ("\n") + 2;
-
-  /* Compute length of visualization string.  */
-  return (MAX_VISUAL_LINES * n);
-}
-
-/* Init block visualization debugging info.  */
-
-static void
-init_block_visualization ()
-{
-  strcpy (visual_tbl, "");
-  n_visual_lines = 0;
-  n_vis_no_unit = 0;
-}
-
-#define BUF_LEN 2048
-
-static char *
-safe_concat (buf, cur, str)
-     char *buf;
-     char *cur;
-     const char *str;
-{
-  char *end = buf + BUF_LEN - 2;	/* Leave room for null.  */
-  int c;
-
-  if (cur > end)
-    {
-      *end = '\0';
-      return end;
-    }
-
-  while (cur < end && (c = *str++) != '\0')
-    *cur++ = c;
-
-  *cur = '\0';
-  return cur;
-}
-
-/* This recognizes rtx, I classified as expressions.  These are always
-   represent some action on values or results of other expression, that
-   may be stored in objects representing values.  */
-
-static void
-print_exp (buf, x, verbose)
-     char *buf;
-     rtx x;
-     int verbose;
-{
-  char tmp[BUF_LEN];
-  const char *st[4];
-  char *cur = buf;
-  const char *fun = (char *) 0;
-  const char *sep;
-  rtx op[4];
-  int i;
-
-  for (i = 0; i < 4; i++)
-    {
-      st[i] = (char *) 0;
-      op[i] = NULL_RTX;
-    }
-
-  switch (GET_CODE (x))
-    {
-    case PLUS:
-      op[0] = XEXP (x, 0);
-      if (GET_CODE (XEXP (x, 1)) == CONST_INT
-	  && INTVAL (XEXP (x, 1)) < 0)
-	{
-	  st[1] = "-";
-	  op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
-	}
-      else
-	{
-	  st[1] = "+";
-	  op[1] = XEXP (x, 1);
-	}
-      break;
-    case LO_SUM:
-      op[0] = XEXP (x, 0);
-      st[1] = "+low(";
-      op[1] = XEXP (x, 1);
-      st[2] = ")";
-      break;
-    case MINUS:
-      op[0] = XEXP (x, 0);
-      st[1] = "-";
-      op[1] = XEXP (x, 1);
-      break;
-    case COMPARE:
-      fun = "cmp";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case NEG:
-      st[0] = "-";
-      op[0] = XEXP (x, 0);
-      break;
-    case MULT:
-      op[0] = XEXP (x, 0);
-      st[1] = "*";
-      op[1] = XEXP (x, 1);
-      break;
-    case DIV:
-      op[0] = XEXP (x, 0);
-      st[1] = "/";
-      op[1] = XEXP (x, 1);
-      break;
-    case UDIV:
-      fun = "udiv";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case MOD:
-      op[0] = XEXP (x, 0);
-      st[1] = "%";
-      op[1] = XEXP (x, 1);
-      break;
-    case UMOD:
-      fun = "umod";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case SMIN:
-      fun = "smin";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case SMAX:
-      fun = "smax";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case UMIN:
-      fun = "umin";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case UMAX:
-      fun = "umax";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case NOT:
-      st[0] = "!";
-      op[0] = XEXP (x, 0);
-      break;
-    case AND:
-      op[0] = XEXP (x, 0);
-      st[1] = "&";
-      op[1] = XEXP (x, 1);
-      break;
-    case IOR:
-      op[0] = XEXP (x, 0);
-      st[1] = "|";
-      op[1] = XEXP (x, 1);
-      break;
-    case XOR:
-      op[0] = XEXP (x, 0);
-      st[1] = "^";
-      op[1] = XEXP (x, 1);
-      break;
-    case ASHIFT:
-      op[0] = XEXP (x, 0);
-      st[1] = "<<";
-      op[1] = XEXP (x, 1);
-      break;
-    case LSHIFTRT:
-      op[0] = XEXP (x, 0);
-      st[1] = " 0>>";
-      op[1] = XEXP (x, 1);
-      break;
-    case ASHIFTRT:
-      op[0] = XEXP (x, 0);
-      st[1] = ">>";
-      op[1] = XEXP (x, 1);
-      break;
-    case ROTATE:
-      op[0] = XEXP (x, 0);
-      st[1] = "<-<";
-      op[1] = XEXP (x, 1);
-      break;
-    case ROTATERT:
-      op[0] = XEXP (x, 0);
-      st[1] = ">->";
-      op[1] = XEXP (x, 1);
-      break;
-    case ABS:
-      fun = "abs";
-      op[0] = XEXP (x, 0);
-      break;
-    case SQRT:
-      fun = "sqrt";
-      op[0] = XEXP (x, 0);
-      break;
-    case FFS:
-      fun = "ffs";
-      op[0] = XEXP (x, 0);
-      break;
-    case EQ:
-      op[0] = XEXP (x, 0);
-      st[1] = "==";
-      op[1] = XEXP (x, 1);
-      break;
-    case NE:
-      op[0] = XEXP (x, 0);
-      st[1] = "!=";
-      op[1] = XEXP (x, 1);
-      break;
-    case GT:
-      op[0] = XEXP (x, 0);
-      st[1] = ">";
-      op[1] = XEXP (x, 1);
-      break;
-    case GTU:
-      fun = "gtu";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case LT:
-      op[0] = XEXP (x, 0);
-      st[1] = "<";
-      op[1] = XEXP (x, 1);
-      break;
-    case LTU:
-      fun = "ltu";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case GE:
-      op[0] = XEXP (x, 0);
-      st[1] = ">=";
-      op[1] = XEXP (x, 1);
-      break;
-    case GEU:
-      fun = "geu";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case LE:
-      op[0] = XEXP (x, 0);
-      st[1] = "<=";
-      op[1] = XEXP (x, 1);
-      break;
-    case LEU:
-      fun = "leu";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      break;
-    case SIGN_EXTRACT:
-      fun = (verbose) ? "sign_extract" : "sxt";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      op[2] = XEXP (x, 2);
-      break;
-    case ZERO_EXTRACT:
-      fun = (verbose) ? "zero_extract" : "zxt";
-      op[0] = XEXP (x, 0);
-      op[1] = XEXP (x, 1);
-      op[2] = XEXP (x, 2);
-      break;
-    case SIGN_EXTEND:
-      fun = (verbose) ? "sign_extend" : "sxn";
-      op[0] = XEXP (x, 0);
-      break;
-    case ZERO_EXTEND:
-      fun = (verbose) ? "zero_extend" : "zxn";
-      op[0] = XEXP (x, 0);
-      break;
-    case FLOAT_EXTEND:
-      fun = (verbose) ? "float_extend" : "fxn";
-      op[0] = XEXP (x, 0);
-      break;
-    case TRUNCATE:
-      fun = (verbose) ? "trunc" : "trn";
-      op[0] = XEXP (x, 0);
-      break;
-    case FLOAT_TRUNCATE:
-      fun = (verbose) ? "float_trunc" : "ftr";
-      op[0] = XEXP (x, 0);
-      break;
-    case FLOAT:
-      fun = (verbose) ? "float" : "flt";
-      op[0] = XEXP (x, 0);
-      break;
-    case UNSIGNED_FLOAT:
-      fun = (verbose) ? "uns_float" : "ufl";
-      op[0] = XEXP (x, 0);
-      break;
-    case FIX:
-      fun = "fix";
-      op[0] = XEXP (x, 0);
-      break;
-    case UNSIGNED_FIX:
-      fun = (verbose) ? "uns_fix" : "ufx";
-      op[0] = XEXP (x, 0);
-      break;
-    case PRE_DEC:
-      st[0] = "--";
-      op[0] = XEXP (x, 0);
-      break;
-    case PRE_INC:
-      st[0] = "++";
-      op[0] = XEXP (x, 0);
-      break;
-    case POST_DEC:
-      op[0] = XEXP (x, 0);
-      st[1] = "--";
-      break;
-    case POST_INC:
-      op[0] = XEXP (x, 0);
-      st[1] = "++";
-      break;
-    case CALL:
-      st[0] = "call ";
-      op[0] = XEXP (x, 0);
-      if (verbose)
-	{
-	  st[1] = " argc:";
-	  op[1] = XEXP (x, 1);
-	}
-      break;
-    case IF_THEN_ELSE:
-      st[0] = "{(";
-      op[0] = XEXP (x, 0);
-      st[1] = ")?";
-      op[1] = XEXP (x, 1);
-      st[2] = ":";
-      op[2] = XEXP (x, 2);
-      st[3] = "}";
-      break;
-    case TRAP_IF:
-      fun = "trap_if";
-      op[0] = TRAP_CONDITION (x);
-      break;
-    case UNSPEC:
-    case UNSPEC_VOLATILE:
-      {
-	cur = safe_concat (buf, cur, "unspec");
-	if (GET_CODE (x) == UNSPEC_VOLATILE)
-	  cur = safe_concat (buf, cur, "/v");
-	cur = safe_concat (buf, cur, "[");
-	sep = "";
-	for (i = 0; i < XVECLEN (x, 0); i++)
-	  {
-	    print_pattern (tmp, XVECEXP (x, 0, i), verbose);
-	    cur = safe_concat (buf, cur, sep);
-	    cur = safe_concat (buf, cur, tmp);
-	    sep = ",";
-	  }
-	cur = safe_concat (buf, cur, "] ");
-	sprintf (tmp, "%d", XINT (x, 1));
-	cur = safe_concat (buf, cur, tmp);
-      }
-      break;
-    default:
-      /* If (verbose) debug_rtx (x);  */
-      st[0] = GET_RTX_NAME (GET_CODE (x));
-      break;
-    }
-
-  /* Print this as a function?  */
-  if (fun)
-    {
-      cur = safe_concat (buf, cur, fun);
-      cur = safe_concat (buf, cur, "(");
-    }
-
-  for (i = 0; i < 4; i++)
-    {
-      if (st[i])
-	cur = safe_concat (buf, cur, st[i]);
-
-      if (op[i])
-	{
-	  if (fun && i != 0)
-	    cur = safe_concat (buf, cur, ",");
-
-	  print_value (tmp, op[i], verbose);
-	  cur = safe_concat (buf, cur, tmp);
-	}
-    }
-
-  if (fun)
-    cur = safe_concat (buf, cur, ")");
-}		/* print_exp */
-
-/* Prints rtxes, I customly classified as values.  They're constants,
-   registers, labels, symbols and memory accesses.  */
-
-static void
-print_value (buf, x, verbose)
-     char *buf;
-     rtx x;
-     int verbose;
-{
-  char t[BUF_LEN];
-  char *cur = buf;
-
-  switch (GET_CODE (x))
-    {
-    case CONST_INT:
-      sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
-      cur = safe_concat (buf, cur, t);
-      break;
-    case CONST_DOUBLE:
-      sprintf (t, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
-      cur = safe_concat (buf, cur, t);
-      break;
-    case CONST_STRING:
-      cur = safe_concat (buf, cur, "\"");
-      cur = safe_concat (buf, cur, XSTR (x, 0));
-      cur = safe_concat (buf, cur, "\"");
-      break;
-    case SYMBOL_REF:
-      cur = safe_concat (buf, cur, "`");
-      cur = safe_concat (buf, cur, XSTR (x, 0));
-      cur = safe_concat (buf, cur, "'");
-      break;
-    case LABEL_REF:
-      sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
-      cur = safe_concat (buf, cur, t);
-      break;
-    case CONST:
-      print_value (t, XEXP (x, 0), verbose);
-      cur = safe_concat (buf, cur, "const(");
-      cur = safe_concat (buf, cur, t);
-      cur = safe_concat (buf, cur, ")");
-      break;
-    case HIGH:
-      print_value (t, XEXP (x, 0), verbose);
-      cur = safe_concat (buf, cur, "high(");
-      cur = safe_concat (buf, cur, t);
-      cur = safe_concat (buf, cur, ")");
-      break;
-    case REG:
-      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
-	{
-	  int c = reg_names[REGNO (x)][0];
-	  if (c >= '0' && c <= '9')
-	    cur = safe_concat (buf, cur, "%");
-
-	  cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
-	}
-      else
-	{
-	  sprintf (t, "r%d", REGNO (x));
-	  cur = safe_concat (buf, cur, t);
-	}
-      break;
-    case SUBREG:
-      print_value (t, SUBREG_REG (x), verbose);
-      cur = safe_concat (buf, cur, t);
-      sprintf (t, "#%d", SUBREG_WORD (x));
-      cur = safe_concat (buf, cur, t);
-      break;
-    case SCRATCH:
-      cur = safe_concat (buf, cur, "scratch");
-      break;
-    case CC0:
-      cur = safe_concat (buf, cur, "cc0");
-      break;
-    case PC:
-      cur = safe_concat (buf, cur, "pc");
-      break;
-    case MEM:
-      print_value (t, XEXP (x, 0), verbose);
-      cur = safe_concat (buf, cur, "[");
-      cur = safe_concat (buf, cur, t);
-      cur = safe_concat (buf, cur, "]");
-      break;
-    default:
-      print_exp (t, x, verbose);
-      cur = safe_concat (buf, cur, t);
-      break;
-    }
-}				/* print_value */
-
-/* The next step in insn detalization, its pattern recognition.  */
-
-static void
-print_pattern (buf, x, verbose)
-     char *buf;
-     rtx x;
-     int verbose;
-{
-  char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
-
-  switch (GET_CODE (x))
-    {
-    case SET:
-      print_value (t1, SET_DEST (x), verbose);
-      print_value (t2, SET_SRC (x), verbose);
-      sprintf (buf, "%s=%s", t1, t2);
-      break;
-    case RETURN:
-      sprintf (buf, "return");
-      break;
-    case CALL:
-      print_exp (buf, x, verbose);
-      break;
-    case CLOBBER:
-      print_value (t1, XEXP (x, 0), verbose);
-      sprintf (buf, "clobber %s", t1);
-      break;
-    case USE:
-      print_value (t1, XEXP (x, 0), verbose);
-      sprintf (buf, "use %s", t1);
-      break;
-    case COND_EXEC:
-      if (GET_CODE (COND_EXEC_TEST (x)) == NE
-	  && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
-	print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
-      else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
-               && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
-        {
-	  t1[0] = '!';
-	  print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
-	}
-      else
-        print_value (t1, COND_EXEC_TEST (x), verbose);
-      print_pattern (t2, COND_EXEC_CODE (x), verbose);
-      sprintf (buf, "(%s) %s", t1, t2);
-      break;
-    case PARALLEL:
-      {
-	int i;
-
-	sprintf (t1, "{");
-	for (i = 0; i < XVECLEN (x, 0); i++)
-	  {
-	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
-	    sprintf (t3, "%s%s;", t1, t2);
-	    strcpy (t1, t3);
-	  }
-	sprintf (buf, "%s}", t1);
-      }
-      break;
-    case SEQUENCE:
-      {
-	int i;
-
-	sprintf (t1, "%%{");
-	for (i = 0; i < XVECLEN (x, 0); i++)
-	  {
-	    print_insn (t2, XVECEXP (x, 0, i), verbose);
-	    sprintf (t3, "%s%s;", t1, t2);
-	    strcpy (t1, t3);
-	  }
-	sprintf (buf, "%s%%}", t1);
-      }
-      break;
-    case ASM_INPUT:
-      sprintf (buf, "asm {%s}", XSTR (x, 0));
-      break;
-    case ADDR_VEC:
-      break;
-    case ADDR_DIFF_VEC:
-      print_value (buf, XEXP (x, 0), verbose);
-      break;
-    case TRAP_IF:
-      print_value (t1, TRAP_CONDITION (x), verbose);
-      sprintf (buf, "trap_if %s", t1);
-      break;
-    case UNSPEC:
-      {
-	int i;
-
-	sprintf (t1, "unspec{");
-	for (i = 0; i < XVECLEN (x, 0); i++)
-	  {
-	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
-	    sprintf (t3, "%s%s;", t1, t2);
-	    strcpy (t1, t3);
-	  }
-	sprintf (buf, "%s}", t1);
-      }
-      break;
-    case UNSPEC_VOLATILE:
-      {
-	int i;
-
-	sprintf (t1, "unspec/v{");
-	for (i = 0; i < XVECLEN (x, 0); i++)
-	  {
-	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
-	    sprintf (t3, "%s%s;", t1, t2);
-	    strcpy (t1, t3);
-	  }
-	sprintf (buf, "%s}", t1);
-      }
-      break;
-    default:
-      print_value (buf, x, verbose);
-    }
-}				/* print_pattern */
-
-/* This is the main function in rtl visualization mechanism. It
-   accepts an rtx and tries to recognize it as an insn, then prints it
-   properly in human readable form, resembling assembler mnemonics.
-   For every insn it prints its UID and BB the insn belongs too.
-   (Probably the last "option" should be extended somehow, since it
-   depends now on sched.c inner variables ...)  */
-
-static void
-print_insn (buf, x, verbose)
-     char *buf;
-     rtx x;
-     int verbose;
-{
-  char t[BUF_LEN];
-  rtx insn = x;
-
-  switch (GET_CODE (x))
-    {
-    case INSN:
-      print_pattern (t, PATTERN (x), verbose);
-      if (verbose)
-	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
-		 t);
-      else
-	sprintf (buf, "%-4d %s", INSN_UID (x), t);
-      break;
-    case JUMP_INSN:
-      print_pattern (t, PATTERN (x), verbose);
-      if (verbose)
-	sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
-		 t);
-      else
-	sprintf (buf, "%-4d %s", INSN_UID (x), t);
-      break;
-    case CALL_INSN:
-      x = PATTERN (insn);
-      if (GET_CODE (x) == PARALLEL)
-	{
-	  x = XVECEXP (x, 0, 0);
-	  print_pattern (t, x, verbose);
-	}
-      else
-	strcpy (t, "call <...>");
-      if (verbose)
-	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
-      else
-	sprintf (buf, "%-4d %s", INSN_UID (insn), t);
-      break;
-    case CODE_LABEL:
-      sprintf (buf, "L%d:", INSN_UID (x));
-      break;
-    case BARRIER:
-      sprintf (buf, "i% 4d: barrier", INSN_UID (x));
-      break;
-    case NOTE:
-      if (NOTE_LINE_NUMBER (x) > 0)
-	sprintf (buf, "%4d note \"%s\" %d", INSN_UID (x),
-		 NOTE_SOURCE_FILE (x), NOTE_LINE_NUMBER (x));
-      else
-	sprintf (buf, "%4d %s", INSN_UID (x),
-		 GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x)));
-      break;
-    default:
-      if (verbose)
-	{
-	  sprintf (buf, "Not an INSN at all\n");
-	  debug_rtx (x);
-	}
-      else
-	sprintf (buf, "i%-4d  <What?>", INSN_UID (x));
-    }
-}				/* print_insn */
-
-/* Print visualization debugging info.  */
-
-static void
-print_block_visualization (b, s)
-     int b;
-     const char *s;
-{
-  int unit, i;
-
-  /* Print header.  */
-  fprintf (sched_dump, "\n;;   ==================== scheduling visualization for block %d %s \n", b, s);
-
-  /* Print names of units.  */
-  fprintf (sched_dump, ";;   %-8s", "clock");
-  for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
-    if (function_units[unit].bitmask & target_units)
-      for (i = 0; i < function_units[unit].multiplicity; i++)
-	fprintf (sched_dump, "  %-33s", function_units[unit].name);
-  fprintf (sched_dump, "  %-8s\n", "no-unit");
-
-  fprintf (sched_dump, ";;   %-8s", "=====");
-  for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
-    if (function_units[unit].bitmask & target_units)
-      for (i = 0; i < function_units[unit].multiplicity; i++)
-	fprintf (sched_dump, "  %-33s", "==============================");
-  fprintf (sched_dump, "  %-8s\n", "=======");
-
-  /* Print insns in each cycle.  */
-  fprintf (sched_dump, "%s\n", visual_tbl);
-}
-
-/* Print insns in the 'no_unit' column of visualization.  */
-
-static void
-visualize_no_unit (insn)
-     rtx insn;
-{
-  vis_no_unit[n_vis_no_unit] = insn;
-  n_vis_no_unit++;
-}
-
-/* Print insns scheduled in clock, for visualization.  */
-
-static void
-visualize_scheduled_insns (b, clock)
-     int b, clock;
-{
-  int i, unit;
-
-  /* If no more room, split table into two.  */
-  if (n_visual_lines >= MAX_VISUAL_LINES)
-    {
-      print_block_visualization (b, "(incomplete)");
-      init_block_visualization ();
-    }
-
-  n_visual_lines++;
-
-  sprintf (visual_tbl + strlen (visual_tbl), ";;   %-8d", clock);
-  for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
-    if (function_units[unit].bitmask & target_units)
-      for (i = 0; i < function_units[unit].multiplicity; i++)
-	{
-	  int instance = unit + i * FUNCTION_UNITS_SIZE;
-	  rtx insn = unit_last_insn[instance];
-
-	  /* Print insns that still keep the unit busy.  */
-	  if (insn &&
-	      actual_hazard_this_instance (unit, instance, insn, clock, 0))
-	    {
-	      char str[BUF_LEN];
-	      print_insn (str, insn, 0);
-	      str[INSN_LEN] = '\0';
-	      sprintf (visual_tbl + strlen (visual_tbl), "  %-33s", str);
-	    }
-	  else
-	    sprintf (visual_tbl + strlen (visual_tbl), "  %-33s", "------------------------------");
-	}
-
-  /* Print insns that are not assigned to any unit.  */
-  for (i = 0; i < n_vis_no_unit; i++)
-    sprintf (visual_tbl + strlen (visual_tbl), "  %-8d",
-	     INSN_UID (vis_no_unit[i]));
-  n_vis_no_unit = 0;
-
-  sprintf (visual_tbl + strlen (visual_tbl), "\n");
-}
-
-/* Print stalled cycles.  */
-
-static void
-visualize_stall_cycles (b, stalls)
-     int b, stalls;
-{
-  int i;
-
-  /* If no more room, split table into two.  */
-  if (n_visual_lines >= MAX_VISUAL_LINES)
-    {
-      print_block_visualization (b, "(incomplete)");
-      init_block_visualization ();
-    }
-
-  n_visual_lines++;
-
-  sprintf (visual_tbl + strlen (visual_tbl), ";;       ");
-  for (i = 0; i < stalls; i++)
-    sprintf (visual_tbl + strlen (visual_tbl), ".");
-  sprintf (visual_tbl + strlen (visual_tbl), "\n");
-}
-
 /* The number of insns from the current block scheduled so far.  */
 static int sched_target_n_insns;
 /* The number of insns from the current block to be scheduled in total.  */
@@ -6248,7 +5366,7 @@ schedule_block (bb, rgn_n_insns)
       fprintf (sched_dump, ";;   ======================================================\n");
       fprintf (sched_dump, "\n");
 
-      visual_tbl = (char *) alloca (get_visual_tbl_length ());
+      visualize_alloc ();
       init_block_visualization ();
     }
 
@@ -6356,7 +5474,7 @@ schedule_block (bb, rgn_n_insns)
 
       /* Debug info.  */
       if (sched_verbose)
-	visualize_scheduled_insns (b, clock_var);
+	visualize_scheduled_insns (clock_var);
     }
 
   /* Debug info.  */
@@ -6364,7 +5482,7 @@ schedule_block (bb, rgn_n_insns)
     {
       fprintf (sched_dump, ";;\tReady list (final):  ");
       debug_ready_list (&ready);
-      print_block_visualization (b, "");
+      print_block_visualization ("");
     }
 
   /* Sanity check -- queue must be empty now.  Meaningless if region has
@@ -6402,14 +5520,13 @@ schedule_block (bb, rgn_n_insns)
 	       clock_var, INSN_UID (head));
       fprintf (sched_dump, ";;   new tail = %d\n\n",
 	       INSN_UID (tail));
+      visualize_free ();
     }
 
   current_sched_info->head = head;
   current_sched_info->tail = tail;
 
   free (ready.vec);
-
-  return 1;
 }
 
 /* Print the bit-set of registers, S, callable from debugger.  */
Index: sched-vis.c
===================================================================
RCS file: sched-vis.c
diff -N sched-vis.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ sched-vis.c	Sun Dec  3 06:33:42 2000
@@ -0,0 +1,929 @@
+/* Instruction scheduling pass.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
+   Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
+   and currently maintained by, Jim Wilson (wilson@cygnus.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to the Free
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "toplev.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "insn-attr.h"
+#include "sched-int.h"
+
+/* target_units bitmask has 1 for each unit in the cpu.  It should be
+   possible to compute this variable from the machine description.
+   But currently it is computed by examining the insn list.  Since
+   this is only needed for visualization, it seems an acceptable
+   solution.  (For understanding the mapping of bits to units, see
+   definition of function_units[] in "insn-attrtab.c".)  */
+
+static int target_units = 0;
+
+static char *safe_concat PARAMS ((char *, char *, const char *));
+static int get_visual_tbl_length PARAMS ((void));
+static void print_exp PARAMS ((char *, rtx, int));
+static void print_value PARAMS ((char *, rtx, int));
+static void print_pattern PARAMS ((char *, rtx, int));
+static void print_insn PARAMS ((char *, rtx, int));
+
+/* Print names of units on which insn can/should execute, for debugging.  */
+
+void
+insn_print_units (insn)
+     rtx insn;
+{
+  int i;
+  int unit = insn_unit (insn);
+
+  if (unit == -1)
+    fprintf (sched_dump, "none");
+  else if (unit >= 0)
+    fprintf (sched_dump, "%s", function_units[unit].name);
+  else
+    {
+      fprintf (sched_dump, "[");
+      for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
+	if (unit & 1)
+	  {
+	    fprintf (sched_dump, "%s", function_units[i].name);
+	    if (unit != 1)
+	      fprintf (sched_dump, " ");
+	  }
+      fprintf (sched_dump, "]");
+    }
+}
+
+/* MAX_VISUAL_LINES is the maximum number of lines in visualization table
+   of a basic block.  If more lines are needed, table is splitted to two.
+   n_visual_lines is the number of lines printed so far for a block.
+   visual_tbl contains the block visualization info.
+   vis_no_unit holds insns in a cycle that are not mapped to any unit.  */
+#define MAX_VISUAL_LINES 100
+#define INSN_LEN 30
+int n_visual_lines;
+char *visual_tbl;
+int n_vis_no_unit;
+rtx vis_no_unit[10];
+
+/* Finds units that are in use in this fuction.  Required only
+   for visualization.  */
+
+void
+init_target_units ()
+{
+  rtx insn;
+  int unit;
+
+  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+    {
+      if (! INSN_P (insn))
+	continue;
+
+      unit = insn_unit (insn);
+
+      if (unit < 0)
+	target_units |= ~unit;
+      else
+	target_units |= (1 << unit);
+    }
+}
+
+/* Return the length of the visualization table.  */
+
+static int
+get_visual_tbl_length ()
+{
+  int unit, i;
+  int n, n1;
+  char *s;
+
+  /* Compute length of one field in line.  */
+  s = (char *) alloca (INSN_LEN + 6);
+  sprintf (s, "  %33s", "uname");
+  n1 = strlen (s);
+
+  /* Compute length of one line.  */
+  n = strlen (";; ");
+  n += n1;
+  for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
+    if (function_units[unit].bitmask & target_units)
+      for (i = 0; i < function_units[unit].multiplicity; i++)
+	n += n1;
+  n += n1;
+  n += strlen ("\n") + 2;
+
+  /* Compute length of visualization string.  */
+  return (MAX_VISUAL_LINES * n);
+}
+
+/* Init block visualization debugging info.  */
+
+void
+init_block_visualization ()
+{
+  strcpy (visual_tbl, "");
+  n_visual_lines = 0;
+  n_vis_no_unit = 0;
+}
+
+#define BUF_LEN 2048
+
+static char *
+safe_concat (buf, cur, str)
+     char *buf;
+     char *cur;
+     const char *str;
+{
+  char *end = buf + BUF_LEN - 2;	/* Leave room for null.  */
+  int c;
+
+  if (cur > end)
+    {
+      *end = '\0';
+      return end;
+    }
+
+  while (cur < end && (c = *str++) != '\0')
+    *cur++ = c;
+
+  *cur = '\0';
+  return cur;
+}
+
+/* This recognizes rtx, I classified as expressions.  These are always
+   represent some action on values or results of other expression, that
+   may be stored in objects representing values.  */
+
+static void
+print_exp (buf, x, verbose)
+     char *buf;
+     rtx x;
+     int verbose;
+{
+  char tmp[BUF_LEN];
+  const char *st[4];
+  char *cur = buf;
+  const char *fun = (char *) 0;
+  const char *sep;
+  rtx op[4];
+  int i;
+
+  for (i = 0; i < 4; i++)
+    {
+      st[i] = (char *) 0;
+      op[i] = NULL_RTX;
+    }
+
+  switch (GET_CODE (x))
+    {
+    case PLUS:
+      op[0] = XEXP (x, 0);
+      if (GET_CODE (XEXP (x, 1)) == CONST_INT
+	  && INTVAL (XEXP (x, 1)) < 0)
+	{
+	  st[1] = "-";
+	  op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
+	}
+      else
+	{
+	  st[1] = "+";
+	  op[1] = XEXP (x, 1);
+	}
+      break;
+    case LO_SUM:
+      op[0] = XEXP (x, 0);
+      st[1] = "+low(";
+      op[1] = XEXP (x, 1);
+      st[2] = ")";
+      break;
+    case MINUS:
+      op[0] = XEXP (x, 0);
+      st[1] = "-";
+      op[1] = XEXP (x, 1);
+      break;
+    case COMPARE:
+      fun = "cmp";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case NEG:
+      st[0] = "-";
+      op[0] = XEXP (x, 0);
+      break;
+    case MULT:
+      op[0] = XEXP (x, 0);
+      st[1] = "*";
+      op[1] = XEXP (x, 1);
+      break;
+    case DIV:
+      op[0] = XEXP (x, 0);
+      st[1] = "/";
+      op[1] = XEXP (x, 1);
+      break;
+    case UDIV:
+      fun = "udiv";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case MOD:
+      op[0] = XEXP (x, 0);
+      st[1] = "%";
+      op[1] = XEXP (x, 1);
+      break;
+    case UMOD:
+      fun = "umod";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case SMIN:
+      fun = "smin";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case SMAX:
+      fun = "smax";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case UMIN:
+      fun = "umin";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case UMAX:
+      fun = "umax";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case NOT:
+      st[0] = "!";
+      op[0] = XEXP (x, 0);
+      break;
+    case AND:
+      op[0] = XEXP (x, 0);
+      st[1] = "&";
+      op[1] = XEXP (x, 1);
+      break;
+    case IOR:
+      op[0] = XEXP (x, 0);
+      st[1] = "|";
+      op[1] = XEXP (x, 1);
+      break;
+    case XOR:
+      op[0] = XEXP (x, 0);
+      st[1] = "^";
+      op[1] = XEXP (x, 1);
+      break;
+    case ASHIFT:
+      op[0] = XEXP (x, 0);
+      st[1] = "<<";
+      op[1] = XEXP (x, 1);
+      break;
+    case LSHIFTRT:
+      op[0] = XEXP (x, 0);
+      st[1] = " 0>>";
+      op[1] = XEXP (x, 1);
+      break;
+    case ASHIFTRT:
+      op[0] = XEXP (x, 0);
+      st[1] = ">>";
+      op[1] = XEXP (x, 1);
+      break;
+    case ROTATE:
+      op[0] = XEXP (x, 0);
+      st[1] = "<-<";
+      op[1] = XEXP (x, 1);
+      break;
+    case ROTATERT:
+      op[0] = XEXP (x, 0);
+      st[1] = ">->";
+      op[1] = XEXP (x, 1);
+      break;
+    case ABS:
+      fun = "abs";
+      op[0] = XEXP (x, 0);
+      break;
+    case SQRT:
+      fun = "sqrt";
+      op[0] = XEXP (x, 0);
+      break;
+    case FFS:
+      fun = "ffs";
+      op[0] = XEXP (x, 0);
+      break;
+    case EQ:
+      op[0] = XEXP (x, 0);
+      st[1] = "==";
+      op[1] = XEXP (x, 1);
+      break;
+    case NE:
+      op[0] = XEXP (x, 0);
+      st[1] = "!=";
+      op[1] = XEXP (x, 1);
+      break;
+    case GT:
+      op[0] = XEXP (x, 0);
+      st[1] = ">";
+      op[1] = XEXP (x, 1);
+      break;
+    case GTU:
+      fun = "gtu";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case LT:
+      op[0] = XEXP (x, 0);
+      st[1] = "<";
+      op[1] = XEXP (x, 1);
+      break;
+    case LTU:
+      fun = "ltu";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case GE:
+      op[0] = XEXP (x, 0);
+      st[1] = ">=";
+      op[1] = XEXP (x, 1);
+      break;
+    case GEU:
+      fun = "geu";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case LE:
+      op[0] = XEXP (x, 0);
+      st[1] = "<=";
+      op[1] = XEXP (x, 1);
+      break;
+    case LEU:
+      fun = "leu";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      break;
+    case SIGN_EXTRACT:
+      fun = (verbose) ? "sign_extract" : "sxt";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      op[2] = XEXP (x, 2);
+      break;
+    case ZERO_EXTRACT:
+      fun = (verbose) ? "zero_extract" : "zxt";
+      op[0] = XEXP (x, 0);
+      op[1] = XEXP (x, 1);
+      op[2] = XEXP (x, 2);
+      break;
+    case SIGN_EXTEND:
+      fun = (verbose) ? "sign_extend" : "sxn";
+      op[0] = XEXP (x, 0);
+      break;
+    case ZERO_EXTEND:
+      fun = (verbose) ? "zero_extend" : "zxn";
+      op[0] = XEXP (x, 0);
+      break;
+    case FLOAT_EXTEND:
+      fun = (verbose) ? "float_extend" : "fxn";
+      op[0] = XEXP (x, 0);
+      break;
+    case TRUNCATE:
+      fun = (verbose) ? "trunc" : "trn";
+      op[0] = XEXP (x, 0);
+      break;
+    case FLOAT_TRUNCATE:
+      fun = (verbose) ? "float_trunc" : "ftr";
+      op[0] = XEXP (x, 0);
+      break;
+    case FLOAT:
+      fun = (verbose) ? "float" : "flt";
+      op[0] = XEXP (x, 0);
+      break;
+    case UNSIGNED_FLOAT:
+      fun = (verbose) ? "uns_float" : "ufl";
+      op[0] = XEXP (x, 0);
+      break;
+    case FIX:
+      fun = "fix";
+      op[0] = XEXP (x, 0);
+      break;
+    case UNSIGNED_FIX:
+      fun = (verbose) ? "uns_fix" : "ufx";
+      op[0] = XEXP (x, 0);
+      break;
+    case PRE_DEC:
+      st[0] = "--";
+      op[0] = XEXP (x, 0);
+      break;
+    case PRE_INC:
+      st[0] = "++";
+      op[0] = XEXP (x, 0);
+      break;
+    case POST_DEC:
+      op[0] = XEXP (x, 0);
+      st[1] = "--";
+      break;
+    case POST_INC:
+      op[0] = XEXP (x, 0);
+      st[1] = "++";
+      break;
+    case CALL:
+      st[0] = "call ";
+      op[0] = XEXP (x, 0);
+      if (verbose)
+	{
+	  st[1] = " argc:";
+	  op[1] = XEXP (x, 1);
+	}
+      break;
+    case IF_THEN_ELSE:
+      st[0] = "{(";
+      op[0] = XEXP (x, 0);
+      st[1] = ")?";
+      op[1] = XEXP (x, 1);
+      st[2] = ":";
+      op[2] = XEXP (x, 2);
+      st[3] = "}";
+      break;
+    case TRAP_IF:
+      fun = "trap_if";
+      op[0] = TRAP_CONDITION (x);
+      break;
+    case UNSPEC:
+    case UNSPEC_VOLATILE:
+      {
+	cur = safe_concat (buf, cur, "unspec");
+	if (GET_CODE (x) == UNSPEC_VOLATILE)
+	  cur = safe_concat (buf, cur, "/v");
+	cur = safe_concat (buf, cur, "[");
+	sep = "";
+	for (i = 0; i < XVECLEN (x, 0); i++)
+	  {
+	    print_pattern (tmp, XVECEXP (x, 0, i), verbose);
+	    cur = safe_concat (buf, cur, sep);
+	    cur = safe_concat (buf, cur, tmp);
+	    sep = ",";
+	  }
+	cur = safe_concat (buf, cur, "] ");
+	sprintf (tmp, "%d", XINT (x, 1));
+	cur = safe_concat (buf, cur, tmp);
+      }
+      break;
+    default:
+      /* If (verbose) debug_rtx (x);  */
+      st[0] = GET_RTX_NAME (GET_CODE (x));
+      break;
+    }
+
+  /* Print this as a function?  */
+  if (fun)
+    {
+      cur = safe_concat (buf, cur, fun);
+      cur = safe_concat (buf, cur, "(");
+    }
+
+  for (i = 0; i < 4; i++)
+    {
+      if (st[i])
+	cur = safe_concat (buf, cur, st[i]);
+
+      if (op[i])
+	{
+	  if (fun && i != 0)
+	    cur = safe_concat (buf, cur, ",");
+
+	  print_value (tmp, op[i], verbose);
+	  cur = safe_concat (buf, cur, tmp);
+	}
+    }
+
+  if (fun)
+    cur = safe_concat (buf, cur, ")");
+}		/* print_exp */
+
+/* Prints rtxes, I customly classified as values.  They're constants,
+   registers, labels, symbols and memory accesses.  */
+
+static void
+print_value (buf, x, verbose)
+     char *buf;
+     rtx x;
+     int verbose;
+{
+  char t[BUF_LEN];
+  char *cur = buf;
+
+  switch (GET_CODE (x))
+    {
+    case CONST_INT:
+      sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
+      cur = safe_concat (buf, cur, t);
+      break;
+    case CONST_DOUBLE:
+      sprintf (t, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
+      cur = safe_concat (buf, cur, t);
+      break;
+    case CONST_STRING:
+      cur = safe_concat (buf, cur, "\"");
+      cur = safe_concat (buf, cur, XSTR (x, 0));
+      cur = safe_concat (buf, cur, "\"");
+      break;
+    case SYMBOL_REF:
+      cur = safe_concat (buf, cur, "`");
+      cur = safe_concat (buf, cur, XSTR (x, 0));
+      cur = safe_concat (buf, cur, "'");
+      break;
+    case LABEL_REF:
+      sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
+    case CONST:
+      print_value (t, XEXP (x, 0), verbose);
+      cur = safe_concat (buf, cur, "const(");
+      cur = safe_concat (buf, cur, t);
+      cur = safe_concat (buf, cur, ")");
+      break;
+    case HIGH:
+      print_value (t, XEXP (x, 0), verbose);
+      cur = safe_concat (buf, cur, "high(");
+      cur = safe_concat (buf, cur, t);
+      cur = safe_concat (buf, cur, ")");
+      break;
+    case REG:
+      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
+	{
+	  int c = reg_names[REGNO (x)][0];
+	  if (c >= '0' && c <= '9')
+	    cur = safe_concat (buf, cur, "%");
+
+	  cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
+	}
+      else
+	{
+	  sprintf (t, "r%d", REGNO (x));
+	  cur = safe_concat (buf, cur, t);
+	}
+      break;
+    case SUBREG:
+      print_value (t, SUBREG_REG (x), verbose);
+      cur = safe_concat (buf, cur, t);
+      sprintf (t, "#%d", SUBREG_WORD (x));
+      cur = safe_concat (buf, cur, t);
+      break;
+    case SCRATCH:
+      cur = safe_concat (buf, cur, "scratch");
+      break;
+    case CC0:
+      cur = safe_concat (buf, cur, "cc0");
+      break;
+    case PC:
+      cur = safe_concat (buf, cur, "pc");
+      break;
+    case MEM:
+      print_value (t, XEXP (x, 0), verbose);
+      cur = safe_concat (buf, cur, "[");
+      cur = safe_concat (buf, cur, t);
+      cur = safe_concat (buf, cur, "]");
+      break;
+    default:
+      print_exp (t, x, verbose);
+      cur = safe_concat (buf, cur, t);
+      break;
+    }
+}				/* print_value */
+
+/* The next step in insn detalization, its pattern recognition.  */
+
+static void
+print_pattern (buf, x, verbose)
+     char *buf;
+     rtx x;
+     int verbose;
+{
+  char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
+
+  switch (GET_CODE (x))
+    {
+    case SET:
+      print_value (t1, SET_DEST (x), verbose);
+      print_value (t2, SET_SRC (x), verbose);
+      sprintf (buf, "%s=%s", t1, t2);
+      break;
+    case RETURN:
+      sprintf (buf, "return");
+      break;
+    case CALL:
+      print_exp (buf, x, verbose);
+      break;
+    case CLOBBER:
+      print_value (t1, XEXP (x, 0), verbose);
+      sprintf (buf, "clobber %s", t1);
+      break;
+    case USE:
+      print_value (t1, XEXP (x, 0), verbose);
+      sprintf (buf, "use %s", t1);
+      break;
+    case COND_EXEC:
+      if (GET_CODE (COND_EXEC_TEST (x)) == NE
+	  && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
+	print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
+      else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
+               && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
+        {
+	  t1[0] = '!';
+	  print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
+	}
+      else
+        print_value (t1, COND_EXEC_TEST (x), verbose);
+      print_pattern (t2, COND_EXEC_CODE (x), verbose);
+      sprintf (buf, "(%s) %s", t1, t2);
+      break;
+    case PARALLEL:
+      {
+	int i;
+
+	sprintf (t1, "{");
+	for (i = 0; i < XVECLEN (x, 0); i++)
+	  {
+	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
+	    sprintf (t3, "%s%s;", t1, t2);
+	    strcpy (t1, t3);
+	  }
+	sprintf (buf, "%s}", t1);
+      }
+      break;
+    case SEQUENCE:
+      {
+	int i;
+
+	sprintf (t1, "%%{");
+	for (i = 0; i < XVECLEN (x, 0); i++)
+	  {
+	    print_insn (t2, XVECEXP (x, 0, i), verbose);
+	    sprintf (t3, "%s%s;", t1, t2);
+	    strcpy (t1, t3);
+	  }
+	sprintf (buf, "%s%%}", t1);
+      }
+      break;
+    case ASM_INPUT:
+      sprintf (buf, "asm {%s}", XSTR (x, 0));
+      break;
+    case ADDR_VEC:
+      break;
+    case ADDR_DIFF_VEC:
+      print_value (buf, XEXP (x, 0), verbose);
+      break;
+    case TRAP_IF:
+      print_value (t1, TRAP_CONDITION (x), verbose);
+      sprintf (buf, "trap_if %s", t1);
+      break;
+    case UNSPEC:
+      {
+	int i;
+
+	sprintf (t1, "unspec{");
+	for (i = 0; i < XVECLEN (x, 0); i++)
+	  {
+	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
+	    sprintf (t3, "%s%s;", t1, t2);
+	    strcpy (t1, t3);
+	  }
+	sprintf (buf, "%s}", t1);
+      }
+      break;
+    case UNSPEC_VOLATILE:
+      {
+	int i;
+
+	sprintf (t1, "unspec/v{");
+	for (i = 0; i < XVECLEN (x, 0); i++)
+	  {
+	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
+	    sprintf (t3, "%s%s;", t1, t2);
+	    strcpy (t1, t3);
+	  }
+	sprintf (buf, "%s}", t1);
+      }
+      break;
+    default:
+      print_value (buf, x, verbose);
+    }
+}				/* print_pattern */
+
+/* This is the main function in rtl visualization mechanism. It
+   accepts an rtx and tries to recognize it as an insn, then prints it
+   properly in human readable form, resembling assembler mnemonics.
+   For every insn it prints its UID and BB the insn belongs too.
+   (Probably the last "option" should be extended somehow, since it
+   depends now on sched.c inner variables ...)  */
+
+static void
+print_insn (buf, x, verbose)
+     char *buf;
+     rtx x;
+     int verbose;
+{
+  char t[BUF_LEN];
+  rtx insn = x;
+
+  switch (GET_CODE (x))
+    {
+    case INSN:
+      print_pattern (t, PATTERN (x), verbose);
+      if (verbose)
+	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
+		 t);
+      else
+	sprintf (buf, "%-4d %s", INSN_UID (x), t);
+      break;
+    case JUMP_INSN:
+      print_pattern (t, PATTERN (x), verbose);
+      if (verbose)
+	sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
+		 t);
+      else
+	sprintf (buf, "%-4d %s", INSN_UID (x), t);
+      break;
+    case CALL_INSN:
+      x = PATTERN (insn);
+      if (GET_CODE (x) == PARALLEL)
+	{
+	  x = XVECEXP (x, 0, 0);
+	  print_pattern (t, x, verbose);
+	}
+      else
+	strcpy (t, "call <...>");
+      if (verbose)
+	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
+      else
+	sprintf (buf, "%-4d %s", INSN_UID (insn), t);
+      break;
+    case CODE_LABEL:
+      sprintf (buf, "L%d:", INSN_UID (x));
+      break;
+    case BARRIER:
+      sprintf (buf, "i% 4d: barrier", INSN_UID (x));
+      break;
+    case NOTE:
+      if (NOTE_LINE_NUMBER (x) > 0)
+	sprintf (buf, "%4d note \"%s\" %d", INSN_UID (x),
+		 NOTE_SOURCE_FILE (x), NOTE_LINE_NUMBER (x));
+      else
+	sprintf (buf, "%4d %s", INSN_UID (x),
+		 GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x)));
+      break;
+    default:
+      if (verbose)
+	{
+	  sprintf (buf, "Not an INSN at all\n");
+	  debug_rtx (x);
+	}
+      else
+	sprintf (buf, "i%-4d  <What?>", INSN_UID (x));
+    }
+}				/* print_insn */
+
+/* Print visualization debugging info.  */
+
+void
+print_block_visualization (s)
+     const char *s;
+{
+  int unit, i;
+
+  /* Print header.  */
+  fprintf (sched_dump, "\n;;   ==================== scheduling visualization %s \n", s);
+
+  /* Print names of units.  */
+  fprintf (sched_dump, ";;   %-8s", "clock");
+  for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
+    if (function_units[unit].bitmask & target_units)
+      for (i = 0; i < function_units[unit].multiplicity; i++)
+	fprintf (sched_dump, "  %-33s", function_units[unit].name);
+  fprintf (sched_dump, "  %-8s\n", "no-unit");
+
+  fprintf (sched_dump, ";;   %-8s", "=====");
+  for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
+    if (function_units[unit].bitmask & target_units)
+      for (i = 0; i < function_units[unit].multiplicity; i++)
+	fprintf (sched_dump, "  %-33s", "==============================");
+  fprintf (sched_dump, "  %-8s\n", "=======");
+
+  /* Print insns in each cycle.  */
+  fprintf (sched_dump, "%s\n", visual_tbl);
+}
+
+/* Print insns in the 'no_unit' column of visualization.  */
+
+void
+visualize_no_unit (insn)
+     rtx insn;
+{
+  vis_no_unit[n_vis_no_unit] = insn;
+  n_vis_no_unit++;
+}
+
+/* Print insns scheduled in clock, for visualization.  */
+
+void
+visualize_scheduled_insns (clock)
+     int clock;
+{
+  int i, unit;
+
+  /* If no more room, split table into two.  */
+  if (n_visual_lines >= MAX_VISUAL_LINES)
+    {
+      print_block_visualization ("(incomplete)");
+      init_block_visualization ();
+    }
+
+  n_visual_lines++;
+
+  sprintf (visual_tbl + strlen (visual_tbl), ";;   %-8d", clock);
+  for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
+    if (function_units[unit].bitmask & target_units)
+      for (i = 0; i < function_units[unit].multiplicity; i++)
+	{
+	  int instance = unit + i * FUNCTION_UNITS_SIZE;
+	  rtx insn = get_unit_last_insn (instance);
+
+	  /* Print insns that still keep the unit busy.  */
+	  if (insn
+	      && actual_hazard_this_instance (unit, instance, insn, clock, 0))
+	    {
+	      char str[BUF_LEN];
+	      print_insn (str, insn, 0);
+	      str[INSN_LEN] = '\0';
+	      sprintf (visual_tbl + strlen (visual_tbl), "  %-33s", str);
+	    }
+	  else
+	    sprintf (visual_tbl + strlen (visual_tbl), "  %-33s", "------------------------------");
+	}
+
+  /* Print insns that are not assigned to any unit.  */
+  for (i = 0; i < n_vis_no_unit; i++)
+    sprintf (visual_tbl + strlen (visual_tbl), "  %-8d",
+	     INSN_UID (vis_no_unit[i]));
+  n_vis_no_unit = 0;
+
+  sprintf (visual_tbl + strlen (visual_tbl), "\n");
+}
+
+/* Print stalled cycles.  */
+
+void
+visualize_stall_cycles (stalls)
+     int stalls;
+{
+  int i;
+
+  /* If no more room, split table into two.  */
+  if (n_visual_lines >= MAX_VISUAL_LINES)
+    {
+      print_block_visualization ("(incomplete)");
+      init_block_visualization ();
+    }
+
+  n_visual_lines++;
+
+  sprintf (visual_tbl + strlen (visual_tbl), ";;       ");
+  for (i = 0; i < stalls; i++)
+    sprintf (visual_tbl + strlen (visual_tbl), ".");
+  sprintf (visual_tbl + strlen (visual_tbl), "\n");
+}
+
+/* Allocate data used for visualization during scheduling.  */
+
+void
+visualize_alloc ()
+{
+  visual_tbl = xmalloc (get_visual_tbl_length ());
+}
+
+/* Free data used for visualization.  */
+
+void
+visualize_free ()
+{
+  free (visual_tbl);
+}
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Makefile.in,v
retrieving revision 1.554
diff -u -p -r1.554 Makefile.in
--- Makefile.in	2000/12/03 12:53:48	1.554
+++ Makefile.in	2000/12/03 14:33:44
@@ -737,7 +737,7 @@ OBJS = diagnostic.o version.o tree.o pri
  mbchar.o splay-tree.o graph.o sbitmap.o resource.o hash.o predict.o	      \
  lists.o ggc-common.o $(GGC) stringpool.o simplify-rtx.o ssa.o bb-reorder.o   \
  sibcall.o conflict.o timevar.o ifcvt.o dominance.o dependence.o dce.o \
- hashtab.o
+ sched-vis.o hashtab.o
 
 BACKEND = toplev.o libbackend.a
 
@@ -1455,6 +1455,8 @@ regmove.o : regmove.c $(CONFIG_H) system
 haifa-sched.o : haifa-sched.c $(CONFIG_H) system.h $(RTL_H) sched-int.h \
    $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
    $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h
+sched-vis.o : sched-vis.c $(CONFIG_H) system.h $(RTL_H) sched-int.h \
+   $(INSN_ATTR_H) $(REGS_H)
 final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h intl.h \
    $(REGS_H) $(RECOG_H) conditions.h insn-config.h $(INSN_ATTR_H) function.h \
    real.h output.h hard-reg-set.h insn-flags.h insn-codes.h gstab.h except.h \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]