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]

ia64 eh, part 8


Three semi-related changes to deal with representing non-call
exception edges explicitly.


r~


        * flow.c (tidy_fallthru_edges): Don't combine complex edges.
        (calculate_global_regs_live): Kill call-clobbered registers
        across exception edges.
        * reg-stack.c (convert_regs_1): Kill the entire target stack
        across non-call exception edges.

Index: flow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flow.c,v
retrieving revision 1.385
diff -c -p -d -r1.385 flow.c
*** flow.c	2001/03/28 04:18:12	1.385
--- flow.c	2001/03/28 06:20:09
*************** tidy_fallthru_edges ()
*** 2995,3000 ****
--- 2995,3001 ----
  	 merge the flags for the duplicate edges.  So we do not want to
  	 check that the edge is not a FALLTHRU edge.  */
        if ((s = b->succ) != NULL
+ 	  && ! (s->flags & EDGE_COMPLEX)
  	  && s->succ_next == NULL
  	  && s->dest == c
  	  /* If the jump insn has side effects, we can't tidy the edge.  */
*************** calculate_global_regs_live (blocks_in, b
*** 3542,3555 ****
       int flags;
  {
    basic_block *queue, *qhead, *qtail, *qend;
!   regset tmp, new_live_at_end;
!   regset_head tmp_head;
    regset_head new_live_at_end_head;
    int i;
  
    tmp = INITIALIZE_REG_SET (tmp_head);
    new_live_at_end = INITIALIZE_REG_SET (new_live_at_end_head);
  
    /* Create a worklist.  Allocate an extra slot for ENTRY_BLOCK, and one
       because the `head == tail' style test for an empty queue doesn't
       work with a full queue.  */
--- 3543,3562 ----
       int flags;
  {
    basic_block *queue, *qhead, *qtail, *qend;
!   regset tmp, new_live_at_end, call_used;
!   regset_head tmp_head, call_used_head;
    regset_head new_live_at_end_head;
    int i;
  
    tmp = INITIALIZE_REG_SET (tmp_head);
    new_live_at_end = INITIALIZE_REG_SET (new_live_at_end_head);
+   call_used = INITIALIZE_REG_SET (call_used_head);
  
+   /* Inconveniently, this is only redily available in hard reg set form.  */
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+     if (call_used_regs[i])
+       SET_REGNO_REG_SET (call_used, i);
+ 
    /* Create a worklist.  Allocate an extra slot for ENTRY_BLOCK, and one
       because the `head == tail' style test for an empty queue doesn't
       work with a full queue.  */
*************** calculate_global_regs_live (blocks_in, b
*** 3602,3608 ****
        for (e = bb->succ; e; e = e->succ_next)
  	{
  	  basic_block sb = e->dest;
! 	  IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
  	}
  
        /* The all-important stack pointer must always be live.  */
--- 3609,3626 ----
        for (e = bb->succ; e; e = e->succ_next)
  	{
  	  basic_block sb = e->dest;
! 
! 	  /* Call-clobbered registers die across exception and call edges.  */
! 	  /* ??? 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_operation (tmp, sb->global_live_at_start,
! 				call_used, BITMAP_AND_COMPL);
! 	      IOR_REG_SET (new_live_at_end, tmp);
! 	    }
! 	  else
! 	    IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
  	}
  
        /* The all-important stack pointer must always be live.  */
*************** calculate_global_regs_live (blocks_in, b
*** 3750,3755 ****
--- 3768,3774 ----
  
    FREE_REG_SET (tmp);
    FREE_REG_SET (new_live_at_end);
+   FREE_REG_SET (call_used);
  
    if (blocks_out)
      {
Index: reg-stack.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reg-stack.c,v
retrieving revision 1.69
diff -c -p -d -r1.69 reg-stack.c
*** reg-stack.c	2001/03/22 18:48:31	1.69
--- reg-stack.c	2001/03/28 06:20:09
*************** convert_regs_1 (file, block)
*** 2553,2562 ****
  	    }
  	}
  
!       /* Care for EH edges specially.  The normal return path may return
! 	 a value in st(0), but the EH path will not, and there's no need
! 	 to add popping code to the edge.  */
!       if (e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
  	{
  	  /* Assert that the lifetimes are as we expect -- one value
  	     live at st(0) on the end of the source block, and no
--- 2553,2567 ----
  	    }
  	}
  
!       /* Care for non-call EH edges specially.  The normal return path have
! 	 values in registers.  These will be popped en masse by the unwind
! 	 library.  */
!       if ((e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) == EDGE_EH)
! 	target_stack->top = -1;
! 
!       /* Other calls may appear to have values live in st(0), but the
! 	 abnormal return path will not have actually loaded the values.  */
!       else if (e->flags & EDGE_ABNORMAL_CALL)
  	{
  	  /* Assert that the lifetimes are as we expect -- one value
  	     live at st(0) on the end of the source block, and no


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