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]
Other format: [Raw text]

Re: [PATCH] Don't emit CLOBBERs for eh registers


Hello,

I've committed the attached patch to mainline after a successful bootstrap
on s390, s390x and i686. No testsuite regressions occured.

Bye,

-Andreas-

2006-09-13  Andreas Krebbel  <krebbel1@de.ibm.com>

	* flow.c (calculate_global_regs_live): Invalidate eh registers
	on eh edges. Renamed invalidated_by_call to invalidated_by_eh_edge.
	(propagate_block): Handle eh registers as if they were set at basic
	block start.
	* except.c (dw2_build_landing_pads): Don't emit clobbers for eh
	registers.
	* global.c (global_conflicts): Make eh registers to conflict with
	pseudos live at basic block begin.
	* basic_block.h (bb_has_eh_pred): New function.


Index: gcc/flow.c
===================================================================
*** gcc/flow.c.orig	2006-09-08 21:14:30.000000000 +0200
--- gcc/flow.c	2006-09-13 09:01:31.000000000 +0200
*************** static void
*** 1040,1046 ****
  calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
  {
    basic_block *queue, *qhead, *qtail, *qend, bb;
!   regset tmp, new_live_at_end, invalidated_by_call;
    regset registers_made_dead;
    bool failure_strategy_required = false;
    int *block_accesses;
--- 1040,1046 ----
  calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
  {
    basic_block *queue, *qhead, *qtail, *qend, bb;
!   regset tmp, new_live_at_end, invalidated_by_eh_edge;
    regset registers_made_dead;
    bool failure_strategy_required = false;
    int *block_accesses;
*************** calculate_global_regs_live (sbitmap bloc
*** 1063,1075 ****
  
    tmp = ALLOC_REG_SET (&reg_obstack);
    new_live_at_end = ALLOC_REG_SET (&reg_obstack);
!   invalidated_by_call = ALLOC_REG_SET (&reg_obstack);
    registers_made_dead = ALLOC_REG_SET (&reg_obstack);
  
    /* Inconveniently, this is only readily available in hard reg set form.  */
    for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
      if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
!       SET_REGNO_REG_SET (invalidated_by_call, i);
  
    /* Allocate space for the sets of local properties.  */
    local_sets = XCNEWVEC (bitmap, last_basic_block);
--- 1063,1086 ----
  
    tmp = ALLOC_REG_SET (&reg_obstack);
    new_live_at_end = ALLOC_REG_SET (&reg_obstack);
!   invalidated_by_eh_edge = ALLOC_REG_SET (&reg_obstack);
    registers_made_dead = ALLOC_REG_SET (&reg_obstack);
  
    /* Inconveniently, this is only readily available in hard reg set form.  */
    for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
      if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
!       SET_REGNO_REG_SET (invalidated_by_eh_edge, i);
! 
!   /* The exception handling registers die at eh edges.  */
! #ifdef EH_RETURN_DATA_REGNO
!   for (i = 0; ; ++i)
!     {
!       unsigned regno = EH_RETURN_DATA_REGNO (i);
!       if (regno == INVALID_REGNUM)
! 	break;
!       SET_REGNO_REG_SET (invalidated_by_eh_edge, regno);
!     }
! #endif
  
    /* Allocate space for the sets of local properties.  */
    local_sets = XCNEWVEC (bitmap, last_basic_block);
*************** calculate_global_regs_live (sbitmap bloc
*** 1202,1208 ****
  	    if (e->flags & EDGE_EH)
  	      bitmap_ior_and_compl_into (new_live_at_end,
  					 sb->il.rtl->global_live_at_start,
! 					 invalidated_by_call);
  	    else
  	      IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
  
--- 1213,1219 ----
  	    if (e->flags & EDGE_EH)
  	      bitmap_ior_and_compl_into (new_live_at_end,
  					 sb->il.rtl->global_live_at_start,
! 					 invalidated_by_eh_edge);
  	    else
  	      IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
  
*************** calculate_global_regs_live (sbitmap bloc
*** 1422,1428 ****
  
    FREE_REG_SET (tmp);
    FREE_REG_SET (new_live_at_end);
!   FREE_REG_SET (invalidated_by_call);
    FREE_REG_SET (registers_made_dead);
  
    if (blocks_out)
--- 1433,1439 ----
  
    FREE_REG_SET (tmp);
    FREE_REG_SET (new_live_at_end);
!   FREE_REG_SET (invalidated_by_eh_edge);
    FREE_REG_SET (registers_made_dead);
  
    if (blocks_out)
*************** propagate_block (basic_block bb, regset 
*** 2214,2219 ****
--- 2225,2252 ----
  	break;
      }
  
+ #ifdef EH_RETURN_DATA_REGNO
+   if (bb_has_eh_pred (bb))
+     {
+       unsigned int i;
+       for (i = 0; ; ++i)
+ 	{
+ 	  unsigned regno = EH_RETURN_DATA_REGNO (i);
+ 	  if (regno == INVALID_REGNUM)
+ 	    break;
+ 	  if (pbi->local_set)
+ 	    {
+ 	      CLEAR_REGNO_REG_SET (pbi->cond_local_set, regno);
+ 	      SET_REGNO_REG_SET (pbi->local_set, regno);
+ 	    }
+ 	  if (REGNO_REG_SET_P (pbi->reg_live, regno))
+ 	    SET_REGNO_REG_SET (pbi->new_set, regno);
+ 	  
+ 	  regs_ever_live[regno] = 1;
+ 	}
+     }
+ #endif
+ 
    free_propagate_block_info (pbi);
  
    return changed;
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig	2006-09-08 21:14:30.000000000 +0200
--- gcc/except.c	2006-09-11 09:50:15.000000000 +0200
*************** static void
*** 1601,1614 ****
  dw2_build_landing_pads (void)
  {
    int i;
-   unsigned int j;
  
    for (i = cfun->eh->last_region_number; i > 0; --i)
      {
        struct eh_region *region;
        rtx seq;
        basic_block bb;
-       bool clobbers_hard_regs = false;
        edge e;
  
        region = VEC_index (eh_region, cfun->eh->region_array, i);
--- 1601,1612 ----
*************** dw2_build_landing_pads (void)
*** 1638,1667 ****
  #endif
  	  { /* Nothing */ }
  
-       /* If the eh_return data registers are call-saved, then we
- 	 won't have considered them clobbered from the call that
- 	 threw.  Kill them now.  */
-       for (j = 0; ; ++j)
- 	{
- 	  unsigned r = EH_RETURN_DATA_REGNO (j);
- 	  if (r == INVALID_REGNUM)
- 	    break;
- 	  if (! call_used_regs[r])
- 	    {
- 	      emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, r)));
- 	      clobbers_hard_regs = true;
- 	    }
- 	}
- 
-       if (clobbers_hard_regs)
- 	{
- 	  /* @@@ This is a kludge.  Not all machine descriptions define a
- 	     blockage insn, but we must not allow the code we just generated
- 	     to be reordered by scheduling.  So emit an ASM_INPUT to act as
- 	     blockage insn.  */
- 	  emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
- 	}
- 
        emit_move_insn (cfun->eh->exc_ptr,
  		      gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
        emit_move_insn (cfun->eh->filter,
--- 1636,1641 ----
Index: gcc/global.c
===================================================================
*** gcc/global.c.orig	2006-09-08 21:14:30.000000000 +0200
--- gcc/global.c	2006-09-13 09:04:18.000000000 +0200
*************** global_conflicts (void)
*** 743,748 ****
--- 743,763 ----
  	    scan the instruction that makes either X or Y become live.  */
  	record_conflicts (block_start_allocnos, ax);
  
+ #ifdef EH_RETURN_DATA_REGNO
+ 	if (bb_has_eh_pred (b))
+ 	  {
+ 	    unsigned int i;
+ 	    
+ 	    for (i = 0; ; ++i)
+ 	      {
+ 		unsigned int regno = EH_RETURN_DATA_REGNO (i);
+ 		if (regno == INVALID_REGNUM)
+ 		  break;
+ 		record_one_conflict (regno);
+ 	      }
+ 	  }
+ #endif
+ 
  	/* Pseudos can't go in stack regs at the start of a basic block that
  	   is reached by an abnormal edge. Likewise for call clobbered regs,
  	   because caller-save, fixup_abnormal_edges and possibly the table
Index: gcc/basic-block.h
===================================================================
*** gcc/basic-block.h.orig	2006-09-08 21:14:30.000000000 +0200
--- gcc/basic-block.h	2006-09-13 08:56:48.000000000 +0200
*************** extern bool rtx_equiv_p (rtx *, rtx, int
*** 1175,1178 ****
--- 1175,1192 ----
  /* In cfgrtl.c */
  extern bool condjump_equiv_p (struct equiv_info *, bool);
  
+ /* Return true when one of the predecessor edges of BB is marked with FLAGS.  */
+ static inline bool bb_has_eh_pred (basic_block bb)
+ {
+   edge e;
+   edge_iterator ei;
+ 
+   FOR_EACH_EDGE (e, ei, bb->preds)
+     {
+       if (e->flags & EDGE_EH)
+ 	return true;
+     }
+   return false;
+ }
+ 
  #endif /* GCC_BASIC_BLOCK_H */


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