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]

Re: stupid.c, rip


On Sun, Jul 18, 1999 at 07:18:07PM -0700, Jason Merrill wrote:
> 11% seems pretty serious to me.  We're already too slow.

With this change to global, the difference between two builds
of cc1 on x86 is in the noise:

	109.81user 9.98system	mainline
	109.36user 9.66system	patched

The EXECUTE_IF_SET_IN_REG_SET part of the change removes 1.3M
calls to bitmap_bit_p over the course of cccp.c, which was 
about 6% of the runtime of the entire program.  Not calling
back into global to try re-allocation takes care of most of 
the rest of the time.



r~



	* global.c (global_alloc): Set GLOBAL argument to reload to zero
	if not optimizing.
	(build_insn_chain): Restructure to iterate over basic blocks,
	and use EXECUTE_IF_SET_IN_REG_SET.

Index: global.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/global.c,v
retrieving revision 1.27
diff -c -p -d -r1.27 global.c
*** global.c	1999/02/25 23:45:19	1.27
--- global.c	1999/07/19 17:48:16
*************** static void set_preference	PROTO((rtx, r
*** 271,277 ****
  static void dump_conflicts	PROTO((FILE *));
  static void reg_becomes_live	PROTO((rtx, rtx));
  static void reg_dies		PROTO((int, enum machine_mode));
! static void build_insn_chain	PROTO((rtx));
  
  /* Perform allocation of pseudo-registers not allocated by local_alloc.
     FILE is a file to output debugging information on,
--- 271,277 ----
  static void dump_conflicts	PROTO((FILE *));
  static void reg_becomes_live	PROTO((rtx, rtx));
  static void reg_dies		PROTO((int, enum machine_mode));
! static void build_insn_chain	PROTO((void));
  
  /* Perform allocation of pseudo-registers not allocated by local_alloc.
     FILE is a file to output debugging information on,
*************** global_alloc (file)
*** 495,501 ****
    /* If there is work to be done (at least one reg to allocate),
       perform global conflict analysis and allocate the regs.  */
  
!   if (max_allocno > 0)
      {
        /* Scan all the insns and compute the conflicts among allocnos
  	 and between allocnos and hard regs.  */
--- 495,501 ----
    /* If there is work to be done (at least one reg to allocate),
       perform global conflict analysis and allocate the regs.  */
  
!   if (optimize && max_allocno > 0)
      {
        /* Scan all the insns and compute the conflicts among allocnos
  	 and between allocnos and hard regs.  */
*************** global_alloc (file)
*** 573,586 ****
    /* Do the reloads now while the allocno data still exist, so that we can
       try to assign new hard regs to any pseudo regs that are spilled.  */
  
! #if 0 /* We need to eliminate regs even if there is no rtl code,
! 	 for the sake of debugging information.  */
!   if (n_basic_blocks > 0)
! #endif
!     {
!       build_insn_chain (get_insns ());
!       retval = reload (get_insns (), 1, file);
!     }
  
    free (conflicts);
    return retval;
--- 573,580 ----
    /* Do the reloads now while the allocno data still exist, so that we can
       try to assign new hard regs to any pseudo regs that are spilled.  */
  
!   build_insn_chain ();
!   retval = reload (get_insns (), optimize != 0, file);
  
    free (conflicts);
    return retval;
*************** reg_dies (regno, mode)
*** 1667,1762 ****
  /* Walk the insns of the current function and build reload_insn_chain,
     and record register life information.  */
  static void
! build_insn_chain (first)
!      rtx first;
  {
    struct insn_chain **p = &reload_insn_chain;
    struct insn_chain *prev = 0;
!   int b = 0;
  
    live_relevant_regs = ALLOCA_REG_SET ();
  
!   for (; first; first = NEXT_INSN (first))
      {
!       struct insn_chain *c;
! 
!       if (first == BLOCK_HEAD (b))
! 	{
! 	  int i;
! 	  CLEAR_REG_SET (live_relevant_regs);
! 	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 	    if (REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, i)
! 		&& ! TEST_HARD_REG_BIT (eliminable_regset, i))
! 	      SET_REGNO_REG_SET (live_relevant_regs, i);
  
! 	  for (; i < max_regno; i++)
! 	    if (reg_renumber[i] >= 0
! 		&& REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, i))
! 	      SET_REGNO_REG_SET (live_relevant_regs, i);
! 	}
  
!       if (GET_CODE (first) != NOTE && GET_CODE (first) != BARRIER)
  	{
! 	  c = new_insn_chain ();
! 	  c->prev = prev;
! 	  prev = c;
! 	  *p = c;
! 	  p = &c->next;
! 	  c->insn = first;
! 	  c->block = b;
  
! 	  COPY_REG_SET (c->live_before, live_relevant_regs);
  
! 	  if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
  	    {
! 	      rtx link;
! 
! 	      /* Mark the death of everything that dies in this instruction.  */
  
! 	      for (link = REG_NOTES (first); link; link = XEXP (link, 1))
! 		if (REG_NOTE_KIND (link) == REG_DEAD
! 		    && GET_CODE (XEXP (link, 0)) == REG)
! 		  reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
  
! 	      /* Mark everything born in this instruction as live.  */
  
! 	      note_stores (PATTERN (first), reg_becomes_live);
! 	    }
  
! 	  /* Remember which registers are live at the end of the insn, before
! 	     killing those with REG_UNUSED notes.  */
! 	  COPY_REG_SET (c->live_after, live_relevant_regs);
  
! 	  if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
! 	    {
! 	      rtx link;
  
! 	      /* Mark anything that is set in this insn and then unused as dying.  */
  
! 	      for (link = REG_NOTES (first); link; link = XEXP (link, 1))
! 		if (REG_NOTE_KIND (link) == REG_UNUSED
! 		    && GET_CODE (XEXP (link, 0)) == REG)
! 		  reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
  	    }
- 	}
- 
-       if (first == BLOCK_END (b))
- 	b++;
  
!       /* Stop after we pass the end of the last basic block.  Verify that
! 	 no real insns are after the end of the last basic block.
! 
! 	 We may want to reorganize the loop somewhat since this test should
! 	 always be the right exit test.  */
!       if (b == n_basic_blocks)
! 	{
! 	  for (first = NEXT_INSN (first) ; first; first = NEXT_INSN (first))
! 	    if (GET_RTX_CLASS (GET_CODE (first)) == 'i'
! 		&& GET_CODE (PATTERN (first)) != USE)
! 	      abort ();
! 	  break;
  	}
      }
    FREE_REG_SET (live_relevant_regs);
    *p = 0;
  }
--- 1661,1748 ----
  /* Walk the insns of the current function and build reload_insn_chain,
     and record register life information.  */
  static void
! build_insn_chain ()
  {
    struct insn_chain **p = &reload_insn_chain;
    struct insn_chain *prev = 0;
!   int b;
  
    live_relevant_regs = ALLOCA_REG_SET ();
  
!   for (b = n_basic_blocks - 1; b >= 0; --b)
      {
!       basic_block bb = BASIC_BLOCK (b);
!       rtx insn, end;
!       int i;
  
!       CLEAR_REG_SET (live_relevant_regs);
  
!       EXECUTE_IF_SET_IN_REG_SET (bb->global_live_at_start, 0, i,
  	{
! 	  if ((i < FIRST_PSEUDO_REGISTER
! 	       && ! TEST_HARD_REG_BIT (eliminable_regset, i))
! 	      || (i >= FIRST_PSEUDO_REGISTER
! 		  && reg_renumber[i] >= 0))
! 	    SET_REGNO_REG_SET (live_relevant_regs, i);
! 	});
  
!       insn = bb->head, end = bb->end;
!       while (1)
! 	{
! 	  struct insn_chain *c;
  
! 	  if (GET_CODE (insn) != NOTE)
  	    {
! 	      c = new_insn_chain ();
! 	      c->prev = prev;
! 	      prev = c;
! 	      *p = c;
! 	      p = &c->next;
! 	      c->insn = insn;
! 	      c->block = b;
  
! 	      COPY_REG_SET (c->live_before, live_relevant_regs);
  
! 	      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
! 		{
! 		  rtx link;
  
! 		  /* Mark the death of everything that dies in this
! 		     instruction.  */
! 		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
! 		    if (REG_NOTE_KIND (link) == REG_DEAD
! 			&& GET_CODE (XEXP (link, 0)) == REG)
! 		      reg_dies (REGNO (XEXP (link, 0)),
! 				GET_MODE (XEXP (link, 0)));
  
! 		  /* Mark everything born in this instruction as live.  */
! 		  note_stores (PATTERN (insn), reg_becomes_live);
! 		}
  
! 	      /* Remember which registers are live at the end of the insn,
! 		 before killing those with REG_UNUSED notes.  */
! 	      COPY_REG_SET (c->live_after, live_relevant_regs);
  
! 	      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
! 		{
! 		  rtx link;
  
! 		  /* Mark anything that is set in this insn and then unused
! 		     as dying.  */
! 		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
! 		    if (REG_NOTE_KIND (link) == REG_UNUSED
! 			&& GET_CODE (XEXP (link, 0)) == REG)
! 		      reg_dies (REGNO (XEXP (link, 0)),
! 				GET_MODE (XEXP (link, 0)));
! 		}
  	    }
  
! 	  if (insn == end)
! 	    break;
! 	  insn = NEXT_INSN (insn);
  	}
      }
+ 
    FREE_REG_SET (live_relevant_regs);
    *p = 0;
  }


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