public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Eric Botcazou <ebotcazou@adacore.com>
To: gcc-patches@gcc.gnu.org
Subject: [PATCH] Fix wrong register allocation for EH
Date: Mon, 10 Nov 2008 23:12:00 -0000	[thread overview]
Message-ID: <200811102356.03693.ebotcazou@adacore.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2605 bytes --]

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

[-- Attachment #2: eh_return_data.diff --]
[-- Type: text/x-diff, Size: 1220 bytes --]

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)

             reply	other threads:[~2008-11-10 22:55 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-10 23:12 Eric Botcazou [this message]
2008-11-11 16:22 ` Vladimir Makarov
2008-11-15 10:23   ` Richard Sandiford
2008-11-15 11:45     ` Eric Botcazou
2008-11-16 17:09     ` Vladimir Makarov
2008-11-14 18:24 ` Laurent GUERBY
2008-11-14 18:28   ` Laurent GUERBY
2008-11-14 19:35     ` Eric Botcazou
2008-11-15 12:44       ` Laurent GUERBY

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200811102356.03693.ebotcazou@adacore.com \
    --to=ebotcazou@adacore.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).