This is the mail archive of the gcc@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: Ongoing problems with resource.c changes


On Mon, Nov 01, 1999 at 07:57:37PM -0700, Jeffrey A Law wrote:
> Apparently the ADDR_VEC insn isn't actually within the bb->head/end bounds
> for its basic block and thus compute_bb_for_insn never initializes an entry
> in basic_block_for_insn for the ADDR_VEC.

Give this a shot -- I've just fired off a Sparc bootstrap.  I'll
find out if it worked after dinner.

This is Jan's patch with minor modifications to cope with the above.



r~



Index: recog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/recog.c,v
retrieving revision 1.51
diff -c -p -d -r1.51 recog.c
*** recog.c	1999/11/01 01:11:21	1.51
--- recog.c	1999/11/02 03:40:22
*************** peephole2_optimize (dump_file)
*** 2719,2725 ****
       way we'll not need to keep searching forward from the beginning of 
       basic blocks to find register life info.  */
  
!   init_resource_info (NULL);
  
    blocks = sbitmap_alloc (n_basic_blocks);
    sbitmap_zero (blocks);
--- 2719,2725 ----
       way we'll not need to keep searching forward from the beginning of 
       basic blocks to find register life info.  */
  
!   init_resource_info (NULL, 1);
  
    blocks = sbitmap_alloc (n_basic_blocks);
    sbitmap_zero (blocks);
Index: reorg.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reorg.c,v
retrieving revision 1.41
diff -c -p -d -r1.41 reorg.c
*** reorg.c	1999/11/01 23:19:44	1.41
--- reorg.c	1999/11/02 03:40:22
*************** dbr_schedule (first, file)
*** 3567,3573 ****
  	redirect_jump (insn, target);
      }
  
!   init_resource_info (epilogue_insn);
  
    /* Show we haven't computed an end-of-function label yet.  */
    end_of_function_label = 0;
--- 3567,3573 ----
  	redirect_jump (insn, target);
      }
  
!   init_resource_info (epilogue_insn, 0);
  
    /* Show we haven't computed an end-of-function label yet.  */
    end_of_function_label = 0;
Index: resource.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/resource.c,v
retrieving revision 1.19
diff -c -p -d -r1.19 resource.c
*** resource.c	1999/10/28 19:30:02	1.19
--- resource.c	1999/11/02 03:40:22
*************** static HARD_REG_SET current_live_regs;
*** 72,83 ****
--- 72,87 ----
     Also only used by the next two functions.  */
  
  static HARD_REG_SET pending_dead_regs;
+ 
+ /* True when REG_DEAD notes and the CFG may be trusted.  */
+ static int cfg_is_reliable;
  
  static void update_live_status		PROTO ((rtx, rtx, void *));
  static rtx next_insn_no_annul		PROTO ((rtx));
  static rtx find_dead_or_set_registers	PROTO ((rtx, struct resources*,
  						rtx*, int, struct resources,
  						struct resources));
+ static int resource_bb_for_insn		PROTO ((rtx));
  
  /* Utility function called from mark_target_live_regs via note_stores.
     It deadens any CLOBBERed registers and livens any SET registers.  */
*************** mark_set_resources (x, res, in_dest, inc
*** 750,755 ****
--- 754,804 ----
        }
  }
  
+ static int
+ resource_bb_for_insn (insn)
+      rtx insn;
+ {
+   basic_block bb = NULL;
+ 
+   /* ??? Special case for ADDR_VEC, which isn't strictly inside a
+ 	 block at all, but is really part of the previous block.  */
+   if (GET_CODE (insn) == JUMP_INSN
+       && (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ 	  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+     insn = prev_real_insn (insn);
+ 
+   if (INSN_UID (insn) < (int) VARRAY_SIZE (basic_block_for_insn))
+     bb = BLOCK_FOR_INSN (insn);
+ 
+   /* We've hit some newly created insn.  Search backward for known
+      insn; we ought to hit at least BASIC_BLOCK note when CFG is
+      not corrupt. */
+   if (bb == NULL)
+     {
+       insn = PREV_INSN (insn);
+       while (GET_CODE (insn) != CODE_LABEL
+ 	     && GET_CODE (insn) != JUMP_INSN)
+ 	{
+ 	  if (INSN_UID (insn) < (int) VARRAY_SIZE (basic_block_for_insn))
+ 	    {
+ 	      bb = BLOCK_FOR_INSN (insn);
+ 	      break;
+ 	    }
+ 	  insn = PREV_INSN (insn);
+ 	}
+     }
+ 
+   if (bb != NULL)
+     {
+       set_block_for_insn (insn, bb);
+       return bb->index;
+     }
+   else if (cfg_is_reliable)
+     abort ();
+   else
+     return -1;
+ }
+ 
  /* Set the resources that are live at TARGET.
  
     If TARGET is zero, we refer to the end of the current function and can
*************** mark_set_resources (x, res, in_dest, inc
*** 760,765 ****
--- 809,818 ----
     reload and jump optimization, which occur after the basic block information
     has been computed.
  
+    In case CFG_IS_RELIABLE is nonzero, we expect life information to
+    be correct.  This can be used for example by peephole2 pass done
+    after flow2.
+ 
     Accordingly, we proceed as follows::
  
     We find the previous BARRIER and look at all immediately following labels
*************** mark_set_resources (x, res, in_dest, inc
*** 778,783 ****
--- 831,837 ----
     updated by such things as find_equiv_reg.  So keep track of registers
     marked as dead that haven't been assigned to, and mark them dead at the
     next CODE_LABEL since reload and jump won't propagate values across labels.
+    In case CFG_IS_RELIABLE, believe to REG_DEAD notes.
  
     If we cannot find the start of a basic block (should be a very rare
     case, if it can happen at all), mark everything as potentially live.
*************** mark_target_live_regs (insns, target, re
*** 832,840 ****
  	b = tinfo->block;
      }
  
!   if (b == -1
!       && INSN_UID (target) < (int) VARRAY_SIZE (basic_block_for_insn))
!     b = BLOCK_NUM (target);
  
    if (target_hash_table != NULL)
      {
--- 886,893 ----
  	b = tinfo->block;
      }
  
!   if (b == -1)
!     b = resource_bb_for_insn (target);
  
    if (target_hash_table != NULL)
      {
*************** mark_target_live_regs (insns, target, re
*** 868,897 ****
    if (b != -1)
      {
        regset regs_live = BASIC_BLOCK (b)->global_live_at_start;
-       int j;
-       int regno;
        rtx start_insn, stop_insn;
  
!       /* Compute hard regs live at start of block -- this is the real hard regs
! 	 marked live, plus live pseudo regs that have been renumbered to
! 	 hard regs.  */
  
        REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
  
-       EXECUTE_IF_SET_IN_REG_SET
- 	(regs_live, FIRST_PSEUDO_REGISTER, i,
- 	 {
- 	   if ((regno = reg_renumber[i]) >= 0)
- 	     for (j = regno;
- 		  j < regno + HARD_REGNO_NREGS (regno,
- 						PSEUDO_REGNO_MODE (i));
- 		  j++)
- 	       SET_HARD_REG_BIT (current_live_regs, j);
- 	 });
- 
        /* Get starting and ending insn, handling the case where each might
  	 be a SEQUENCE.  */
!       start_insn = (b == 0 ? insns : BLOCK_HEAD (b));
        stop_insn = target;
  
        if (GET_CODE (start_insn) == INSN
--- 921,943 ----
    if (b != -1)
      {
        regset regs_live = BASIC_BLOCK (b)->global_live_at_start;
        rtx start_insn, stop_insn;
  
!       /* Compute hard regs live at start of block */
  
        REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
  
        /* Get starting and ending insn, handling the case where each might
  	 be a SEQUENCE.  */
!       if (cfg_is_reliable)
! 	{
! 	  start_insn = BLOCK_HEAD (b);
! 	  if (GET_CODE (start_insn) == CODE_LABEL)
! 	    start_insn = NEXT_INSN (start_insn);
! 	}
!       else
!         start_insn = (b == 0 ? insns : BLOCK_HEAD (b));
! 
        stop_insn = target;
  
        if (GET_CODE (start_insn) == INSN
*************** mark_target_live_regs (insns, target, re
*** 971,977 ****
  					     GET_MODE (XEXP (link, 0))));
  			 
  		    for (i = first_regno; i < last_regno; i++)
! 		      SET_HARD_REG_BIT (pending_dead_regs, i);
  		  }
  
  	      note_stores (PATTERN (real_insn), update_live_status, NULL);
--- 1017,1028 ----
  					     GET_MODE (XEXP (link, 0))));
  			 
  		    for (i = first_regno; i < last_regno; i++)
! 		      {
! 			if (cfg_is_reliable)
! 		          CLEAR_HARD_REG_BIT (current_live_regs, i);
! 			else
! 		          SET_HARD_REG_BIT (pending_dead_regs, i);
! 		      }
  		  }
  
  	      note_stores (PATTERN (real_insn), update_live_status, NULL);
*************** mark_target_live_regs (insns, target, re
*** 996,1001 ****
--- 1047,1054 ----
  
  	  else if (GET_CODE (real_insn) == CODE_LABEL)
  	    {
+ 	      if (cfg_is_reliable)
+ 		abort();
  	      /* A label clobbers the pending dead registers since neither
  		 reload nor jump will propagate a value across a label.  */
  	      AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
*************** mark_target_live_regs (insns, target, re
*** 1021,1061 ****
      /* We didn't find the start of a basic block.  Assume everything
         in use.  This should happen only extremely rarely.  */
      SET_HARD_REG_SET (res->regs);
- 
-   CLEAR_RESOURCE (&set);
-   CLEAR_RESOURCE (&needed);
- 
-   jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
- 					  set, needed);
  
!   /* If we hit an unconditional branch, we have another way of finding out
!      what is live: we can see what is live at the branch target and include
!      anything used but not set before the branch.  The only things that are
!      live are those that are live using the above test and the test below.  */
  
!   if (jump_insn)
      {
-       struct resources new_resources;
-       rtx stop_insn = next_active_insn (jump_insn);
- 
-       mark_target_live_regs (insns, next_active_insn (jump_target),
- 			     &new_resources);
        CLEAR_RESOURCE (&set);
        CLEAR_RESOURCE (&needed);
  
!       /* Include JUMP_INSN in the needed registers.  */
!       for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
  	{
! 	  mark_referenced_resources (insn, &needed, 1);
  
! 	  COPY_HARD_REG_SET (scratch, needed.regs);
! 	  AND_COMPL_HARD_REG_SET (scratch, set.regs);
! 	  IOR_HARD_REG_SET (new_resources.regs, scratch);
  
! 	  mark_set_resources (insn, &set, 0, 1);
! 	}
  
!       AND_HARD_REG_SET (res->regs, new_resources.regs);
      }
  
    if (tinfo != NULL)
--- 1074,1127 ----
      /* We didn't find the start of a basic block.  Assume everything
         in use.  This should happen only extremely rarely.  */
      SET_HARD_REG_SET (res->regs);
  
!   /* With reliable flow info we ought to get accurate info by checking
!      the basic block.  */
  
!   if (!cfg_is_reliable)
      {
        CLEAR_RESOURCE (&set);
        CLEAR_RESOURCE (&needed);
  
!       jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
! 					      set, needed);
! 
!       /* If we hit an unconditional branch, we have another way of finding out
! 	 what is live: we can see what is live at the branch target and include
! 	 anything used but not set before the branch.  The only things that are
! 	 live are those that are live using the above test and the test below.  */
! 
!       if (jump_insn)
  	{
! 	  struct resources new_resources;
! 	  rtx stop_insn = next_active_insn (jump_insn);
  
! 	  mark_target_live_regs (insns, next_active_insn (jump_target),
! 				 &new_resources);
! 	  CLEAR_RESOURCE (&set);
! 	  CLEAR_RESOURCE (&needed);
  
! 	  /* Include JUMP_INSN in the needed registers.  */
! 	  for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
! 	    {
! 	      mark_referenced_resources (insn, &needed, 1);
  
! 	      COPY_HARD_REG_SET (scratch, needed.regs);
! 	      AND_COMPL_HARD_REG_SET (scratch, set.regs);
! 	      IOR_HARD_REG_SET (new_resources.regs, scratch);
! 
! 	      mark_set_resources (insn, &set, 0, 1);
! 	    }
! 
! 	  if (cfg_is_reliable)
! 	    {
! 	      GO_IF_HARD_REG_SUBSET (res->regs, new_resources.regs, win);
! 	      abort();
! 	      win:
! 	    }
! 
! 	  AND_HARD_REG_SET (res->regs, new_resources.regs);
! 	}
      }
  
    if (tinfo != NULL)
*************** mark_target_live_regs (insns, target, re
*** 1068,1078 ****
     This should be invoked before the first call to mark_target_live_regs.  */
  
  void
! init_resource_info (epilogue_insn)
       rtx epilogue_insn;
  {
    int i;
  
    /* Indicate what resources are required to be valid at the end of the current
       function.  The condition code never is and memory always is.  If the
       frame pointer is needed, it is and so is the stack pointer unless
--- 1134,1146 ----
     This should be invoked before the first call to mark_target_live_regs.  */
  
  void
! init_resource_info (epilogue_insn, reliable)
       rtx epilogue_insn;
+      int reliable;
  {
    int i;
  
+   cfg_is_reliable = reliable;
    /* Indicate what resources are required to be valid at the end of the current
       function.  The condition code never is and memory always is.  If the
       frame pointer is needed, it is and so is the stack pointer unless
*************** void
*** 1187,1194 ****
  incr_ticks_for_insn (insn)
       rtx insn;
  {
!   int b = BLOCK_NUM (insn);
! 
    if (b != -1)
      bb_ticks[b]++;
  }
--- 1255,1261 ----
  incr_ticks_for_insn (insn)
       rtx insn;
  {
!   int b = resource_bb_for_insn (insn);
    if (b != -1)
      bb_ticks[b]++;
  }
Index: resource.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/resource.h,v
retrieving revision 1.4
diff -c -p -d -r1.4 resource.h
*** resource.h	1999/10/05 05:00:55	1.4
--- resource.h	1999/11/02 03:40:22
*************** extern void mark_referenced_resources	PR
*** 40,46 ****
  extern void clear_hashed_info_for_insn	PROTO((rtx));
  extern void incr_ticks_for_insn		PROTO((rtx));
  extern void mark_end_of_function_resources PROTO ((rtx, int));
! extern void init_resource_info		PROTO((rtx));
  extern void free_resource_info		PROTO((void));
  extern rtx find_free_register		PROTO((rtx, rtx, const char *, int,
  					       HARD_REG_SET *));
--- 40,46 ----
  extern void clear_hashed_info_for_insn	PROTO((rtx));
  extern void incr_ticks_for_insn		PROTO((rtx));
  extern void mark_end_of_function_resources PROTO ((rtx, int));
! extern void init_resource_info		PROTO((rtx, int));
  extern void free_resource_info		PROTO((void));
  extern rtx find_free_register		PROTO((rtx, rtx, const char *, int,
  					       HARD_REG_SET *));


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