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]

More MUST_NOT_THROW region cleanups


Hi,
this patch makes remove_unreachable_regions to unify all MUST_NOT_THROW regions
that are handled by runtime to single; they are all equivalent.
Locally handled ones are bit harder since CFG update is needed and we might
want to preserve unwind info, so I am just bringing them to root of tree.

The patch eliminates about half of the regions on tramp3d saving
primarily some memory, making dumps more readable and hopefully helping
LTO. During expanding dwarf we expand action records as paths from
throwing statement to the root of tree stopping at first catch that is
basically unchanged by the transformation.

Bootstrapped/regtested x86_64-linux, OK?

	* except.c (eh_region): New allocator.
	(bring_to_root): New.
	(remove_unreachable_regions): Collect MUST_NOT_THROWs, unify runtime
	handled ones to single region, put all to the root of tree.
	(remove_eh_handler_and_replace): Break out of ...
	(remove_eh_handler): ... here.
Index: except.c
===================================================================
--- except.c	(revision 145262)
+++ except.c	(working copy)
@@ -208,6 +208,7 @@ struct call_site_record GTY(())
 
 DEF_VEC_P(eh_region);
 DEF_VEC_ALLOC_P(eh_region, gc);
+DEF_VEC_ALLOC_P(eh_region, heap);
 
 /* Used to save exception status for each function.  */
 struct eh_status GTY(())
@@ -252,6 +253,8 @@ static int ehl_eq (const void *, const v
 static void add_ehl_entry (rtx, struct eh_region *);
 static void remove_exception_handler_label (rtx);
 static void remove_eh_handler (struct eh_region *);
+static void remove_eh_handler_and_replace (struct eh_region *,
+					   struct eh_region *);
 static int for_each_eh_label_1 (void **, void *);
 
 /* The return value of reachable_next_level.  */
@@ -712,21 +721,42 @@ can_be_reached_by_runtime (sbitmap conta
     }
 }
 
+/* Bring region R to the root of tree.  */
+
+static void
+bring_to_root (struct eh_region *r)
+{
+  struct eh_region **pp;
+  struct eh_region *outer = r->outer;
+  if (!r->outer)
+    return;
+  for (pp = &outer->inner; *pp != r; pp = &(*pp)->next_peer)
+    continue;
+  *pp = r->next_peer;
+  r->outer = NULL;
+  r->next_peer = cfun->eh->region_tree;
+  cfun->eh->region_tree = r;
+}
+
 /* Remove all regions whose labels are not reachable.
    REACHABLE is bitmap of all regions that are used by the function
    CONTAINS_STMT is bitmap of all regions that contains stmt (or NULL). */
+
 void
 remove_unreachable_regions (sbitmap reachable, sbitmap contains_stmt)
 {
   int i;
   struct eh_region *r;
+  VEC(eh_region,heap) *must_not_throws = VEC_alloc (eh_region, heap, 16);
+  struct eh_region *local_must_not_throw = NULL;
+  struct eh_region *first_must_not_throw = NULL;
 
   for (i = cfun->eh->last_region_number; i > 0; --i)
     {
       r = VEC_index (eh_region, cfun->eh->region_array, i);
-      if (!r)
+      if (!r || r->region_number != i)
 	continue;
-      if (r->region_number == i && !TEST_BIT (reachable, i) && !r->resume)
+      if (!TEST_BIT (reachable, i) && !r->resume)
 	{
 	  bool kill_it = true;
 
@@ -777,11 +807,60 @@ remove_unreachable_regions (sbitmap reac
 			 r->region_number);
 	      remove_eh_handler (r);
 	    }
+	  else if (r->type == ERT_MUST_NOT_THROW)
+	    {
+	      if (!first_must_not_throw)
+	        first_must_not_throw = r;
+	      VEC_safe_push (eh_region, heap, must_not_throws, r);
+	    }
+	}
+      else
+	if (r->type == ERT_MUST_NOT_THROW)
+	  {
+	    if (!local_must_not_throw)
+	      local_must_not_throw = r;
+	    if (r->outer)
+	      VEC_safe_push (eh_region, heap, must_not_throws, r);
+	  }
+    }
+
+  /* MUST_NOT_THROW regions without local handler are all the same; they
+     trigger terminate call in runtime.
+     MUST_NOT_THROW handled locally can differ in debug info associated
+     to std::terminate () call or if one is comming from Java and other
+     from C++ whether they call terminate or abort.  
+
+     We merge all runtime handler MUST_NOT_THROW region into single
+     and bring all local must not throw to the roots of EH tree
+     (since unwinding never continues to the outer region anyway).
+     If MUST_NOT_THROW with local handler is present in the tree, we use
+     that region to merge into, since it will remain in tree anyway;
+     otherwise we use first MUST_NOT_THROW.
+
+     Merging of local receivers can not be done without redirecting CFG
+     and is job for crossjumping that can decide whether cleanup really
+     is the same.  */
+
+  if (local_must_not_throw)
+    first_must_not_throw = local_must_not_throw;
+
+  for (i = 0; VEC_iterate (eh_region, must_not_throws, i, r); i++)
+    {
+      if (!r->label && !r->tree_label && r != first_must_not_throw)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Replacing MUST_NOT_THROW region %i by %i\n",
+		     r->region_number,
+		     first_must_not_throw->region_number);
+	  remove_eh_handler_and_replace (r, first_must_not_throw);
 	}
+      else
+	bring_to_root (r);
     }
 #ifdef ENABLE_CHECKING
   verify_eh_tree (cfun);
 #endif
+  VEC_free (eh_region, heap, must_not_throws);
 }
 
 /* Return array mapping LABEL_DECL_UID to region such that region's tree_label
@@ -2386,22 +2459,24 @@ remove_exception_handler_label (rtx labe
   htab_clear_slot (crtl->eh.exception_handler_label_map, (void **) slot);
 }
 
-/* Splice REGION from the region tree etc.  */
+/* Splice REGION from the region tree and replace it by OUTER etc.  */
 
 static void
-remove_eh_handler (struct eh_region *region)
+remove_eh_handler_and_replace (struct eh_region *region,
+			       struct eh_region *replace)
 {
   struct eh_region **pp, **pp_start, *p, *outer, *inner;
   rtx lab;
 
+  outer = region->outer;
   /* For the benefit of efficiently handling REG_EH_REGION notes,
      replace this region in the region array with its containing
      region.  Note that previous region deletions may result in
      multiple copies of this region in the array, so we have a
      list of alternate numbers by which we are known.  */
 
-  outer = region->outer;
-  VEC_replace (eh_region, cfun->eh->region_array, region->region_number, outer);
+  VEC_replace (eh_region, cfun->eh->region_array, region->region_number,
+	       replace);
   if (region->aka)
     {
       unsigned i;
@@ -2409,17 +2484,17 @@ remove_eh_handler (struct eh_region *reg
 
       EXECUTE_IF_SET_IN_BITMAP (region->aka, 0, i, bi)
 	{
-          VEC_replace (eh_region, cfun->eh->region_array, i, outer);
+          VEC_replace (eh_region, cfun->eh->region_array, i, replace);
 	}
     }
 
-  if (outer)
+  if (replace)
     {
-      if (!outer->aka)
-        outer->aka = BITMAP_GGC_ALLOC ();
+      if (!replace->aka)
+        replace->aka = BITMAP_GGC_ALLOC ();
       if (region->aka)
-	bitmap_ior_into (outer->aka, region->aka);
-      bitmap_set_bit (outer->aka, region->region_number);
+	bitmap_ior_into (replace->aka, region->aka);
+      bitmap_set_bit (replace->aka, region->region_number);
     }
 
   if (crtl->eh.built_landing_pads)
@@ -2437,12 +2512,16 @@ remove_eh_handler (struct eh_region *reg
     continue;
   *pp = region->next_peer;
 
+  if (replace)
+    pp_start = &replace->inner;
+  else
+    pp_start = &cfun->eh->region_tree;
   inner = region->inner;
   if (inner)
     {
       for (p = inner; p->next_peer ; p = p->next_peer)
-	p->outer = outer;
-      p->outer = outer;
+	p->outer = replace;
+      p->outer = replace;
 
       p->next_peer = *pp_start;
       *pp_start = inner;
@@ -2476,6 +2555,14 @@ remove_eh_handler (struct eh_region *reg
     }
 }
 
+/* Splice REGION from the region tree etc.  */
+
+static void
+remove_eh_handler (struct eh_region *region)
+{
+  remove_eh_handler_and_replace (region, region->outer);
+}
+
 /* LABEL heads a basic block that is about to be deleted.  If this
    label corresponds to an exception region, we may be able to
    delete the region.  */


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