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]

[ tree-ssa ] Minor EH CFG improvement


A few months ago we discussed the utility of connecting edges from
nonreturning function calls to the exit block and decided that it
shouldn't be necessary :-)

I made a couple attempts to cleanup the CFG builder to not create those
edges and, well, decided that the CFG builder needs to be reimplemented.

Until that happens this patch is sufficient to eliminate those edges.  We
mark them as fake edges (which is what they really are).  Then we remove
fake edges after building the CFG.

I stumbled upon this while looking at something like this:


try
  {
    try
      {
        (void) 0
      }
    catch
      {
        __cxa_call_unexpected (...)
      }
  }
finally
  {
    if (...)
      {
        ...
      }
    else
      {
        (void)0
      }
  }
[ ... more useful code ... ]

The block with the call to __cxa_call_unexpected has an edge to the
exit block.  This is considered a call out of the TRY block.  So we
wire up an edge from the end of the FINALLY block to the exit block
(among other actions).  This new edge is associated with the ELSE block
in the FINALLY.

Now DCE comes along and decides that the IF conditional is useless
and tries to wire up an edge to the postdominator of the IF conditional.
However, no post dominator exists since the ELSE block can reach EXIT
without traversing through any other block.

So rather than placing an edge to [ ... more useful code ... ] we 
create an edge to the exit block.  In an ugly-enough hunk of code this
resulted in the [ ... more useful code ... ] becoming unreachable and
thus getting removed and several tests in libstdc++ started failing.
Ugh.

[ Note you need other changes which try to cut down on the number of
  unnecessary edges in the CFG to trigger this. ]

Anyway, this zaps those edges before anyone sees them.  If we have
algorithms that really need these problem edges, we already have
routines which walk the CFG and know where to insert these fake
noreturn edges.


	* tree-cfg.c (make_edges): Remove fake edges.
	(make_exit_edges): Mark edges from nonreturning functions to the
	exit block as being fake edges.

	
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.114
diff -c -3 -p -r1.1.4.114 tree-cfg.c
*** tree-cfg.c	23 Jun 2003 15:51:11 -0000	1.1.4.114
--- tree-cfg.c	23 Jun 2003 18:02:18 -0000
*************** make_edges (void)
*** 959,964 ****
--- 959,968 ----
  
    try_finallys = NULL;
  
+   /* We do not care about fake edges, so remove any that the CFG
+      builder inserted for completeness.  */
+   remove_fake_edges ();
+ 
    /* Clean up the graph and warn for unreachable code.  */
    cleanup_tree_cfg ();
  }
*************** make_exit_edges (basic_block bb)
*** 1188,1199 ****
  	    make_edge (bb, bb_for_stmt (TREE_VALUE (t)), EDGE_ABNORMAL);
  	}
  
!       /* Some calls are known not to return.  For such calls we need to
! 	 add an edge to the exit block.  No fall thru edge is needed
! 	 as these calls can not return in the normal sense.  */
        if (call_expr_flags (last) & (ECF_NORETURN | ECF_LONGJMP))
  	{
! 	  make_edge (bb, EXIT_BLOCK_PTR, 0);
  	  return;
  	}
  
--- 1192,1207 ----
  	    make_edge (bb, bb_for_stmt (TREE_VALUE (t)), EDGE_ABNORMAL);
  	}
  
!       /* Some calls are known not to return.  For such calls we create
! 	 a fake edge.
! 
! 	 We really need to revamp how we build edges so that it's not
! 	 such a bloody pain to avoid creating edges for this case since
! 	 all we do is remove these edges when we're done building the
! 	 CFG.  */
        if (call_expr_flags (last) & (ECF_NORETURN | ECF_LONGJMP))
  	{
! 	  make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
  	  return;
  	}
  









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