This is the mail archive of the 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]

[pretty-ipa] Enable IPA nothrow discovery

this patch make ipa-pure-const to set NOTHROW flags in the IPA mode I promised
while merging the ipa-pure-const reqrite.  There was two major problems here; firstly
the ipa-pure-const propgate properties over all edges, while throwing calls
make callers throwing only when things are not caught locally.
So I added hook to ipa_utils_reduced_inorder to compute inorder for cases
where we ignore some edges, added flag to cgraph edges specifying if they
can end up throwing externally and made ipa-pure-const to propagate only this way.

This makes pass to find 400 new nothrow flags on tramp3d compared to version
propagating over all edges that found only 60. Tramp3d is not best testcase
here; acyclic graphs are well handled by early optimizers.  So in fact I am quite
surprised there are so many extra nothrow functions found and will look into why.

Second problem was the fact that making function NOTHROW requires fixup_cfg
to be performed on the callers, otherwise verify_stmt fails.  Passmanager
calls verify_ssa and verify_stmt on all bodies in between IPA passes, so it
gets false positives here.  This is fixed by relaxing this check in verify_stmt
when in IPA mode.

There is still one issue left: when there is local handler that continue
throwing externally via RESX that is reached only via possibly throwing
calls, proving the calles non-throwing will not make caller non-throwing
since we mark it locally throwing when visiting the RESX.  This can be
fixed: when visiting RESX look for all EH edges that leads to this RESX
and if they are all calls, mark them all throwing externally.  This
seems like case that we can be interested to handle well, since local
cleanups are common, but I will do this incrementally.

I plan to commit the patch today to pretty-ipa for further testing and if there
are no complains, I will prepare mainline version and merge next week.


	* cgraph.c (cgraph_make_edge, dump_cgraph_node, cgraph_set_call_stmt):
	Set nothrow flag.
	* cgraph.h (struct function): Reduce loop_nest to 30 bits; add
	can_throw_external flag.
	* ipa-reference.c (ipa_utils_reduced_inorder): Update call.
	* ipa-pure-const.c (ignore_edge): New function.
	(propagate): Compute order for NOTHROW computation; set NOTHROWs
	only over can_throw_external edges.
	(local_pure_const): Add nothrow flag.
	* ipa-utils.c (searchc): Add ignore_edge callback.
	(ipa_utils_reduced_inorder): Add ignore_edge callback.
	* ipa-utils.h (ipa_utils_reduced_inorder): Update prototype.
	(set_nothrow_function_flags): Update cgraph.
	* tree-cfg.c (verify_stmt): Relax nothrow checking when in IPA mode.
Index: cgraph.c
--- cgraph.c	(revision 146003)
+++ cgraph.c	(working copy)
@@ -639,6 +639,7 @@
 				 htab_hash_pointer (e->call_stmt));
   e->call_stmt = new_stmt;
+  e->can_throw_external = stmt_can_throw_external (new_stmt);
   if (e->caller->call_site_hash)
       void **slot;
@@ -667,7 +668,6 @@
     for (node = orig->clones; node != orig;)
 	struct cgraph_edge *edge = cgraph_edge (node, old_stmt);
 	if (edge)
 	  cgraph_set_call_stmt (edge, new_stmt);
 	if (node->clones)
@@ -774,6 +774,7 @@
   edge->caller = caller;
   edge->callee = callee;
   edge->call_stmt = call_stmt;
+  edge->can_throw_external = stmt_can_throw_external (call_stmt);
   edge->prev_caller = NULL;
   edge->next_caller = callee->callers;
   if (callee->callers)
@@ -1386,6 +1387,8 @@
 	fprintf(f, "(inlined) ");
       if (edge->indirect_call)
 	fprintf(f, "(indirect) ");
+      if (edge->can_throw_external)
+	fprintf(f, "(can throw external) ");
   fprintf (f, "\n  calls: ");
Index: cgraph.h
--- cgraph.h	(revision 146003)
+++ cgraph.h	(working copy)
@@ -248,9 +248,11 @@
      per function call.  The range is 0 to CGRAPH_FREQ_MAX.  */
   int frequency;
   /* Depth of loop nest, 1 means no loop nest.  */
-  unsigned int loop_nest : 31;
+  unsigned int loop_nest : 30;
   /* Whether this edge describes a call that was originally indirect.  */
   unsigned int indirect_call : 1;
+  /* Can this call throw external

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