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]

[PING] Loop invariant motion and call-saved eh regs


Hello,

the following patch fixes a problem for plattforms where
call-saved registers are used for exception handling (s390 and sparc).

http://gcc.gnu.org/ml/gcc-patches/2006-07/msg01060.html

See: http://gcc.gnu.org/ml/gcc-patches/2006-07/msg00767.html
for a description of the problem.

The proposed patch works around the real problem. A better fix would get
rid of the CLOBBERs issued for eh regs completely as in:
http://gcc.gnu.org/ml/gcc-patches/2006-07/msg00850.html

Unfortunately I couldn't get this working properly by now. There occur
problems when you have a throw in a catch block. In this case (and without
the eh reg CLOBBERs) flow considers the eh regs not to be altered between the use in
the second catch block and use in the throw/catch block. So a copy of an eh
reg created in the throw/catch block is happily used within the second catch
block.

I think what is missing is flow to be aware of eh regs being set on eh edges.
So neither the throw nor the catch block are responsible for the change of
the eh regs it is a property of the eh edge between the blocks!

I've tried to teach flow that with the attached patch but got a nasty miscompile
of libstdc++ which a havn't tracked down yet. Maybe I can get this working
for gcc 4.2. Otherwise please consider to accept the workaround patch although
it is not the best solution.

Bye,

-Andreas-



Index: gcc/flow.c
===================================================================
*** gcc/flow.c.orig	2006-08-08 10:28:32.000000000 +0200
--- gcc/flow.c	2006-08-10 11:14:07.000000000 +0200
*************** static void
*** 1029,1035 ****
  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;
--- 1029,1035 ----
  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, invalidated_by_eh_edge;
    regset registers_made_dead;
    bool failure_strategy_required = false;
    int *block_accesses;
*************** calculate_global_regs_live (sbitmap bloc
*** 1054,1065 ****
--- 1054,1075 ----
    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);
+   invalidated_by_eh_edge = 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);
  
+   /* The exception handling registes die at eh edges.  */
+   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);
+     }
+ 
    /* Allocate space for the sets of local properties.  */
    local_sets = XCNEWVEC (bitmap, last_basic_block);
    cond_local_sets = XCNEWVEC (bitmap, last_basic_block);
*************** calculate_global_regs_live (sbitmap bloc
*** 1189,1197 ****
  	    /* ??? Abnormal call edges ignored for the moment, as this gets
  	       confused by sibling call edges, which crashes reg-stack.  */
  	    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);
  
--- 1199,1210 ----
  	    /* ??? Abnormal call edges ignored for the moment, as this gets
  	       confused by sibling call edges, which crashes reg-stack.  */
  	    if (e->flags & EDGE_EH)
! 	      {
! 		bitmap_ior_and_compl_into (new_live_at_end,
! 					   sb->il.rtl->global_live_at_start,
! 					   invalidated_by_call);
! 		AND_COMPL_REG_SET (new_live_at_end, invalidated_by_eh_edge);
! 	      }
  	    else
  	      IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
  


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