rs6000.h (DWARF_FRAME_REGISTERS): Define.

2003-03-10  Aldy Hernandez  <aldyh@redhat.com>

        * config/rs6000/rs6000.h (DWARF_FRAME_REGISTERS): Define.
        (rs6000_stack_t): Add spe_64bit_regs_used.

        * config/rs6000/rs6000.c (rs6000_stack_info): Calculate
        spe_64bit_regs_used, and use it to determine the size of the
        frame.
        (spe_func_has_64bit_regs_p): New.
        (spe_synthesize_frame_save): New.
        (rs6000_frame_related): Handle SPE synthetic registers.
        (rs6000_emit_prologue): Only save in 64-bits if the function used
        any registers in 64-bit mode.
        (rs6000_emit_epilogue): Same, but for restore.

From-SVN: r64102
This commit is contained in:
Aldy Hernandez 2003-03-10 18:03:17 +00:00 committed by Aldy Hernandez
parent 29ad969430
commit c19de7aa68
3 changed files with 156 additions and 16 deletions

View File

@ -1,3 +1,18 @@
2003-03-10 Aldy Hernandez <aldyh@redhat.com>
* config/rs6000/rs6000.h (DWARF_FRAME_REGISTERS): Define.
(rs6000_stack_t): Add spe_64bit_regs_used.
* config/rs6000/rs6000.c (rs6000_stack_info): Calculate
spe_64bit_regs_used, and use it to determine the size of the
frame.
(spe_func_has_64bit_regs_p): New.
(spe_synthesize_frame_save): New.
(rs6000_frame_related): Handle SPE synthetic registers.
(rs6000_emit_prologue): Only save in 64-bits if the function used
any registers in 64-bit mode.
(rs6000_emit_epilogue): Same, but for restore.
2003-03-10 Richard Earnshaw <rearnsha@arm.com>
* arm.h (enum floating_point_type): Delete. Replace with...

View File

@ -175,6 +175,8 @@ static rtx rs6000_generate_compare PARAMS ((enum rtx_code));
static void rs6000_maybe_dead PARAMS ((rtx));
static void rs6000_emit_stack_tie PARAMS ((void));
static void rs6000_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT, rtx, rtx));
static rtx spe_synthesize_frame_save PARAMS ((rtx));
static bool spe_func_has_64bit_regs_p PARAMS ((void));
static void emit_frame_save PARAMS ((rtx, rtx, enum machine_mode,
unsigned int, int, int));
static rtx gen_frame_mem_offset PARAMS ((enum machine_mode, rtx, int));
@ -9134,10 +9136,19 @@ rs6000_stack_info ()
enum rs6000_abi abi;
int ehrd_size;
int total_raw_size;
static int insn_chain_scanned = -1;
/* Zero all fields portably. */
info = zero_info;
if (TARGET_SPE)
{
/* Cache value so we don't rescan instruction chain over and over. */
if (insn_chain_scanned < 0)
insn_chain_scanned = (int) spe_func_has_64bit_regs_p ();
info_ptr->spe_64bit_regs_used = insn_chain_scanned;
}
/* Select which calling sequence. */
info_ptr->abi = abi = DEFAULT_ABI;
@ -9159,12 +9170,13 @@ rs6000_stack_info ()
registers live (not the size they are used in), this proves
difficult because we'd have to traverse the instruction chain at
the right time, taking reload into account. This is a real pain,
so we opt to save the GPRs in 64-bits always. Anyone overly
concerned with frame size can fix this. ;-).
so we opt to save the GPRs in 64-bits always if but one register
gets used in 64-bits. Otherwise, all the registers in the frame
get saved in 32-bits.
So... since we save all GPRs (except the SP) in 64-bits, the
So... since when we save all GPRs (except the SP) in 64-bits, the
traditional GP save area will be empty. */
if (TARGET_SPE_ABI)
if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
info_ptr->gp_size = 0;
info_ptr->first_fp_reg_save = first_fp_reg_to_save ();
@ -9217,7 +9229,9 @@ rs6000_stack_info ()
continue;
/* SPE saves EH registers in 64-bits. */
ehrd_size = i * (TARGET_SPE_ABI ? UNITS_PER_SPE_WORD : UNITS_PER_WORD);
ehrd_size = i * (TARGET_SPE_ABI
&& info_ptr->spe_64bit_regs_used != 0
? UNITS_PER_SPE_WORD : UNITS_PER_WORD);
}
else
ehrd_size = 0;
@ -9230,7 +9244,7 @@ rs6000_stack_info ()
info_ptr->parm_size = RS6000_ALIGN (current_function_outgoing_args_size,
8);
if (TARGET_SPE_ABI)
if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
info_ptr->spe_gp_size = 8 * (32 - info_ptr->first_gp_reg_save);
else
info_ptr->spe_gp_size = 0;
@ -9290,7 +9304,7 @@ rs6000_stack_info ()
info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
info_ptr->cr_save_offset = info_ptr->gp_save_offset - info_ptr->cr_size;
if (TARGET_SPE_ABI)
if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
{
/* Align stack so SPE GPR save area is aligned on a
double-word boundary. */
@ -9398,7 +9412,9 @@ rs6000_stack_info ()
if (! TARGET_ALTIVEC_ABI || info_ptr->vrsave_mask == 0)
info_ptr->vrsave_save_offset = 0;
if (! TARGET_SPE_ABI || info_ptr->spe_gp_size == 0)
if (! TARGET_SPE_ABI
|| info_ptr->spe_64bit_regs_used == 0
|| info_ptr->spe_gp_size == 0)
info_ptr->spe_gp_save_offset = 0;
if (! info_ptr->lr_save_p)
@ -9413,6 +9429,39 @@ rs6000_stack_info ()
return info_ptr;
}
/* Return true if the current function uses any GPRs in 64-bit SIMD
mode. */
static bool
spe_func_has_64bit_regs_p ()
{
rtx insns, insn;
/* Functions that save and restore all the call-saved registers will
need to save/restore the registers in 64-bits. */
if (current_function_calls_eh_return
|| current_function_calls_setjmp
|| current_function_has_nonlocal_goto)
return true;
insns = get_insns ();
for (insn = NEXT_INSN (insns); insn != NULL_RTX; insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
{
rtx i;
i = PATTERN (insn);
if (GET_CODE (i) == SET
&& SPE_VECTOR_MODE (GET_MODE (SET_SRC (i))))
return true;
}
}
return false;
}
void
debug_stack_info (info)
rs6000_stack_t *info;
@ -10159,13 +10208,81 @@ rs6000_frame_related (insn, reg, val, reg2, rreg)
}
else
abort ();
if (TARGET_SPE)
real = spe_synthesize_frame_save (real);
RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
real,
REG_NOTES (insn));
}
/* Given an SPE frame note, return a PARALLEL of SETs with the
original note, plus a synthetic register save. */
static rtx
spe_synthesize_frame_save (real)
rtx real;
{
rtx synth, offset, reg, real2;
if (GET_CODE (real) != SET
|| GET_MODE (SET_SRC (real)) != V2SImode)
return real;
/* For the SPE, registers saved in 64-bits, get a PARALLEL for their
frame related note. The parallel contains a set of the register
being saved, and another set to a synthetic register (n+113).
This is so we can differentiate between 64-bit and 32-bit saves.
Words cannot describe this nastiness. */
if (GET_CODE (SET_DEST (real)) != MEM
|| GET_CODE (XEXP (SET_DEST (real), 0)) != PLUS
|| GET_CODE (SET_SRC (real)) != REG)
abort ();
/* Transform:
(set (mem (plus (reg x) (const y)))
(reg z))
into:
(set (mem (plus (reg x) (const y+4)))
(reg z+113))
*/
real2 = copy_rtx (real);
PUT_MODE (SET_DEST (real2), SImode);
reg = SET_SRC (real2);
real2 = replace_rtx (real2, reg, gen_rtx_REG (SImode, REGNO (reg)));
synth = copy_rtx (real2);
if (BYTES_BIG_ENDIAN)
{
offset = XEXP (XEXP (SET_DEST (real2), 0), 1);
real2 = replace_rtx (real2, offset, GEN_INT (INTVAL (offset) + 4));
}
reg = SET_SRC (synth);
/* FIXME: the ABI says REGNO+1200, but this creates a huge hole
in the unwinder tables. I'm still unsure what to do. */
synth = replace_rtx (synth, reg,
gen_rtx_REG (SImode, REGNO (reg) + 113));
offset = XEXP (XEXP (SET_DEST (synth), 0), 1);
synth = replace_rtx (synth, offset,
GEN_INT (INTVAL (offset)
+ (BYTES_BIG_ENDIAN ? 0 : 4)));
RTX_FRAME_RELATED_P (synth) = 1;
RTX_FRAME_RELATED_P (real2) = 1;
if (BYTES_BIG_ENDIAN)
real = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, synth, real2));
else
real = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, real2, synth));
return real;
}
/* Returns an insn that has a vrsave set operation with the
appropriate CLOBBERs. */
@ -10317,14 +10434,15 @@ rs6000_emit_prologue ()
int using_store_multiple;
HOST_WIDE_INT sp_offset = 0;
if (TARGET_SPE_ABI)
if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
{
reg_mode = V2SImode;
reg_size = 8;
}
using_store_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
&& !TARGET_SPE_ABI
&& (!TARGET_SPE_ABI
|| info->spe_64bit_regs_used == 0)
&& info->first_gp_reg_save < 31);
saving_FPRs_inline = (info->first_fp_reg_save == 64
|| FP_SAVE_INLINE (info->first_fp_reg_save));
@ -10510,7 +10628,7 @@ rs6000_emit_prologue ()
rtx addr, reg, mem;
reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
if (TARGET_SPE_ABI)
if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
{
int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
rtx b;
@ -10752,15 +10870,17 @@ rs6000_emit_epilogue (sibcall)
int reg_size = TARGET_POWERPC64 ? 8 : 4;
int i;
if (TARGET_SPE_ABI)
info = rs6000_stack_info ();
if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
{
reg_mode = V2SImode;
reg_size = 8;
}
info = rs6000_stack_info ();
using_load_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
&& !TARGET_SPE_ABI
&& (!TARGET_SPE_ABI
|| info->spe_64bit_regs_used == 0)
&& info->first_gp_reg_save < 31);
restoring_FPRs_inline = (sibcall
|| current_function_calls_eh_return
@ -10930,7 +11050,7 @@ rs6000_emit_epilogue (sibcall)
rtx mem = gen_rtx_MEM (reg_mode, addr);
/* Restore 64-bit quantities for SPE. */
if (TARGET_SPE_ABI)
if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
{
int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
rtx b;

View File

@ -704,6 +704,10 @@ extern int rs6000_default_long_calls;
/* This must be included for pre gcc 3.0 glibc compatibility. */
#define PRE_GCC3_DWARF_FRAME_REGISTERS 77
/* Add 32 dwarf columns for synthetic SPE registers. The SPE
synthetic registers are 113 through 145. */
#define DWARF_FRAME_REGISTERS (FIRST_PSEUDO_REGISTER + 32)
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
@ -1395,6 +1399,7 @@ typedef struct rs6000_stack {
int spe_padding_size;
int toc_size; /* size to hold TOC if not in save_size */
int total_size; /* total bytes allocated for stack */
int spe_64bit_regs_used;
} rs6000_stack_t;
/* Define this if pushing a word on the stack