mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-01 07:44:05 +08:00
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:
parent
6f536f74ed
commit
e41b2a33b3
@ -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
|
||||
|
@ -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 ();
|
||||
|
||||
|
@ -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"))]
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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, \
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user