backport r151691 and r151729 to gcc-4.4 branch
Alan Modra
amodra@gmail.com
Mon May 31 09:06:00 GMT 2010
Hi David,
I'd like to apply a backport of these fixes to the 4.4 branch.
Cures 113 gcc testsuite failures. Bootstrapped etc. powerpc-linux.
Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog (revision 160024)
+++ gcc/ChangeLog (working copy)
@@ -1,3 +1,66 @@
+2010-05-31 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.
+
+2010-05-31 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/41331
+ * config/rs6000/rs6000.c (rs6000_emit_move): Use gen_add3_insn
+ instead of explicit addsi3/adddi3 calls.
+ (rs6000_split_multireg_move): Ditto.
+ (rs6000_emit_allocate_stack): Ditto.
+ (rs6000_emit_prologue): Ditto.
+ (rs6000_output_mi_thunk): Ditto.
+
+2010-05-31 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (rs6000_emit_stack_reset): Delete redundant
+ rs6000_emit_stack_tie.
+
2010-05-28 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* config/s390/s390.md (movqi): Fix typo ('*' -> '#').
Index: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog (revision 160024)
+++ gcc/testsuite/ChangeLog (working copy)
@@ -1,3 +1,9 @@
+2010-05-31 Nathan Froyd <froydnj@codesourcery.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR target/41175
+ * gcc.target/powerpc/pr41175.c: New test.
+
2010-05-27 Jason Merrill <jason@redhat.com>
PR c++/43555
Index: gcc/config/rs6000/spe.md
===================================================================
--- gcc/config/rs6000/spe.md (revision 160024)
+++ 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/linux64.h
===================================================================
--- gcc/config/rs6000/linux64.h (revision 160024)
+++ gcc/config/rs6000/linux64.h (working copy)
@@ -433,11 +433,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
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (revision 160024)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -5262,10 +5262,7 @@ rs6000_emit_move (rtx dest, rtx source,
rtx other = XEXP (XEXP (operands[1], 0), 1);
sym = force_reg (mode, sym);
- if (mode == SImode)
- emit_insn (gen_addsi3 (operands[0], sym, other));
- else
- emit_insn (gen_adddi3 (operands[0], sym, other));
+ emit_insn (gen_add3_insn (operands[0], sym, other));
return;
}
@@ -14341,9 +14338,7 @@ rs6000_split_multireg_move (rtx dst, rtx
delta_rtx = (GET_CODE (XEXP (src, 0)) == PRE_INC
? GEN_INT (GET_MODE_SIZE (GET_MODE (src)))
: GEN_INT (-GET_MODE_SIZE (GET_MODE (src))));
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (breg, breg, delta_rtx)
- : gen_adddi3 (breg, breg, delta_rtx));
+ emit_insn (gen_add3_insn (breg, breg, delta_rtx));
src = replace_equiv_address (src, breg);
}
else if (! rs6000_offsettable_memref_p (src))
@@ -14393,9 +14388,7 @@ rs6000_split_multireg_move (rtx dst, rtx
used_update = true;
}
else
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (breg, breg, delta_rtx)
- : gen_adddi3 (breg, breg, delta_rtx));
+ emit_insn (gen_add3_insn (breg, breg, delta_rtx));
dst = replace_equiv_address (dst, breg);
}
else
@@ -15572,14 +15565,7 @@ rs6000_emit_allocate_stack (HOST_WIDE_IN
&& REGNO (stack_limit_rtx) > 1
&& REGNO (stack_limit_rtx) <= 31)
{
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (tmp_reg,
- stack_limit_rtx,
- GEN_INT (size))
- : gen_adddi3 (tmp_reg,
- stack_limit_rtx,
- GEN_INT (size)));
-
+ emit_insn (gen_add3_insn (tmp_reg, stack_limit_rtx, GEN_INT (size)));
emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
const0_rtx));
}
@@ -15855,7 +15841,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;
@@ -15872,54 +15859,136 @@ 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 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";
-
- /* 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);
+ 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));
+ SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_FUNCTION;
}
return sym;
@@ -15945,10 +16014,12 @@ rs6000_emit_stack_reset (rs6000_stack_t
if (frame_reg_rtx != sp_reg_rtx)
{
- rs6000_emit_stack_tie ();
if (sp_offset != 0)
- 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;
+ emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx,
+ GEN_INT (sp_offset)));
+ }
else if (!savres)
emit_move_insn (sp_reg_rtx, frame_reg_rtx);
}
@@ -15977,7 +16048,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;
@@ -15991,20 +16062,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);
-
- /* If we're saving registers, then we should never say we're exiting. */
- gcc_assert ((savep && !exitp) || !savep);
+ p = rtvec_alloc ((lr ? 4 : 3) + n_regs);
- 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++)
{
@@ -16019,6 +16091,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);
}
@@ -16039,7 +16121,10 @@ 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,
+ SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR = 0x20
};
/* Determine the strategy for savings/restoring registers. */
@@ -16054,6 +16139,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
@@ -16073,6 +16159,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
@@ -16110,9 +16200,22 @@ 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;
+ }
+#else
+ if (TARGET_AIX && !savres_fprs_inline)
+ strategy |= SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR;
+#endif
+ return strategy;
}
/* Emit function prologue as insns. */
@@ -16134,7 +16237,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)
@@ -16332,24 +16435,30 @@ 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, 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
@@ -16388,7 +16497,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);
@@ -16484,7 +16595,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);
@@ -16499,25 +16610,23 @@ 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, 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);
@@ -16800,9 +16909,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, /*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)
@@ -16925,6 +17043,7 @@ rs6000_emit_epilogue (int sibcall)
int sp_offset = 0;
rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
rtx frame_reg_rtx = sp_reg_rtx;
+ rtx cr_save_reg = NULL_RTX;
enum machine_mode reg_mode = Pmode;
int reg_size = TARGET_32BIT ? 4 : 8;
int i;
@@ -16958,8 +17077,10 @@ rs6000_emit_epilogue (int sibcall)
|| (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))
{
@@ -17249,7 +17370,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);
@@ -17264,11 +17385,16 @@ 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,
+ 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. */
- if (restore_lr)
+ if (restore_lr && restoring_GPRs_inline)
emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
gen_rtx_REG (Pmode, 0));
@@ -17370,7 +17496,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
@@ -17389,20 +17515,24 @@ 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, 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);
emit_jump_insn (par);
@@ -17448,6 +17578,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++)
@@ -17471,7 +17611,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 this is V.4, unwind the stack pointer after all of the loads
have been done. */
@@ -17489,13 +17629,14 @@ rs6000_emit_epilogue (int sibcall)
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)));
@@ -17510,10 +17651,12 @@ rs6000_emit_epilogue (int sibcall)
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;
@@ -17883,12 +18026,7 @@ rs6000_output_mi_thunk (FILE *file, tree
/* Apply the constant offset, if required. */
if (delta)
- {
- rtx delta_rtx = GEN_INT (delta);
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (this_rtx, this_rtx, delta_rtx)
- : gen_adddi3 (this_rtx, this_rtx, delta_rtx));
- }
+ emit_insn (gen_add3_insn (this_rtx, this_rtx, GEN_INT (delta)));
/* Apply the offset from the vtable, if required. */
if (vcall_offset)
@@ -17899,9 +18037,7 @@ rs6000_output_mi_thunk (FILE *file, tree
emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
if (((unsigned HOST_WIDE_INT) vcall_offset) + 0x8000 >= 0x10000)
{
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (tmp, tmp, vcall_offset_rtx)
- : gen_adddi3 (tmp, tmp, vcall_offset_rtx));
+ emit_insn (gen_add3_insn (tmp, tmp, vcall_offset_rtx));
emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
}
else
@@ -17910,9 +18046,7 @@ rs6000_output_mi_thunk (FILE *file, tree
emit_move_insn (tmp, gen_rtx_MEM (Pmode, loc));
}
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (this_rtx, this_rtx, tmp)
- : gen_adddi3 (this_rtx, this_rtx, tmp));
+ emit_insn (gen_add3_insn (this_rtx, this_rtx, tmp));
}
/* Generate a tail call to the target function. */
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 160024)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -14853,6 +14853,19 @@ (define_insn "*return_and_restore_fpregs
[(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" "=f")
+ (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" ""))]
Index: gcc/config/rs6000/sysv4.h
===================================================================
--- gcc/config/rs6000/sysv4.h (revision 160024)
+++ gcc/config/rs6000/sysv4.h (working copy)
@@ -271,27 +271,25 @@ 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
/* 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"
--
Alan Modra
Australia Development Lab, IBM
More information about the Gcc-patches
mailing list