* [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
@ 2008-11-19 21:35 Nathan Froyd
2008-11-21 16:11 ` Nathan Froyd
0 siblings, 1 reply; 19+ messages in thread
From: Nathan Froyd @ 2008-11-19 21:35 UTC (permalink / raw)
To: gcc-patches; +Cc: dje.gcc
This patch is a repost of:
http://gcc.gnu.org/ml/gcc-patches/2008-10/msg01375.html
with more bugs flushed--in particular, the bootstrap problems reported:
http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00047.html
should be fixed.
Regtested on powerpc64-unknown-linux-gnu. OK to commit?
-Nathan
2008-11-19 Nathan Froyd <froydnj@codesourcery.com>
* config/rs6000/rs6000.c (no_global_regs_above): Fix precedence
problem.
(rs6000_savres_routine_sym): Fix computation for cache selector.
Mark the generated symbol as a function.
(rs6000_emit_prologue): Correct use of call_used_regs.
(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.
* 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.
Index: gcc/config/rs6000/spe.md
===================================================================
--- gcc/config/rs6000/spe.md (revision 142005)
+++ gcc/config/rs6000/spe.md (working copy)
@@ -3144,9 +3144,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")
@@ -3156,9 +3156,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")
@@ -3169,9 +3169,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 142005)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -15842,7 +15848,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;
@@ -15868,11 +15875,11 @@ rs6000_savres_routine_sym (rs6000_stack_
int regno = gpr ? info->first_gp_reg_save : (info->first_fp_reg_save - 32);
rtx sym;
int select = ((savep ? 1 : 0) << 2
- | (gpr
+ | (TARGET_SPE_ABI
/* 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
+ ? (info->spe_64bit_regs_used ? 1 : 0)
+ : (gpr ? 1 : 0)) << 1
| (exitp ? 1: 0));
/* Don't generate bogus routine names. */
@@ -15907,6 +15914,7 @@ rs6000_savres_routine_sym (rs6000_stack_
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;
@@ -16121,7 +16129,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)
@@ -16923,8 +16931,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))
{
@@ -17196,7 +17205,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);
@@ -17215,7 +17224,7 @@ rs6000_emit_epilogue (int sibcall)
}
/* Set LR here to try to overlap restores below. */
- if (restore_lr)
+ if (restore_lr && restoring_GPRs_inline)
emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
gen_rtx_REG (Pmode, 0));
@@ -17395,6 +17404,18 @@ 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);
+ }
+
+ if (restore_lr && !restoring_GPRs_inline)
+ 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 142005)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -14604,9 +14604,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")
@@ -14616,9 +14616,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" "f"))])]
+ (use (reg:P 11))
+ (set (match_operand:DF 2 "memory_operand" "=m")
+ (match_operand:DF 3 "gpc_reg_operand" "f"))])]
""
"bl %z1"
[(set_attr "type" "branch")
@@ -14711,9 +14711,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")
@@ -14724,9 +14724,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")
@@ -14737,9 +14737,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" "=f")
- (match_operand:DF 5 "memory_operand" "m"))])]
+ (use (reg:P 11))
+ (set (match_operand:DF 3 "gpc_reg_operand" "=f")
+ (match_operand:DF 4 "memory_operand" "m"))])]
""
"b %z2"
[(set_attr "type" "branch")
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2008-11-19 21:35 [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2 Nathan Froyd
@ 2008-11-21 16:11 ` Nathan Froyd
2008-11-21 18:03 ` David Edelsohn
2009-09-09 18:50 ` David Edelsohn
0 siblings, 2 replies; 19+ messages in thread
From: Nathan Froyd @ 2008-11-21 16:11 UTC (permalink / raw)
To: gcc-patches, dje.gcc
On Wed, Nov 19, 2008 at 01:16:43PM -0800, Nathan Froyd wrote:
> This patch is a repost of:
>
> http://gcc.gnu.org/ml/gcc-patches/2008-10/msg01375.html
>
> with more bugs flushed--in particular, the bootstrap problems reported:
>
> http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00047.html
>
> should be fixed.
David asked me to rebuild and retest on powerpc64-unknown-linux-gnu
using {GP,FP}_SAVE_INLINE from config/rs6000/aix.h to ensure that the
aforementioned bootstrap problems went away. They did go away--after
flushing another small bug--but turned up a more interesting problem
that I'm not quite sure how to solve.
(A bit of background: the rs6000 backend has logic to emit calls to
out-of-line register save/restore routines. Target platforms can
control how often these routines get used through the
{GP,FP}_SAVE_INLINE macros: 32-bit SVR4 derivatives use the routines
when optimizing for size, AIX uses the out-of-line floating-point save
routines quite frequently, and Darwin eschews the routines entirely.
These functions use a non-standard calling convention and are placed in
libgcc.a and marked as .hidden to avoid problems with dynamic libraries
and symbol resolution.)
The problem is this: during compilation of several g++ testcases with
-m32, we get errors about:
$MUMBLE/ld: $MUMBLE/g++-bprob-1.x01: hidden symbol `_restfpr_14_x' in $MUMBLE/libgcc.a(crtresxfpr.o) is referenced by DSO
This sort of problem was supposed to be fixed with r141090, which added
.hidden declarations to all the out-of-line functions.
What happens is that since the aix.h {GP,FP}_SAVE_INLINE macros are
willing to save registers out-of-line at all optimization settings--not
just -Os, like their counterparts in svr4.h--some of the libstdc++
sources are compiled to use the out-of-line save/restore functions.
However, when libstdc++ is linked, it links against libgcc_s.so, but not
libgcc.a. The references to out-of-line functions in libstdc++ objects
are not resolved against libgcc.a (where the functions normally reside),
nor are they resolved against libgcc_s.so (because the out-of-line
save/restore routines are hidden symbols). libstdc++ winds up with
undefined symbols that no shared library is going to resolve and can't
be linked along with libgcc.a, because then we are attempting to resolve
symbols in libstdc++ against hidden symbols in libgcc.a and doing that
produces the error message shown above.
(Suddenly the choice of the linker providing these functions on
powerpc64 is starting to make more sense.)
Notice that this also affects any configs built with
config/rs6000/svr4.h as well. However, since libstdc++ isn't usually
compiled with -Os, calls to the out-of-line routines are not (usually)
used and the problem never surfaces.
From what I can gather, not linking libstdc++ against libgcc.a is a
deliberate decision, so the burden of resolving the problem falls to the
powerpc backend. Furthermore, IIUC, this is a failure mode that could
easily be seen in the real world if C++ libraries compile with -Os and
link with -shared-libgcc. What's the right thing to do here? How does
AIX avoid the same sort of problem?
-Nathan
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2008-11-21 16:11 ` Nathan Froyd
@ 2008-11-21 18:03 ` David Edelsohn
2008-11-21 19:00 ` Nathan Froyd
2009-09-09 18:50 ` David Edelsohn
1 sibling, 1 reply; 19+ messages in thread
From: David Edelsohn @ 2008-11-21 18:03 UTC (permalink / raw)
To: gcc-patches, dje.gcc
On Fri, Nov 21, 2008 at 10:43 AM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> What's the right thing to do here? How does
> AIX avoid the same sort of problem?
AIX XCOFF file format does not support .hidden.
David
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2008-11-21 18:03 ` David Edelsohn
@ 2008-11-21 19:00 ` Nathan Froyd
2009-07-15 13:08 ` David Edelsohn
0 siblings, 1 reply; 19+ messages in thread
From: Nathan Froyd @ 2008-11-21 19:00 UTC (permalink / raw)
To: David Edelsohn; +Cc: gcc-patches
On Fri, Nov 21, 2008 at 12:53:25PM -0500, David Edelsohn wrote:
> On Fri, Nov 21, 2008 at 10:43 AM, Nathan Froyd <froydnj@codesourcery.com> wrote:
>
> > What's the right thing to do here? How does
> > AIX avoid the same sort of problem?
>
> AIX XCOFF file format does not support .hidden.
Ah, that would make things much easier. So things should work on AIX
just fine, then.
But the problem as stands is not specific to PowerPC--it would affect
any target that has .hidden functions in libgcc.a. I will put the patch
on hold for the time being until we figure out what to do to make
-shared-libgcc work properly.
-Nathan
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2008-11-21 19:00 ` Nathan Froyd
@ 2009-07-15 13:08 ` David Edelsohn
2009-07-15 14:11 ` Nathan Froyd
0 siblings, 1 reply; 19+ messages in thread
From: David Edelsohn @ 2009-07-15 13:08 UTC (permalink / raw)
To: gcc-patches
Nathan,
What is the status of this patch?
Thanks, David
On Fri, Nov 21, 2008 at 2:38 PM, Nathan Froyd<froydnj@codesourcery.com> wrote:
> On Fri, Nov 21, 2008 at 12:53:25PM -0500, David Edelsohn wrote:
>> On Fri, Nov 21, 2008 at 10:43 AM, Nathan Froyd <froydnj@codesourcery.com> wrote:
>>
>> > What's the right thing to do here? How does
>> > AIX avoid the same sort of problem?
>>
>> AIX XCOFF file format does not support .hidden.
>
> Ah, that would make things much easier. So things should work on AIX
> just fine, then.
>
> But the problem as stands is not specific to PowerPC--it would affect
> any target that has .hidden functions in libgcc.a. I will put the patch
> on hold for the time being until we figure out what to do to make
> -shared-libgcc work properly.
>
> -Nathan
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2009-07-15 13:08 ` David Edelsohn
@ 2009-07-15 14:11 ` Nathan Froyd
2009-07-15 17:42 ` David Edelsohn
0 siblings, 1 reply; 19+ messages in thread
From: Nathan Froyd @ 2009-07-15 14:11 UTC (permalink / raw)
To: David Edelsohn; +Cc: gcc-patches
On Wed, Jul 15, 2009 at 08:48:14AM -0400, David Edelsohn wrote:
> What is the status of this patch?
>
> On Fri, Nov 21, 2008 at 2:38 PM, Nathan Froyd<froydnj@codesourcery.com> wrote:
> > But the problem as stands is not specific to PowerPC--it would affect
> > any target that has .hidden functions in libgcc.a. Â I will put the patch
> > on hold for the time being until we figure out what to do to make
> > -shared-libgcc work properly.
The patch is still in limbo. PR 40134, which concerns similar problems
on ARM, has not yet been resolved; a proposed patch is here:
http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html
Jakub objected to the patch, saying that this issue (.hidden functions
in libgcc.a) should be worked around in a target-independent manner; he
also proposed a target-independent patch for it, which Matthias tested
on arm and was testing on x86 and powerpc. I don't know the outcome of
Matthias's extra testing, nor has a maintainer commented on the goodness
of Jakub's patch.
-Nathan
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2009-07-15 14:11 ` Nathan Froyd
@ 2009-07-15 17:42 ` David Edelsohn
0 siblings, 0 replies; 19+ messages in thread
From: David Edelsohn @ 2009-07-15 17:42 UTC (permalink / raw)
To: Nathan Froyd; +Cc: gcc-patches
On Wed, Jul 15, 2009 at 9:08 AM, Nathan Froyd<froydnj@codesourcery.com> wrote:
> The patch is still in limbo. PR 40134, which concerns similar problems
> on ARM, has not yet been resolved; a proposed patch is here:
>
> http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html
>
> Jakub objected to the patch, saying that this issue (.hidden functions
> in libgcc.a) should be worked around in a target-independent manner; he
> also proposed a target-independent patch for it, which Matthias tested
> on arm and was testing on x86 and powerpc. I don't know the outcome of
> Matthias's extra testing, nor has a maintainer commented on the goodness
> of Jakub's patch.
FYI,
The PPC problem was reported as PR 40677.
David
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2008-11-21 16:11 ` Nathan Froyd
2008-11-21 18:03 ` David Edelsohn
@ 2009-09-09 18:50 ` David Edelsohn
2009-09-09 19:07 ` Jakub Jelinek
1 sibling, 1 reply; 19+ messages in thread
From: David Edelsohn @ 2009-09-09 18:50 UTC (permalink / raw)
To: Nathan Froyd, Jakub Jelinek; +Cc: gcc-patches
On Fri, Nov 21, 2008 at 11:43 AM, Nathan Froyd<froydnj@codesourcery.com> wrote:
> On Wed, Nov 19, 2008 at 01:16:43PM -0800, Nathan Froyd wrote:
>> This patch is a repost of:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2008-10/msg01375.html
>>
>> with more bugs flushed--in particular, the bootstrap problems reported:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00047.html
>>
>> should be fixed.
>
> David asked me to rebuild and retest on powerpc64-unknown-linux-gnu
> using {GP,FP}_SAVE_INLINE from config/rs6000/aix.h to ensure that the
> aforementioned bootstrap problems went away. They did go away--after
> flushing another small bug--but turned up a more interesting problem
> that I'm not quite sure how to solve.
Nathan,
There seems to be a consensus on a solution to the other problem that
also affected ARM. However, you never posted the final version of
your patch "flushing another small bug". Jakub has volunteered to
test and commit all of the patches, but we need your final version.
Thanks, David
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2009-09-09 18:50 ` David Edelsohn
@ 2009-09-09 19:07 ` Jakub Jelinek
2009-09-10 6:39 ` Jakub Jelinek
0 siblings, 1 reply; 19+ messages in thread
From: Jakub Jelinek @ 2009-09-09 19:07 UTC (permalink / raw)
To: David Edelsohn; +Cc: Nathan Froyd, gcc-patches
On Wed, Sep 09, 2009 at 02:50:09PM -0400, David Edelsohn wrote:
> There seems to be a consensus on a solution to the other problem that
> also affected ARM. However, you never posted the final version of
> your patch "flushing another small bug". Jakub has volunteered to
> test and commit all of the patches, but we need your final version.
The 2008-11-19 patch doesn't apply cleanly any longer, due to
"d" constraint addition and epilogue unwinding changes, here is an updated
version that at least applies. But knowing whether it has been the latest
version or not would be helpful.
2008-11-19 Nathan Froyd <froydnj@codesourcery.com>
* config/rs6000/rs6000.c (no_global_regs_above): Fix precedence
problem.
(rs6000_savres_routine_sym): Fix computation for cache selector.
Mark the generated symbol as a function.
(rs6000_emit_prologue): Correct use of call_used_regs.
(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.
* 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.
--- gcc/config/rs6000/spe.md.jj 2009-08-31 23:30:14.352526952 +0200
+++ gcc/config/rs6000/spe.md 2009-09-09 20:46:08.391404851 +0200
@@ -3156,9 +3156,9 @@
[(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 @@
[(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 @@
[(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")
--- gcc/config/rs6000/rs6000.c.jj 2009-09-09 20:45:10.794535794 +0200
+++ gcc/config/rs6000/rs6000.c 2009-09-09 20:46:57.195401830 +0200
@@ -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;
@@ -18037,11 +18038,11 @@ rs6000_savres_routine_sym (rs6000_stack_
int regno = gpr ? info->first_gp_reg_save : (info->first_fp_reg_save - 32);
rtx sym;
int select = ((savep ? 1 : 0) << 2
- | (gpr
+ | (TARGET_SPE_ABI
/* 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
+ ? (info->spe_64bit_regs_used ? 1 : 0)
+ : (gpr ? 1 : 0)) << 1
| (exitp ? 1: 0));
/* Don't generate bogus routine names. */
@@ -18076,6 +18077,7 @@ rs6000_savres_routine_sym (rs6000_stack_
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;
@@ -18289,7 +18291,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)
@@ -19095,8 +19097,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 +19386,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 +19406,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));
@@ -19639,6 +19642,18 @@ 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);
+ }
+
+ if (restore_lr && !restoring_GPRs_inline)
+ 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++)
--- gcc/config/rs6000/rs6000.md.jj 2009-08-31 23:30:14.383526862 +0200
+++ gcc/config/rs6000/rs6000.md 2009-09-09 21:03:19.667779689 +0200
@@ -15289,9 +15289,9 @@
[(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")
@@ -15301,9 +15301,9 @@
[(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")
@@ -15394,11 +15394,11 @@
(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"))])]
+ [(clobber (match_operand:P 1 "register_operand" "=l"))
+ (use (match_operand:P 2 "symbol_ref_operand" "s"))
+ (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")
@@ -15406,12 +15406,12 @@
(define_insn "*return_and_restore_gpregs_<mode>"
[(match_parallel 0 "any_parallel_operand"
- [(return)
+ [(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")
@@ -15419,12 +15419,12 @@
(define_insn "*return_and_restore_fpregs_<mode>"
[(match_parallel 0 "any_parallel_operand"
- [(return)
+ [(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")
Jakub
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2
2009-09-09 19:07 ` Jakub Jelinek
@ 2009-09-10 6:39 ` Jakub Jelinek
2009-09-11 8:41 ` [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff Jakub Jelinek
0 siblings, 1 reply; 19+ messages in thread
From: Jakub Jelinek @ 2009-09-10 6:39 UTC (permalink / raw)
To: David Edelsohn; +Cc: Nathan Froyd, gcc-patches
On Wed, Sep 09, 2009 at 09:06:55PM +0200, Jakub Jelinek wrote:
> On Wed, Sep 09, 2009 at 02:50:09PM -0400, David Edelsohn wrote:
> > There seems to be a consensus on a solution to the other problem that
> > also affected ARM. However, you never posted the final version of
> > your patch "flushing another small bug". Jakub has volunteered to
> > test and commit all of the patches, but we need your final version.
>
> The 2008-11-19 patch doesn't apply cleanly any longer, due to
> "d" constraint addition and epilogue unwinding changes, here is an updated
> version that at least applies. But knowing whether it has been the latest
> version or not would be helpful.
FYI, the patch I've posted bootstrapped on powerpc64-linux --with-cpu=default32
and regtested with RUNTESTFLAGS="--target_board=unix/\{-m32,-m64\}".
I'll wait a little bit for Nathan to respond before committing it though.
Jakub
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff
2009-09-10 6:39 ` Jakub Jelinek
@ 2009-09-11 8:41 ` Jakub Jelinek
2009-09-11 16:17 ` Nathan Froyd
0 siblings, 1 reply; 19+ messages in thread
From: Jakub Jelinek @ 2009-09-11 8:41 UTC (permalink / raw)
To: David Edelsohn; +Cc: Nathan Froyd, gcc-patches
Hi!
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.
Note the 64-bit out of line saving/restoring stuff for Linux looks broken
(e.g. doesn't match the names that ld synthetizes), but it isn't enabled at
all unless one changes the *_INLINE macros.
2009-09-11 Jakub Jelinek <jakub@redhat.com>
PR target/41175
* config/rs6000/rs6000.c (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): Set r11 from offsetted frame_reg_rtx instead
sp_reg_rtx, if frame_reg_rtx is r11, adjust sp_offset. Use
gen_add3_insn instead of gen_addsi3. Merge two adjacent ifs with the
same condition.
* gcc.target/powerpc/pr41175.c: New test.
--- gcc/config/rs6000/rs6000.c.jj 2009-09-09 20:46:57.000000000 +0200
+++ gcc/config/rs6000/rs6000.c 2009-09-11 10:29:01.101406443 +0200
@@ -18104,8 +18104,12 @@ 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);
}
@@ -19541,9 +19545,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,
@@ -19648,12 +19656,10 @@ rs6000_emit_epilogue (int sibcall)
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));
}
- if (restore_lr && !restoring_GPRs_inline)
- 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++)
--- gcc/testsuite/gcc.target/powerpc/pr41175.c.jj 2009-09-11 10:28:50.529527601 +0200
+++ gcc/testsuite/gcc.target/powerpc/pr41175.c 2009-09-11 10:18:59.000000000 +0200
@@ -0,0 +1,451 @@
+/* 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)
+
+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");
+}
+
+__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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (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) "+f" (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) "f" (fpr##n),
+ asm volatile ("" : : X8(d) "m" (mem) : "memory");
+}
+
+int
+main ()
+{
+ ll = 60;
+ f1 ();
+ f2 ();
+ f3 ();
+ f4 ();
+ f5 ();
+ f6 ();
+ f7 ();
+ f8 ();
+ f9 ();
+ f10 ();
+ f11 ();
+ f12 ();
+ f13 ();
+ f14 ();
+ f15 ();
+ return 0;
+}
Jakub
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff
2009-09-11 8:41 ` [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff Jakub Jelinek
@ 2009-09-11 16:17 ` Nathan Froyd
2009-09-12 15:12 ` Nathan Froyd
0 siblings, 1 reply; 19+ messages in thread
From: Nathan Froyd @ 2009-09-11 16:17 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: David Edelsohn, gcc-patches
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__.
I'm not sure that the testcase works right on those (Xilinx-only?)
targets that have single-float but not double. Should the testcase be
using "f" and float on such targets and "d" and double everywhere else?
> Note the 64-bit out of line saving/restoring stuff for Linux looks broken
> (e.g. doesn't match the names that ld synthetizes), but it isn't enabled at
> all unless one changes the *_INLINE macros.
Yeah, I didn't try to get the 64-bit cases right because the calling
conventions and names are slightly different. I suppose it would be nice
if it got the names right, at least.
-Nathan
Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog (revision 151626)
+++ gcc/ChangeLog (working copy)
@@ -1,3 +1,34 @@
+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.
+ (rs6000_emit_prologue): Correct use of call_used_regs.
+ (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;
@@ -18037,11 +18038,11 @@ rs6000_savres_routine_sym (rs6000_stack_
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. */
@@ -18076,6 +18077,7 @@ rs6000_savres_routine_sym (rs6000_stack_
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 +18104,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 +18233,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 +18298,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)
@@ -19095,8 +19104,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 +19393,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 +19413,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 +19548,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),
+ sp_reg_rtx,
+ GEN_INT (sp_offset - info->fp_size)));
+ if (REGNO (frame_reg_rtx) == 1)
+ sp_offset += info->fp_size;
+ }
par = rs6000_make_savres_rtx (info, frame_reg_rtx,
info->gp_save_offset, reg_mode,
@@ -19639,6 +19653,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")
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff
2009-09-12 15:12 ` Nathan Froyd
@ 2009-09-12 6:44 ` Jakub Jelinek
2009-09-12 16:58 ` Jakub Jelinek
2009-09-13 1:48 ` [PATCH] Incremental fix of " David Edelsohn
1 sibling, 1 reply; 19+ messages in thread
From: Jakub Jelinek @ 2009-09-12 6:44 UTC (permalink / raw)
To: Nathan Froyd; +Cc: David Edelsohn, gcc-patches
On Fri, Sep 11, 2009 at 08:24:03PM -0700, Nathan Froyd wrote:
> 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.
I'll test on powerpc*-linux. Before doing so, the *SUFFIX definitions in
sysv4.h/linux64.h look wrong, I'm not aware of any "_l" suffixed routines
and sysv4.h vs. linux64.h were even disagreeing about them between -m32 and
-m64.
--- gcc/config/rs6000/sysv4.h.jj 2009-06-30 13:10:26.000000000 +0200
+++ gcc/config/rs6000/sysv4.h 2009-09-12 08:31:43.000000000 +0200
@@ -288,11 +288,11 @@ do { \
/* Prefix and suffix to use to saving floating point. */
#define SAVE_FP_PREFIX "_savefpr_"
-#define SAVE_FP_SUFFIX (TARGET_64BIT ? "_l" : "")
+#define SAVE_FP_SUFFIX ""
/* Prefix and suffix to use to restoring floating point. */
#define RESTORE_FP_PREFIX "_restfpr_"
-#define RESTORE_FP_SUFFIX (TARGET_64BIT ? "_l" : "")
+#define RESTORE_FP_SUFFIX ""
/* Type used for ptrdiff_t, as a string used in a declaration. */
#define PTRDIFF_TYPE "int"
--- gcc/config/rs6000/linux64.h.jj 2009-06-30 13:10:26.000000000 +0200
+++ gcc/config/rs6000/linux64.h 2009-09-12 08:31:15.000000000 +0200
@@ -437,11 +437,11 @@ extern int dot_symbols;
#undef SAVE_FP_PREFIX
#define SAVE_FP_PREFIX (TARGET_64BIT ? "._savef" : "_savefpr_")
#undef SAVE_FP_SUFFIX
-#define SAVE_FP_SUFFIX (TARGET_64BIT ? "" : "_l")
+#define SAVE_FP_SUFFIX ""
#undef RESTORE_FP_PREFIX
#define RESTORE_FP_PREFIX (TARGET_64BIT ? "._restf" : "_restfpr_")
#undef RESTORE_FP_SUFFIX
-#define RESTORE_FP_SUFFIX (TARGET_64BIT ? "" : "_l")
+#define RESTORE_FP_SUFFIX ""
/* Dwarf2 debugging. */
#undef PREFERRED_DEBUGGING_TYPE
Jakub
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff
2009-09-11 16:17 ` Nathan Froyd
@ 2009-09-12 15:12 ` Nathan Froyd
2009-09-12 6:44 ` Jakub Jelinek
2009-09-13 1:48 ` [PATCH] Incremental fix of " David Edelsohn
0 siblings, 2 replies; 19+ messages in thread
From: Nathan Froyd @ 2009-09-12 15:12 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: David Edelsohn, gcc-patches
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")
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff
2009-09-12 6:44 ` Jakub Jelinek
@ 2009-09-12 16:58 ` Jakub Jelinek
2009-09-14 13:45 ` Jakub Jelinek
0 siblings, 1 reply; 19+ messages in thread
From: Jakub Jelinek @ 2009-09-12 16:58 UTC (permalink / raw)
To: Nathan Froyd; +Cc: David Edelsohn, gcc-patches
On Sat, Sep 12, 2009 at 08:44:24AM +0200, Jakub Jelinek wrote:
> I'll test on powerpc*-linux. Before doing so, the *SUFFIX definitions in
> sysv4.h/linux64.h look wrong, I'm not aware of any "_l" suffixed routines
> and sysv4.h vs. linux64.h were even disagreeing about them between -m32 and
> -m64.
With that sysv4.h/linux64.h fixlet it bootstrapped/regtested on
powerpc64-linux.
Jakub
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff
2009-09-12 15:12 ` Nathan Froyd
2009-09-12 6:44 ` Jakub Jelinek
@ 2009-09-13 1:48 ` David Edelsohn
1 sibling, 0 replies; 19+ messages in thread
From: David Edelsohn @ 2009-09-13 1:48 UTC (permalink / raw)
To: Nathan Froyd; +Cc: Jakub Jelinek, gcc-patches
On Fri, Sep 11, 2009 at 11:24 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
>> 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.
This is a lot better and thanks for cleaning this up.
However, the AIX restfXX routines want the return address moved to the
link register before calling the routine; it does not perform mtlr
itself. GCC 4.1 generated calls to the routines correctly, if you
want a working example.
As an aside, AIX now has the POWER ABI GPR restore routines
_restgpr0_XX and _restgpr1_XX, which can be ignored. FPR restore
routines _restfpr0_XX and _restfpr1_XX are documented and follow the
new behavior, but I cannot find them in the system. And the new AIX
routines must be called with branch absolute (bla/ba) instruction.
Each OS is just a little bit different. Sigh.
David
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff
2009-09-12 16:58 ` Jakub Jelinek
@ 2009-09-14 13:45 ` Jakub Jelinek
2009-09-15 9:24 ` [PATCH] Updated version of the " Jakub Jelinek
0 siblings, 1 reply; 19+ messages in thread
From: Jakub Jelinek @ 2009-09-14 13:45 UTC (permalink / raw)
To: Nathan Froyd; +Cc: David Edelsohn, Alan Modra, gcc-patches
On Sat, Sep 12, 2009 at 06:58:29PM +0200, Jakub Jelinek wrote:
> On Sat, Sep 12, 2009 at 08:44:24AM +0200, Jakub Jelinek wrote:
> > I'll test on powerpc*-linux. Before doing so, the *SUFFIX definitions in
> > sysv4.h/linux64.h look wrong, I'm not aware of any "_l" suffixed routines
> > and sysv4.h vs. linux64.h were even disagreeing about them between -m32 and
> > -m64.
>
> With that sysv4.h/linux64.h fixlet it bootstrapped/regtested on
> powerpc64-linux.
And with this patch on top of those 2 patches Linux emits out of line
gpr/fpr saving calls also at -Os -m64.
So far eyeballed and tested on the pr41175.c testcase.
The changes are:
1) use also the r0 (which holds lr) saving gpr/fpr routines for TARGET_64BIT
2) ensure the correct base register is initialized for gpr saving/restoring
when fp_size != 0 (r12 for -m64 instead of r11)
3) adjust cr saving in that case, so that it use of r12 doesn't clash with
it
4) fix restore_lr computation (this matters for -m32 as well)
I had to revert your rs6000.md changes to depend on explicit r11, because,
well, for -m64 they don't (depend either on r12 or just on r1), not sure why
they have been done.
Things that should be potentially dealt with later:
1) we could use the _restgpr0_* instead of _restgpr1_* GPR restoring with
-m64 even when saving fprs inline - just the restoring of fprs would need
to be moved before the gprs restoring call in that case.
2) linux -m64 ABI has also altivec saving/restoring routines, perhaps we
could use them too
--- gcc/config/rs6000/rs6000.c.jj 2009-09-12 09:54:07.000000000 +0200
+++ gcc/config/rs6000/rs6000.c 2009-09-14 15:20:19.738529753 +0200
@@ -18038,7 +18038,7 @@ static char savres_routine_name[30];
static char *
rs6000_savres_routine_name (rs6000_stack_t *info, int regno,
- bool savep, bool gpr, bool exitp)
+ bool savep, bool gpr, bool lr)
{
const char *prefix = "";
const char *suffix = "";
@@ -18081,7 +18081,7 @@ rs6000_savres_routine_name (rs6000_stack
else
prefix = info->spe_64bit_regs_used ? "_rest64gpr_" : "_rest32gpr_";
- if (exitp)
+ if (lr)
suffix = "_x";
}
else if (DEFAULT_ABI == ABI_V4)
@@ -18094,19 +18094,25 @@ rs6000_savres_routine_name (rs6000_stack
else
prefix = savep ? "_savefpr_" : "_restfpr_";
- if (exitp)
+ if (lr)
suffix = "_x";
}
else if (DEFAULT_ABI == ABI_AIX)
{
+#ifndef POWERPC_LINUX
/* No out-of-line save/restore routines for GPRs on AIX. */
gcc_assert (!TARGET_AIX || !gpr);
+#endif
aix_names:
if (gpr)
prefix = (savep
- ? "_savegpr1_"
- : (exitp ? "_restgpr0_" : "_restgpr1_"));
+ ? (lr ? "_savegpr0_" : "_savegpr1_")
+ : (lr ? "_restgpr0_" : "_restgpr1_"));
+#ifdef POWERPC_LINUX
+ else if (lr)
+ prefix = (savep ? "_savefpr_" : "_restfpr_");
+#endif
else
{
prefix = savep ? SAVE_FP_PREFIX : RESTORE_FP_PREFIX;
@@ -18126,7 +18132,7 @@ rs6000_savres_routine_name (rs6000_stack
static rtx
rs6000_savres_routine_sym (rs6000_stack_t *info, bool savep,
- bool gpr, bool exitp)
+ bool gpr, bool lr)
{
int regno = gpr ? info->first_gp_reg_save : (info->first_fp_reg_save - 32);
rtx sym;
@@ -18136,7 +18142,7 @@ rs6000_savres_routine_sym (rs6000_stack_
32/64-bit versions of the routines. */
? (info->spe_64bit_regs_used ? 1 : 0)
: (gpr ? 1 : 0)) << 1)
- | (exitp ? 1: 0));
+ | (lr ? 1: 0));
/* Don't generate bogus routine names. */
gcc_assert (FIRST_SAVRES_REGISTER <= regno
@@ -18148,7 +18154,7 @@ rs6000_savres_routine_sym (rs6000_stack_
{
char *name;
- name = rs6000_savres_routine_name (info, regno, savep, gpr, exitp);
+ name = rs6000_savres_routine_name (info, regno, savep, gpr, lr);
sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select]
= gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
@@ -18212,7 +18218,7 @@ static rtx
rs6000_make_savres_rtx (rs6000_stack_t *info,
rtx frame_reg_rtx, int save_area_offset,
enum machine_mode reg_mode,
- bool savep, bool gpr, bool exitp)
+ bool savep, bool gpr, bool lr)
{
int i;
int offset, start_reg, end_reg, n_regs;
@@ -18226,20 +18232,21 @@ rs6000_make_savres_rtx (rs6000_stack_t *
: info->first_fp_reg_save);
end_reg = gpr ? 32 : 64;
n_regs = end_reg - start_reg;
- p = rtvec_alloc ((exitp ? 4 : 3) + n_regs);
+ p = rtvec_alloc ((lr ? 4 : 3) + n_regs);
- /* If we're saving registers, then we should never say we're exiting. */
- gcc_assert ((savep && !exitp) || !savep);
-
- if (exitp)
+ if (!savep && lr)
RTVEC_ELT (p, offset++) = gen_rtx_RETURN (VOIDmode);
RTVEC_ELT (p, offset++)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
- sym = rs6000_savres_routine_sym (info, savep, gpr, exitp);
+ sym = rs6000_savres_routine_sym (info, savep, gpr, lr);
RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym);
- RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 11));
+ RTVEC_ELT (p, offset++)
+ = gen_rtx_USE (VOIDmode,
+ gen_rtx_REG (Pmode, !TARGET_64BIT ? 11
+ : gpr && !lr ? 12
+ : 1));
for (i = 0; i < end_reg - start_reg; i++)
{
@@ -18254,6 +18261,16 @@ rs6000_make_savres_rtx (rs6000_stack_t *
savep ? reg : mem);
}
+ if (savep && lr)
+ {
+ rtx addr, reg, mem;
+ reg = gen_rtx_REG (Pmode, 0);
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->lr_save_offset));
+ mem = gen_frame_mem (Pmode, addr);
+ RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg);
+ }
+
return gen_rtx_PARALLEL (VOIDmode, p);
}
@@ -18274,7 +18291,9 @@ rs6000_reg_live_or_pic_offset_p (int reg
enum {
SAVRES_MULTIPLE = 0x1,
SAVRES_INLINE_FPRS = 0x2,
- SAVRES_INLINE_GPRS = 0x4
+ SAVRES_INLINE_GPRS = 0x4,
+ SAVRES_NOINLINE_GPRS_SAVES_LR = 0x8,
+ SAVRES_NOINLINE_FPRS_SAVES_LR = 0x10
};
/* Determine the strategy for savings/restoring registers. */
@@ -18289,6 +18308,7 @@ rs6000_savres_strategy (rs6000_stack_t *
bool savres_gprs_inline;
bool noclobber_global_gprs
= no_global_regs_above (info->first_gp_reg_save, /*gpr=*/true);
+ int strategy;
using_multiple_p = (TARGET_MULTIPLE && ! TARGET_POWERPC64
&& (!TARGET_SPE_ABI
@@ -18349,9 +18369,19 @@ rs6000_savres_strategy (rs6000_stack_t *
savres_gprs_inline = savres_gprs_inline || using_multiple_p;
}
- return (using_multiple_p
- | (savres_fprs_inline << 1)
- | (savres_gprs_inline << 2));
+ strategy = (using_multiple_p
+ | (savres_fprs_inline << 1)
+ | (savres_gprs_inline << 2));
+#ifdef POWERPC_LINUX
+ if (TARGET_64BIT)
+ {
+ if (!savres_fprs_inline)
+ strategy |= SAVRES_NOINLINE_FPRS_SAVES_LR;
+ else if (!savres_gprs_inline && info->first_fp_reg_save == 64)
+ strategy |= SAVRES_NOINLINE_GPRS_SAVES_LR;
+ }
+#endif
+ return strategy;
}
/* Emit function prologue as insns. */
@@ -18558,24 +18588,29 @@ rs6000_emit_prologue (void)
gen_rtx_REG (Pmode, LR_REGNO));
RTX_FRAME_RELATED_P (insn) = 1;
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ if (!(strategy & (SAVRES_NOINLINE_GPRS_SAVES_LR
+ | SAVRES_NOINLINE_FPRS_SAVES_LR)))
+ {
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->lr_save_offset + sp_offset));
- reg = gen_rtx_REG (Pmode, 0);
- mem = gen_rtx_MEM (Pmode, addr);
- /* This should not be of rs6000_sr_alias_set, because of
- __builtin_return_address. */
+ reg = gen_rtx_REG (Pmode, 0);
+ mem = gen_rtx_MEM (Pmode, addr);
+ /* This should not be of rs6000_sr_alias_set, because of
+ __builtin_return_address. */
- insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- NULL_RTX, NULL_RTX);
+ insn = emit_move_insn (mem, reg);
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
+ }
}
- /* If we need to save CR, put it into r12. */
+ /* If we need to save CR, put it into r12 or r11. */
if (!WORLD_SAVE_P (info) && info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
{
rtx set;
- cr_save_rtx = gen_rtx_REG (SImode, 12);
+ cr_save_rtx
+ = gen_rtx_REG (SImode, TARGET_64BIT && !saving_GPRs_inline ? 11 : 12);
insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
RTX_FRAME_RELATED_P (insn) = 1;
/* Now, there's no way that dwarf2out_frame_debug_expr is going
@@ -18612,7 +18647,9 @@ rs6000_emit_prologue (void)
info->fp_save_offset + sp_offset,
DFmode,
/*savep=*/true, /*gpr=*/false,
- /*exitp=*/false);
+ /*lr=*/(strategy
+ & SAVRES_NOINLINE_FPRS_SAVES_LR)
+ != 0);
insn = emit_insn (par);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
@@ -18708,7 +18745,7 @@ rs6000_emit_prologue (void)
par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
0, reg_mode,
/*savep=*/true, /*gpr=*/true,
- /*exitp=*/false);
+ /*lr=*/false);
insn = emit_insn (par);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
@@ -18723,25 +18760,22 @@ rs6000_emit_prologue (void)
{
rtx par;
- /* Need to adjust r11 if we saved any FPRs. */
+ /* Need to adjust r11 (r12) if we saved any FPRs. */
if (info->first_fp_reg_save != 64)
{
- rtx r11 = gen_rtx_REG (reg_mode, 11);
- rtx offset = GEN_INT (info->total_size
+ rtx dest_reg = gen_rtx_REG (reg_mode, TARGET_64BIT ? 12 : 11);
+ rtx offset = GEN_INT (sp_offset
+ (-8 * (64-info->first_fp_reg_save)));
- rtx ptr_reg = (sp_reg_rtx == frame_reg_rtx
- ? sp_reg_rtx : r11);
-
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (r11, ptr_reg, offset)
- : gen_adddi3 (r11, ptr_reg, offset));
+ emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
}
par = rs6000_make_savres_rtx (info, frame_reg_rtx,
info->gp_save_offset + sp_offset,
reg_mode,
/*savep=*/true, /*gpr=*/true,
- /*exitp=*/false);
+ /*lr=*/(strategy
+ & SAVRES_NOINLINE_GPRS_SAVES_LR)
+ != 0);
insn = emit_insn (par);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
@@ -19023,11 +19057,11 @@ rs6000_output_function_prologue (FILE *f
int regno = info->first_fp_reg_save - 32;
name = rs6000_savres_routine_name (info, regno, /*savep=*/true,
- /*gpr=*/false, /*exitp=*/false);
+ /*gpr=*/false, /*lr=*/false);
fprintf (file, "\t.extern %s\n", name);
name = rs6000_savres_routine_name (info, regno, /*savep=*/false,
- /*gpr=*/false, /*exitp=*/true);
+ /*gpr=*/false, /*lr=*/true);
fprintf (file, "\t.extern %s\n", name);
}
@@ -19155,6 +19189,7 @@ rs6000_emit_epilogue (int sibcall)
rtx frame_reg_rtx = sp_reg_rtx;
rtx cfa_restores = NULL_RTX;
rtx insn;
+ rtx cr_save_reg = NULL_RTX;
enum machine_mode reg_mode = Pmode;
int reg_size = TARGET_32BIT ? 4 : 8;
int i;
@@ -19188,9 +19223,9 @@ rs6000_emit_epilogue (int sibcall)
|| (cfun->calls_alloca
&& !frame_pointer_needed));
restore_lr = (info->lr_save_p
+ && restoring_FPRs_inline
&& (restoring_GPRs_inline
- || (restoring_FPRs_inline
- && info->first_fp_reg_save < 64)));
+ || info->first_fp_reg_save < 64));
if (WORLD_SAVE_P (info))
{
@@ -19492,7 +19527,11 @@ rs6000_emit_epilogue (int sibcall)
GEN_INT (info->cr_save_offset + sp_offset));
rtx mem = gen_frame_mem (SImode, addr);
- emit_move_insn (gen_rtx_REG (SImode, 12), mem);
+ cr_save_reg = gen_rtx_REG (SImode,
+ TARGET_64BIT && !restoring_GPRs_inline
+ && info->first_fp_reg_save < 64
+ ? 11 : 12);
+ emit_move_insn (cr_save_reg, mem);
}
/* Set LR here to try to overlap restores below. LR is always saved
@@ -19614,7 +19653,7 @@ rs6000_emit_epilogue (int sibcall)
par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
0, reg_mode,
/*savep=*/false, /*gpr=*/true,
- /*exitp=*/true);
+ /*lr=*/true);
emit_jump_insn (par);
/* We don't want anybody else emitting things after we jumped
back. */
@@ -19633,7 +19672,7 @@ rs6000_emit_epilogue (int sibcall)
sp_offset, can_use_exit);
else
{
- emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, 11),
+ emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, TARGET_64BIT ? 12 : 11),
frame_reg_rtx,
GEN_INT (sp_offset - info->fp_size)));
if (REGNO (frame_reg_rtx) == 11)
@@ -19643,14 +19682,13 @@ rs6000_emit_epilogue (int sibcall)
par = rs6000_make_savres_rtx (info, frame_reg_rtx,
info->gp_save_offset, reg_mode,
/*savep=*/false, /*gpr=*/true,
- /*exitp=*/can_use_exit);
+ /*lr=*/can_use_exit);
if (can_use_exit)
{
if (info->cr_save_p)
{
- rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12),
- using_mtcr_multiple);
+ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
if (DEFAULT_ABI == ABI_V4)
cfa_restores
= alloc_reg_note (REG_CFA_RESTORE,
@@ -19773,7 +19811,7 @@ rs6000_emit_epilogue (int sibcall)
/* If we saved cr, restore it here. Just those that were used. */
if (info->cr_save_p)
{
- rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), using_mtcr_multiple);
+ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
if (DEFAULT_ABI == ABI_V4)
cfa_restores
= alloc_reg_note (REG_CFA_RESTORE, gen_rtx_REG (SImode, CR2_REGNO),
@@ -19825,7 +19863,7 @@ rs6000_emit_epilogue (int sibcall)
sym = rs6000_savres_routine_sym (info,
/*savep=*/false,
/*gpr=*/false,
- /*exitp=*/true);
+ /*lr=*/true);
RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym);
RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode,
gen_rtx_REG (Pmode, 11));
--- gcc/config/rs6000/sysv4.h.jj 2009-09-12 12:06:56.000000000 +0200
+++ gcc/config/rs6000/sysv4.h 2009-09-12 12:06:56.000000000 +0200
@@ -272,16 +272,14 @@ do { \
#endif
/* Define cutoff for using external functions to save floating point.
- Currently on 64-bit V.4, always use inline stores. When optimizing
- for size on 32-bit targets, use external functions when
- profitable. */
-#define FP_SAVE_INLINE(FIRST_REG) (optimize_size && !TARGET_64BIT \
+ When optimizing for size, use external functions when profitable. */
+#define FP_SAVE_INLINE(FIRST_REG) (optimize_size \
? ((FIRST_REG) == 62 \
|| (FIRST_REG) == 63) \
: (FIRST_REG) < 64)
/* And similarly for general purpose registers. */
#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32 \
- && (TARGET_64BIT || !optimize_size))
+ && !optimize_size)
/* Put jump tables in read-only memory, rather than in .text. */
#define JUMP_TABLES_IN_TEXT_SECTION 0
--- gcc/config/rs6000/rs6000.md.jj 2009-09-12 09:54:07.000000000 +0200
+++ gcc/config/rs6000/rs6000.md 2009-09-14 12:35:26.186532013 +0200
@@ -15293,9 +15293,9 @@
[(match_parallel 0 "any_parallel_operand"
[(clobber (reg:P 65))
(use (match_operand:P 1 "symbol_ref_operand" "s"))
- (use (reg:P 11))
- (set (match_operand:P 2 "memory_operand" "=m")
- (match_operand:P 3 "gpc_reg_operand" "r"))])]
+ (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"))])]
""
"bl %z1"
[(set_attr "type" "branch")
@@ -15305,9 +15305,9 @@
[(match_parallel 0 "any_parallel_operand"
[(clobber (reg:P 65))
(use (match_operand:P 1 "symbol_ref_operand" "s"))
- (use (reg:P 11))
- (set (match_operand:DF 2 "memory_operand" "=m")
- (match_operand:DF 3 "gpc_reg_operand" "d"))])]
+ (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"))])]
""
"bl %z1"
[(set_attr "type" "branch")
@@ -15400,9 +15400,9 @@
[(match_parallel 0 "any_parallel_operand"
[(clobber (match_operand:P 1 "register_operand" "=l"))
(use (match_operand:P 2 "symbol_ref_operand" "s"))
- (use (reg:P 11))
- (set (match_operand:P 3 "gpc_reg_operand" "=r")
- (match_operand:P 4 "memory_operand" "m"))])]
+ (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"))])]
""
"bl %z2"
[(set_attr "type" "branch")
@@ -15413,9 +15413,9 @@
[(return)
(clobber (match_operand:P 1 "register_operand" "=l"))
(use (match_operand:P 2 "symbol_ref_operand" "s"))
- (use (reg:P 11))
- (set (match_operand:P 3 "gpc_reg_operand" "=r")
- (match_operand:P 4 "memory_operand" "m"))])]
+ (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"))])]
""
"b %z2"
[(set_attr "type" "branch")
@@ -15426,9 +15426,9 @@
[(return)
(clobber (match_operand:P 1 "register_operand" "=l"))
(use (match_operand:P 2 "symbol_ref_operand" "s"))
- (use (reg:P 11))
- (set (match_operand:DF 3 "gpc_reg_operand" "=d")
- (match_operand:DF 4 "memory_operand" "m"))])]
+ (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"))])]
""
"b %z2"
[(set_attr "type" "branch")
Jakub
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH] Updated version of the out-of-line fpr/gpr restoring ppc stuff
2009-09-14 13:45 ` Jakub Jelinek
@ 2009-09-15 9:24 ` Jakub Jelinek
2009-09-15 20:00 ` David Edelsohn
0 siblings, 1 reply; 19+ messages in thread
From: Jakub Jelinek @ 2009-09-15 9:24 UTC (permalink / raw)
To: David Edelsohn; +Cc: Nathan Froyd, Alan Modra, gcc-patches
On Mon, Sep 14, 2009 at 03:44:56PM +0200, Jakub Jelinek wrote:
> And with this patch on top of those 2 patches Linux emits out of line
> gpr/fpr saving calls also at -Os -m64.
Here is a new version of the whole patch, instead of several incremental
patches. Compared to what I've posted yesterday it has AIX support as well.
Bootstrapped on powerpc64-linux --with-cpu=default32, regtested both -m32
and -m64.
2009-09-15 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.
(SAVRES_NOINLINE_GPRS_SAVES_LR, SAVRES_NOINLINE_FPRS_SAVES_LR,
SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR): New strategy bits.
(rs6000_savres_strategy): Always save FP registers inline if the
target doesn't support hardware double-precision. Set the above
bits in return value when needed.
(rs6000_savres_routine_sym): Fix computation for cache selector.
Mark the generated symbol as a function. Rename exitp argument to
lr. 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_make_savres_rtx): Rename exitp argument to lr. Don't assert
lr isn't set when savep. Use r12 resp. r1 instead of r11 depending
on what the target routine uses as a base register. If savep && lr
describe saving of r0 into memory slot.
(rs6000_emit_prologue): Correct use of call_used_regs. Fix out of
line calls for AIX ABI.
(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.
Fix out of line calls for AIX ABI.
* config/rs6000/rs6000.md (*return_and_restore_fpregs_aix_<mode>):
New insn.
* config/rs6000/spe.md (*save_gpregs_spe): Use explicit match for
register 11.
(*restore_gpregs_spe): Likewise.
(*return_and_restore_gpregs_spe): Likewise.
* config/rs6000/linux64.h (SAVE_FP_SUFFIX, RESTORE_FP_SUFFIX):
Define to empty string unconditionally.
* config/rs6000/sysv4.h (SAVE_FP_SUFFIX, RESTORE_FP_SUFFIX):
Define to empty string unconditionally.
(GP_SAVE_INLINE, FP_SAVE_INLINE): Handle TARGET_64BIT the same as
!TARGET_64BIT.
* gcc.target/powerpc/pr41175.c: New test.
--- gcc/testsuite/gcc.target/powerpc/pr41175.c 2009-08-31 11:06:42.595126879 +0200
+++ gcc/testsuite/gcc.target/powerpc/pr41175.c 2009-09-12 09:54:07.541527611 +0200
@@ -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;
+}
--- gcc/config/rs6000/spe.md (revision 151650)
+++ gcc/config/rs6000/spe.md (working copy)
@@ -3156,9 +3156,9 @@
[(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 @@
[(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 @@
[(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")
--- gcc/config/rs6000/rs6000.c (revision 151650)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -18011,7 +18011,8 @@
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,136 @@
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 lr)
+{
+ 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 (lr)
+ 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 (lr)
+ suffix = "_x";
+ }
+ else if (DEFAULT_ABI == ABI_AIX)
+ {
+#ifndef POWERPC_LINUX
+ /* No out-of-line save/restore routines for GPRs on AIX. */
+ gcc_assert (!TARGET_AIX || !gpr);
+#endif
+
+ aix_names:
+ if (gpr)
+ prefix = (savep
+ ? (lr ? "_savegpr0_" : "_savegpr1_")
+ : (lr ? "_restgpr0_" : "_restgpr1_"));
+#ifdef POWERPC_LINUX
+ else if (lr)
+ prefix = (savep ? "_savefpr_" : "_restfpr_");
+#endif
+ 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 lr)
{
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
- | (exitp ? 1: 0));
+ | ((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)
+ | (lr ? 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;
+ char *name;
- action = savep ? "save" : "rest";
+ name = rs6000_savres_routine_name (info, regno, savep, gpr, lr);
- /* 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" : "";
-
- sprintf (name, "_%s%s_%d%s", action, regkind, regno, exit_suffix);
-
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 +18185,11 @@
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);
}
@@ -18132,7 +18218,7 @@
rs6000_make_savres_rtx (rs6000_stack_t *info,
rtx frame_reg_rtx, int save_area_offset,
enum machine_mode reg_mode,
- bool savep, bool gpr, bool exitp)
+ bool savep, bool gpr, bool lr)
{
int i;
int offset, start_reg, end_reg, n_regs;
@@ -18146,20 +18232,21 @@
: info->first_fp_reg_save);
end_reg = gpr ? 32 : 64;
n_regs = end_reg - start_reg;
- p = rtvec_alloc ((exitp ? 4 : 3) + n_regs);
+ p = rtvec_alloc ((lr ? 4 : 3) + n_regs);
- /* If we're saving registers, then we should never say we're exiting. */
- gcc_assert ((savep && !exitp) || !savep);
-
- if (exitp)
+ if (!savep && lr)
RTVEC_ELT (p, offset++) = gen_rtx_RETURN (VOIDmode);
RTVEC_ELT (p, offset++)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
- sym = rs6000_savres_routine_sym (info, savep, gpr, exitp);
+ sym = rs6000_savres_routine_sym (info, savep, gpr, lr);
RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym);
- RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 11));
+ RTVEC_ELT (p, offset++)
+ = gen_rtx_USE (VOIDmode,
+ gen_rtx_REG (Pmode, DEFAULT_ABI != ABI_AIX ? 11
+ : gpr && !lr ? 12
+ : 1));
for (i = 0; i < end_reg - start_reg; i++)
{
@@ -18174,6 +18261,16 @@
savep ? reg : mem);
}
+ if (savep && lr)
+ {
+ rtx addr, reg, mem;
+ reg = gen_rtx_REG (Pmode, 0);
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->lr_save_offset));
+ mem = gen_frame_mem (Pmode, addr);
+ RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg);
+ }
+
return gen_rtx_PARALLEL (VOIDmode, p);
}
@@ -18194,7 +18291,10 @@
enum {
SAVRES_MULTIPLE = 0x1,
SAVRES_INLINE_FPRS = 0x2,
- SAVRES_INLINE_GPRS = 0x4
+ SAVRES_INLINE_GPRS = 0x4,
+ SAVRES_NOINLINE_GPRS_SAVES_LR = 0x8,
+ SAVRES_NOINLINE_FPRS_SAVES_LR = 0x10,
+ SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR = 0x20
};
/* Determine the strategy for savings/restoring registers. */
@@ -18209,6 +18309,7 @@
bool savres_gprs_inline;
bool noclobber_global_gprs
= no_global_regs_above (info->first_gp_reg_save, /*gpr=*/true);
+ int strategy;
using_multiple_p = (TARGET_MULTIPLE && ! TARGET_POWERPC64
&& (!TARGET_SPE_ABI
@@ -18228,6 +18329,10 @@
|| 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
@@ -18265,9 +18370,22 @@
savres_gprs_inline = savres_gprs_inline || using_multiple_p;
}
- return (using_multiple_p
- | (savres_fprs_inline << 1)
- | (savres_gprs_inline << 2));
+ strategy = (using_multiple_p
+ | (savres_fprs_inline << 1)
+ | (savres_gprs_inline << 2));
+#ifdef POWERPC_LINUX
+ if (TARGET_64BIT)
+ {
+ if (!savres_fprs_inline)
+ strategy |= SAVRES_NOINLINE_FPRS_SAVES_LR;
+ else if (!savres_gprs_inline && info->first_fp_reg_save == 64)
+ strategy |= SAVRES_NOINLINE_GPRS_SAVES_LR;
+ }
+#else
+ if (TARGET_AIX && !savres_fprs_inline)
+ strategy |= SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR;
+#endif
+ return strategy;
}
/* Emit function prologue as insns. */
@@ -18289,7 +18407,7 @@
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)
@@ -18474,24 +18592,30 @@
gen_rtx_REG (Pmode, LR_REGNO));
RTX_FRAME_RELATED_P (insn) = 1;
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ if (!(strategy & (SAVRES_NOINLINE_GPRS_SAVES_LR
+ | SAVRES_NOINLINE_FPRS_SAVES_LR)))
+ {
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->lr_save_offset + sp_offset));
- reg = gen_rtx_REG (Pmode, 0);
- mem = gen_rtx_MEM (Pmode, addr);
- /* This should not be of rs6000_sr_alias_set, because of
- __builtin_return_address. */
+ reg = gen_rtx_REG (Pmode, 0);
+ mem = gen_rtx_MEM (Pmode, addr);
+ /* This should not be of rs6000_sr_alias_set, because of
+ __builtin_return_address. */
- insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- NULL_RTX, NULL_RTX);
+ insn = emit_move_insn (mem, reg);
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
+ }
}
- /* If we need to save CR, put it into r12. */
+ /* If we need to save CR, put it into r12 or r11. */
if (!WORLD_SAVE_P (info) && info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
{
rtx set;
- cr_save_rtx = gen_rtx_REG (SImode, 12);
+ cr_save_rtx
+ = gen_rtx_REG (SImode, DEFAULT_ABI == ABI_AIX && !saving_GPRs_inline
+ ? 11 : 12);
insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
RTX_FRAME_RELATED_P (insn) = 1;
/* Now, there's no way that dwarf2out_frame_debug_expr is going
@@ -18528,7 +18652,9 @@
info->fp_save_offset + sp_offset,
DFmode,
/*savep=*/true, /*gpr=*/false,
- /*exitp=*/false);
+ /*lr=*/(strategy
+ & SAVRES_NOINLINE_FPRS_SAVES_LR)
+ != 0);
insn = emit_insn (par);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
@@ -18624,7 +18750,7 @@
par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
0, reg_mode,
/*savep=*/true, /*gpr=*/true,
- /*exitp=*/false);
+ /*lr=*/false);
insn = emit_insn (par);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
@@ -18639,25 +18765,23 @@
{
rtx par;
- /* Need to adjust r11 if we saved any FPRs. */
+ /* Need to adjust r11 (r12) if we saved any FPRs. */
if (info->first_fp_reg_save != 64)
{
- rtx r11 = gen_rtx_REG (reg_mode, 11);
- rtx offset = GEN_INT (info->total_size
+ rtx dest_reg = gen_rtx_REG (reg_mode, DEFAULT_ABI == ABI_AIX
+ ? 12 : 11);
+ rtx offset = GEN_INT (sp_offset
+ (-8 * (64-info->first_fp_reg_save)));
- rtx ptr_reg = (sp_reg_rtx == frame_reg_rtx
- ? sp_reg_rtx : r11);
-
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (r11, ptr_reg, offset)
- : gen_adddi3 (r11, ptr_reg, offset));
+ emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
}
par = rs6000_make_savres_rtx (info, frame_reg_rtx,
info->gp_save_offset + sp_offset,
reg_mode,
/*savep=*/true, /*gpr=*/true,
- /*exitp=*/false);
+ /*lr=*/(strategy
+ & SAVRES_NOINLINE_GPRS_SAVES_LR)
+ != 0);
insn = emit_insn (par);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
@@ -18934,10 +19058,19 @@
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, /*lr=*/false);
+ fprintf (file, "\t.extern %s\n", name);
+
+ name = rs6000_savres_routine_name (info, regno, /*savep=*/false,
+ /*gpr=*/false, /*lr=*/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)
{
@@ -19062,6 +19195,7 @@
rtx frame_reg_rtx = sp_reg_rtx;
rtx cfa_restores = NULL_RTX;
rtx insn;
+ rtx cr_save_reg = NULL_RTX;
enum machine_mode reg_mode = Pmode;
int reg_size = TARGET_32BIT ? 4 : 8;
int i;
@@ -19095,8 +19229,10 @@
|| (cfun->calls_alloca
&& !frame_pointer_needed));
restore_lr = (info->lr_save_p
- && restoring_GPRs_inline
- && restoring_FPRs_inline);
+ && (restoring_FPRs_inline
+ || (strategy & SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR))
+ && (restoring_GPRs_inline
+ || info->first_fp_reg_save < 64));
if (WORLD_SAVE_P (info))
{
@@ -19383,7 +19519,7 @@
/* 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);
@@ -19398,12 +19534,17 @@
GEN_INT (info->cr_save_offset + sp_offset));
rtx mem = gen_frame_mem (SImode, addr);
- emit_move_insn (gen_rtx_REG (SImode, 12), mem);
+ cr_save_reg = gen_rtx_REG (SImode,
+ DEFAULT_ABI == ABI_AIX
+ && !restoring_GPRs_inline
+ && info->first_fp_reg_save < 64
+ ? 11 : 12);
+ emit_move_insn (cr_save_reg, mem);
}
/* 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));
@@ -19520,7 +19661,7 @@
par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
0, reg_mode,
/*savep=*/false, /*gpr=*/true,
- /*exitp=*/true);
+ /*lr=*/true);
emit_jump_insn (par);
/* We don't want anybody else emitting things after we jumped
back. */
@@ -19538,21 +19679,25 @@
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, DEFAULT_ABI == ABI_AIX
+ ? 12 : 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,
/*savep=*/false, /*gpr=*/true,
- /*exitp=*/can_use_exit);
+ /*lr=*/can_use_exit);
if (can_use_exit)
{
if (info->cr_save_p)
{
- rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12),
- using_mtcr_multiple);
+ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
if (DEFAULT_ABI == ABI_V4)
cfa_restores
= alloc_reg_note (REG_CFA_RESTORE,
@@ -19639,6 +19784,16 @@
}
}
+ 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++)
@@ -19665,7 +19820,7 @@
/* If we saved cr, restore it here. Just those that were used. */
if (info->cr_save_p)
{
- rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), using_mtcr_multiple);
+ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
if (DEFAULT_ABI == ABI_V4)
cfa_restores
= alloc_reg_note (REG_CFA_RESTORE, gen_rtx_REG (SImode, CR2_REGNO),
@@ -19696,13 +19851,14 @@
if (!sibcall)
{
rtvec p;
+ bool lr = (strategy & SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
if (! restoring_FPRs_inline)
p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
else
p = rtvec_alloc (2);
RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
- RTVEC_ELT (p, 1) = (restoring_FPRs_inline
+ RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65))
: gen_rtx_CLOBBER (VOIDmode,
gen_rtx_REG (Pmode, 65)));
@@ -19717,10 +19873,12 @@
sym = rs6000_savres_routine_sym (info,
/*savep=*/false,
/*gpr=*/false,
- /*exitp=*/true);
+ /*lr=*/lr);
RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym);
RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode, 11));
+ gen_rtx_REG (Pmode,
+ DEFAULT_ABI == ABI_AIX
+ ? 1 : 11));
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
{
rtx addr, mem;
--- gcc/config/rs6000/rs6000.md (revision 151650)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -15434,6 +15434,19 @@
[(set_attr "type" "branch")
(set_attr "length" "4")])
+(define_insn "*return_and_restore_fpregs_aix_<mode>"
+ [(match_parallel 0 "any_parallel_operand"
+ [(return)
+ (use (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"))])]
+ ""
+ "b %z2"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
; This is used in compiling the unwind routines.
(define_expand "eh_return"
[(use (match_operand 0 "general_operand" ""))]
--- gcc/config/rs6000/linux64.h (revision 151650)
+++ gcc/config/rs6000/linux64.h (working copy)
@@ -437,11 +437,11 @@
#undef SAVE_FP_PREFIX
#define SAVE_FP_PREFIX (TARGET_64BIT ? "._savef" : "_savefpr_")
#undef SAVE_FP_SUFFIX
-#define SAVE_FP_SUFFIX (TARGET_64BIT ? "" : "_l")
+#define SAVE_FP_SUFFIX ""
#undef RESTORE_FP_PREFIX
#define RESTORE_FP_PREFIX (TARGET_64BIT ? "._restf" : "_restfpr_")
#undef RESTORE_FP_SUFFIX
-#define RESTORE_FP_SUFFIX (TARGET_64BIT ? "" : "_l")
+#define RESTORE_FP_SUFFIX ""
/* Dwarf2 debugging. */
#undef PREFERRED_DEBUGGING_TYPE
--- gcc/config/rs6000/sysv4.h (revision 151650)
+++ gcc/config/rs6000/sysv4.h (working copy)
@@ -272,27 +272,25 @@
#endif
/* Define cutoff for using external functions to save floating point.
- Currently on 64-bit V.4, always use inline stores. When optimizing
- for size on 32-bit targets, use external functions when
- profitable. */
-#define FP_SAVE_INLINE(FIRST_REG) (optimize_size && !TARGET_64BIT \
+ When optimizing for size, use external functions when profitable. */
+#define FP_SAVE_INLINE(FIRST_REG) (optimize_size \
? ((FIRST_REG) == 62 \
|| (FIRST_REG) == 63) \
: (FIRST_REG) < 64)
/* And similarly for general purpose registers. */
#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32 \
- && (TARGET_64BIT || !optimize_size))
+ && !optimize_size)
/* Put jump tables in read-only memory, rather than in .text. */
#define JUMP_TABLES_IN_TEXT_SECTION 0
/* Prefix and suffix to use to saving floating point. */
#define SAVE_FP_PREFIX "_savefpr_"
-#define SAVE_FP_SUFFIX (TARGET_64BIT ? "_l" : "")
+#define SAVE_FP_SUFFIX ""
/* Prefix and suffix to use to restoring floating point. */
#define RESTORE_FP_PREFIX "_restfpr_"
-#define RESTORE_FP_SUFFIX (TARGET_64BIT ? "_l" : "")
+#define RESTORE_FP_SUFFIX ""
/* Type used for ptrdiff_t, as a string used in a declaration. */
#define PTRDIFF_TYPE "int"
Jakub
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Updated version of the out-of-line fpr/gpr restoring ppc stuff
2009-09-15 9:24 ` [PATCH] Updated version of the " Jakub Jelinek
@ 2009-09-15 20:00 ` David Edelsohn
0 siblings, 0 replies; 19+ messages in thread
From: David Edelsohn @ 2009-09-15 20:00 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Nathan Froyd, Alan Modra, gcc-patches
On Tue, Sep 15, 2009 at 5:23 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Sep 14, 2009 at 03:44:56PM +0200, Jakub Jelinek wrote:
>> And with this patch on top of those 2 patches Linux emits out of line
>> gpr/fpr saving calls also at -Os -m64.
>
> Here is a new version of the whole patch, instead of several incremental
> patches. Compared to what I've posted yesterday it has AIX support as well.
>
> Bootstrapped on powerpc64-linux --with-cpu=default32, regtested both -m32
> and -m64.
>
> 2009-09-15 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.
> (SAVRES_NOINLINE_GPRS_SAVES_LR, SAVRES_NOINLINE_FPRS_SAVES_LR,
> SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR): New strategy bits.
> (rs6000_savres_strategy): Always save FP registers inline if the
> target doesn't support hardware double-precision. Set the above
> bits in return value when needed.
> (rs6000_savres_routine_sym): Fix computation for cache selector.
> Mark the generated symbol as a function. Rename exitp argument to
> lr. 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_make_savres_rtx): Rename exitp argument to lr. Don't assert
> lr isn't set when savep. Use r12 resp. r1 instead of r11 depending
> on what the target routine uses as a base register. If savep && lr
> describe saving of r0 into memory slot.
> (rs6000_emit_prologue): Correct use of call_used_regs. Fix out of
> line calls for AIX ABI.
> (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.
> Fix out of line calls for AIX ABI.
> * config/rs6000/rs6000.md (*return_and_restore_fpregs_aix_<mode>):
> New insn.
> * config/rs6000/spe.md (*save_gpregs_spe): Use explicit match for
> register 11.
> (*restore_gpregs_spe): Likewise.
> (*return_and_restore_gpregs_spe): Likewise.
> * config/rs6000/linux64.h (SAVE_FP_SUFFIX, RESTORE_FP_SUFFIX):
> Define to empty string unconditionally.
> * config/rs6000/sysv4.h (SAVE_FP_SUFFIX, RESTORE_FP_SUFFIX):
> Define to empty string unconditionally.
> (GP_SAVE_INLINE, FP_SAVE_INLINE): Handle TARGET_64BIT the same as
> !TARGET_64BIT.
>
> * gcc.target/powerpc/pr41175.c: New test.
Hi, Jakub
This revised and combined patch bootstraps and regression tests
successfully on AIX.
This patch is okay.
Thanks for everyone's hard work disentangling and restoring this feature.
Thanks, David
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2009-09-15 20:00 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-19 21:35 [PATCH,rs6000] fix bugs with out-of-line prologues/epilogues, take 2 Nathan Froyd
2008-11-21 16:11 ` Nathan Froyd
2008-11-21 18:03 ` David Edelsohn
2008-11-21 19:00 ` Nathan Froyd
2009-07-15 13:08 ` David Edelsohn
2009-07-15 14:11 ` Nathan Froyd
2009-07-15 17:42 ` David Edelsohn
2009-09-09 18:50 ` David Edelsohn
2009-09-09 19:07 ` Jakub Jelinek
2009-09-10 6:39 ` Jakub Jelinek
2009-09-11 8:41 ` [PATCH] Incremental fix of out-of-line fpr/gpr restoring ppc stuff Jakub Jelinek
2009-09-11 16:17 ` Nathan Froyd
2009-09-12 15:12 ` Nathan Froyd
2009-09-12 6:44 ` Jakub Jelinek
2009-09-12 16:58 ` Jakub Jelinek
2009-09-14 13:45 ` Jakub Jelinek
2009-09-15 9:24 ` [PATCH] Updated version of the " Jakub Jelinek
2009-09-15 20:00 ` David Edelsohn
2009-09-13 1:48 ` [PATCH] Incremental fix of " David Edelsohn
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).