[PATCH][updated] Force SDmode function args into FP registers per the ABI
Paolo Bonzini
bonzini@gnu.org
Tue Jun 19 07:31:00 GMT 2007
Peter Bergner wrote:
> On Tue, Jun 12, 2007 at 12:34:59PM -0700, Mark Mitchell wrote:
>> Peter Bergner wrote:
>>> So something along the lines of the totally untested/compiled code below?
>>> If so, I'll bootstrap and regtest the changes along with the rs6000 portion
>>> of the patch and resubmit with ChangeLog.
>> Yes, that's exactly what I had in mind.
>
> Ok, here's an updated patch that uses the target hook. Note that instead
> of min_stack_slot_size_for_reg like we talked about, I implemented
> min_stack_slot_size_for_mode which allowed me to use the target hook within
> the rs6000 files where we have the mode, but no reg. This passed bootstrap
> and regtesting. Is this ok for mainline after the freeze?
>
> Peter
>
> * targhooks.c (default_min_stack_slot_size_for_mode): New default
> target hook.
> * targhooks.h (default_min_stack_slot_size_for_mode): Add prototype.
> * target.h (struct gcc_target): Add min_stack_slot_size_for_mode.
> * target-def.h (TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE): Define as
> default_min_stack_slot_size_for_mode.
> (TARGET_INITIALIZER): Initialize min_stack_slot_size_for_mode with
> TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE.
> * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Treat SDmode
> similar to the other floating point modes.
> (num_insns_constant): Likewise.
> (function_arg_advance): Likewise.
> (function_arg): Likewise.
> (rs6000_output_function_epilogue): Likewise.
> (rs6000_function_value): Likewise. Simplify code.
> (rs6000_libcall_value): Likewise.
> (rs6000_gimplify_va_arg): Treat SDmode similar to the other floating
> point modes. Handle 32-bit mode SDmode varargs.
> (rs6000_emit_move): Treat SDmode similar to the other floating point
> modes. Force SDmode MEM to MEM copies through the integer registers.
> (rs6000_min_stack_slot_size_for_mode): New function.
> (TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE): Use it.
> * config/rs6000/rs6000.h (SLOW_UNALIGNED_ACCESS): Treat SDmode
> similar to the other floating point modes.
> (SECONDARY_MEMORY_NEEDED): Handle SDmode.
> (SECONDARY_MEMORY_NEEDED_RTX): Define.
> * config/rs6000/dfp.md (movsd): New define_expand and splitter.
> (movsd_hardfloat, movsd_softfloat, movsd_store, movsd_load):
> New define_insn's.
> (movdd_hardfloat64): Fixup comment.
> * config/rs6000/rs6000.md (UNSPEC_MOVSD_LOAD): New constant.
> (UNSPEC_MOVSD_STORE): Likewise.
> * reload1.c (alter_reg): Use new min_stack_slot_size_for_mode target
> hook.
>
> Index: targhooks.c
> ===================================================================
> --- targhooks.c (revision 125765)
> +++ targhooks.c (working copy)
> @@ -633,4 +633,13 @@ tree default_mangle_decl_assembler_name
> return id;
> }
>
> +/* By default, the stack slot size used to hold a reg of mode MODE is
> + equal to its mode size. */
> +
> +unsigned int
> +default_min_stack_slot_size_for_mode (enum machine_mode mode)
> +{
> + return GET_MODE_SIZE (mode);
> +}
> +
> #include "gt-targhooks.h"
> Index: targhooks.h
> ===================================================================
> --- targhooks.h (revision 125765)
> +++ targhooks.h (working copy)
> @@ -86,3 +86,4 @@ extern void hook_void_bitmap (bitmap);
> extern bool default_handle_c_option (size_t, const char *, int);
> extern int default_reloc_rw_mask (void);
> extern tree default_mangle_decl_assembler_name (tree, tree);
> +extern unsigned int default_min_stack_slot_size_for_mode (enum machine_mode);
> Index: target.h
> ===================================================================
> --- target.h (revision 125765)
> +++ target.h (working copy)
> @@ -798,6 +798,9 @@ struct gcc_target
> enum machine_mode,
> struct secondary_reload_info *);
>
> + /* Return the size in bytes required to hold MODE on the stack. */
> + unsigned int (* min_stack_slot_size_for_mode) (enum machine_mode mode);
> +
> /* Functions specific to the C++ frontend. */
> struct cxx {
> /* Return the integer type used for guard variables. */
> Index: target-def.h
> ===================================================================
> --- target-def.h (revision 125765)
> +++ target-def.h (working copy)
> @@ -578,6 +578,9 @@ Foundation, 51 Franklin Street, Fifth Fl
> #define TARGET_SECONDARY_RELOAD default_secondary_reload
> #endif
>
> +#ifndef TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE
> +#define TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE default_min_stack_slot_size_for_mode
> +#endif
>
> /* C++ specific. */
> #ifndef TARGET_CXX_GUARD_TYPE
> @@ -729,6 +732,7 @@ Foundation, 51 Franklin Street, Fifth Fl
> TARGET_INVALID_UNARY_OP, \
> TARGET_INVALID_BINARY_OP, \
> TARGET_SECONDARY_RELOAD, \
> + TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE, \
> TARGET_CXX, \
> TARGET_EXTRA_LIVE_ON_ENTRY, \
> TARGET_UNWIND_TABLES_DEFAULT, \
> Index: config/rs6000/rs6000.c
> ===================================================================
> --- config/rs6000/rs6000.c (revision 125765)
> +++ config/rs6000/rs6000.c (working copy)
> @@ -666,6 +666,7 @@ static void rs6000_elf_encode_section_in
> ATTRIBUTE_UNUSED;
> #endif
> static bool rs6000_use_blocks_for_constant_p (enum machine_mode, rtx);
> +static unsigned int rs6000_min_stack_slot_size_for_mode (enum machine_mode);
> #if TARGET_XCOFF
> static void rs6000_xcoff_asm_output_anchor (rtx);
> static void rs6000_xcoff_asm_globalize_label (FILE *, const char *);
> @@ -1115,6 +1116,9 @@ static const char alt_reg_names[][8] =
> #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
> #define TARGET_USE_BLOCKS_FOR_CONSTANT_P rs6000_use_blocks_for_constant_p
>
> +#undef TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE
> +#define TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE rs6000_min_stack_slot_size_for_mode
> +
> struct gcc_target targetm = TARGET_INITIALIZER;
>
>
> @@ -1134,7 +1138,6 @@ rs6000_hard_regno_mode_ok (int regno, en
> 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);
> @@ -2290,13 +2293,16 @@ num_insns_constant (rtx op, enum machine
> 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);
> }
>
> @@ -4273,6 +4279,21 @@ rs6000_emit_move (rtx dest, rtx source,
> return;
> }
>
> + /* Force SDmode MEM to MEM copies to go through the integer registers
> + since non POWER6 hardware cannot load 32-bit quantities into the
> + FP registers without munging the bits. */
> + if (mode == SDmode
> + && TARGET_HARD_FLOAT && TARGET_FPRS
> + && GET_CODE (operands[0]) == MEM
> + && GET_CODE (operands[1]) == MEM
> + && ! MEM_VOLATILE_P (operands [0])
> + && ! MEM_VOLATILE_P (operands [1]))
> + {
> + emit_move_insn (adjust_address (operands[0], SImode, 0),
> + adjust_address (operands[1], SImode, 0));
> + return;
> + }
> +
> if (!no_new_pseudos && GET_CODE (operands[0]) == MEM
> && !gpc_reg_operand (operands[1], mode))
> operands[1] = force_reg (mode, operands[1]);
> @@ -4375,6 +4396,7 @@ rs6000_emit_move (rtx dest, rtx source,
> 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]);
> @@ -4585,7 +4607,6 @@ rs6000_emit_move (rtx dest, rtx source,
> /* 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)
>
> @@ -5065,7 +5086,7 @@ function_arg_advance (CUMULATIVE_ARGS *c
> {
> 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
> @@ -5131,7 +5152,6 @@ function_arg_advance (CUMULATIVE_ARGS *c
> 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.
> @@ -5630,7 +5650,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum
> 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. */
> @@ -6303,6 +6323,7 @@ rs6000_gimplify_va_arg (tree valist, tre
> && (TYPE_MODE (type) == SFmode
> || TYPE_MODE (type) == DFmode
> || TYPE_MODE (type) == TFmode
> + || TYPE_MODE (type) == SDmode
> || TYPE_MODE (type) == DDmode
> || TYPE_MODE (type) == TDmode))
> {
> @@ -6311,7 +6332,7 @@ rs6000_gimplify_va_arg (tree valist, tre
> 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
> @@ -6374,6 +6395,11 @@ rs6000_gimplify_va_arg (tree valist, tre
> 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);
>
> @@ -16003,6 +16029,7 @@ rs6000_output_function_epilogue (FILE *f
> switch (mode)
> {
> case SFmode:
> + case SDmode:
> bits = 0x2;
> break;
>
> @@ -19115,6 +19142,18 @@ rs6000_use_blocks_for_constant_p (enum m
> {
> return !ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode);
> }
> +
> +/* Implement TARGET_MIN_STACK_SLOT_SIZE_FOR_MODE. */
> +
> +static unsigned int
> +rs6000_min_stack_slot_size_for_mode (enum machine_mode mode)
> +{
> + if (mode == SDmode)
> + return GET_MODE_SIZE (DDmode);
> +
> + return GET_MODE_SIZE (mode);
> +}
> +
>
> /* Return a REG that occurs in ADDR with coefficient 1.
> ADDR can be effectively incremented by incrementing REG.
> @@ -20652,29 +20691,9 @@ rs6000_function_value (tree valtype, tre
> || 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
> @@ -20715,29 +20734,9 @@ rs6000_libcall_value (enum machine_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;
> Index: config/rs6000/rs6000.h
> ===================================================================
> --- config/rs6000/rs6000.h (revision 125765)
> +++ config/rs6000/rs6000.h (working copy)
> @@ -590,7 +590,7 @@ extern enum rs6000_nop_insertion rs6000_
> #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))
>
> @@ -1151,7 +1151,15 @@ enum reg_class
> && (MODE != DDmode) \
> && (MODE != DImode)))) \
> || (CLASS1) == ALTIVEC_REGS \
> - || (CLASS2) == ALTIVEC_REGS))
> + || (CLASS2) == ALTIVEC_REGS \
> + || (MODE) == SDmode))
> +
> +/* 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) \
> + assign_stack_local (MODE, targetm.min_stack_slot_size_for_mode (MODE), 0)
>
> /* Return the maximum number of consecutive registers
> needed to represent mode MODE in a register of class CLASS.
> @@ -1171,6 +1179,7 @@ enum reg_class
> (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
> ? ((GET_MODE_SIZE (FROM) < 8 || GET_MODE_SIZE (TO) < 8 \
> || TARGET_IEEEQUAD) \
> + && (FROM != SDmode || TO != DDmode || CLASS != FLOAT_REGS) \
> && reg_classes_intersect_p (FLOAT_REGS, CLASS)) \
> : (((TARGET_E500_DOUBLE \
> && ((((TO) == DFmode) + ((FROM) == DFmode)) == 1 \
> Index: config/rs6000/dfp.md
> ===================================================================
> --- config/rs6000/dfp.md (revision 125765)
> +++ config/rs6000/dfp.md (working copy)
> @@ -21,6 +21,189 @@
> ;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
> ;; MA 02110-1301, USA.
>
> +(define_expand "movsd"
> + [(set (match_operand:SD 0 "nonimmediate_operand" "")
> + (match_operand:SD 1 "any_operand" ""))]
> + "TARGET_HARD_FLOAT && TARGET_FPRS && !no_new_pseudos"
> + "
> +{
> + if (no_new_pseudos)
> + FAIL;
> + else if (MEM_P (operands[0]) && REG_P (operands[1]))
> + {
> + rtx intreg = gen_reg_rtx (SImode);
> + rtx stack = assign_stack_temp (DDmode, GET_MODE_SIZE (DDmode), 0);
> + rtx dst = adjust_address (operands[0], SImode, 0);
> + emit_insn (gen_movsd_store (stack, operands[1]));
> + emit_move_insn (intreg, adjust_address (stack, SImode, 4));
> + emit_move_insn (dst, intreg);
> + DONE;
> + }
> + else if (REG_P (operands[0]) && MEM_P (operands[1]))
> + {
> + rtx intreg = gen_reg_rtx (SImode);
> + rtx stack = assign_stack_temp (DDmode, GET_MODE_SIZE (DDmode), 0);
> + rtx src = adjust_address (operands[1], SImode, 0);
> + emit_move_insn (intreg, src);
> + emit_move_insn (adjust_address (stack, SImode, 4), intreg);
> + emit_insn (gen_movsd_load (operands[0], stack));
> + DONE;
> + }
> + else if (MEM_P (operands[0]) && MEM_P (operands[1]))
> + {
> + rtx src = adjust_address (operands[1], SImode, 0);
> + rtx dst = adjust_address (operands[0], SImode, 0);
> + emit_move_insn (dst, src);
> + DONE;
> + }
> + else if (GET_CODE (operands[0]) == SUBREG
> + && GET_CODE (SUBREG_REG (operands[0])) == REG)
> + {
> + rtx dst = SUBREG_REG (operands[0]);
> + enum machine_mode mode = GET_MODE (dst);
> +
> + if (MEM_P (operands[1]))
> + {
> + rtx src = adjust_address (operands[1], mode, 0);
> + emit_move_insn (dst, src);
> + }
> + else if (GET_CODE (operands[1]) == SUBREG
> + && GET_CODE (SUBREG_REG (operands[1])) == REG
> + && mode == GET_MODE (SUBREG_REG (operands[1])))
> + {
> + rtx src = SUBREG_REG (operands[1]);
> + emit_move_insn (dst, src);
> + }
> + else
> + {
> + rtx stack = assign_stack_temp (DDmode, GET_MODE_SIZE (DDmode), 0);
> + emit_insn (gen_movsd_store (stack, operands[1]));
> + emit_move_insn (dst, adjust_address (stack, SImode, 4));
> + }
> + DONE;
> + }
> + else if (GET_CODE (operands[1]) == SUBREG
> + && GET_CODE (SUBREG_REG (operands[1])) == REG)
> + {
> + rtx src = SUBREG_REG (operands[1]);
> + enum machine_mode mode = GET_MODE (src);
> +
> + if (MEM_P (operands[0]))
> + {
> + rtx dst = adjust_address (operands[0], mode, 0);
> + emit_move_insn (dst, src);
> + }
> + else
> + {
> + rtx stack = assign_stack_temp (DDmode, GET_MODE_SIZE (DDmode), 0);
> + emit_move_insn (adjust_address (stack, SImode, 4), src);
> + emit_insn (gen_movsd_load (operands[0], stack));
> + }
> + DONE;
> + }
> + else if (REG_P (operands[0]) && REGNO (operands[0]) <= 31
> + && REG_P (operands[1]) && REGNO (operands[1]) > 31)
> + {
> + rtx subreg = simplify_gen_subreg (SImode, operands[0], SDmode, 0);
> + rtx stack = assign_stack_temp (DDmode, GET_MODE_SIZE (DDmode), 0);
> + emit_insn (gen_movsd_store (stack, operands[1]));
> + emit_move_insn (subreg, adjust_address (stack, SImode, 4));
> + DONE;
> + }
> + else
> + 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")])
> +
> (define_expand "negdd2"
> [(set (match_operand:DD 0 "gpc_reg_operand" "")
> (neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
> @@ -310,7 +493,7 @@ (define_insn "*movdd_hardfloat64_mfpgpr"
> (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"))]
> Index: config/rs6000/rs6000.md
> ===================================================================
> --- config/rs6000/rs6000.md (revision 125765)
> +++ config/rs6000/rs6000.md (working copy)
> @@ -72,6 +72,8 @@ (define_constants
> (UNSPEC_DLMZB 45)
> (UNSPEC_DLMZB_CR 46)
> (UNSPEC_DLMZB_STRLEN 47)
> + (UNSPEC_MOVSD_LOAD 48)
> + (UNSPEC_MOVSD_STORE 49)
> ])
>
> ;;
> Index: reload1.c
> ===================================================================
> --- reload1.c (revision 125765)
> +++ reload1.c (working copy)
> @@ -2063,7 +2063,9 @@ alter_reg (int i, int from_reg)
> enum machine_mode mode = GET_MODE (regno_reg_rtx[i]);
> unsigned int inherent_size = PSEUDO_REGNO_BYTES (i);
> unsigned int inherent_align = GET_MODE_ALIGNMENT (mode);
> - unsigned int total_size = MAX (inherent_size, reg_max_ref_width[i]);
> + unsigned int total_size =
> + MAX (targetm.min_stack_slot_size_for_mode (mode),
> + reg_max_ref_width[i]);
> unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
> int adjust = 0;
This can be simplified to be just
enum machine_mode mode = PSEUDO_REGNO_MODE (i);
unsigned int inherent_size = targetm.min_stack_slot_size_for_mode (mode);
unsigned int total_size = MAX (inherent_size, reg_max_ref_width[i]);
because of these definitions
/* this is exactly how mode is computed above */
#define PSEUDO_REGNO_MODE(N) GET_MODE (regno_reg_rtx[N])
/* this is exactly the default definition of the hook. */
#define PSEUDO_REGNO_BYTES(N) \
GET_MODE_SIZE (PSEUDO_REGNO_MODE (N))
Sorry for the further nitpicking... I can take care of this, but I
wouldn't mind preapproval since this was what Mark mentioned here:
> The
> default would be PSEUDO_REGNO_BYTES (REGNO (reg)). Then, in alter reg,
> use the max of reg_max_ref_width and the value of the hook?
The patch would only touch reload1.c.
Paolo
More information about the Gcc-patches
mailing list