[RFA] pretty-ipa merge 8: handle aka bitmaps in EH duplication

Jan Hubicka hubicka@ucw.cz
Sat Mar 28 23:42:00 GMT 2009


Hi,
this patch update EH duplication code to handle AKA bitmaps I need for
the ehcleanup pass.  It depends on bitmap_last_set_bit I am retesting
after some last minute change and will send soon.

There is nothing earthshaking, just extra logic to duplicate the
aka bitmaps and find completely removed toplevel regions and add
them to the outer region of inlined function.

Path also makes foreach_reachable_handler, can_throw_internal_1,
can_throw_external_1 to handle case where toplevel handler was removed
(because it was empty catch block)

Bootstrapped/regtested x86_64-linux, OK?

	* except.c (duplicate_eh_regions_0): Handle AKA bitmap.
	(duplicate_eh_regions_1): Likewise.
	(duplicate_eh_regions): Likewise; cleanup code gorwing the region
	vector; call EH verification.
	(foreach_reachable_handler, can_throw_internal_1, can_throw_external_1):
	Be ready for region being removed.
	(struct reachable_info): Remove dead saw_any_handlers.

Index: except.c
===================================================================
--- except.c	(revision 145204)
+++ except.c	(working copy)
@@ -821,6 +959,17 @@ current_function_has_exception_handlers 
 static void
 duplicate_eh_regions_0 (eh_region o, int *min, int *max)
 {
+  int i;
+
+  if (o->aka)
+    {
+      i = bitmap_first_set_bit (o->aka);
+      if (i < *min)
+        *min = i;
+      i = bitmap_last_set_bit (o->aka);
+      if (i > *max)
+        *max = i;
+    }
   if (o->region_number < *min)
     *min = o->region_number;
   if (o->region_number > *max)
@@ -852,7 +1001,18 @@ duplicate_eh_regions_1 (eh_region old, e
   *n = *old;
   n->outer = outer;
   n->next_peer = NULL;
-  gcc_assert (!old->aka);
+  if (old->aka)
+    {
+      unsigned i;
+      bitmap_iterator bi;
+      n->aka = BITMAP_GGC_ALLOC ();
+
+      EXECUTE_IF_SET_IN_BITMAP (old->aka, 0, i, bi)
+	{
+	  bitmap_set_bit (n->aka, i + eh_offset);
+          VEC_replace (eh_region, cfun->eh->region_array, i + eh_offset, n);
+	}
+    }
 
   n->region_number += eh_offset;
   VEC_replace (eh_region, cfun->eh->region_array, n->region_number, n);
@@ -883,8 +1043,11 @@ duplicate_eh_regions (struct function *i
   int i, min_region, max_region, eh_offset, cfun_last_region_number;
   int num_regions;
 
-  if (!ifun->eh->region_tree)
+  if (!ifun->eh)
     return 0;
+#ifdef ENABLE_CHECKING
+  verify_eh_tree (ifun);
+#endif
 
   /* Find the range of region numbers to be copied.  The interface we 
      provide here mandates a single offset to find new number from old,
@@ -905,23 +1068,18 @@ duplicate_eh_regions (struct function *i
   eh_offset = cfun_last_region_number + 1 - min_region;
 
   /* If we've not yet created a region array, do so now.  */
-  VEC_safe_grow (eh_region, gc, cfun->eh->region_array,
-		 cfun_last_region_number + 1 + num_regions);
-  cfun->eh->last_region_number = max_region + eh_offset;
-
-  /* We may have just allocated the array for the first time.
-     Make sure that element zero is null.  */
-  VEC_replace (eh_region, cfun->eh->region_array, 0, 0);
-
-  /* Zero all entries in the range allocated.  */
-  memset (VEC_address (eh_region, cfun->eh->region_array)
-	  + cfun_last_region_number + 1, 0, num_regions * sizeof (eh_region));
+  cfun->eh->last_region_number = cfun_last_region_number + num_regions;
+  VEC_safe_grow_cleared (eh_region, gc, cfun->eh->region_array,
+		         cfun->eh->last_region_number + 1);
 
   /* Locate the spot at which to insert the new tree.  */
   if (outer_region > 0)
     {
       outer = VEC_index (eh_region, cfun->eh->region_array, outer_region);
-      splice = &outer->inner;
+      if (outer)
+        splice = &outer->inner;
+      else
+        splice = &cfun->eh->region_tree;
     }
   else
     {
@@ -931,6 +1089,19 @@ duplicate_eh_regions (struct function *i
   while (*splice)
     splice = &(*splice)->next_peer;
 
+  if (!ifun->eh->region_tree)
+    {
+      if (outer)
+        for (i = cfun_last_region_number + 1; i <= cfun->eh->last_region_number; i++)
+	  {
+	    VEC_replace (eh_region, cfun->eh->region_array, i, outer);
+	    if (outer->aka == NULL)
+	      outer->aka = BITMAP_GGC_ALLOC ();
+	    bitmap_set_bit (outer->aka, i);
+ 	  }
+      return eh_offset;
+    }
+
   /* Copy all the regions in the subtree.  */
   if (copy_region > 0)
     {
@@ -978,7 +1149,21 @@ duplicate_eh_regions (struct function *i
   for (i = cfun_last_region_number + 1;
        VEC_iterate (eh_region, cfun->eh->region_array, i, cur); ++i)
     {
+      /* All removed EH that is toplevel in input function is now
+         in outer EH of output function.  */
       if (cur == NULL)
+	{
+	  gcc_assert (VEC_index (eh_region, ifun->eh->region_array, i - eh_offset) == NULL);
+	  if (outer)
+	    {
+	      VEC_replace (eh_region, cfun->eh->region_array, i, outer);
+	      if (outer->aka == NULL)
+		outer->aka = BITMAP_GGC_ALLOC ();
+	      bitmap_set_bit (outer->aka, i);
+	    }
+	  continue;
+	}
+      if (i != cur->region_number)
 	continue;
 
 #define REMAP(REG) \
@@ -1014,6 +1199,9 @@ duplicate_eh_regions (struct function *i
 
 #undef REMAP
     }
+#ifdef ENABLE_CHECKING
+  verify_eh_tree (cfun);
+#endif
 
   return eh_offset;
 }
@@ -2316,7 +2515,6 @@ struct reachable_info
   tree types_allowed;
   void (*callback) (struct eh_region *, void *);
   void *callback_data;
-  bool saw_any_handlers;
 };
 
 /* A subroutine of reachable_next_level.  Return true if TYPE, or a
@@ -2552,6 +2750,8 @@ foreach_reachable_handler (int region_nu
   info.callback_data = callback_data;
 
   region = VEC_index (eh_region, cfun->eh->region_array, region_number);
+  if (!region)
+    return;
 
   type_thrown = NULL_TREE;
   if (is_resx)
@@ -2642,6 +2842,8 @@ can_throw_internal_1 (int region_number,
   tree type_thrown;
 
   region = VEC_index (eh_region, cfun->eh->region_array, region_number);
+  if (!region)
+    return false;
 
   type_thrown = NULL_TREE;
   if (is_resx)
@@ -2703,6 +2905,8 @@ can_throw_external_1 (int region_number,
   tree type_thrown;
 
   region = VEC_index (eh_region, cfun->eh->region_array, region_number);
+  if (!region)
+    return true;
 
   type_thrown = NULL_TREE;
   if (is_resx)



More information about the Gcc-patches mailing list