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]

Small preparatory cleanup patch


Before I send the next parts of the extract_insn changes, here is a small
patch that makes part of the affected code more readable so that it's
easier to verify the next patch.  This patch shouldn't change any behaviour.

Bernd

	* regclass.c (regclass): Break out some code into new function
	scan_one_insn, and into regclass_init.
	(init_cost): New static variable, moved out of regclass.
	(regclass_init): Initialize it here, not in .
	(scan_one_insn): New static function, broken out of regclass.
	* recog.c (apply_change_group): Break out some code into new
	function insn_invalid_p.
	(insn_invalid_p): New static fn, broken out of apply_change_group.

Index: regclass.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/regclass.c,v
retrieving revision 1.35
diff -u -p -r1.35 regclass.c
--- regclass.c	1998/10/20 08:03:34	1.35
+++ regclass.c	1998/10/22 09:42:10
@@ -648,6 +648,10 @@ struct costs
 
 static struct costs *costs;
 
+/* Initialized once, and used to initialize cost values for each insn.  */
+
+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.  */
@@ -685,6 +689,7 @@ static int loop_depth;
 static int loop_cost;
 
 static int n_occurrences	PROTO((int, char *));
+static rtx scan_one_insn	PROTO((rtx, int));
 static void record_reg_classes	PROTO((int, int, rtx *, enum machine_mode *,
 				       char **, rtx));
 static int copy_cost		PROTO((rtx, enum machine_mode, 
@@ -718,12 +723,19 @@ reg_alternate_class (regno)
   return (enum reg_class) altclass[regno];
 }
 
-/* This prevents dump_flow_info from losing if called
-   before regclass is run.  */
+/* Initialize some global data for this pass.  */
 
 void
 regclass_init ()
 {
+  int i;
+
+  init_cost.mem_cost = 10000;
+  for (i = 0; i < N_REG_CLASSES; i++)
+    init_cost.cost[i] = 10000;
+
+  /* This prevents dump_flow_info from losing if called
+     before regclass is run.  */
   prefclass = 0;
 }
 
@@ -739,6 +751,221 @@ n_occurrences (c, s)
   return n;
 }
 
+/* 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.
+   PASS, when nonzero, inhibits some optimizations which need only be done
+   once.
+   Return the last insn processed, so that the scan can be continued from
+   there.  */
+
+static rtx
+scan_one_insn (insn, pass)
+     rtx insn;
+     int pass;
+{
+  enum rtx_code code = GET_CODE (insn);
+  enum rtx_code pat_code;
+
+  char *constraints[MAX_RECOG_OPERANDS];
+  enum machine_mode modes[MAX_RECOG_OPERANDS];
+  int nalternatives;
+  int noperands;
+  rtx set;
+  int i, j;
+
+  /* Show that an insn inside a loop is likely to be executed three
+     times more than insns outside a loop.  This is much more aggressive
+     than the assumptions made elsewhere and is being tried as an
+     experiment.  */
+
+  if (code == NOTE)
+    {
+      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+	loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5));
+      else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+	loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5));
+
+      return insn;
+    }
+
+  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;
+
+  if (code == INSN
+      && (noperands = asm_noperands (PATTERN (insn))) >= 0)
+    {
+      decode_asm_operands (PATTERN (insn), recog_operand, NULL_PTR,
+			   constraints, modes);
+      nalternatives = (noperands == 0 ? 0
+		       : n_occurrences (',', constraints[0]) + 1);
+    }
+  else
+    {
+      int insn_code_number = recog_memoized (insn);
+      rtx note;
+
+      set = single_set (insn);
+      insn_extract (insn);
+
+      nalternatives = insn_n_alternatives[insn_code_number];
+      noperands = insn_n_operands[insn_code_number];
+
+      /* 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.  */
+
+      if (set != 0 && GET_CODE (SET_DEST (set)) == REG
+	  && GET_CODE (SET_SRC (set)) == MEM
+	  && (note = find_reg_note (insn, REG_EQUIV,
+				    NULL_RTX)) != 0
+	  && GET_CODE (XEXP (note, 0)) == MEM)
+	{
+	  costs[REGNO (SET_DEST (set))].mem_cost
+	    -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
+				  GENERAL_REGS, 1)
+		* loop_cost);
+	  record_address_regs (XEXP (SET_SRC (set), 0),
+			       BASE_REG_CLASS, loop_cost * 2);
+	  return insn;
+	}
+
+      /* Improve handling of two-address insns such as
+	 (set X (ashift CONST Y)) where CONST must be made to
+	 match X. Change it into two insns: (set X CONST)
+	 (set X (ashift X Y)).  If we left this for reloading, it
+	 would probably get three insns because X and Y might go
+	 in the same place. This prevents X and Y from receiving
+	 the same hard reg.
+
+	 We can only do this if the modes of operands 0 and 1
+	 (which might not be the same) are tieable and we only need
+	 do this during our first pass.  */
+
+      if (pass == 0 && optimize
+	  && noperands >= 3
+	  && insn_operand_constraint[insn_code_number][1][0] == '0'
+	  && insn_operand_constraint[insn_code_number][1][1] == 0
+	  && CONSTANT_P (recog_operand[1])
+	  && ! rtx_equal_p (recog_operand[0], recog_operand[1])
+	  && ! rtx_equal_p (recog_operand[0], recog_operand[2])
+	  && GET_CODE (recog_operand[0]) == REG
+	  && MODES_TIEABLE_P (GET_MODE (recog_operand[0]),
+			      insn_operand_mode[insn_code_number][1]))
+	{
+	  rtx previnsn = prev_real_insn (insn);
+	  rtx dest
+	    = gen_lowpart (insn_operand_mode[insn_code_number][1],
+			   recog_operand[0]);
+	  rtx newinsn
+	    = emit_insn_before (gen_move_insn (dest,
+					       recog_operand[1]),
+				insn);
+
+	  /* If this insn was the start of a basic block,
+	     include the new insn in that block.
+	     We need not check for code_label here;
+	     while a basic block can start with a code_label,
+	     INSN could not be at the beginning of that block.  */
+	  if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN)
+	    {
+	      int b;
+	      for (b = 0; b < n_basic_blocks; b++)
+		if (insn == basic_block_head[b])
+		  basic_block_head[b] = newinsn;
+	    }
+
+	  /* This makes one more setting of new insns's dest.  */
+	  REG_N_SETS (REGNO (recog_operand[0]))++;
+
+	  *recog_operand_loc[1] = recog_operand[0];
+	  for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
+	    if (recog_dup_num[i] == 1)
+	      *recog_dup_loc[i] = recog_operand[0];
+
+	  return PREV_INSN (newinsn);
+	}
+
+      for (i = 0; i < noperands; i++)
+	{
+	  constraints[i]
+	    = insn_operand_constraint[insn_code_number][i];
+	  modes[i] = insn_operand_mode[insn_code_number][i];
+	}
+    }
+
+  /* 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 < noperands; i++)
+    {
+      op_costs[i] = init_cost;
+
+      if (GET_CODE (recog_operand[i]) == SUBREG)
+	recog_operand[i] = SUBREG_REG (recog_operand[i]);
+
+      if (GET_CODE (recog_operand[i]) == MEM)
+	record_address_regs (XEXP (recog_operand[i], 0),
+			     BASE_REG_CLASS, loop_cost * 2);
+      else if (constraints[i][0] == 'p')
+	record_address_regs (recog_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 < noperands - 1; i++)
+    if (constraints[i][0] == '%')
+      {
+	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 < noperands; j++)
+	  xconstraints[j] = constraints[j];
+
+	xconstraints[i] = constraints[i+1];
+	xconstraints[i+1] = constraints[i];
+	record_reg_classes (nalternatives, noperands,
+			    recog_operand, modes, xconstraints,
+			    insn);
+      }
+
+  record_reg_classes (nalternatives, noperands, recog_operand,
+		      modes, constraints, insn);
+
+  /* Now add the cost for each operand to the total costs for
+     its register.  */
+
+  for (i = 0; i < noperands; i++)
+    if (GET_CODE (recog_operand[i]) == REG
+	&& REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER)
+      {
+	int regno = REGNO (recog_operand[i]);
+	struct costs *p = &costs[regno], *q = &op_costs[i];
+
+	p->mem_cost += q->mem_cost * loop_cost;
+	for (j = 0; j < N_REG_CLASSES; j++)
+	  p->cost[j] += q->cost[j] * loop_cost;
+      }
+
+  return insn;
+}
+
 /* This is a pass of the compiler that scans all instructions
    and calculates the preferred class for each pseudo-register.
    This information can be accessed later by calling `reg_preferred_class'.
@@ -751,9 +978,7 @@ regclass (f, nregs)
 {
 #ifdef REGISTER_CONSTRAINTS
   register rtx insn;
-  register int i, j;
-  struct costs init_cost;
-  rtx set;
+  register int i;
   int pass;
 
   init_recog ();
@@ -812,10 +1037,6 @@ regclass (f, nregs)
     }
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
 
-  init_cost.mem_cost = 10000;
-  for (i = 0; i < N_REG_CLASSES; i++)
-    init_cost.cost[i] = 10000;
-
   /* Normally we scan the insns once and determine the best class to use for
      each register.  However, if -fexpensive_optimizations are on, we do so
      twice, the second time using the tentative best classes to guide the
@@ -838,199 +1059,9 @@ regclass (f, nregs)
 
       for (insn = f; insn; insn = NEXT_INSN (insn))
 	{
-	  char *constraints[MAX_RECOG_OPERANDS];
-	  enum machine_mode modes[MAX_RECOG_OPERANDS];
-	  int nalternatives;
-	  int noperands;
-
-	  /* Show that an insn inside a loop is likely to be executed three
-	     times more than insns outside a loop.  This is much more aggressive
-	     than the assumptions made elsewhere and is being tried as an
-	     experiment.  */
-
-	  if (GET_CODE (insn) == NOTE
-	      && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
-	    loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5));
-	  else if (GET_CODE (insn) == NOTE
-		   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
-	    loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5));
-
-	  else if ((GET_CODE (insn) == INSN
-		    && GET_CODE (PATTERN (insn)) != USE
-		    && GET_CODE (PATTERN (insn)) != CLOBBER
-		    && GET_CODE (PATTERN (insn)) != ASM_INPUT)
-		   || (GET_CODE (insn) == JUMP_INSN
-		       && GET_CODE (PATTERN (insn)) != ADDR_VEC
-		       && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
-		   || GET_CODE (insn) == CALL_INSN)
-	    {
-	      if (GET_CODE (insn) == INSN
-		  && (noperands = asm_noperands (PATTERN (insn))) >= 0)
-		{
-		  decode_asm_operands (PATTERN (insn), recog_operand, NULL_PTR,
-				       constraints, modes);
-		  nalternatives = (noperands == 0 ? 0
-				   : n_occurrences (',', constraints[0]) + 1);
-		}
-	      else
-		{
-		  int insn_code_number = recog_memoized (insn);
-		  rtx note;
-
-		  set = single_set (insn);
-		  insn_extract (insn);
-
-		  nalternatives = insn_n_alternatives[insn_code_number];
-		  noperands = insn_n_operands[insn_code_number];
-
-		  /* 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.  */
-
-		  if (set != 0 && GET_CODE (SET_DEST (set)) == REG
-		      && GET_CODE (SET_SRC (set)) == MEM
-		      && (note = find_reg_note (insn, REG_EQUIV,
-						NULL_RTX)) != 0
-		      && GET_CODE (XEXP (note, 0)) == MEM)
-		    {
-		      costs[REGNO (SET_DEST (set))].mem_cost
-			-= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
-					      GENERAL_REGS, 1)
-			    * loop_cost);
-		      record_address_regs (XEXP (SET_SRC (set), 0),
-					   BASE_REG_CLASS, loop_cost * 2);
-		      continue;
-		    }
-	      
-		  /* Improve handling of two-address insns such as
-		     (set X (ashift CONST Y)) where CONST must be made to
-		     match X. Change it into two insns: (set X CONST)
-		     (set X (ashift X Y)).  If we left this for reloading, it
-		     would probably get three insns because X and Y might go
-		     in the same place. This prevents X and Y from receiving
-		     the same hard reg.
-
-		     We can only do this if the modes of operands 0 and 1
-		     (which might not be the same) are tieable and we only need
-		     do this during our first pass.  */
-
-		  if (pass == 0 && optimize
-		      && noperands >= 3
-		      && insn_operand_constraint[insn_code_number][1][0] == '0'
-		      && insn_operand_constraint[insn_code_number][1][1] == 0
-		      && CONSTANT_P (recog_operand[1])
-		      && ! rtx_equal_p (recog_operand[0], recog_operand[1])
-		      && ! rtx_equal_p (recog_operand[0], recog_operand[2])
-		      && GET_CODE (recog_operand[0]) == REG
-		      && MODES_TIEABLE_P (GET_MODE (recog_operand[0]),
-					  insn_operand_mode[insn_code_number][1]))
-		    {
-		      rtx previnsn = prev_real_insn (insn);
-		      rtx dest
-			= gen_lowpart (insn_operand_mode[insn_code_number][1],
-				       recog_operand[0]);
-		      rtx newinsn
-			= emit_insn_before (gen_move_insn (dest,
-							   recog_operand[1]),
-					    insn);
-
-		      /* If this insn was the start of a basic block,
-			 include the new insn in that block.
-			 We need not check for code_label here;
-			 while a basic block can start with a code_label,
-			 INSN could not be at the beginning of that block.  */
-		      if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN)
-			{
-			  int b;
-			  for (b = 0; b < n_basic_blocks; b++)
-			    if (insn == basic_block_head[b])
-			      basic_block_head[b] = newinsn;
-			}
-
-		      /* This makes one more setting of new insns's dest.  */
-		      REG_N_SETS (REGNO (recog_operand[0]))++;
-
-		      *recog_operand_loc[1] = recog_operand[0];
-		      for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
-			if (recog_dup_num[i] == 1)
-			  *recog_dup_loc[i] = recog_operand[0];
-
-		      insn = PREV_INSN (newinsn);
-		      continue;
-		    }
-
-		  for (i = 0; i < noperands; i++)
-		    {
-		      constraints[i]
-			= insn_operand_constraint[insn_code_number][i];
-		      modes[i] = insn_operand_mode[insn_code_number][i];
-		    }
-		}
-
-	      /* 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 < noperands; i++)
-		{
-		  op_costs[i] = init_cost;
-
-		  if (GET_CODE (recog_operand[i]) == SUBREG)
-		    recog_operand[i] = SUBREG_REG (recog_operand[i]);
-
-		  if (GET_CODE (recog_operand[i]) == MEM)
-		    record_address_regs (XEXP (recog_operand[i], 0),
-					 BASE_REG_CLASS, loop_cost * 2);
-		  else if (constraints[i][0] == 'p')
-		    record_address_regs (recog_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 < noperands - 1; i++)
-		if (constraints[i][0] == '%')
-		  {
-		    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 < noperands; j++)
-		      xconstraints[j] = constraints[j];
-
-		    xconstraints[i] = constraints[i+1];
-		    xconstraints[i+1] = constraints[i];
-		    record_reg_classes (nalternatives, noperands,
-					recog_operand, modes, xconstraints,
-					insn);
-		  }
-
-	      record_reg_classes (nalternatives, noperands, recog_operand,
-				  modes, constraints, insn);
-
-	      /* Now add the cost for each operand to the total costs for
-		 its register.  */
-
-	      for (i = 0; i < noperands; i++)
-		if (GET_CODE (recog_operand[i]) == REG
-		    && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER)
-		  {
-		    int regno = REGNO (recog_operand[i]);
-		    struct costs *p = &costs[regno], *q = &op_costs[i];
-
-		    p->mem_cost += q->mem_cost * loop_cost;
-		    for (j = 0; j < N_REG_CLASSES; j++)
-		      p->cost[j] += q->cost[j] * loop_cost;
-		  }
-	    }
+	  insn = scan_one_insn (insn, pass);
 	}
-
+      
       /* Now for each register look at how desirable each class is
 	 and find which class is preferred.  Store that in
 	 `prefclass[REGNO]'.  Record in `altclass[REGNO]' the largest register
Index: recog.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/recog.c,v
retrieving revision 1.15
diff -u -p -r1.15 recog.c
--- recog.c	1998/10/17 01:28:52	1.15
+++ recog.c	1998/10/22 09:42:10
@@ -40,9 +40,10 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #endif
 
-static void validate_replace_rtx_1 PROTO((rtx *, rtx, rtx, rtx));
-static rtx *find_single_use_1 PROTO((rtx, rtx *));
-static rtx *find_constant_term_loc PROTO((rtx *));
+static void validate_replace_rtx_1	PROTO((rtx *, rtx, rtx, rtx));
+static rtx *find_single_use_1		PROTO((rtx, rtx *));
+static rtx *find_constant_term_loc	PROTO((rtx *));
+static int insn_invalid_p		PROTO((rtx));
 
 /* Nonzero means allow operands to be volatile.
    This should be 0 if you are generating rtl, such as if you are calling
@@ -252,6 +253,41 @@ validate_change (object, loc, new, in_gr
     return apply_change_group ();
 }
 
+/* This subroutine of apply_change_group verifies whether the changes to INSN
+   were valid; i.e. whether INSN can still be recognized.  */
+
+static int
+insn_invalid_p (insn)
+     rtx insn;
+{
+  int icode = recog_memoized (insn);
+  int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
+
+  if (is_asm)
+    {
+      if (! check_asm_operands (PATTERN (insn)))
+	return 1;
+
+      /* Disallow modification of ASM_OPERANDS after reload; verifying the
+	 constraints is too difficult.  */
+      if (reload_completed)
+	return 1;
+    }
+  else if (icode < 0)
+    return 1;
+
+  /* After reload, verify that all constraints are satisfied.  */
+  if (reload_completed)
+    {
+      insn_extract (insn);
+
+      if (! constrain_operands (INSN_CODE (insn), 1))
+	return 1;
+    }
+
+  return 0;
+}
+
 /* Apply a group of changes previously issued with `validate_change'.
    Return 1 if all changes are valid, zero otherwise.  */
 
@@ -282,13 +318,7 @@ apply_change_group ()
 	  if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
 	    break;
 	}
-      else if ((recog_memoized (object) < 0
-		&& (asm_noperands (PATTERN (object)) < 0
-		    || ! check_asm_operands (PATTERN (object))
-		    || reload_completed))
-	       || (reload_completed
-		   && (insn_extract (object),
-		       ! constrain_operands (INSN_CODE (object), 1))))
+      else if (insn_invalid_p (object))
 	{
 	  rtx pat = PATTERN (object);
 



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