[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