Commit bb12a72a by David S. Miller Committed by David S. Miller

Add support for sparc VIS3 fp<-->int moves.

	* config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED): We can move
	between float and non-float regs when VIS3.
	* config/sparc/sparc.c (eligible_for_restore_insn): We can't
	use a restore when the source is a float register.
	(sparc_split_regreg_legitimate): When VIS3 allow moves between
	float and integer regs.
	(sparc_register_move_cost): Adjust to account for VIS3 moves.
	(sparc_preferred_reload_class): On 32-bit with VIS3 when moving an
	integer reg to a class containing EXTRA_FP_REGS, constrain to
	FP_REGS.
	(sparc_secondary_reload): On 32-bit with VIS3 when moving between
	float and integer regs we sometimes need a FP_REGS class
	intermediate move to satisfy the reload.  When this happens
	specify an extra cost of 2.
	(*movsi_insn): Rename to have "_novis3" suffix and add !VIS3
	guard.
	(*movdi_insn_sp32_v9): Likewise.
	(*movdi_insn_sp64): Likewise.
	(*movsf_insn): Likewise.
	(*movdf_insn_sp32_v9): Likewise.
	(*movdf_insn_sp64): Likewise.
	(*zero_extendsidi2_insn_sp64): Likewise.
	(*sign_extendsidi2_insn): Likewise.
	(*movsi_insn_vis3): New insn.
	(*movdi_insn_sp32_v9_vis3): New insn.
	(*movdi_insn_sp64_vis3): New insn.
	(*movsf_insn_vis3): New insn.
	(*movdf_insn_sp32_v9_vis3): New insn.
	(*movdf_insn_sp64_vis3): New insn.
	(*zero_extendsidi2_insn_sp64_vis3): New insn.
	(*sign_extendsidi2_insn_vis3): New insn.
	(TFmode reg/reg split): Make sure both REG operands are float.
	(*mov<VM32:mode>_insn): Add "_novis3" suffix and !VIS3 guard. Remove
	easy constant to integer reg alternatives.
	(*mov<VM64:mode>_insn_sp64): Likewise.
	(*mov<VM64:mode>_insn_sp32_novis3): Likewise.
	(*mov<VM32:mode>_insn_vis3): New insn.
	(*mov<VM64:mode>_insn_sp64_vis3): New insn.
	(*mov<VM64:mode>_insn_sp32_vis3): New insn.
	(VM64 reg<-->reg split): New spliiter for 32-bit.

From-SVN: r180360
parent ec8ab7c4
2011-10-23 David S. Miller <davem@davemloft.net> 2011-10-23 David S. Miller <davem@davemloft.net>
* config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED): We can move
between float and non-float regs when VIS3.
* config/sparc/sparc.c (eligible_for_restore_insn): We can't
use a restore when the source is a float register.
(sparc_split_regreg_legitimate): When VIS3 allow moves between
float and integer regs.
(sparc_register_move_cost): Adjust to account for VIS3 moves.
(sparc_preferred_reload_class): On 32-bit with VIS3 when moving an
integer reg to a class containing EXTRA_FP_REGS, constrain to
FP_REGS.
(sparc_secondary_reload): On 32-bit with VIS3 when moving between
float and integer regs we sometimes need a FP_REGS class
intermediate move to satisfy the reload. When this happens
specify an extra cost of 2.
(*movsi_insn): Rename to have "_novis3" suffix and add !VIS3
guard.
(*movdi_insn_sp32_v9): Likewise.
(*movdi_insn_sp64): Likewise.
(*movsf_insn): Likewise.
(*movdf_insn_sp32_v9): Likewise.
(*movdf_insn_sp64): Likewise.
(*zero_extendsidi2_insn_sp64): Likewise.
(*sign_extendsidi2_insn): Likewise.
(*movsi_insn_vis3): New insn.
(*movdi_insn_sp32_v9_vis3): New insn.
(*movdi_insn_sp64_vis3): New insn.
(*movsf_insn_vis3): New insn.
(*movdf_insn_sp32_v9_vis3): New insn.
(*movdf_insn_sp64_vis3): New insn.
(*zero_extendsidi2_insn_sp64_vis3): New insn.
(*sign_extendsidi2_insn_vis3): New insn.
(TFmode reg/reg split): Make sure both REG operands are float.
(*mov<VM32:mode>_insn): Add "_novis3" suffix and !VIS3 guard. Remove
easy constant to integer reg alternatives.
(*mov<VM64:mode>_insn_sp64): Likewise.
(*mov<VM64:mode>_insn_sp32_novis3): Likewise.
(*mov<VM32:mode>_insn_vis3): New insn.
(*mov<VM64:mode>_insn_sp64_vis3): New insn.
(*mov<VM64:mode>_insn_sp32_vis3): New insn.
(VM64 reg<-->reg split): New spliiter for 32-bit.
* config/sparc/sparc.c (sparc_split_regreg_legitimate): New * config/sparc/sparc.c (sparc_split_regreg_legitimate): New
function. function.
* config/sparc/sparc-protos.h (sparc_split_regreg_legitimate): * config/sparc/sparc-protos.h (sparc_split_regreg_legitimate):
...@@ -2996,10 +2996,23 @@ eligible_for_restore_insn (rtx trial, bool return_p) ...@@ -2996,10 +2996,23 @@ eligible_for_restore_insn (rtx trial, bool return_p)
{ {
rtx pat = PATTERN (trial); rtx pat = PATTERN (trial);
rtx src = SET_SRC (pat); rtx src = SET_SRC (pat);
bool src_is_freg = false;
rtx src_reg;
/* Since we now can do moves between float and integer registers when
VIS3 is enabled, we have to catch this case. We can allow such
moves when doing a 'return' however. */
src_reg = src;
if (GET_CODE (src_reg) == SUBREG)
src_reg = SUBREG_REG (src_reg);
if (GET_CODE (src_reg) == REG
&& SPARC_FP_REG_P (REGNO (src_reg)))
src_is_freg = true;
/* The 'restore src,%g0,dest' pattern for word mode and below. */ /* The 'restore src,%g0,dest' pattern for word mode and below. */
if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
&& arith_operand (src, GET_MODE (src))) && arith_operand (src, GET_MODE (src))
&& ! src_is_freg)
{ {
if (TARGET_ARCH64) if (TARGET_ARCH64)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode); return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
...@@ -3009,7 +3022,8 @@ eligible_for_restore_insn (rtx trial, bool return_p) ...@@ -3009,7 +3022,8 @@ eligible_for_restore_insn (rtx trial, bool return_p)
/* The 'restore src,%g0,dest' pattern for double-word mode. */ /* The 'restore src,%g0,dest' pattern for double-word mode. */
else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
&& arith_double_operand (src, GET_MODE (src))) && arith_double_operand (src, GET_MODE (src))
&& ! src_is_freg)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode); return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
/* The 'restore src,%g0,dest' pattern for float if no FPU. */ /* The 'restore src,%g0,dest' pattern for float if no FPU. */
...@@ -7784,6 +7798,13 @@ sparc_split_regreg_legitimate (rtx reg1, rtx reg2) ...@@ -7784,6 +7798,13 @@ sparc_split_regreg_legitimate (rtx reg1, rtx reg2)
if (SPARC_INT_REG_P (regno1) && SPARC_INT_REG_P (regno2)) if (SPARC_INT_REG_P (regno1) && SPARC_INT_REG_P (regno2))
return 1; return 1;
if (TARGET_VIS3)
{
if ((SPARC_INT_REG_P (regno1) && SPARC_FP_REG_P (regno2))
|| (SPARC_FP_REG_P (regno1) && SPARC_INT_REG_P (regno2)))
return 1;
}
return 0; return 0;
} }
...@@ -10302,10 +10323,28 @@ static int ...@@ -10302,10 +10323,28 @@ static int
sparc_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, sparc_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
reg_class_t from, reg_class_t to) reg_class_t from, reg_class_t to)
{ {
if ((FP_REG_CLASS_P (from) && general_or_i64_p (to)) bool need_memory = false;
|| (general_or_i64_p (from) && FP_REG_CLASS_P (to))
|| from == FPCC_REGS if (from == FPCC_REGS || to == FPCC_REGS)
|| to == FPCC_REGS) need_memory = true;
else if ((FP_REG_CLASS_P (from) && general_or_i64_p (to))
|| (general_or_i64_p (from) && FP_REG_CLASS_P (to)))
{
if (TARGET_VIS3)
{
int size = GET_MODE_SIZE (mode);
if (size == 8 || size == 4)
{
if (! TARGET_ARCH32 || size == 4)
return 4;
else
return 6;
}
}
need_memory = true;
}
if (need_memory)
{ {
if (sparc_cpu == PROCESSOR_ULTRASPARC if (sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_ULTRASPARC3 || sparc_cpu == PROCESSOR_ULTRASPARC3
...@@ -11163,6 +11202,18 @@ sparc_preferred_reload_class (rtx x, reg_class_t rclass) ...@@ -11163,6 +11202,18 @@ sparc_preferred_reload_class (rtx x, reg_class_t rclass)
} }
} }
if (TARGET_VIS3
&& ! TARGET_ARCH64
&& (rclass == EXTRA_FP_REGS
|| rclass == GENERAL_OR_EXTRA_FP_REGS))
{
int regno = true_regnum (x);
if (SPARC_INT_REG_P (regno))
return (rclass == EXTRA_FP_REGS
? FP_REGS : GENERAL_OR_FP_REGS);
}
return rclass; return rclass;
} }
...@@ -11275,6 +11326,9 @@ sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, ...@@ -11275,6 +11326,9 @@ sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
{ {
enum reg_class rclass = (enum reg_class) rclass_i; enum reg_class rclass = (enum reg_class) rclass_i;
sri->icode = CODE_FOR_nothing;
sri->extra_cost = 0;
/* We need a temporary when loading/storing a HImode/QImode value /* We need a temporary when loading/storing a HImode/QImode value
between memory and the FPU registers. This can happen when combine puts between memory and the FPU registers. This can happen when combine puts
a paradoxical subreg in a float/fix conversion insn. */ a paradoxical subreg in a float/fix conversion insn. */
...@@ -11307,6 +11361,25 @@ sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, ...@@ -11307,6 +11361,25 @@ sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
return NO_REGS; return NO_REGS;
} }
if (TARGET_VIS3 && TARGET_ARCH32)
{
int regno = true_regnum (x);
/* When using VIS3 fp<-->int register moves, on 32-bit we have
to move 8-byte values in 4-byte pieces. This only works via
FP_REGS, and not via EXTRA_FP_REGS. Therefore if we try to
move between EXTRA_FP_REGS and GENERAL_REGS, we will need
an FP_REGS intermediate move. */
if ((rclass == EXTRA_FP_REGS && SPARC_INT_REG_P (regno))
|| ((general_or_i64_p (rclass)
|| rclass == GENERAL_OR_FP_REGS)
&& SPARC_FP_REG_P (regno)))
{
sri->extra_cost = 2;
return FP_REGS;
}
}
return NO_REGS; return NO_REGS;
} }
......
...@@ -1040,10 +1040,13 @@ extern char leaf_reg_remap[]; ...@@ -1040,10 +1040,13 @@ extern char leaf_reg_remap[];
#define SPARC_SETHI32_P(X) \ #define SPARC_SETHI32_P(X) \
(SPARC_SETHI_P ((unsigned HOST_WIDE_INT) (X) & GET_MODE_MASK (SImode))) (SPARC_SETHI_P ((unsigned HOST_WIDE_INT) (X) & GET_MODE_MASK (SImode)))
/* On SPARC it is not possible to directly move data between /* On SPARC when not VIS3 it is not possible to directly move data
GENERAL_REGS and FP_REGS. */ between GENERAL_REGS and FP_REGS. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
(FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)) ((FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)) \
&& (! TARGET_VIS3 \
|| GET_MODE_SIZE (MODE) > 8 \
|| GET_MODE_SIZE (MODE) < 4))
/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9 /* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
because the movsi and movsf patterns don't handle r/f moves. because the movsi and movsf patterns don't handle r/f moves.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment