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]

[PATCH] Fix wrong register allocation for EH


Hi,

the problem is responsible for ACATS and C++ failures on SPARC/Solaris,
for example g++.old-deja/g++.eh/inline2.C.  IRA doesn't correctly deal
with EH_RETURN_DATA_REGNO, unlike the old RA:

struct A {
  ~A()
  {
    try { throw 1; }
    catch (...) { }
  }
};

int main ()
{
  try
    {
      A a;
      throw 42;
    }
  catch (int i)
    {
      return (i != 42);
    }
}

When the first try/catch block is inlined into the second catch, the incoming
EH_RETURN_DATA_REGNO values for the second throw must be preserved while the 
first throw is being expanded and clobbers the EH_RETURN_DATA_REGNO registers.

These values are saved into pseudos but IRA can assign EH_RETURN_DATA_REGNO 
registers to these pseudos across EH edges, which defeats the purpose of 
saving the values of EH_RETURN_DATA_REGNO altogether.

The old RA has explicit couter-measures for such "problematic" cases:

#ifdef EH_RETURN_DATA_REGNO
      if (bb_has_eh_pred (bb))
	{
	  unsigned int i;
    
	  for (i = 0; ; ++i)
	    {
	      unsigned int regno = EH_RETURN_DATA_REGNO (i);
	      if (regno == INVALID_REGNUM)
		break;
	      record_one_conflict (allocnos_live, &hard_regs_live, regno);
	    }

	  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
	    {
	      allocno[i].no_eh_reg = 1;
	    }
	}
#endif

      if (bb_has_abnormal_pred (bb))
	{
	  unsigned int i;
#ifdef STACK_REGS
	  /* Pseudos can't go in stack regs at the start of a basic block that
	     is reached by an abnormal edge. Likewise for call clobbered regs,
	     because caller-save, fixup_abnormal_edges and possibly the table
	     driven EH machinery are not quite ready to handle such regs live
	     across such edges.  */
	  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
	    {
	      allocno[i].no_stack_reg = 1;
	    }

	  for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
	    record_one_conflict (allocnos_live, &hard_regs_live, i);
#endif
	  
	  /* No need to record conflicts for call clobbered regs if we have
	     nonlocal labels around, as we don't ever try to allocate such
	     regs in this case.  */
	  if (! cfun->has_nonlocal_label)
	    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
	      if (call_used_regs [i])
		record_one_conflict (allocnos_live, &hard_regs_live, i);
	}

but, while the second part (for abnormal edges) has been transposed in 
process_bb_node_lives, the first part (for EH edges) hasn't.

Hence the attached patch, tested on SPARC/Solaris, OK for mainline?


2008-11-10  Eric Botcazou  <ebotcazou@adacore.com>

	* ira-lives.c (process_bb_node_lives): Deal with EH_RETURN_DATA_REGNO.
	

-- 
Eric Botcazou
Index: ira-lives.c
===================================================================
--- ira-lives.c	(revision 141707)
+++ ira-lives.c	(working copy)
@@ -785,8 +785,6 @@ process_bb_node_lives (ira_loop_tree_nod
   unsigned int j;
   basic_block bb;
   rtx insn;
-  edge e;
-  edge_iterator ei;
   bitmap_iterator bi;
   bitmap reg_live_out;
   unsigned int px;
@@ -985,16 +983,23 @@ process_bb_node_lives (ira_loop_tree_nod
 	  curr_point++;
 	}
 
+#ifdef EH_RETURN_DATA_REGNO
+      if (bb_has_eh_pred (bb))
+	for (j = 0; ; ++j)
+	  {
+	    unsigned int regno = EH_RETURN_DATA_REGNO (j);
+	    if (regno == INVALID_REGNUM)
+	      break;
+	    make_regno_born (regno);
+	  }
+#endif
+
       /* Allocnos can't go in stack regs at the start of a basic block
 	 that is reached by an abnormal edge. Likewise for call
 	 clobbered regs, because caller-save, fixup_abnormal_edges and
 	 possibly the table driven EH machinery are not quite ready to
 	 handle such allocnos live across such edges.  */
-      FOR_EACH_EDGE (e, ei, bb->preds)
-	if (e->flags & EDGE_ABNORMAL)
-	  break;
-
-      if (e != NULL)
+      if (bb_has_abnormal_pred (bb))
 	{
 #ifdef STACK_REGS
 	  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, px)

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