public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Sandiford <richard@codesourcery.com>
To: gcc-patches@gcc.gnu.org
Subject: [tree->rtl] Fix execute/20041124-1.c for SH PIC
Date: Fri, 10 Aug 2007 18:31:00 -0000	[thread overview]
Message-ID: <87abszb5sl.fsf@firetop.home> (raw)

This patch fixes an sh-elf ICE on gcc.c-torture/execute/20041124-1.c
for -O -fPIC.  The testcase is simple:

-------------------------------------------------------------------
struct s { _Complex unsigned short x; };
struct s gs = { 100 + 200i };
struct s __attribute__((noinline)) foo (void) { return gs; }

int main ()
{
  if (foo ().x != gs.x)
    abort ();
  exit (0);
}
-------------------------------------------------------------------

foo() returns in (reg:CHI r0).  Because r0 is a likely-spilled register,
we would normally try to copy it into a pseudo register immediately
after a call to foo().  Passes like combine would then check for such
a move and refuse to propagate r0 into later instructions, avoiding the
risk of a spill failure.

Unfortunately, CHI is special.  The "pseudo register" we create is
actually a CONCAT of two HImode pseudo registers, and the assigment
to the high part is an lshiftrt of r0 rather than a simple move.
This assignment therefore avoids the special checks done in combine,
and we try to combine the lshiftrt into later instructions.  In the test
case, we extend r0's lifetime across a GOT load, and the GOT load must
use r0 for the index.

The two obvious fixes seem to be: make combine smarter, or avoid using
a likely-spilled return register on the rhs of the CONCAT assignment.
The latter seemed better to me, as it should work with any similar
checks in passes besides combine.

It wasn't safe at one time to create a true CHI pseudo register, but
rth's emit_move_insn_1/emit_move_complex_parts improvements should have
fixed that.  The patch therefore copies a likely-spilled hard register
to a non-CONCAT register.

Bootstrapped & regression-tested on x86_64-linux-gnu.
Also regression-tested on i586-wrs-vxworks, sh-wrs-vxworks
and sh-elf (options {,-m2,-m3,-m4,-m4/-ml}).  OK to install?

Richard


gcc/
	* calls.c (avoid_likely_spilled_reg): New function.
	(expand_call): Use it.

Index: gcc/calls.c
===================================================================
--- gcc/calls.c	(revision 127322)
+++ gcc/calls.c	(working copy)
@@ -1856,6 +1856,31 @@ shift_return_value (enum machine_mode mo
   return true;
 }
 
+/* If X is a likely-spilled register value, copy it to a pseudo
+   register and return that register.  Return X otherwise.  */
+
+static rtx
+avoid_likely_spilled_reg (rtx x)
+{
+  rtx new;
+
+  if (REG_P (x)
+      && HARD_REGISTER_P (x)
+      && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (x))))
+    {
+      /* Make sure that we generate a REG rather than a CONCAT.
+	 Moves into CONCATs can need nontrivial instructions,
+	 and the whole point of this function is to avoid
+	 using the hard register directly in such a situation.  */
+      generating_concat_p = 0;
+      new = gen_reg_rtx (GET_MODE (x));
+      generating_concat_p = 1;
+      emit_move_insn (new, x);
+      return new;
+    }
+  return x;
+}
+
 /* Generate all the code for a CALL_EXPR exp
    and return an rtx for its value.
    Store the value in TARGET (specified as an rtx) if convenient.
@@ -2953,11 +2978,7 @@ expand_call (tree exp, rtx target, int i
 
 	  /* We have to copy a return value in a CLASS_LIKELY_SPILLED hard
 	     reg to a plain register.  */
-	  if (REG_P (valreg)
-	      && HARD_REGISTER_P (valreg)
-	      && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (valreg)))
-	      && !(REG_P (target) && !HARD_REGISTER_P (target)))
-	    valreg = copy_to_reg (valreg);
+	  valreg = avoid_likely_spilled_reg (valreg);
 
 	  /* If TARGET is a MEM in the argument area, and we have
 	     saved part of the argument area, then we can't store
@@ -3002,7 +3023,7 @@ expand_call (tree exp, rtx target, int i
 	  sibcall_failure = 1;
 	}
       else
-	target = copy_to_reg (valreg);
+	target = copy_to_reg (avoid_likely_spilled_reg (valreg));
 
       if (targetm.calls.promote_function_return(funtype))
 	{

             reply	other threads:[~2007-08-10 18:31 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-08-10 18:31 Richard Sandiford [this message]
2007-08-11  0:34 ` Ian Lance Taylor
2007-08-11 13:09   ` Richard Sandiford
2007-08-11 15:49     ` Ian Lance Taylor

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=87abszb5sl.fsf@firetop.home \
    --to=richard@codesourcery.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).