[committed] cfgrtl.c patch for IA-64 libada build failure

James E Wilson wilson@specifix.com
Tue Oct 18 00:48:00 GMT 2005


libada was failing to build on IA-64, giving errors like this
  a-teioed.adb:843: error: Call edges for non-call insn in bb 526
I tracked it down to a problem with call-insn splitting done by the
IA-64 port, and the fact that Ada uses flag_non_call_exceptions.

The IA-64 port was splitting a call into a call and a gp load, so now we
have a basic block ending with a load that has an abnormal call edge
leaving it.  purge_dead_edges in cfgrtl was supposed to fix this, but
got confused by the fact that because flag_non_call_exceptions is true a
load is a potential throwing insn, and so an EH edge is OK here, just
not a abnormal call EH edge.  Full gory details are in the PR.

The flaw with the purge_dead_edges code is that it was testing for EH
edges and abnormal call edges in the wrong order.  Since an abnormal
call edge can also be an EH edge, we never verified that abnormal call
EH edges were still attached to call insns.  Since this matters only if
flag_non_call_exceptions is true, it didn't show up in C++ code.  This
is trivial to fix by switching the order of the tests.

I've tested this with a C and Ada only IA-64 bootstrap.  There were no
regressions for the C part.  Ada does not build without this patch.

Andreas Schwab also did a full build including Ada with this patch, and
the results are here.  I think they look very good.
    http://gcc.gnu.org/ml/gcc-testresults/2005-10/msg00730.html

I've added the patch to mainline.  I plan to add it to the gcc-4.0
branch soon, after I do the necessary builds to test it there.

PS Since the gp load is from the stack, we probably don't need to
consider this a potential trapping insn.  Maybe we should be setting
MEM_NOTRAP_P in ia64_reload_gp?
-- 
Jim Wilson, GNU Tools Support, http://www.specifix.com
-------------- next part --------------
2005-10-16  James E Wilson  <wilson@specifix.com>

	PR rtl-optimization/17356
	* cfgrtl.c (purge_dead_edges): Check for EDGE_ABNORMAL_CALL before
	checking for EDGE_EH.

Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.181
diff -p -p -r1.181 cfgrtl.c
*** cfgrtl.c	28 Jul 2005 21:11:30 -0000	1.181
--- cfgrtl.c	17 Oct 2005 01:41:58 -0000
*************** purge_dead_edges (basic_block bb)
*** 2300,2318 ****
    /* Cleanup abnormal edges caused by exceptions or non-local gotos.  */
    for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
      {
!       if (e->flags & EDGE_EH)
  	{
! 	  if (can_throw_internal (BB_END (bb)))
  	    {
  	      ei_next (&ei);
  	      continue;
  	    }
  	}
!       else if (e->flags & EDGE_ABNORMAL_CALL)
  	{
! 	  if (CALL_P (BB_END (bb))
! 	      && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
! 		  || INTVAL (XEXP (note, 0)) >= 0))
  	    {
  	      ei_next (&ei);
  	      continue;
--- 2300,2322 ----
    /* Cleanup abnormal edges caused by exceptions or non-local gotos.  */
    for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
      {
!       /* We must check for the most restrictive condition first.  Since
! 	 an abnormal call edge is always an EH edge, but an EH edge is not
! 	 always an abnormal call edge, we must check for an abnormal call
! 	 edge first.  */
!       if (e->flags & EDGE_ABNORMAL_CALL)
  	{
! 	  if (CALL_P (BB_END (bb))
! 	      && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
! 		  || INTVAL (XEXP (note, 0)) >= 0))
  	    {
  	      ei_next (&ei);
  	      continue;
  	    }
  	}
!       else if (e->flags & EDGE_EH)
  	{
! 	  if (can_throw_internal (BB_END (bb)))
  	    {
  	      ei_next (&ei);
  	      continue;


More information about the Gcc-patches mailing list