public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jan Hubicka <jh@suse.cz>
To: Paolo Bonzini <bonzini@gnu.org>
Cc: Richard Guenther <richard.guenther@gmail.com>,
		Jan Hubicka <jh@suse.cz>, GCC Patches <gcc-patches@gcc.gnu.org>
Subject: Re: Reduce startup cost of compiler (patch 2)
Date: Tue, 24 Jul 2007 15:14:00 -0000	[thread overview]
Message-ID: <20070724150127.GE10270@kam.mff.cuni.cz> (raw)
In-Reply-To: <46A5A7D8.6070503@gnu.org>

> 
> >>Bootstrapped/regtested i686-linux?
> >
> >Nice!  Yes, this is ok.
> 
> all_match is write only, though:

Uh, good catch.  I was testing if removing that trick slows down startup
(and it does) and forgot to put it back.  I am re-testing the attached
patch which I will commit if it passes.

Honza

Index: regclass.c
===================================================================
*** regclass.c	(revision 126859)
--- regclass.c	(working copy)
*************** bool have_regs_of_mode [MAX_MACHINE_MODE
*** 214,233 ****
  
  static char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
  
  /* Maximum cost of moving from a register in one class to a register in
     another class.  Based on REGISTER_MOVE_COST.  */
  
! static int move_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
  
  /* Similar, but here we don't have to move if the first index is a subset
     of the second so in that case the cost is zero.  */
  
! static int may_move_in_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
  
  /* Similar, but here we don't have to move if the first index is a superset
     of the second so in that case the cost is zero.  */
  
! static int may_move_out_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
  
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  
--- 214,235 ----
  
  static char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
  
+ typedef unsigned short move_table[N_REG_CLASSES];
+ 
  /* Maximum cost of moving from a register in one class to a register in
     another class.  Based on REGISTER_MOVE_COST.  */
  
! static move_table *move_cost[MAX_MACHINE_MODE];
  
  /* Similar, but here we don't have to move if the first index is a subset
     of the second so in that case the cost is zero.  */
  
! static move_table *may_move_in_cost[MAX_MACHINE_MODE];
  
  /* Similar, but here we don't have to move if the first index is a superset
     of the second so in that case the cost is zero.  */
  
! static move_table *may_move_out_cost[MAX_MACHINE_MODE];
  
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  
*************** init_reg_sets (void)
*** 312,317 ****
--- 314,409 ----
  #endif
  }
  
+ /* Initialize may_move_cost and friends for mode M.  */
+ 
+ static void
+ init_move_cost (enum machine_mode m)
+ {
+   static unsigned short last_move_cost[N_REG_CLASSES][N_REG_CLASSES];
+   static int last_mode = -1;
+   bool all_match = true;
+   unsigned int i, j;
+ 
+   gcc_assert (have_regs_of_mode[m]);
+   for (i = 0; i < N_REG_CLASSES; i++)
+     if (contains_reg_of_mode[i][m])
+       for (j = 0; j < N_REG_CLASSES; j++)
+ 	{
+ 	  int cost;
+ 	  if (!contains_reg_of_mode[j][m])
+ 	    cost = 65535;
+ 	  else
+ 	    {
+ 	      cost = REGISTER_MOVE_COST (m, i, j);
+ 	      gcc_assert (cost < 65535);
+ 	    }
+ 	  all_match &= (last_move_cost[i][j] == cost);
+ 	  last_move_cost[i][j] = cost;
+ 	}
+   if (all_match && last_mode != -1)
+     {
+       move_cost[m] = move_cost[last_mode];
+       may_move_in_cost[m] = may_move_in_cost[last_mode];
+       may_move_out_cost[m] = may_move_out_cost[last_mode];
+       return;
+     }
+   last_mode = m;
+   move_cost[m] = (move_table *)xmalloc (sizeof (move_table)
+ 					* N_REG_CLASSES);
+   may_move_in_cost[m] = (move_table *)xmalloc (sizeof (move_table)
+ 					       * N_REG_CLASSES);
+   may_move_out_cost[m] = (move_table *)xmalloc (sizeof (move_table)
+ 					        * N_REG_CLASSES);
+   for (i = 0; i < N_REG_CLASSES; i++)
+     if (contains_reg_of_mode[i][m])
+       for (j = 0; j < N_REG_CLASSES; j++)
+ 	{
+ 	  int cost;
+ 	  enum reg_class *p1, *p2;
+ 
+ 	  if (last_move_cost[i][j] == 65535)
+ 	    {
+ 	      move_cost[m][i][j] = 65535;
+ 	      may_move_in_cost[m][i][j] = 65535;
+ 	      may_move_out_cost[m][i][j] = 65535;
+ 	    }
+ 	  else
+ 	    {
+ 	      cost = last_move_cost[i][j];
+ 
+ 	      for (p2 = &reg_class_subclasses[j][0];
+ 		   *p2 != LIM_REG_CLASSES; p2++)
+ 		if (*p2 != i && contains_reg_of_mode[*p2][m])
+ 		  cost = MAX (cost, move_cost[m][i][*p2]);
+ 
+ 	      for (p1 = &reg_class_subclasses[i][0];
+ 		   *p1 != LIM_REG_CLASSES; p1++)
+ 		if (*p1 != j && contains_reg_of_mode[*p1][m])
+ 		  cost = MAX (cost, move_cost[m][*p1][j]);
+ 
+ 	      gcc_assert (cost <= 65535);
+ 	      move_cost[m][i][j] = cost;
+ 
+ 	      if (reg_class_subset_p (i, j))
+ 		may_move_in_cost[m][i][j] = 0;
+ 	      else
+ 		may_move_in_cost[m][i][j] = cost;
+ 
+ 	      if (reg_class_subset_p (j, i))
+ 		may_move_out_cost[m][i][j] = 0;
+ 	      else
+ 		may_move_out_cost[m][i][j] = cost;
+ 	    }
+ 	}
+     else
+       for (j = 0; j < N_REG_CLASSES; j++)
+ 	{
+ 	  move_cost[m][i][j] = 65535;
+ 	  may_move_in_cost[m][i][j] = 65535;
+ 	  may_move_out_cost[m][i][j] = 65535;
+ 	}
+ }
+ 
  /* After switches have been processed, which perhaps alter
     `fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs.  */
  
*************** init_reg_sets_1 (void)
*** 476,548 ****
    memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode));
    memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
    for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
!     for (i = 0; i < N_REG_CLASSES; i++)
!       if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i])
! 	for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
! 	  if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j)
! 	      && HARD_REGNO_MODE_OK (j, m))
! 	     {
! 	       contains_reg_of_mode [i][m] = 1;
! 	       have_regs_of_mode [m] = 1;
! 	       break;
! 	     }
! 
!   /* Initialize the move cost table.  Find every subset of each class
!      and take the maximum cost of moving any subset to any other.  */
! 
!   for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
!     if (have_regs_of_mode [m])
!       {
! 	for (i = 0; i < N_REG_CLASSES; i++)
! 	  if (contains_reg_of_mode [i][m])
! 	    for (j = 0; j < N_REG_CLASSES; j++)
! 	      {
! 		int cost;
! 		enum reg_class *p1, *p2;
! 
! 		if (!contains_reg_of_mode [j][m])
! 		  {
! 		    move_cost[m][i][j] = 65536;
! 		    may_move_in_cost[m][i][j] = 65536;
! 		    may_move_out_cost[m][i][j] = 65536;
! 		  }
! 		else
! 		  {
! 		    cost = REGISTER_MOVE_COST (m, i, j);
! 
! 		    for (p2 = &reg_class_subclasses[j][0];
! 			 *p2 != LIM_REG_CLASSES;
! 			 p2++)
! 		      if (*p2 != i && contains_reg_of_mode [*p2][m])
! 			cost = MAX (cost, move_cost [m][i][*p2]);
! 
! 		    for (p1 = &reg_class_subclasses[i][0];
! 			 *p1 != LIM_REG_CLASSES;
! 			 p1++)
! 		      if (*p1 != j && contains_reg_of_mode [*p1][m])
! 			cost = MAX (cost, move_cost [m][*p1][j]);
! 
! 		    move_cost[m][i][j] = cost;
! 
! 		    if (reg_class_subset_p (i, j))
! 		      may_move_in_cost[m][i][j] = 0;
! 		    else
! 		      may_move_in_cost[m][i][j] = cost;
! 
! 		    if (reg_class_subset_p (j, i))
! 		      may_move_out_cost[m][i][j] = 0;
! 		    else
! 		      may_move_out_cost[m][i][j] = cost;
! 		  }
! 	      }
! 	  else
! 	    for (j = 0; j < N_REG_CLASSES; j++)
! 	      {
! 		move_cost[m][i][j] = 65536;
! 		may_move_in_cost[m][i][j] = 65536;
! 		may_move_out_cost[m][i][j] = 65536;
! 	      }
!       }
  }
  
  /* Compute the table of register modes.
--- 568,588 ----
    memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode));
    memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
    for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
!     {
!       HARD_REG_SET ok_regs;
!       CLEAR_HARD_REG_SET (ok_regs);
!       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
! 	if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, m))
! 	  SET_HARD_REG_BIT (ok_regs, j);
!       
!       for (i = 0; i < N_REG_CLASSES; i++)
! 	if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i]
! 	    && hard_reg_set_intersect_p (ok_regs, reg_class_contents[i]))
! 	  {
! 	     contains_reg_of_mode [i][m] = 1;
! 	     have_regs_of_mode [m] = 1;
! 	  }
!      }
  }
  
  /* Compute the table of register modes.
*************** record_reg_classes (int n_alts, int n_op
*** 1465,1479 ****
  		     copy, which is one instruction.  */
  
  		  struct costs *pp = &this_op_costs[i];
! 
! 		  for (class = 0; class < N_REG_CLASSES; class++)
! 		    pp->cost[class]
! 		      = ((recog_data.operand_type[i] != OP_OUT
! 			  ? may_move_in_cost[mode][class][(int) classes[i]]
! 			  : 0)
! 			 + (recog_data.operand_type[i] != OP_IN
! 			    ? may_move_out_cost[mode][(int) classes[i]][class]
! 			    : 0));
  
  		  /* If the alternative actually allows memory, make things
  		     a bit cheaper since we won't need an extra insn to
--- 1505,1537 ----
  		     copy, which is one instruction.  */
  
  		  struct costs *pp = &this_op_costs[i];
! 		  move_table *intable = NULL;
! 		  move_table *outtable = NULL;
! 		  int op_class = (int) classes[i];
! 
! 		  if (!move_cost[mode])
! 		    init_move_cost (mode);
! 		  intable = may_move_in_cost[mode];
! 		  outtable = may_move_out_cost[mode];
! 
! 		  /* The loop is performance critical, so unswitch it manually.
! 		   */
! 		  switch (recog_data.operand_type[i])
! 		    {
! 		    case OP_INOUT:
! 		      for (class = 0; class < N_REG_CLASSES; class++)
! 			pp->cost[class] = (intable[class][op_class]
! 					   + outtable[op_class][class]);
! 		      break;
! 		    case OP_IN:
! 		      for (class = 0; class < N_REG_CLASSES; class++)
! 			pp->cost[class] = intable[class][op_class];
! 		      break;
! 		    case OP_OUT:
! 		      for (class = 0; class < N_REG_CLASSES; class++)
! 			pp->cost[class] = outtable[op_class][class];
! 		      break;
! 		    }
  
  		  /* If the alternative actually allows memory, make things
  		     a bit cheaper since we won't need an extra insn to
*************** record_reg_classes (int n_alts, int n_op
*** 1691,1705 ****
  	      else
  		{
  		  struct costs *pp = &this_op_costs[i];
! 
! 		  for (class = 0; class < N_REG_CLASSES; class++)
! 		    pp->cost[class]
! 		      = ((recog_data.operand_type[i] != OP_OUT
! 			  ? may_move_in_cost[mode][class][(int) classes[i]]
! 			  : 0)
! 			 + (recog_data.operand_type[i] != OP_IN
! 			    ? may_move_out_cost[mode][(int) classes[i]][class]
! 			    : 0));
  
  		  /* If the alternative actually allows memory, make things
  		     a bit cheaper since we won't need an extra insn to
--- 1749,1781 ----
  	      else
  		{
  		  struct costs *pp = &this_op_costs[i];
! 		  move_table *intable = NULL;
! 		  move_table *outtable = NULL;
! 		  int op_class = (int) classes[i];
! 
! 		  if (!move_cost[mode])
! 		    init_move_cost (mode);
! 		  intable = may_move_in_cost[mode];
! 		  outtable = may_move_out_cost[mode];
! 
! 		  /* The loop is performance critical, so unswitch it manually.
! 		   */
! 		  switch (recog_data.operand_type[i])
! 		    {
! 		    case OP_INOUT:
! 		      for (class = 0; class < N_REG_CLASSES; class++)
! 			pp->cost[class] = (intable[class][op_class]
! 					   + outtable[op_class][class]);
! 		      break;
! 		    case OP_IN:
! 		      for (class = 0; class < N_REG_CLASSES; class++)
! 			pp->cost[class] = intable[class][op_class];
! 		      break;
! 		    case OP_OUT:
! 		      for (class = 0; class < N_REG_CLASSES; class++)
! 			pp->cost[class] = outtable[op_class][class];
! 		      break;
! 		    }
  
  		  /* If the alternative actually allows memory, make things
  		     a bit cheaper since we won't need an extra insn to
*************** copy_cost (rtx x, enum machine_mode mode
*** 1856,1861 ****
--- 1932,1940 ----
    sri.extra_cost = 0;
    secondary_class = targetm.secondary_reload (to_p, x, class, mode, &sri);
  
+   if (!move_cost[mode])
+     init_move_cost (mode);
+ 
    if (secondary_class != NO_REGS)
      return (move_cost[mode][(int) secondary_class][(int) class]
  	    + sri.extra_cost
*************** record_address_regs (enum machine_mode m
*** 2056,2061 ****
--- 2135,2142 ----
  
  	pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2;
  
+ 	if (!move_cost[Pmode])
+ 	  init_move_cost (Pmode);
  	for (i = 0; i < N_REG_CLASSES; i++)
  	  pp->cost[i] += (may_move_in_cost[Pmode][i][(int) class] * scale) / 2;
        }

  reply	other threads:[~2007-07-24 15:01 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-24  5:54 Jan Hubicka
2007-07-24  7:29 ` Richard Guenther
2007-07-24  7:52   ` Paolo Bonzini
2007-07-24 15:14     ` Jan Hubicka [this message]
2007-07-29 21:32 ` Rask Ingemann Lambertsen
2007-07-31  6:44   ` Jan Hubicka
2007-07-31 12:49     ` Rask Ingemann Lambertsen
2007-07-31 16:26       ` Jan Hubicka
2007-08-03  9:16         ` Rask Ingemann Lambertsen
2007-08-03 12:13           ` Michael Matz
2007-08-03 12:43             ` Rask Ingemann Lambertsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070724150127.GE10270@kam.mff.cuni.cz \
    --to=jh@suse.cz \
    --cc=bonzini@gnu.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).