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]

Re: [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff


On Fri, Sep 11, 2009 at 09:17:05AM -0700, Nathan Froyd wrote:
> On Fri, Sep 11, 2009 at 10:41:41AM +0200, Jakub Jelinek wrote:
> > Here is an incremental fix on top of Nathan's patch, which fixes
> > libgomp.fortran/vla*.f90 -Os failures on powerpc64-linux -m32 as well as
> > attached testcase.
> > 
> > Bootstrapped/regtested on powerpc64-linux --with-cpu=default32.
> 
> Thanks for this.  The below patch is what I currently have in my tree.
> Changes from my earlier patch + your patch:
> 
> * the computation in rs6000_savres_routine_sym was wrong for some cases
>   on SPE targets; we just needed a couple of parentheses;
> 
> * using the out-of-line FP routines is not possible on single float-only
>   targets because said routines use lfd/stfd;
> 
> * the new testcase didn't work on SPE targets because the "f" constraint
>   is not available (SPE stores float values in GPRs).  Changed to use
>   "r" for such targets and changed to avoid the floating-point-using
>   testcases if __NO_FPRS__.

Jakub pointed out that I botched applying his patch.  David pointed out
that I was doing bogus things with the names of the out-of-line routines
on AIX.  The patch below is my attempt to solve both of those problems.

Tested with cross to powerpc-linux-gnuspe.  Trying to get to a point
where I can test on powerpc-linux-gnu, but having some difficulties
doing so.

-Nathan

Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 151626)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,40 @@
+2009-09-11  Nathan Froyd  <froydnj@codesourcery.com>
+	    Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/41175
+	PR target/40677
+	* config/rs6000/rs6000.c (no_global_regs_above): Fix precedence
+	problem.
+	(rs6000_savres_strategy): Always save FP registers inline if the
+	target doesn't support hardware double-precision.
+	(rs6000_savres_routine_sym): Fix computation for cache selector.
+	Mark the generated symbol as a function.  Move code for determining
+	the name of the symbol...
+	(rs6000_savres_routine_name): ...here.  New function.  Add cases for
+	getting the names right on AIX and 64-bit Linux.
+	(savres_routine_name): New variable.
+	(rs6000_emit_prologue): Correct use of call_used_regs.
+	(rs6000_output_function_prologue): Use rs6000_savres_routine_name to
+	determine FP save/restore functions.
+	(rs6000_emit_stack_reset): Handle savres if sp_offset != 0 and
+	frame_reg_rtx != sp_reg_rtx.  Use gen_add3_insn instead of
+	gen_addsi3.
+	(rs6000_emit_epilogue): Adjust computation of restore_lr.
+	Duplicate restoration of LR and execute the appropriate one
+	depending on whether GPRs are being restored inline.  Set r11 from
+	offsetted frame_reg_rtx instead of sp_reg_rtx; if frame_reg_rtx is
+	r11, adjust sp_offset.  Use gen_add3_insn instead of gen_addsi3.
+	* config/rs6000/rs6000.md (*save_gpregs_<mode>): Use explicit match
+	for register 11.
+	(*save_fpregs_<mode>): Likewise.
+	(*restore_gpregs_<mode>): Likewise.
+	(*return_and_restore_gpregs_<mode>): Likewise.
+	(*return_and_restore_fpregs_<mode>): Likewise.
+	* config/rs6000/spe.md (*save_gpregs_spe): Use explicit match for
+	register 11.
+	(*restore_gpregs_spe): Likewise.
+	(*return_and_restore_gpregs_spe): Likewise.
+
 2009-09-10  Nathan Froyd  <froydnj@codesourcery.com>
 
 	* config/rs6000/rs6000.h (DATA_ALIGNMENT): Check that we are dealing
Index: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog	(revision 151625)
+++ gcc/testsuite/ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2009-09-11  Jakub Jelinek  <jakub@redhat.com>
+	    Nathan Froyd  <froydnj@codesourcery.com>
+
+	* gcc.target/powerpc/pr41175.c: New test.
+
 2009-09-11  Janus Weil  <janus@gcc.gnu.org>
 
 	PR fortran/41242
Index: gcc/testsuite/gcc.target/powerpc/pr41175.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr41175.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr41175.c	(revision 0)
@@ -0,0 +1,461 @@
+/* PR target/41175 */
+/* { dg-do run } */
+/* { dg-options "-Os" } */
+
+#define X2(n) X1(n##0) X1(n##1)
+#define X4(n) X2(n##0) X2(n##1)
+#define X8(n) X4(n##0) X4(n##1)
+
+#ifndef __SPE__
+#define FLOAT_REG_CONSTRAINT "f"
+#else
+#define FLOAT_REG_CONSTRAINT "r"
+#endif
+
+volatile int ll;
+
+__attribute__((noinline)) void
+foo (void)
+{
+  asm volatile ("" : : : "memory");
+}
+
+__attribute__((noinline)) void
+bar (char *p)
+{
+  asm volatile ("" : : "r" (p) : "memory");
+}
+
+__attribute__((noinline)) void
+f1 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+  foo ();
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f2 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+  char *pp = __builtin_alloca (ll);
+  bar (pp);
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f3 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+}
+
+#ifndef __NO_FPRS__
+__attribute__((noinline)) void
+f4 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X4(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X4(d) "=m" (mem) : : "memory");
+  foo ();
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X4(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f5 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X4(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X4(d) "=m" (mem) : : "memory");
+  char *pp = __builtin_alloca (ll);
+  bar (pp);
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X4(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f6 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X4(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X4(d) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X4(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f7 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X2(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X2(d) "=m" (mem) : : "memory");
+  foo ();
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X2(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f8 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X2(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X2(d) "=m" (mem) : : "memory");
+  char *pp = __builtin_alloca (ll);
+  bar (pp);
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X2(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f9 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X8(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X2(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X2(d) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X8(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X2(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f10 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X4(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X1(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X4(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X1(d) "=m" (mem) : : "memory");
+  foo ();
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X4(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X1(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f11 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X4(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X1(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X4(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X1(d) "=m" (mem) : : "memory");
+  char *pp = __builtin_alloca (ll);
+  bar (pp);
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X4(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X1(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f12 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X4(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X1(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X4(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X1(d) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X4(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X1(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f13 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X2(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X8(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X2(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X8(d) "=m" (mem) : : "memory");
+  foo ();
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X2(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X8(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f14 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X2(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X8(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X2(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X8(d) "=m" (mem) : : "memory");
+  char *pp = __builtin_alloca (ll);
+  bar (pp);
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X2(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X8(d) "m" (mem) : "memory");
+}
+
+__attribute__((noinline)) void
+f15 (void)
+{
+  int mem;
+#undef X1
+#define X1(n) int gpr##n = 0;
+  X8(a) X8(b) X2(c)
+#undef X1
+#define X1(n) double fpr##n = 0.0;
+  X8(d)
+#undef X1
+#define X1(n) "+r" (gpr##n),
+  asm volatile ("" : X8(a) "=m" (mem) : : "memory");
+  asm volatile ("" : X8(b) "=m" (mem) : : "memory");
+  asm volatile ("" : X2(c) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : X8(d) "=m" (mem) : : "memory");
+#undef X1
+#define X1(n) "r" (gpr##n),
+  asm volatile ("" : : X8(a) "m" (mem) : "memory");
+  asm volatile ("" : : X8(b) "m" (mem) : "memory");
+  asm volatile ("" : : X2(c) "m" (mem) : "memory");
+#undef X1
+#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
+  asm volatile ("" : : X8(d) "m" (mem) : "memory");
+}
+#endif
+
+int
+main ()
+{
+  ll = 60;
+  f1 ();
+  f2 ();
+  f3 ();
+#ifndef __NO_FPRS__
+  f4 ();
+  f5 ();
+  f6 ();
+  f7 ();
+  f8 ();
+  f9 ();
+  f10 ();
+  f11 ();
+  f12 ();
+  f13 ();
+  f14 ();
+  f15 ();
+#endif
+  return 0;
+}
Index: gcc/config/rs6000/spe.md
===================================================================
--- gcc/config/rs6000/spe.md	(revision 151625)
+++ gcc/config/rs6000/spe.md	(working copy)
@@ -3156,9 +3156,9 @@ (define_insn "*save_gpregs_spe"
   [(match_parallel 0 "any_parallel_operand"
 		   [(clobber (reg:P 65))
 		    (use (match_operand:P 1 "symbol_ref_operand" "s"))
-		    (use (match_operand:P 2 "gpc_reg_operand" "r"))
-		    (set (match_operand:V2SI 3 "memory_operand" "=m")
-			 (match_operand:V2SI 4 "gpc_reg_operand" "r"))])]
+		    (use (reg:P 11))
+		    (set (match_operand:V2SI 2 "memory_operand" "=m")
+			 (match_operand:V2SI 3 "gpc_reg_operand" "r"))])]
   "TARGET_SPE_ABI"
   "bl %z1"
   [(set_attr "type" "branch")
@@ -3168,9 +3168,9 @@ (define_insn "*restore_gpregs_spe"
  [(match_parallel 0 "any_parallel_operand"
 		  [(clobber (reg:P 65))
 		   (use (match_operand:P 1 "symbol_ref_operand" "s"))
-		   (use (match_operand:P 2 "gpc_reg_operand" "r"))
-		   (set (match_operand:V2SI 3 "gpc_reg_operand" "=r")
-			(match_operand:V2SI 4 "memory_operand" "m"))])]
+		   (use (reg:P 11))
+		   (set (match_operand:V2SI 2 "gpc_reg_operand" "=r")
+			(match_operand:V2SI 3 "memory_operand" "m"))])]
  "TARGET_SPE_ABI"
  "bl %z1"
  [(set_attr "type" "branch")
@@ -3181,9 +3181,9 @@ (define_insn "*return_and_restore_gpregs
 		  [(return)
 		   (clobber (reg:P 65))
 		   (use (match_operand:P 1 "symbol_ref_operand" "s"))
-		   (use (match_operand:P 2 "gpc_reg_operand" "r"))
-		   (set (match_operand:V2SI 3 "gpc_reg_operand" "=r")
-			(match_operand:V2SI 4 "memory_operand" "m"))])]
+		   (use (reg:P 11))
+		   (set (match_operand:V2SI 2 "gpc_reg_operand" "=r")
+			(match_operand:V2SI 3 "memory_operand" "m"))])]
  "TARGET_SPE_ABI"
  "b %z1"
  [(set_attr "type" "branch")
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 151625)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -18011,7 +18011,8 @@ static bool
 no_global_regs_above (int first, bool gpr)
 {
   int i;
-  for (i = first; i < gpr ? 32 : 64 ; i++)
+  int last = gpr ? 32 : 64;
+  for (i = first; i < last; i++)
     if (global_regs[i])
       return false;
   return true;
@@ -18028,54 +18029,130 @@ no_global_regs_above (int first, bool gp
 
 static GTY(()) rtx savres_routine_syms[N_SAVRES_REGISTERS][8];
 
-/* Return the symbol for an out-of-line register save/restore routine.
+/* Temporary holding space for an out-of-line register save/restore
+   routine name.  */
+static char savres_routine_name[30];
+
+/* Return the name for an out-of-line register save/restore routine.
+   We are saving/restoring GPRs if GPR is true.  */
+
+static char *
+rs6000_savres_routine_name (rs6000_stack_t *info, int regno,
+			    bool savep, bool gpr, bool exitp)
+{
+  const char *prefix = "";
+  const char *suffix = "";
+
+  /* Different targets are supposed to define
+     {SAVE,RESTORE}_FP_{PREFIX,SUFFIX} with the idea that the needed
+     routine name could be defined with:
+
+     sprintf (name, "%s%d%s", SAVE_FP_PREFIX, regno, SAVE_FP_SUFFIX)
+
+     This is a nice idea in practice, but in reality, things are
+     complicated in several ways:
+
+     - ELF targets have save/restore routines for GPRs.
+
+     - SPE targets use different prefixes for 32/64-bit registers, and
+       neither of them fit neatly in the FOO_{PREFIX,SUFFIX} regimen.
+
+     - PPC64 ELF targets have routines for save/restore of GPRs that
+       differ in what they do with the link register, so having a set
+       prefix doesn't work.  (We only use one of the save routines at
+       the moment, though.)
+
+     - PPC32 elf targets have "exit" versions of the restore routines
+       that restore the link register and can save some extra space.
+       These require an extra suffix.  (There are also "tail" versions
+       of the restore routines and "GOT" versions of the save routines,
+       but we don't generate those at present.  Same problems apply,
+       though.)
+
+     We deal with all this by synthesizing our own prefix/suffix and
+     using that for the simple sprintf call shown above.  */
+  if (TARGET_SPE)
+    {
+      /* No floating point saves on the SPE.  */
+      gcc_assert (gpr);
+
+      if (savep)
+	prefix = info->spe_64bit_regs_used ? "_save64gpr_" : "_save32gpr_";
+      else
+	prefix = info->spe_64bit_regs_used ? "_rest64gpr_" : "_rest32gpr_";
+
+      if (exitp)
+	suffix = "_x";
+    }
+  else if (DEFAULT_ABI == ABI_V4)
+    {
+      if (TARGET_64BIT)
+	goto aix_names;
+
+      if (gpr)
+	prefix = savep ? "_savegpr_" : "_restgpr_";
+      else
+	prefix = savep ? "_savefpr_" : "_restfpr_";
+
+      if (exitp)
+	suffix = "_x";
+    }
+  else if (DEFAULT_ABI == ABI_AIX)
+    {
+      /* No out-of-line save/restore routines for GPRs on AIX.  */
+      gcc_assert (!TARGET_AIX || !gpr);
+
+    aix_names:
+      if (gpr)
+	prefix = (savep
+		  ? "_savegpr1_"
+		  : (exitp ? "_restgpr0_" : "_restgpr1_"));
+      else
+	{
+	  prefix = savep ? SAVE_FP_PREFIX : RESTORE_FP_PREFIX;
+	  suffix = savep ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX;
+	}
+    }
+  else if (DEFAULT_ABI == ABI_DARWIN)
+    sorry ("Out-of-line save/restore routines not supported on Darwin");
+
+  sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix);
+
+  return savres_routine_name;
+}
+
+/* Return an RTL SYMBOL_REF for an out-of-line register save/restore routine.
    We are saving/restoring GPRs if GPR is true.  */
 
 static rtx
-rs6000_savres_routine_sym (rs6000_stack_t *info, bool savep, bool gpr, bool exitp)
+rs6000_savres_routine_sym (rs6000_stack_t *info, bool savep,
+			   bool gpr, bool exitp)
 {
   int regno = gpr ? info->first_gp_reg_save : (info->first_fp_reg_save - 32);
   rtx sym;
   int select = ((savep ? 1 : 0) << 2
-		| (gpr
-		   /* On the SPE, we never have any FPRs, but we do have
-		      32/64-bit versions of the routines.  */
-		   ? (TARGET_SPE_ABI && info->spe_64bit_regs_used ? 1 : 0)
-		   : 0) << 1
+		| ((TARGET_SPE_ABI
+		    /* On the SPE, we never have any FPRs, but we do have
+		       32/64-bit versions of the routines.  */
+		    ? (info->spe_64bit_regs_used ? 1 : 0)
+		    : (gpr ? 1 : 0)) << 1)
 		| (exitp ? 1: 0));
 
   /* Don't generate bogus routine names.  */
-  gcc_assert (FIRST_SAVRES_REGISTER <= regno && regno <= LAST_SAVRES_REGISTER);
+  gcc_assert (FIRST_SAVRES_REGISTER <= regno
+	      && regno <= LAST_SAVRES_REGISTER);
 
   sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select];
 
   if (sym == NULL)
     {
-      char name[30];
-      const char *action;
-      const char *regkind;
-      const char *exit_suffix;
-
-      action = savep ? "save" : "rest";
-
-      /* SPE has slightly different names for its routines depending on
-	 whether we are saving 32-bit or 64-bit registers.  */
-      if (TARGET_SPE_ABI)
-	{
-	  /* No floating point saves on the SPE.  */
-	  gcc_assert (gpr);
-
-	  regkind = info->spe_64bit_regs_used ? "64gpr" : "32gpr";
-	}
-      else
-	regkind = gpr ? "gpr" : "fpr";
-
-      exit_suffix = exitp ? "_x" : "";
+      char *name;
 
-      sprintf (name, "_%s%s_%d%s", action, regkind, regno, exit_suffix);
+      name = rs6000_savres_routine_name (info, regno, savep, gpr, exitp);
 
       sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select]
 	= gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+      SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_FUNCTION;
     }
 
   return sym;
@@ -18102,8 +18179,11 @@ rs6000_emit_stack_reset (rs6000_stack_t 
   if (frame_reg_rtx != sp_reg_rtx)
     {
       if (sp_offset != 0)
-	return emit_insn (gen_addsi3 (sp_reg_rtx, frame_reg_rtx,
-				      GEN_INT (sp_offset)));
+	{
+	  rtx dest_reg = savres ? gen_rtx_REG (Pmode, 11) : sp_reg_rtx;
+	  return emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx,
+					   GEN_INT (sp_offset)));
+	}
       else if (!savres)
 	return emit_move_insn (sp_reg_rtx, frame_reg_rtx);
     }
@@ -18228,6 +18308,10 @@ rs6000_savres_strategy (rs6000_stack_t *
 			|| info->first_fp_reg_save == 64
 			|| !no_global_regs_above (info->first_fp_reg_save,
 						  /*gpr=*/false)
+			/* The out-of-line FP routines use
+			   double-precision stores; we can't use those
+			   routines if we don't have such stores.  */
+			|| (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT)
 			|| FP_SAVE_INLINE (info->first_fp_reg_save));
   savres_gprs_inline = (common
 			/* Saving CR interferes with the exit routines
@@ -18289,7 +18373,7 @@ rs6000_emit_prologue (void)
   int using_store_multiple;
   int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
                               && df_regs_ever_live_p (STATIC_CHAIN_REGNUM)
-                              && !call_used_regs[STATIC_CHAIN_REGNUM]);
+                              && call_used_regs[STATIC_CHAIN_REGNUM]);
   HOST_WIDE_INT sp_offset = 0;
 
   if (TARGET_FIX_AND_CONTINUE)
@@ -18934,9 +19018,18 @@ rs6000_output_function_prologue (FILE *f
      fp values.  */
   if (info->first_fp_reg_save < 64
       && !FP_SAVE_INLINE (info->first_fp_reg_save))
-    fprintf (file, "\t.extern %s%d%s\n\t.extern %s%d%s\n",
-	     SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX,
-	     RESTORE_FP_PREFIX, info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
+    {
+      char *name;
+      int regno = info->first_fp_reg_save - 32;
+
+      name = rs6000_savres_routine_name (info, regno, /*savep=*/true,
+					 /*gpr=*/false, /*exitp=*/false);
+      fprintf (file, "\t.extern %s\n", name);
+
+      name = rs6000_savres_routine_name (info, regno, /*savep=*/false,
+					 /*gpr=*/false, /*exitp=*/true);
+      fprintf (file, "\t.extern %s\n", name);
+    }
 
   /* Write .extern for AIX common mode routines, if needed.  */
   if (! TARGET_POWER && ! TARGET_POWERPC && ! common_mode_defined)
@@ -19095,8 +19188,9 @@ rs6000_emit_epilogue (int sibcall)
 				 || (cfun->calls_alloca
 				     && !frame_pointer_needed));
   restore_lr = (info->lr_save_p
-		&& restoring_GPRs_inline
-		&& restoring_FPRs_inline);
+		&& (restoring_GPRs_inline
+		    || (restoring_FPRs_inline
+			&& info->first_fp_reg_save < 64)));
 
   if (WORLD_SAVE_P (info))
     {
@@ -19383,7 +19477,7 @@ rs6000_emit_epilogue (int sibcall)
 
   /* Get the old lr if we saved it.  If we are restoring registers
      out-of-line, then the out-of-line routines can do this for us.  */
-  if (restore_lr)
+  if (restore_lr && restoring_GPRs_inline)
     {
       rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
 				      info->lr_save_offset + sp_offset);
@@ -19403,7 +19497,7 @@ rs6000_emit_epilogue (int sibcall)
 
   /* Set LR here to try to overlap restores below.  LR is always saved
      above incoming stack, so it never needs REG_CFA_RESTORE.  */
-  if (restore_lr)
+  if (restore_lr && restoring_GPRs_inline)
     emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
 		    gen_rtx_REG (Pmode, 0));
 
@@ -19538,9 +19632,13 @@ rs6000_emit_epilogue (int sibcall)
 	rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
 				 sp_offset, can_use_exit);
       else
-	emit_insn (gen_addsi3 (gen_rtx_REG (Pmode, 11),
-			       sp_reg_rtx,
-			       GEN_INT (sp_offset - info->fp_size)));
+	{
+	  emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, 11),
+				    frame_reg_rtx,
+				    GEN_INT (sp_offset - info->fp_size)));
+	  if (REGNO (frame_reg_rtx) == 11)
+	    sp_offset += info->fp_size;
+	}
 
       par = rs6000_make_savres_rtx (info, frame_reg_rtx,
 				    info->gp_save_offset, reg_mode,
@@ -19639,6 +19737,16 @@ rs6000_emit_epilogue (int sibcall)
           }
     }
 
+  if (restore_lr && !restoring_GPRs_inline)
+    {
+      rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
+                                     info->lr_save_offset + sp_offset);
+
+      emit_move_insn (gen_rtx_REG (Pmode, 0), mem);
+      emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
+		      gen_rtx_REG (Pmode, 0));
+    }
+
   /* Restore fpr's if we need to do it without calling a function.  */
   if (restoring_FPRs_inline)
     for (i = 0; i < 64 - info->first_fp_reg_save; i++)
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 151625)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -15293,9 +15293,9 @@ (define_insn "*save_gpregs_<mode>"
   [(match_parallel 0 "any_parallel_operand"
 		   [(clobber (reg:P 65))
 		    (use (match_operand:P 1 "symbol_ref_operand" "s"))
-                    (use (match_operand:P 2 "gpc_reg_operand" "r"))
-		    (set (match_operand:P 3 "memory_operand" "=m")
-			 (match_operand:P 4 "gpc_reg_operand" "r"))])]
+                    (use (reg:P 11))
+		    (set (match_operand:P 2 "memory_operand" "=m")
+			 (match_operand:P 3 "gpc_reg_operand" "r"))])]
   ""
   "bl %z1"
   [(set_attr "type" "branch")
@@ -15305,9 +15305,9 @@ (define_insn "*save_fpregs_<mode>"
   [(match_parallel 0 "any_parallel_operand"
 		   [(clobber (reg:P 65))
 		    (use (match_operand:P 1 "symbol_ref_operand" "s"))
-                    (use (match_operand:P 2 "gpc_reg_operand" "r"))
-		    (set (match_operand:DF 3 "memory_operand" "=m")
-			 (match_operand:DF 4 "gpc_reg_operand" "d"))])]
+                    (use (reg:P 11))
+		    (set (match_operand:DF 2 "memory_operand" "=m")
+			 (match_operand:DF 3 "gpc_reg_operand" "d"))])]
   ""
   "bl %z1"
   [(set_attr "type" "branch")
@@ -15400,9 +15400,9 @@ (define_insn "*restore_gpregs_<mode>"
  [(match_parallel 0 "any_parallel_operand"
                   [(clobber (match_operand:P 1 "register_operand" "=l"))
                    (use (match_operand:P 2 "symbol_ref_operand" "s"))
-                   (use (match_operand:P 3 "gpc_reg_operand" "r"))
-		   (set (match_operand:P 4 "gpc_reg_operand" "=r")
-			(match_operand:P 5 "memory_operand" "m"))])]
+                   (use (reg:P 11))
+		   (set (match_operand:P 3 "gpc_reg_operand" "=r")
+			(match_operand:P 4 "memory_operand" "m"))])]
  ""
  "bl %z2"
  [(set_attr "type" "branch")
@@ -15413,9 +15413,9 @@ (define_insn "*return_and_restore_gpregs
                   [(return)
 		   (clobber (match_operand:P 1 "register_operand" "=l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
-                   (use (match_operand:P 3 "gpc_reg_operand" "r"))
-		   (set (match_operand:P 4 "gpc_reg_operand" "=r")
-			(match_operand:P 5 "memory_operand" "m"))])]
+                   (use (reg:P 11))
+		   (set (match_operand:P 3 "gpc_reg_operand" "=r")
+			(match_operand:P 4 "memory_operand" "m"))])]
  ""
  "b %z2"
  [(set_attr "type" "branch")
@@ -15426,9 +15426,9 @@ (define_insn "*return_and_restore_fpregs
                   [(return)
 		   (clobber (match_operand:P 1 "register_operand" "=l"))
 		   (use (match_operand:P 2 "symbol_ref_operand" "s"))
-                   (use (match_operand:P 3 "gpc_reg_operand" "r"))
-		   (set (match_operand:DF 4 "gpc_reg_operand" "=d")
-			(match_operand:DF 5 "memory_operand" "m"))])]
+                   (use (reg:P 11))
+		   (set (match_operand:DF 3 "gpc_reg_operand" "=d")
+			(match_operand:DF 4 "memory_operand" "m"))])]
  ""
  "b %z2"
  [(set_attr "type" "branch")


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