re PR target/34814 (SDmode function args not passed according to ABI specification)

PR target/34814
	* doc/tm.texi (TARGET_EXPAND_TO_RTL_HOOK): Document.
	(TARGET_INSTANTIATE_DECLS): Likewise.
	* target.h (expand_to_rtl_hook): New target hook.
	(instantiate_decls): Likewise.
	* function.c (instantiate_decl): Make non-static.  Rename to...
	(instantiate_decl_rtl): ... this.
	(instantiate_expr): Use instantiate_decl_rtl.
	(instantiate_decls_1): Likewise.
	(instantiate_decls): Likewise.
	(instantiate_virtual_regs: Call new instantiate_decls taget hook.
	* function.h (instantiate_decl_rtl): Add prototype.
	* cfgexpand.c (target.h): New include.
	(tree_expand_cfg): Call new expand_to_rtl_hook target hook.
	* target-def.h (TARGET_EXPAND_TO_RTL_HOOK): New define.
	(TARGET_INSTANTIATE_DECLS): Likewise.
	(TARGET_INITIALIZER): New target hooks added.
	* config/rs6000/rs6000-protos.h (rs6000_secondary_memory_needed_rtx):
	New prototype.
	* config/rs6000/rs6000.c (tree-flow.h): New include.
	(machine_function): Add sdmode_stack_slot field.
	(rs6000_alloc_sdmode_stack_slot): New function.
	(rs6000_instantiate_decls): Likewise.
	(rs6000_secondary_memory_needed_rtx): Likewise.
	(rs6000_check_sdmode): Likewise.
	(TARGET_EXPAND_TO_RTL_HOOK): Target macro defined.
	(TARGET_INSTANTIATE_DECLS): Likewise.
	(rs6000_hard_regno_mode_ok): Allow SDmode.
	(num_insns_constant): Likewise.  Handle _Decimal32 constants.
	(rs6000_emit_move): Handle SDmode.
	(function_arg_advance): Likewise.
	(function_arg): Likewise.
	(rs6000_gimplify_va_arg): Likewise.  Add special handling of
	SDmode var args for 32-bit compiles.
	(rs6000_secondary_reload_class): Handle SDmode.
	(rs6000_output_function_epilogue): Likewise.
	(rs6000_function_value): Simplify if statement.
	(rs6000_libcall_value): Likewise.
	* config/rs6000/rs6000.h (SLOW_UNALIGNED_ACCESS): Handle SDmode.
	(SECONDARY_MEMORY_NEEDED_RTX): Add define.
	* config/rs6000/dfp.md (movsd): New define_expand and splitter.
	(movsd_hardfloat): New define_insn.
	(movsd_softfloat): Likewise.
	(movsd_store): Likewise.
	(movsd_load): Likewise.
	(extendsddd2): Likewise.
	(extendsdtd2): Likewise.
	(truncddsd2): Likewise.
	(movdd_hardfloat64): Fixup comment.
	(UNSPEC_MOVSD_LOAD): New constant.
	(UNSPEC_MOVSD_STORE): Likewise.

Co-Authored-By: Janis Johnson <janis187@us.ibm.com>

From-SVN: r131869
This commit is contained in:
Peter Bergner 2008-01-26 11:18:35 -06:00 committed by Peter Bergner
parent 6f536f74ed
commit e41b2a33b3
11 changed files with 429 additions and 65 deletions

View File

@ -1,3 +1,58 @@
2007-01-26 Peter Bergner <bergner@vnet.ibm.com>
Janis Johnson <janis187@us.ibm.com>
PR target/34814
* doc/tm.texi (TARGET_EXPAND_TO_RTL_HOOK): Document.
(TARGET_INSTANTIATE_DECLS): Likewise.
* target.h (expand_to_rtl_hook): New target hook.
(instantiate_decls): Likewise.
* function.c (instantiate_decl): Make non-static. Rename to...
(instantiate_decl_rtl): ... this.
(instantiate_expr): Use instantiate_decl_rtl.
(instantiate_decls_1): Likewise.
(instantiate_decls): Likewise.
(instantiate_virtual_regs: Call new instantiate_decls taget hook.
* function.h (instantiate_decl_rtl): Add prototype.
* cfgexpand.c (target.h): New include.
(tree_expand_cfg): Call new expand_to_rtl_hook target hook.
* target-def.h (TARGET_EXPAND_TO_RTL_HOOK): New define.
(TARGET_INSTANTIATE_DECLS): Likewise.
(TARGET_INITIALIZER): New target hooks added.
* config/rs6000/rs6000-protos.h (rs6000_secondary_memory_needed_rtx):
New prototype.
* config/rs6000/rs6000.c (tree-flow.h): New include.
(machine_function): Add sdmode_stack_slot field.
(rs6000_alloc_sdmode_stack_slot): New function.
(rs6000_instantiate_decls): Likewise.
(rs6000_secondary_memory_needed_rtx): Likewise.
(rs6000_check_sdmode): Likewise.
(TARGET_EXPAND_TO_RTL_HOOK): Target macro defined.
(TARGET_INSTANTIATE_DECLS): Likewise.
(rs6000_hard_regno_mode_ok): Allow SDmode.
(num_insns_constant): Likewise. Handle _Decimal32 constants.
(rs6000_emit_move): Handle SDmode.
(function_arg_advance): Likewise.
(function_arg): Likewise.
(rs6000_gimplify_va_arg): Likewise. Add special handling of
SDmode var args for 32-bit compiles.
(rs6000_secondary_reload_class): Handle SDmode.
(rs6000_output_function_epilogue): Likewise.
(rs6000_function_value): Simplify if statement.
(rs6000_libcall_value): Likewise.
* config/rs6000/rs6000.h (SLOW_UNALIGNED_ACCESS): Handle SDmode.
(SECONDARY_MEMORY_NEEDED_RTX): Add define.
* config/rs6000/dfp.md (movsd): New define_expand and splitter.
(movsd_hardfloat): New define_insn.
(movsd_softfloat): Likewise.
(movsd_store): Likewise.
(movsd_load): Likewise.
(extendsddd2): Likewise.
(extendsdtd2): Likewise.
(truncddsd2): Likewise.
(movdd_hardfloat64): Fixup comment.
(UNSPEC_MOVSD_LOAD): New constant.
(UNSPEC_MOVSD_STORE): Likewise.
2008-01-26 Jakub Jelinek <jakub@redhat.com>
PR c++/34965

View File

@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "tree-inline.h"
#include "value-prof.h"
#include "target.h"
/* Verify that there is exactly single jump instruction since last and attach
REG_BR_PROB note specifying probability.
@ -1873,6 +1874,8 @@ tree_expand_cfg (void)
/* Mark arrays indexed with non-constant indices with TREE_ADDRESSABLE. */
discover_nonconstant_array_refs ();
targetm.expand_to_rtl_hook ();
/* Expand the variables recorded during gimple lowering. */
expand_used_vars ();

View File

@ -20,6 +20,138 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
;;
;; UNSPEC usage
;;
(define_constants
[(UNSPEC_MOVSD_LOAD 400)
(UNSPEC_MOVSD_STORE 401)
])
(define_expand "movsd"
[(set (match_operand:SD 0 "nonimmediate_operand" "")
(match_operand:SD 1 "any_operand" ""))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
"{ rs6000_emit_move (operands[0], operands[1], SDmode); DONE; }")
(define_split
[(set (match_operand:SD 0 "gpc_reg_operand" "")
(match_operand:SD 1 "const_double_operand" ""))]
"reload_completed
&& ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
&& REGNO (SUBREG_REG (operands[0])) <= 31))"
[(set (match_dup 2) (match_dup 3))]
"
{
long l;
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
REAL_VALUE_TO_TARGET_DECIMAL32 (rv, l);
if (! TARGET_POWERPC64)
operands[2] = operand_subword (operands[0], 0, 0, SDmode);
else
operands[2] = gen_lowpart (SImode, operands[0]);
operands[3] = gen_int_mode (l, SImode);
}")
(define_insn "movsd_hardfloat"
[(set (match_operand:SD 0 "nonimmediate_operand" "=r,r,m,f,*c*l,*q,!r,*h,!r,!r")
(match_operand:SD 1 "input_operand" "r,m,r,f,r,r,h,0,G,Fn"))]
"(gpc_reg_operand (operands[0], SDmode)
|| gpc_reg_operand (operands[1], SDmode))
&& (TARGET_HARD_FLOAT && TARGET_FPRS)"
"@
mr %0,%1
{l%U1%X1|lwz%U1%X1} %0,%1
{st%U0%X0|stw%U0%X0} %1,%0
fmr %0,%1
mt%0 %1
mt%0 %1
mf%1 %0
{cror 0,0,0|nop}
#
#"
[(set_attr "type" "*,load,store,fp,mtjmpr,*,mfjmpr,*,*,*")
(set_attr "length" "4,4,4,4,4,4,4,4,4,8")])
(define_insn "movsd_softfloat"
[(set (match_operand:SD 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,r,*h")
(match_operand:SD 1 "input_operand" "r,r,r,h,m,r,I,L,R,G,Fn,0"))]
"(gpc_reg_operand (operands[0], SDmode)
|| gpc_reg_operand (operands[1], SDmode))
&& (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
"@
mr %0,%1
mt%0 %1
mt%0 %1
mf%1 %0
{l%U1%X1|lwz%U1%X1} %0,%1
{st%U0%X0|stw%U0%X0} %1,%0
{lil|li} %0,%1
{liu|lis} %0,%v1
{cal|la} %0,%a1
#
#
{cror 0,0,0|nop}"
[(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*,*")
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,4")])
(define_insn "movsd_store"
[(set (match_operand:DD 0 "nonimmediate_operand" "=m")
(unspec:DD [(match_operand:SD 1 "input_operand" "f")]
UNSPEC_MOVSD_STORE))]
"(gpc_reg_operand (operands[0], DDmode)
|| gpc_reg_operand (operands[1], SDmode))
&& TARGET_HARD_FLOAT && TARGET_FPRS"
"stfd%U0%X0 %1,%0"
[(set_attr "type" "fpstore")
(set_attr "length" "4")])
(define_insn "movsd_load"
[(set (match_operand:SD 0 "nonimmediate_operand" "=f")
(unspec:SD [(match_operand:DD 1 "input_operand" "m")]
UNSPEC_MOVSD_LOAD))]
"(gpc_reg_operand (operands[0], SDmode)
|| gpc_reg_operand (operands[1], DDmode))
&& TARGET_HARD_FLOAT && TARGET_FPRS"
"lfd%U1%X1 %0,%1"
[(set_attr "type" "fpload")
(set_attr "length" "4")])
;; Hardware support for decimal floating point operations.
(define_insn "extendsddd2"
[(set (match_operand:DD 0 "gpc_reg_operand" "=f")
(float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))]
"TARGET_DFP"
"dctdp %0,%1"
[(set_attr "type" "fp")])
(define_expand "extendsdtd2"
[(set (match_operand:TD 0 "gpc_reg_operand" "=f")
(float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "f")))]
"TARGET_DFP"
{
rtx tmp = gen_reg_rtx (DDmode);
emit_insn (gen_extendsddd2 (tmp, operands[1]));
emit_insn (gen_extendddtd2 (operands[0], tmp));
DONE;
})
(define_insn "truncddsd2"
[(set (match_operand:SD 0 "gpc_reg_operand" "=f")
(float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "f")))]
"TARGET_DFP"
"drsp %0,%1"
[(set_attr "type" "fp")])
(define_expand "negdd2"
[(set (match_operand:DD 0 "gpc_reg_operand" "")
(neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
@ -309,7 +441,7 @@
(set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
; ld/std require word-aligned displacements -> 'Y' constraint.
; List Y->r and r->Y before r->r for reload.(define_insn "*movdd_hardfloat64"
; List Y->r and r->Y before r->r for reload.
(define_insn "*movdd_hardfloat64"
[(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r")
(match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]

View File

@ -103,6 +103,7 @@ extern void rs6000_fatal_bad_address (rtx);
extern rtx create_TOC_reference (rtx);
extern void rs6000_split_multireg_move (rtx, rtx);
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
extern rtx rs6000_secondary_memory_needed_rtx (enum machine_mode);
extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
int, int, int, int *);

View File

@ -53,6 +53,7 @@
#include "cfglayout.h"
#include "sched-int.h"
#include "tree-gimple.h"
#include "tree-flow.h"
#include "intl.h"
#include "params.h"
#include "tm-constrs.h"
@ -125,6 +126,10 @@ typedef struct machine_function GTY(())
/* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
varargs save area. */
HOST_WIDE_INT varargs_save_offset;
/* Temporary stack slot to use for SDmode copies. This slot is
64-bits wide and is allocated early enough so that the offset
does not overflow the 16-bit load/store offset field. */
rtx sdmode_stack_slot;
} machine_function;
/* Target cpu type */
@ -754,6 +759,8 @@ static void rs6000_elf_encode_section_info (tree, rtx, int)
ATTRIBUTE_UNUSED;
#endif
static bool rs6000_use_blocks_for_constant_p (enum machine_mode, const_rtx);
static void rs6000_alloc_sdmode_stack_slot (void);
static void rs6000_instantiate_decls (void);
#if TARGET_XCOFF
static void rs6000_xcoff_asm_output_anchor (rtx);
static void rs6000_xcoff_asm_globalize_label (FILE *, const char *);
@ -1221,6 +1228,12 @@ static const char alt_reg_names[][8] =
#undef TARGET_BUILTIN_RECIPROCAL
#define TARGET_BUILTIN_RECIPROCAL rs6000_builtin_reciprocal
#undef TARGET_EXPAND_TO_RTL_HOOK
#define TARGET_EXPAND_TO_RTL_HOOK rs6000_alloc_sdmode_stack_slot
#undef TARGET_INSTANTIATE_DECLS
#define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls
struct gcc_target targetm = TARGET_INITIALIZER;
@ -1240,7 +1253,6 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
return
((SCALAR_FLOAT_MODE_P (mode)
&& (mode != TDmode || (regno % 2) == 0)
&& mode != SDmode
&& FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
|| (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
@ -2460,13 +2472,16 @@ num_insns_constant (rtx op, enum machine_mode mode)
return num_insns_constant_wide (INTVAL (op));
case CONST_DOUBLE:
if (mode == SFmode)
if (mode == SFmode || mode == SDmode)
{
long l;
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_SINGLE (rv, l);
if (DECIMAL_FLOAT_MODE_P (mode))
REAL_VALUE_TO_TARGET_DECIMAL32 (rv, l);
else
REAL_VALUE_TO_TARGET_SINGLE (rv, l);
return num_insns_constant_wide ((HOST_WIDE_INT) l);
}
@ -4697,6 +4712,55 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
return;
}
if (reload_in_progress && cfun->machine->sdmode_stack_slot != NULL_RTX)
cfun->machine->sdmode_stack_slot =
eliminate_regs (cfun->machine->sdmode_stack_slot, VOIDmode, NULL_RTX);
if (reload_in_progress
&& mode == SDmode
&& MEM_P (operands[0])
&& rtx_equal_p (operands[0], cfun->machine->sdmode_stack_slot)
&& REG_P (operands[1]))
{
if (FP_REGNO_P (REGNO (operands[1])))
{
rtx mem = adjust_address_nv (operands[0], DDmode, 0);
mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
emit_insn (gen_movsd_store (mem, operands[1]));
}
else if (INT_REGNO_P (REGNO (operands[1])))
{
rtx mem = adjust_address_nv (operands[0], mode, 4);
mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
emit_insn (gen_movsd_hardfloat (mem, operands[1]));
}
else
gcc_unreachable();
return;
}
if (reload_in_progress
&& mode == SDmode
&& REG_P (operands[0])
&& MEM_P (operands[1])
&& rtx_equal_p (operands[1], cfun->machine->sdmode_stack_slot))
{
if (FP_REGNO_P (REGNO (operands[0])))
{
rtx mem = adjust_address_nv (operands[1], DDmode, 0);
mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
emit_insn (gen_movsd_load (operands[0], mem));
}
else if (INT_REGNO_P (REGNO (operands[0])))
{
rtx mem = adjust_address_nv (operands[1], mode, 4);
mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
emit_insn (gen_movsd_hardfloat (operands[0], mem));
}
else
gcc_unreachable();
return;
}
/* FIXME: In the long term, this switch statement should go away
and be replaced by a sequence of tests based on things like
mode == Pmode. */
@ -4717,6 +4781,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
case DFmode:
case DDmode:
case SFmode:
case SDmode:
if (CONSTANT_P (operands[1])
&& ! easy_fp_constant (operands[1], mode))
operands[1] = force_const_mem (mode, operands[1]);
@ -4929,7 +4994,6 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
/* Nonzero if we can use a floating-point register to pass this arg. */
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
(SCALAR_FLOAT_MODE_P (MODE) \
&& (MODE) != SDmode \
&& (CUM)->fregno <= FP_ARG_MAX_REG \
&& TARGET_HARD_FLOAT && TARGET_FPRS)
@ -5409,7 +5473,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
{
if (TARGET_HARD_FLOAT && TARGET_FPRS
&& (mode == SFmode || mode == DFmode
|| mode == DDmode || mode == TDmode
|| mode == SDmode || mode == DDmode || mode == TDmode
|| (mode == TFmode && !TARGET_IEEEQUAD)))
{
/* _Decimal128 must use an even/odd register pair. This assumes
@ -5476,7 +5540,6 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
cum->words = align_words + n_words;
if (SCALAR_FLOAT_MODE_P (mode)
&& mode != SDmode
&& TARGET_HARD_FLOAT && TARGET_FPRS)
{
/* _Decimal128 must be passed in an even/odd float register pair.
@ -5978,7 +6041,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (TARGET_HARD_FLOAT && TARGET_FPRS
&& (mode == SFmode || mode == DFmode
|| (mode == TFmode && !TARGET_IEEEQUAD)
|| mode == DDmode || mode == TDmode))
|| mode == SDmode || mode == DDmode || mode == TDmode))
{
/* _Decimal128 must use an even/odd register pair. This assumes
that the register number is odd when fregno is odd. */
@ -6652,6 +6715,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
&& (TYPE_MODE (type) == SFmode
|| TYPE_MODE (type) == DFmode
|| TYPE_MODE (type) == TFmode
|| TYPE_MODE (type) == SDmode
|| TYPE_MODE (type) == DDmode
|| TYPE_MODE (type) == TDmode))
{
@ -6660,7 +6724,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
n_reg = (size + 7) / 8;
sav_ofs = 8*4;
sav_scale = 8;
if (TYPE_MODE (type) != SFmode)
if (TYPE_MODE (type) != SFmode && TYPE_MODE (type) != SDmode)
align = 8;
}
else
@ -6724,6 +6788,11 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
u = build2 (MULT_EXPR, sizetype, u, size_int (sav_scale));
t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t, u);
/* _Decimal32 varargs are located in the second word of the 64-bit
FP register for 32-bit binaries. */
if (!TARGET_POWERPC64 && TYPE_MODE (type) == SDmode)
t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
gimplify_and_add (t, pre_p);
@ -11055,6 +11124,106 @@ mems_ok_for_quad_peep (rtx mem1, rtx mem2)
return 1;
}
rtx
rs6000_secondary_memory_needed_rtx (enum machine_mode mode)
{
static bool eliminated = false;
if (mode != SDmode)
return assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
else
{
rtx mem = cfun->machine->sdmode_stack_slot;
gcc_assert (mem != NULL_RTX);
if (!eliminated)
{
mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
cfun->machine->sdmode_stack_slot = mem;
eliminated = true;
}
return mem;
}
}
static tree
rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
{
/* Don't walk into types. */
if (*tp == NULL_TREE || *tp == error_mark_node || TYPE_P (*tp))
{
*walk_subtrees = 0;
return NULL_TREE;
}
switch (TREE_CODE (*tp))
{
case VAR_DECL:
case PARM_DECL:
case FIELD_DECL:
case RESULT_DECL:
case REAL_CST:
if (TYPE_MODE (TREE_TYPE (*tp)) == SDmode)
return *tp;
break;
default:
break;
}
return NULL_TREE;
}
/* Allocate a 64-bit stack slot to be used for copying SDmode
values through if this function has any SDmode references. */
static void
rs6000_alloc_sdmode_stack_slot (void)
{
tree t;
basic_block bb;
block_stmt_iterator bsi;
gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX);
FOR_EACH_BB (bb)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree ret = walk_tree_without_duplicates (bsi_stmt_ptr (bsi),
rs6000_check_sdmode, NULL);
if (ret)
{
rtx stack = assign_stack_local (DDmode, GET_MODE_SIZE (DDmode), 0);
cfun->machine->sdmode_stack_slot = adjust_address_nv (stack,
SDmode, 0);
return;
}
}
/* Check for any SDmode parameters of the function. */
for (t = DECL_ARGUMENTS (cfun->decl); t; t = TREE_CHAIN (t))
{
if (TREE_TYPE (t) == error_mark_node)
continue;
if (TYPE_MODE (TREE_TYPE (t)) == SDmode
|| TYPE_MODE (DECL_ARG_TYPE (t)) == SDmode)
{
rtx stack = assign_stack_local (DDmode, GET_MODE_SIZE (DDmode), 0);
cfun->machine->sdmode_stack_slot = adjust_address_nv (stack,
SDmode, 0);
return;
}
}
}
static void
rs6000_instantiate_decls (void)
{
if (cfun->machine->sdmode_stack_slot != NULL_RTX)
instantiate_decl_rtl (cfun->machine->sdmode_stack_slot);
}
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
@ -11115,7 +11284,7 @@ rs6000_secondary_reload_class (enum reg_class class,
/* Constants, memory, and FP registers can go into FP registers. */
if ((regno == -1 || FP_REGNO_P (regno))
&& (class == FLOAT_REGS || class == NON_SPECIAL_REGS))
return NO_REGS;
return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
/* Memory, and AltiVec registers can go into AltiVec registers. */
if ((regno == -1 || ALTIVEC_REGNO_P (regno))
@ -16727,6 +16896,7 @@ rs6000_output_function_epilogue (FILE *file,
switch (mode)
{
case SFmode:
case SDmode:
bits = 0x2;
break;
@ -21513,29 +21683,9 @@ rs6000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
|| POINTER_TYPE_P (valtype))
mode = TARGET_32BIT ? SImode : DImode;
if (DECIMAL_FLOAT_MODE_P (mode))
{
if (TARGET_HARD_FLOAT && TARGET_FPRS)
{
switch (mode)
{
default:
gcc_unreachable ();
case SDmode:
regno = GP_ARG_RETURN;
break;
case DDmode:
regno = FP_ARG_RETURN;
break;
case TDmode:
/* Use f2:f3 specified by the ABI. */
regno = FP_ARG_RETURN + 1;
break;
}
}
else
regno = GP_ARG_RETURN;
}
if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
/* _Decimal128 must use an even/odd register pair. */
regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS)
regno = FP_ARG_RETURN;
else if (TREE_CODE (valtype) == COMPLEX_TYPE
@ -21576,29 +21726,9 @@ rs6000_libcall_value (enum machine_mode mode)
GEN_INT (4))));
}
if (DECIMAL_FLOAT_MODE_P (mode))
{
if (TARGET_HARD_FLOAT && TARGET_FPRS)
{
switch (mode)
{
default:
gcc_unreachable ();
case SDmode:
regno = GP_ARG_RETURN;
break;
case DDmode:
regno = FP_ARG_RETURN;
break;
case TDmode:
/* Use f2:f3 specified by the ABI. */
regno = FP_ARG_RETURN + 1;
break;
}
}
else
regno = GP_ARG_RETURN;
}
if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
/* _Decimal128 must use an even/odd register pair. */
regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
else if (SCALAR_FLOAT_MODE_P (mode)
&& TARGET_HARD_FLOAT && TARGET_FPRS)
regno = FP_ARG_RETURN;

View File

@ -622,7 +622,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \
(STRICT_ALIGNMENT \
|| (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \
|| (MODE) == DDmode || (MODE) == TDmode \
|| (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode \
|| (MODE) == DImode) \
&& (ALIGN) < 32))
@ -1173,6 +1173,13 @@ enum reg_class
|| (CLASS1) == ALTIVEC_REGS \
|| (CLASS2) == ALTIVEC_REGS))
/* For cpus that cannot load/store SDmode values from the 64-bit
FP registers without using a full 64-bit load/store, we need
to allocate a full 64-bit stack slot for them. */
#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
rs6000_secondary_memory_needed_rtx (MODE)
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.

View File

@ -1502,6 +1502,20 @@ Returns true if the target supports decimal floating point.
Returns true if the target supports fixed-point arithmetic.
@end deftypefn
@deftypefn {Target Hook} void TARGET_EXPAND_TO_RTL_HOOK (void)
This hook is called just before expansion into rtl, allowing the target
to perform additional initializations or analysis before the expansion.
For example, the rs6000 port uses it to allocate a scratch stack slot
for use in copying SDmode values between memory and floating point
registers whenever the function being expanded has any SDmode
usage.
@end deftypefn
@deftypefn {Target Hook} void TARGET_INSTANTIATE_DECLS (void)
This hook allows the backend to perform additional instantiations on rtl
that are not actually in any insns yet, but will be later.
@end deftypefn
@deftypefn {Target Hook} {const char *} TARGET_MANGLE_TYPE (tree @var{type})
If your target defines any fundamental types, or any types your target
uses should be mangled differently from the default, define this hook

View File

@ -1568,8 +1568,8 @@ instantiate_virtual_regs_in_insn (rtx insn)
/* Subroutine of instantiate_decls. Given RTL representing a decl,
do any instantiation required. */
static void
instantiate_decl (rtx x)
void
instantiate_decl_rtl (rtx x)
{
rtx addr;
@ -1579,8 +1579,8 @@ instantiate_decl (rtx x)
/* If this is a CONCAT, recurse for the pieces. */
if (GET_CODE (x) == CONCAT)
{
instantiate_decl (XEXP (x, 0));
instantiate_decl (XEXP (x, 1));
instantiate_decl_rtl (XEXP (x, 0));
instantiate_decl_rtl (XEXP (x, 1));
return;
}
@ -1610,7 +1610,7 @@ instantiate_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
{
*walk_subtrees = 0;
if (DECL_P (t) && DECL_RTL_SET_P (t))
instantiate_decl (DECL_RTL (t));
instantiate_decl_rtl (DECL_RTL (t));
}
return NULL;
}
@ -1626,7 +1626,7 @@ instantiate_decls_1 (tree let)
for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
{
if (DECL_RTL_SET_P (t))
instantiate_decl (DECL_RTL (t));
instantiate_decl_rtl (DECL_RTL (t));
if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
{
tree v = DECL_VALUE_EXPR (t);
@ -1650,8 +1650,8 @@ instantiate_decls (tree fndecl)
/* Process all parameters of the function. */
for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
{
instantiate_decl (DECL_RTL (decl));
instantiate_decl (DECL_INCOMING_RTL (decl));
instantiate_decl_rtl (DECL_RTL (decl));
instantiate_decl_rtl (DECL_INCOMING_RTL (decl));
if (DECL_HAS_VALUE_EXPR_P (decl))
{
tree v = DECL_VALUE_EXPR (decl);
@ -1715,6 +1715,8 @@ instantiate_virtual_regs (void)
/* Instantiate the virtual registers in the DECLs for debugging purposes. */
instantiate_decls (current_function_decl);
targetm.instantiate_decls ();
/* Indicate that, from now on, assign_stack_local should use
frame_pointer_rtx. */
virtuals_instantiated = 1;

View File

@ -491,6 +491,7 @@ extern int trampolines_created;
extern void set_cfun (struct function *new_cfun);
extern void push_cfun (struct function *new_cfun);
extern void pop_cfun (void);
extern void instantiate_decl_rtl (rtx x);
/* For backward compatibility... eventually these should all go away. */
#define current_function_pops_args (cfun->pops_args)

View File

@ -604,6 +604,14 @@
#define TARGET_SECONDARY_RELOAD default_secondary_reload
#endif
#ifndef TARGET_EXPAND_TO_RTL_HOOK
#define TARGET_EXPAND_TO_RTL_HOOK hook_void_void
#endif
#ifndef TARGET_INSTANTIATE_DECLS
#define TARGET_INSTANTIATE_DECLS hook_void_void
#endif
/* C specific. */
#ifndef TARGET_C_MODE_FOR_SUFFIX
#define TARGET_C_MODE_FOR_SUFFIX default_mode_for_suffix
@ -771,6 +779,8 @@
TARGET_INVALID_UNARY_OP, \
TARGET_INVALID_BINARY_OP, \
TARGET_SECONDARY_RELOAD, \
TARGET_EXPAND_TO_RTL_HOOK, \
TARGET_INSTANTIATE_DECLS, \
TARGET_C, \
TARGET_CXX, \
TARGET_EXTRA_LIVE_ON_ENTRY, \

View File

@ -849,6 +849,15 @@ struct gcc_target
enum machine_mode,
struct secondary_reload_info *);
/* This target hook allows the backend to perform additional
processing while initializing for variable expansion. */
void (* expand_to_rtl_hook) (void);
/* This target hook allows the backend to perform additional
instantiations on rtx that are not actually in insns yet,
but will be later. */
void (* instantiate_decls) (void);
/* Functions specific to the C family of frontends. */
struct c {
/* Return machine mode for non-standard suffix