]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
flow.c (calculate_global_regs_live): Invalidate eh registers on eh edges.
authorAndreas Krebbel <krebbel1@de.ibm.com>
Wed, 13 Sep 2006 10:59:03 +0000 (10:59 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 13 Sep 2006 10:59:03 +0000 (10:59 +0000)
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.

From-SVN: r116920

gcc/ChangeLog
gcc/basic-block.h
gcc/except.c
gcc/flow.c
gcc/global.c

index 0eab63e51a540ecba40e0e0ae6941c28348be3d1..63188b874e3d209269cf10919fc7a3af41fcea33 100644 (file)
@@ -1,3 +1,15 @@
+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.
+
 2006-09-13  Richard Sandiford  <richard@codesourcery.com>
 
        PR rtl-optimization/28982
index bc9f6650c9ad61d99b125a6ae93f1ab50c6d8afc..a95e5b8781bc9f2b9c0a3415d20e46de293a1607 100644 (file)
@@ -1175,4 +1175,18 @@ extern bool rtx_equiv_p (rtx *, rtx, int, struct equiv_info *);
 /* 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 2e65340dceafe535f4d937d082d8dea204979979..b344087672b45522f06de084b82faaf1450e08bb 100644 (file)
@@ -1601,14 +1601,12 @@ static void
 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);
@@ -1638,30 +1636,6 @@ dw2_build_landing_pads (void)
 #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,
index 47e49f484e7f34ce7ed4e48f0c3d886743fd5f93..2b5d3032bf754405b01435bc460d3f4eadd682be 100644 (file)
@@ -1040,7 +1040,7 @@ static void
 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 tmp, new_live_at_end, invalidated_by_eh_edge;
   regset registers_made_dead;
   bool failure_strategy_required = false;
   int *block_accesses;
@@ -1063,13 +1063,24 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
 
   tmp = ALLOC_REG_SET (&reg_obstack);
   new_live_at_end = ALLOC_REG_SET (&reg_obstack);
-  invalidated_by_call = 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_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);
@@ -1202,7 +1213,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
            if (e->flags & EDGE_EH)
              bitmap_ior_and_compl_into (new_live_at_end,
                                         sb->il.rtl->global_live_at_start,
-                                        invalidated_by_call);
+                                        invalidated_by_eh_edge);
            else
              IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
 
@@ -1422,7 +1433,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
 
   FREE_REG_SET (tmp);
   FREE_REG_SET (new_live_at_end);
-  FREE_REG_SET (invalidated_by_call);
+  FREE_REG_SET (invalidated_by_eh_edge);
   FREE_REG_SET (registers_made_dead);
 
   if (blocks_out)
@@ -2214,6 +2225,28 @@ propagate_block (basic_block bb, regset live, regset local_set,
        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 7bc9233c43425b302fc9c4cfb7d03e50e4ccd922..229f862c28cf763d7e71be345abddc68eee472e2 100644 (file)
@@ -743,6 +743,21 @@ global_conflicts (void)
            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