Commit 76594d53 by Michael Meissner Committed by Michael Meissner

Add -mno-r11 support to PowerPC 64

From-SVN: r175943
parent 04543ace
2011-07-06 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000-protos.h (rs6000_call_indirect_aix): New
declaration.
(rs6000_save_toc_in_prologue_p): Ditto.
* config/rs6000/rs6000.opt (-mr11): New switch to disable loading
up the static chain (r11) during indirect function calls.
(-msave-toc-indirect): New undocumented debug switch.
* config/rs6000/rs6000.c (struct machine_function): Add
save_toc_in_prologue field to note whether the prologue needs to
save the TOC value in the reserved stack location.
(rs6000_emit_prologue): Use TOC_REGNUM instead of 2. If we need
to save the TOC in the prologue, do so.
(rs6000_trampoline_init): Don't allow creating AIX style
trampolines if -mno-r11 is in effect.
(rs6000_call_indirect_aix): New function to create AIX style
indirect calls, adding support for -mno-r11 to suppress loading
the static chain, and saving the TOC in the prologue instead of
the call body.
(rs6000_save_toc_in_prologue_p): Return true if we are saving the
TOC in the prologue.
* config/rs6000/rs6000.md (STACK_POINTER_REGNUM): Add more fixed
register numbers.
(TOC_REGNUM): Ditto.
(STATIC_CHAIN_REGNUM): Ditto.
(ARG_POINTER_REGNUM): Ditto.
(SFP_REGNO): Delete, unused.
(TOC_SAVE_OFFSET_32BIT): Add constants for AIX TOC save and
function descriptor offsets.
(TOC_SAVE_OFFSET_64BIT): Ditto.
(AIX_FUNC_DESC_TOC_32BIT): Ditto.
(AIX_FUNC_DESC_TOC_64BIT): Ditto.
(AIX_FUNC_DESC_SC_32BIT): Ditto.
(AIX_FUNC_DESC_SC_64BIT): Ditto.
(ptrload): New mode attribute for the appropriate load of a
pointer.
(call_indirect_aix32): Delete, rewrite AIX indirect function
calls.
(call_indirect_aix64): Ditto.
(call_value_indirect_aix32): Ditto.
(call_value_indirect_aix64): Ditto.
(call_indirect_nonlocal_aix32_internal): Ditto.
(call_indirect_nonlocal_aix32): Ditto.
(call_indirect_nonlocal_aix64_internal): Ditto.
(call_indirect_nonlocal_aix64): Ditto.
(call): Rewrite AIX indirect function calls. Add support for
eliminating the static chain, and for moving the save of the TOC
to the function prologue.
(call_value): Ditto.
(call_indirect_aix<ptrsize>): Ditto.
(call_indirect_aix<ptrsize>_internal): Ditto.
(call_indirect_aix<ptrsize>_internal2): Ditto.
(call_indirect_aix<ptrsize>_nor11): Ditto.
(call_value_indirect_aix<ptrsize>): Ditto.
(call_value_indirect_aix<ptrsize>_internal): Ditto.
(call_value_indirect_aix<ptrsize>_internal2): Ditto.
(call_value_indirect_aix<ptrsize>_nor11): Ditto.
(call_nonlocal_aix32): Relocate in the rs6000.md file.
(call_nonlocal_aix64): Ditto.
* doc/invoke.texi (RS/6000 and PowerPC Options): Add -mr11 and
-mno-r11 documentation.
2011-07-06 Jonathan Wakely <jwakely.gcc@gmail.com>
PR other/49658
......
......@@ -171,6 +171,8 @@ extern unsigned int rs6000_dbx_register_number (unsigned int);
extern void rs6000_emit_epilogue (int);
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
extern const char * output_isel (rtx *);
extern void rs6000_call_indirect_aix (rtx, rtx, rtx);
extern bool rs6000_save_toc_in_prologue_p (void);
extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
......
......@@ -130,6 +130,9 @@ typedef struct GTY(()) machine_function
int ra_need_lr;
/* Cache lr_save_p after expansion of builtin_eh_return. */
int lr_save_state;
/* Whether we need to save the TOC to the reserved stack location in the
function prologue. */
bool save_toc_in_prologue;
/* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
varargs save area. */
HOST_WIDE_INT varargs_save_offset;
......@@ -20325,7 +20328,7 @@ rs6000_emit_prologue (void)
JUMP_LABEL (jump) = toc_save_done;
LABEL_NUSES (toc_save_done) += 1;
emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, 2,
emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, TOC_REGNUM,
sp_offset + 5 * reg_size, info->total_size);
emit_label (toc_save_done);
if (using_static_chain_p)
......@@ -20516,6 +20519,11 @@ rs6000_emit_prologue (void)
emit_move_insn (lr, gen_rtx_REG (Pmode, 0));
}
#endif
/* If we need to, save the TOC register after doing the stack setup. */
if (rs6000_save_toc_in_prologue_p ())
emit_frame_save (sp_reg_rtx, sp_reg_rtx, reg_mode, TOC_REGNUM,
5 * reg_size, info->total_size);
}
/* Write function prologue. */
......@@ -24469,9 +24477,14 @@ rs6000_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
/* Under AIX, just build the 3 word function descriptor */
case ABI_AIX:
{
rtx fnmem = gen_const_mem (Pmode, force_reg (Pmode, fnaddr));
rtx fn_reg = gen_reg_rtx (Pmode);
rtx toc_reg = gen_reg_rtx (Pmode);
rtx fnmem, fn_reg, toc_reg;
if (!TARGET_R11)
error ("-mno-r11 must not be used if you have trampolines");
fnmem = gen_const_mem (Pmode, force_reg (Pmode, fnaddr));
fn_reg = gen_reg_rtx (Pmode);
toc_reg = gen_reg_rtx (Pmode);
/* Macro to shorten the code expansions below. */
# define MEM_PLUS(MEM, OFFSET) adjust_address (MEM, Pmode, OFFSET)
......@@ -27760,4 +27773,132 @@ rs6000_legitimate_constant_p (enum machine_mode mode, rtx x)
|| easy_vector_constant (x, mode));
}
/* A function pointer under AIX is a pointer to a data area whose first word
contains the actual address of the function, whose second word contains a
pointer to its TOC, and whose third word contains a value to place in the
static chain register (r11). Note that if we load the static chain, our
"trampoline" need not have any executable code. */
void
rs6000_call_indirect_aix (rtx value, rtx func_desc, rtx flag)
{
rtx func_addr;
rtx toc_reg;
rtx sc_reg;
rtx stack_ptr;
rtx stack_toc_offset;
rtx stack_toc_mem;
rtx func_toc_offset;
rtx func_toc_mem;
rtx func_sc_offset;
rtx func_sc_mem;
rtx insn;
rtx (*call_func) (rtx, rtx, rtx, rtx);
rtx (*call_value_func) (rtx, rtx, rtx, rtx, rtx);
stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM);
/* Load up address of the actual function. */
func_desc = force_reg (Pmode, func_desc);
func_addr = gen_reg_rtx (Pmode);
emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
if (TARGET_32BIT)
{
stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_32BIT);
func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_32BIT);
func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_32BIT);
if (TARGET_R11)
{
call_func = gen_call_indirect_aix32bit;
call_value_func = gen_call_value_indirect_aix32bit;
}
else
{
call_func = gen_call_indirect_aix32bit_nor11;
call_value_func = gen_call_value_indirect_aix32bit_nor11;
}
}
else
{
stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_64BIT);
func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_64BIT);
func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_64BIT);
if (TARGET_R11)
{
call_func = gen_call_indirect_aix64bit;
call_value_func = gen_call_value_indirect_aix64bit;
}
else
{
call_func = gen_call_indirect_aix64bit_nor11;
call_value_func = gen_call_value_indirect_aix64bit_nor11;
}
}
/* Reserved spot to store the TOC. */
stack_toc_mem = gen_frame_mem (Pmode,
gen_rtx_PLUS (Pmode,
stack_ptr,
stack_toc_offset));
gcc_assert (cfun);
gcc_assert (cfun->machine);
/* Can we optimize saving the TOC in the prologue or do we need to do it at
every call? */
if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca
&& !cfun->calls_setjmp && !cfun->has_nonlocal_label
&& !cfun->can_throw_non_call_exceptions
&& ((flags_from_decl_or_type (cfun->decl) & ECF_NOTHROW) == ECF_NOTHROW))
cfun->machine->save_toc_in_prologue = true;
else
{
MEM_VOLATILE_P (stack_toc_mem) = 1;
emit_move_insn (stack_toc_mem, toc_reg);
}
/* Calculate the address to load the TOC of the called function. We don't
actually load this until the split after reload. */
func_toc_mem = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode,
func_desc,
func_toc_offset));
/* If we have a static chain, load it up. */
if (TARGET_R11)
{
func_sc_mem = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode,
func_desc,
func_sc_offset));
sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
emit_move_insn (sc_reg, func_sc_mem);
}
/* Create the call. */
if (value)
insn = call_value_func (value, func_addr, flag, func_toc_mem,
stack_toc_mem);
else
insn = call_func (func_addr, flag, func_toc_mem, stack_toc_mem);
emit_call_insn (insn);
return;
}
/* Return whether we need to always update the saved TOC pointer when we update
the stack pointer. */
bool
rs6000_save_toc_in_prologue_p (void)
{
return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue);
}
#include "gt-rs6000.h"
......@@ -521,4 +521,10 @@ mxilinx-fpu
Target Var(rs6000_xilinx_fpu) Save
Specify Xilinx FPU.
mr11
Target Report Var(TARGET_R11) Init(1) Save
Use/do not use r11 to hold the static link in calls.
msave-toc-indirect
Target Undocumented Var(TARGET_SAVE_TOC_INDIRECT) Save Init(1)
; Control whether we save the TOC in the prologue for indirect calls or generate the save inline
......@@ -807,7 +807,7 @@ See RS/6000 and PowerPC Options.
-msdata=@var{opt} -mvxworks -G @var{num} -pthread @gol
-mrecip -mrecip=@var{opt} -mno-recip -mrecip-precision @gol
-mno-recip-precision @gol
-mveclibabi=@var{type} -mfriz -mno-friz}
-mveclibabi=@var{type} -mfriz -mno-friz -mr11 -mno-r11}
@emph{RX Options}
@gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol
......@@ -16325,6 +16325,19 @@ Generate (do not generate) the @code{friz} instruction when the
rounding a floating point value to 64-bit integer and back to floating
point. The @code{friz} instruction does not return the same value if
the floating point number is too large to fit in an integer.
@item -mr11
@itemx -mno-r11
@opindex mr11
Generate (do not generate) code to load up the static chain register
(@var{r11}) when calling through a pointer on AIX and 64-bit Linux
systems where a function pointer points to a 3 word descriptor giving
the function address, TOC value to be loaded in register @var{r2}, and
static chain value to be loaded in register @var{r11}. The
@option{-mr11} is on by default. You will not be able to call through
pointers to nested functions or pointers to functions compiled in
other languages that use the static chain if you use the
@option{-mno-r11}.
@end table
@node RX Options
......
2011-07-06 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc.target/powerpc/no-r11-1.c: New test for -mr11, -mno-r11.
* gcc.target/powerpc/no-r11-2.c: Ditto.
* gcc.target/powerpc/no-r11-3.c: Ditto.
2011-07-06 Uros Bizjak <ubizjak@gmail.com>
* gcc.dg/stack-layout-2.c: Cleanup expand rtl dump.
......
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-options "-O2 -mno-r11" } */
int
call_ptr (int (func) (void))
{
return func () + 1;
}
/* { dg-final { scan-assembler-not "ld 11,16(3)" } } */
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-options "-O2 -mr11" } */
int
call_ptr (int (func) (void))
{
return func () + 1;
}
/* { dg-final { scan-assembler "ld 11,16" } } */
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-options "-O2 -mno-r11" } */
extern void ext_call (int (func) (void));
int
outer_func (int init) /* { dg-error "-mno-r11 must not be used if you have trampolines" "" } */
{
int value = init;
int inner (void)
{
return ++value;
}
ext_call (inner);
return value;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment