Regclass cleanups

Jan Hubicka hubicka@atrey.karlin.mff.cuni.cz
Sat Jan 1 15:05:00 GMT 2000


Hi
This patch contains some preparation work necesary for my propagation patch.
Basically it just converts op_costs to local variable, adds new parameter to
record_reg_classes to specify reg_pref structure currently in use, breaks out
the operand cost calculations from scan_one_insn and improves dumps (prints the
preferences choosed and changes made in the second pass), makes regclass to
ignore unreferenced registers and fixes simple bug in scan_one_insn, that was
ignoring ASM_INPUT instructions for no purpose.  I believe it is incorrect to
just ignore their preferrences.

Sat Jan  1 13:57:40 CET 2000  Jan Hubicka  <hubicka@freesoft.cz>
	* regclass.c (op_costs): Remove global variable.
	(record_reg_classes): New parameter "op_costs" and "reg_pref".
	(record_operand_costs): Break out from ...
	(scan_one_insn): ... here; process ASM_INPUT insns.
	(dump_regclass): Make dumps nicer.
	(regclass): Dump preferrences choosed and changes done during passes.
*** regclass.c.nopro	Sat Jan  1 12:16:55 2000
--- regclass.c	Sat Jan  1 13:53:39 2000
*************** static struct costs *costs;
*** 703,714 ****
  
  static struct costs init_cost;
  
- /* Record the same data by operand number, accumulated for each alternative
-    in an insn.  The contribution to a pseudo is that of the minimum-cost
-    alternative.  */
- 
- static struct costs op_costs[MAX_RECOG_OPERANDS];
- 
  /* Record preferrences of each pseudo.
     This is available after `regclass' is run.  */
  
--- 703,708 ----
*************** static struct reg_pref *reg_pref_buffer;
*** 724,732 ****
  static int loop_cost;
  
  static rtx scan_one_insn	PROTO((rtx, int));
  static void dump_regclass	PROTO((FILE *));
  static void record_reg_classes	PROTO((int, int, rtx *, enum machine_mode *,
! 				       char *, const char **, rtx));
  static int copy_cost		PROTO((rtx, enum machine_mode, 
  				       enum reg_class, int));
  static void record_address_regs	PROTO((rtx, enum reg_class, int));
--- 718,728 ----
  static int loop_cost;
  
  static rtx scan_one_insn	PROTO((rtx, int));
+ static void record_operand_costs PROTO((rtx, struct costs *, struct reg_pref *));
  static void dump_regclass	PROTO((FILE *));
  static void record_reg_classes	PROTO((int, int, rtx *, enum machine_mode *,
! 				       char *, const char **, rtx,
! 				       struct costs *, struct reg_pref *));
  static int copy_cost		PROTO((rtx, enum machine_mode, 
  				       enum reg_class, int));
  static void record_address_regs	PROTO((rtx, enum reg_class, int));
*************** dump_regclass (dump)
*** 789,803 ****
        enum reg_class class;
        if (REG_N_REFS (i))
  	{
! 	  fprintf (dump, ";; Register %i costs:", i);
  	  for (class = 0; class < N_REG_CLASSES; class++)
  	    fprintf (dump, " %s:%i", reg_class_names[(int) class],
  		     costs[i].cost[class]);
! 	  fprintf (dump, " MEM:%i\n\n", costs[i].mem_cost);
  	}
      }
  }
  
  
  /* Subroutine of regclass, processes one insn INSN.  Scan it and record each
     time it would save code to put a certain register in a certain class.
--- 785,873 ----
        enum reg_class class;
        if (REG_N_REFS (i))
  	{
! 	  fprintf (dump, "  Register %i costs:", i);
  	  for (class = 0; class < N_REG_CLASSES; class++)
  	    fprintf (dump, " %s:%i", reg_class_names[(int) class],
  		     costs[i].cost[class]);
! 	  fprintf (dump, " MEM:%i\n", costs[i].mem_cost);
  	}
      }
  }
+ 
+ 
+ /* Calculate the costs of insn operands.  */
+ 
+ static void
+ record_operand_costs (insn, op_costs, reg_pref)
+      rtx insn;
+      struct costs *op_costs;
+      struct reg_pref *reg_pref;
+ {
+   const char *constraints[MAX_RECOG_OPERANDS];
+   enum machine_mode modes[MAX_RECOG_OPERANDS];
+   char subreg_changes_size[MAX_RECOG_OPERANDS];
+   int i;
+ 
+   for (i = 0; i < recog_data.n_operands; i++)
+     {
+       constraints[i] = recog_data.constraints[i];
+       modes[i] = recog_data.operand_mode[i];
+     }
+   memset (subreg_changes_size, 0, sizeof (subreg_changes_size));
+ 
+   /* If we get here, we are set up to record the costs of all the
+      operands for this insn.  Start by initializing the costs.
+      Then handle any address registers.  Finally record the desired
+      classes for any pseudos, doing it twice if some pair of
+      operands are commutative.  */
+ 	     
+   for (i = 0; i < recog_data.n_operands; i++)
+     {
+       op_costs[i] = init_cost;
+ 
+       if (GET_CODE (recog_data.operand[i]) == SUBREG)
+ 	{
+ 	  rtx inner = SUBREG_REG (recog_data.operand[i]);
+ 	  if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner)))
+ 	    subreg_changes_size[i] = 1;
+ 	  recog_data.operand[i] = inner;
+ 	}
+ 
+       if (GET_CODE (recog_data.operand[i]) == MEM)
+ 	record_address_regs (XEXP (recog_data.operand[i], 0),
+ 			     BASE_REG_CLASS, loop_cost * 2);
+       else if (constraints[i][0] == 'p')
+ 	record_address_regs (recog_data.operand[i],
+ 			     BASE_REG_CLASS, loop_cost * 2);
+     }
+ 
+   /* Check for commutative in a separate loop so everything will
+      have been initialized.  We must do this even if one operand
+      is a constant--see addsi3 in m68k.md.  */
+ 
+   for (i = 0; i < (int) recog_data.n_operands - 1; i++)
+     if (constraints[i][0] == '%')
+       {
+ 	const char *xconstraints[MAX_RECOG_OPERANDS];
+ 	int j;
+ 
+ 	/* Handle commutative operands by swapping the constraints.
+ 	   We assume the modes are the same.  */
+ 
+ 	for (j = 0; j < recog_data.n_operands; j++)
+ 	  xconstraints[j] = constraints[j];
+ 
+ 	xconstraints[i] = constraints[i+1];
+ 	xconstraints[i+1] = constraints[i];
+ 	record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
+ 			    recog_data.operand, modes, subreg_changes_size,
+ 			    xconstraints, insn, op_costs, reg_pref);
+       }
  
+   record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
+ 		      recog_data.operand, modes, subreg_changes_size,
+ 		      constraints, insn, op_costs, reg_pref);
+ }
  
  /* Subroutine of regclass, processes one insn INSN.  Scan it and record each
     time it would save code to put a certain register in a certain class.
*************** scan_one_insn (insn, pass)
*** 813,831 ****
  {
    enum rtx_code code = GET_CODE (insn);
    enum rtx_code pat_code;
-   const char *constraints[MAX_RECOG_OPERANDS];
-   enum machine_mode modes[MAX_RECOG_OPERANDS];
-   char subreg_changes_size[MAX_RECOG_OPERANDS];
    rtx set, note;
    int i, j;
  
    if (GET_RTX_CLASS (code) != 'i')
      return insn;
  
    pat_code = GET_CODE (PATTERN (insn));
    if (pat_code == USE
        || pat_code == CLOBBER
-       || pat_code == ASM_INPUT
        || pat_code == ADDR_VEC
        || pat_code == ADDR_DIFF_VEC)
      return insn;
--- 883,899 ----
  {
    enum rtx_code code = GET_CODE (insn);
    enum rtx_code pat_code;
    rtx set, note;
    int i, j;
  
+   struct costs op_costs[MAX_RECOG_OPERANDS];
+ 
    if (GET_RTX_CLASS (code) != 'i')
      return insn;
  
    pat_code = GET_CODE (PATTERN (insn));
    if (pat_code == USE
        || pat_code == CLOBBER
        || pat_code == ADDR_VEC
        || pat_code == ADDR_DIFF_VEC)
      return insn;
*************** scan_one_insn (insn, pass)
*** 833,845 ****
    set = single_set (insn);
    extract_insn (insn);
  
-   for (i = 0; i < recog_data.n_operands; i++)
-     {
-       constraints[i] = recog_data.constraints[i];
-       modes[i] = recog_data.operand_mode[i];
-     }
-   memset (subreg_changes_size, 0, sizeof (subreg_changes_size));
- 
    /* If this insn loads a parameter from its stack slot, then
       it represents a savings, rather than a cost, if the
       parameter is stored in memory.  Record this fact.  */
--- 901,906 ----
*************** scan_one_insn (insn, pass)
*** 911,968 ****
        return PREV_INSN (newinsn);
      }
  
!   /* If we get here, we are set up to record the costs of all the
!      operands for this insn.  Start by initializing the costs.
!      Then handle any address registers.  Finally record the desired
!      classes for any pseudos, doing it twice if some pair of
!      operands are commutative.  */
! 	     
!   for (i = 0; i < recog_data.n_operands; i++)
!     {
!       op_costs[i] = init_cost;
! 
!       if (GET_CODE (recog_data.operand[i]) == SUBREG)
! 	{
! 	  rtx inner = SUBREG_REG (recog_data.operand[i]);
! 	  if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner)))
! 	    subreg_changes_size[i] = 1;
! 	  recog_data.operand[i] = inner;
! 	}
! 
!       if (GET_CODE (recog_data.operand[i]) == MEM)
! 	record_address_regs (XEXP (recog_data.operand[i], 0),
! 			     BASE_REG_CLASS, loop_cost * 2);
!       else if (constraints[i][0] == 'p')
! 	record_address_regs (recog_data.operand[i],
! 			     BASE_REG_CLASS, loop_cost * 2);
!     }
! 
!   /* Check for commutative in a separate loop so everything will
!      have been initialized.  We must do this even if one operand
!      is a constant--see addsi3 in m68k.md.  */
! 
!   for (i = 0; i < (int) recog_data.n_operands - 1; i++)
!     if (constraints[i][0] == '%')
!       {
! 	const char *xconstraints[MAX_RECOG_OPERANDS];
! 	int j;
! 
! 	/* Handle commutative operands by swapping the constraints.
! 	   We assume the modes are the same.  */
! 
! 	for (j = 0; j < recog_data.n_operands; j++)
! 	  xconstraints[j] = constraints[j];
! 
! 	xconstraints[i] = constraints[i+1];
! 	xconstraints[i+1] = constraints[i];
! 	record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
! 			    recog_data.operand, modes, subreg_changes_size,
! 			    xconstraints, insn);
!       }
! 
!   record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
! 		      recog_data.operand, modes, subreg_changes_size,
! 		      constraints, insn);
  
    /* Now add the cost for each operand to the total costs for
       its register.  */
--- 972,978 ----
        return PREV_INSN (newinsn);
      }
  
!   record_operand_costs(insn, op_costs, reg_pref);
  
    /* Now add the cost for each operand to the total costs for
       its register.  */
*************** regclass (f, nregs, dump)
*** 1062,1067 ****
--- 1072,1080 ----
    for (pass = 0; pass <= flag_expensive_optimizations; pass++)
      {
        int index;
+ 
+       if (dump)
+         fprintf (dump, "\n\nPass %i\n\n",pass);
        /* Zero out our accumulation of the cost of each class for each reg.  */
  
        bzero ((char *) costs, nregs * sizeof (struct costs));
*************** regclass (f, nregs, dump)
*** 1102,1107 ****
--- 1115,1125 ----
        if (pass == 0)
  	reg_pref = reg_pref_buffer;
  
+       if (dump)
+         {
+ 	  dump_regclass (dump);
+ 	  fprintf(dump,"\n");
+ 	}
        for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
  	{
  	  register int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
*************** regclass (f, nregs, dump)
*** 1111,1116 ****
--- 1129,1137 ----
  	  register int class;
  	  register struct costs *p = &costs[i];
  
+ 	  if (!REG_N_REFS (i))
+ 	    continue;
+ 
  	  for (class = (int) ALL_REGS - 1; class > 0; class--)
  	    {
  	      /* Ignore classes that are too small for this operand or
*************** regclass (f, nregs, dump)
*** 1138,1144 ****
  	     should be provided as a register class.  Don't do this if we
  	     will be doing it again later.  */
  
! 	  if (pass == 1 || ! flag_expensive_optimizations)
  	    for (class = 0; class < N_REG_CLASSES; class++)
  	      if (p->cost[class] < p->mem_cost
  		  && (reg_class_size[(int) reg_class_subunion[(int) alt][class]]
--- 1159,1165 ----
  	     should be provided as a register class.  Don't do this if we
  	     will be doing it again later.  */
  
! 	  if ((pass == 1  || dump) || ! flag_expensive_optimizations)
  	    for (class = 0; class < N_REG_CLASSES; class++)
  	      if (p->cost[class] < p->mem_cost
  		  && (reg_class_size[(int) reg_class_subunion[(int) alt][class]]
*************** regclass (f, nregs, dump)
*** 1153,1167 ****
  	  if (alt == best)
  	    alt = NO_REGS;
  
  	  /* We cast to (int) because (char) hits bugs in some compilers.  */
  	  reg_pref[i].prefclass = (int) best;
  	  reg_pref[i].altclass = (int) alt;
  	}
-       if (dump)
- 	{
- 	  fprintf (dump, "\nPass %i\n",pass);
- 	  dump_regclass (dump);
- 	}
      }
  
  #ifdef FORBIDDEN_INC_DEC_CLASSES
--- 1174,1197 ----
  	  if (alt == best)
  	    alt = NO_REGS;
  
+ 	  if (dump 
+ 	      && (reg_pref[i].prefclass != (int) best || reg_pref[i].altclass != (int) alt))
+ 	    {
+ 	      static const char *const reg_class_names[] = REG_CLASS_NAMES;
+ 	      fprintf(dump, "  Register %i", i);
+ 	      if (alt == ALL_REGS || best == ALL_REGS)
+ 		fprintf (dump, " pref %s\n", reg_class_names[(int) best]);
+ 	      else if (alt == NO_REGS)
+ 		fprintf (dump, " pref %s or none\n", reg_class_names[(int) best]);
+ 	      else
+ 		fprintf (dump, " pref %s, else %s\n",
+ 			 reg_class_names[(int) best],
+ 			 reg_class_names[(int) alt]);
+ 	    }
  	  /* We cast to (int) because (char) hits bugs in some compilers.  */
  	  reg_pref[i].prefclass = (int) best;
  	  reg_pref[i].altclass = (int) alt;
  	}
      }
  
  #ifdef FORBIDDEN_INC_DEC_CLASSES
*************** regclass (f, nregs, dump)
*** 1196,1202 ****
  
  static void
  record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
! 		    constraints, insn)
       int n_alts;
       int n_ops;
       rtx *ops;
--- 1226,1232 ----
  
  static void
  record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
! 		    constraints, insn, op_costs, reg_pref)
       int n_alts;
       int n_ops;
       rtx *ops;
*************** record_reg_classes (n_alts, n_ops, ops, 
*** 1204,1209 ****
--- 1234,1241 ----
       char *subreg_changes_size ATTRIBUTE_UNUSED;
       const char **constraints;
       rtx insn;
+      struct costs *op_costs;
+      struct reg_pref *reg_pref;
  {
    int alt;
    int i, j;


More information about the Gcc-patches mailing list