re PR target/19653 (x87 reg allocated for constants for -mfpmath=sse)

2005-08-08  Paolo Bonzini  <bonzini@gnu.org>
	    Dale Johannesen  <dalej@apple.com>

	PR target/19653
	* regclass.c (struct reg_pref): Update documentation.
	(regclass): Set prefclass to NO_REGS if memory is the best option.
	(record_reg_classes): Cope with a prefclass set to NO_REGS.
	* reload.c (find_reloads): Take PREFERRED_OUTPUT_RELOAD_CLASS
	into account.  For non-registers, equate an empty preferred
	reload class to a `!' in the constraint; move the if clause to
	do so after those that reject the insn.
	(push_reload): Allow PREFERRED_*_RELOAD_CLASS to liberally
	return NO_REGS.
	(find_dummy_reload): Likewise.
	* doc/tm.texi (Register Classes): Document what it means
	if PREFERRED_*_RELOAD_CLASS return NO_REGS.
	* config/i386/i386.c (ix86_preferred_reload_class): Force
	using SSE registers (and return NO_REGS for floating-point
	constants) if math is done with SSE.
	(ix86_preferred_output_reload_class): New.
	* config/i386/i386-protos.h (ix86_preferred_output_reload_class): New.
	* config/i386/i386.h (PREFERRED_OUTPUT_RELOAD_CLASS): New.
	* config/i386/i386.md: Remove # register preferences.


Co-Authored-By: Dale Johannesen <dalej@apple.com>

From-SVN: r112637
This commit is contained in:
Paolo Bonzini 2006-04-03 11:20:07 +00:00 committed by Paolo Bonzini
parent f096660b46
commit b5c82fa138
8 changed files with 191 additions and 85 deletions

View File

@ -1,3 +1,27 @@
2005-08-08 Paolo Bonzini <bonzini@gnu.org>
Dale Johannesen <dalej@apple.com>
PR target/19653
* regclass.c (struct reg_pref): Update documentation.
(regclass): Set prefclass to NO_REGS if memory is the best option.
(record_reg_classes): Cope with a prefclass set to NO_REGS.
* reload.c (find_reloads): Take PREFERRED_OUTPUT_RELOAD_CLASS
into account. For non-registers, equate an empty preferred
reload class to a `!' in the constraint; move the if clause to
do so after those that reject the insn.
(push_reload): Allow PREFERRED_*_RELOAD_CLASS to liberally
return NO_REGS.
(find_dummy_reload): Likewise.
* doc/tm.texi (Register Classes): Document what it means
if PREFERRED_*_RELOAD_CLASS return NO_REGS.
* config/i386/i386.c (ix86_preferred_reload_class): Force
using SSE registers (and return NO_REGS for floating-point
constants) if math is done with SSE.
(ix86_preferred_output_reload_class): New.
* config/i386/i386-protos.h (ix86_preferred_output_reload_class): New.
* config/i386/i386.h (PREFERRED_OUTPUT_RELOAD_CLASS): New.
* config/i386/i386.md: Remove # register preferences.
2006-04-02 Sebastian Pop <pop@cri.ensmp.fr>
PR bootstrap/26992

View File

@ -142,6 +142,7 @@ extern int ix86_secondary_memory_needed (enum reg_class, enum reg_class,
extern bool ix86_cannot_change_mode_class (enum machine_mode,
enum machine_mode, enum reg_class);
extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class);
extern enum reg_class ix86_preferred_output_reload_class (rtx, enum reg_class);
extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int);
extern int ix86_mode_needed (int, rtx);
extern void emit_i387_cw_initialization (int);

View File

@ -16361,15 +16361,28 @@ ix86_free_from_memory (enum machine_mode mode)
enum reg_class
ix86_preferred_reload_class (rtx x, enum reg_class class)
{
enum machine_mode mode = GET_MODE (x);
/* We're only allowed to return a subclass of CLASS. Many of the
following checks fail for NO_REGS, so eliminate that early. */
if (class == NO_REGS)
return NO_REGS;
/* All classes can load zeros. */
if (x == CONST0_RTX (GET_MODE (x)))
if (x == CONST0_RTX (mode))
return class;
/* Force constants into memory if we are loading a (non-zero) constant into
an MMX or SSE register. This is because there are no MMX/SSE instructions
to load from a constant. */
if (CONSTANT_P (x)
&& (MAYBE_MMX_CLASS_P (class) || MAYBE_SSE_CLASS_P (class)))
return NO_REGS;
/* Prefer SSE regs only, if we can use them for math. */
if (TARGET_SSE_MATH && !TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (mode))
return SSE_CLASS_P (class) ? class : NO_REGS;
/* Floating-point constants need more complex checks. */
if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
{
@ -16381,8 +16394,6 @@ ix86_preferred_reload_class (rtx x, enum reg_class class)
zero above. We only want to wind up preferring 80387 registers if
we plan on doing computation with them. */
if (TARGET_80387
&& (TARGET_MIX_SSE_I387
|| !(TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (x))))
&& standard_80387_constant_p (x))
{
/* Limit class to non-sse. */
@ -16398,10 +16409,6 @@ ix86_preferred_reload_class (rtx x, enum reg_class class)
return NO_REGS;
}
if (MAYBE_MMX_CLASS_P (class) && CONSTANT_P (x))
return NO_REGS;
if (MAYBE_SSE_CLASS_P (class) && CONSTANT_P (x))
return NO_REGS;
/* Generally when we see PLUS here, it's the function invariant
(plus soft-fp const_int). Which can only be computed into general
@ -16423,6 +16430,33 @@ ix86_preferred_reload_class (rtx x, enum reg_class class)
return class;
}
/* Discourage putting floating-point values in SSE registers unless
SSE math is being used, and likewise for the 387 registers. */
enum reg_class
ix86_preferred_output_reload_class (rtx x, enum reg_class class)
{
enum machine_mode mode = GET_MODE (x);
/* Restrict the output reload class to the register bank that we are doing
math on. If we would like not to return a subset of CLASS, reject this
alternative: if reload cannot do this, it will still use its choice. */
mode = GET_MODE (x);
if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
return MAYBE_SSE_CLASS_P (class) ? SSE_REGS : NO_REGS;
if (TARGET_80387 && SCALAR_FLOAT_MODE_P (mode))
{
if (class == FP_TOP_SSE_REGS)
return FP_TOP_REG;
else if (class == FP_SECOND_SSE_REGS)
return FP_SECOND_REG;
else
return FLOAT_CLASS_P (class) ? class : NO_REGS;
}
return class;
}
/* If we are copying between general and FP registers, we need a memory
location. The same is true for SSE and MMX registers.

View File

@ -669,7 +669,9 @@ extern int x86_prefetch_sse;
#define STACK_REGS
#define IS_STACK_MODE(MODE) \
((MODE) == DFmode || (MODE) == SFmode || (MODE) == XFmode) \
(((MODE) == SFmode && (!TARGET_SSE || !TARGET_SSE_MATH)) \
|| ((MODE) == DFmode && (!TARGET_SSE2 || !TARGET_SSE_MATH)) \
|| (MODE) == XFmode)
/* Number of actual hardware registers.
The hardware registers are assigned numbers for the compiler
@ -1222,6 +1224,12 @@ enum reg_class
#define PREFERRED_RELOAD_CLASS(X, CLASS) \
ix86_preferred_reload_class ((X), (CLASS))
/* Discourage putting floating-point values in SSE registers unless
SSE math is being used, and likewise for the 387 registers. */
#define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \
ix86_preferred_output_reload_class ((X), (CLASS))
/* If we are copying between general and FP registers, we need a memory
location. The same is true for SSE and MMX registers. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \

View File

@ -968,8 +968,8 @@
(define_insn "*cmpfp_i_mixed"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "f#x,x#f")
(match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
(compare:CCFP (match_operand 0 "register_operand" "f,x")
(match_operand 1 "nonimmediate_operand" "f,xm")))]
"TARGET_MIX_SSE_I387
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
@ -1017,8 +1017,8 @@
(define_insn "*cmpfp_iu_mixed"
[(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f")
(match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
(compare:CCFPU (match_operand 0 "register_operand" "f,x")
(match_operand 1 "nonimmediate_operand" "f,xm")))]
"TARGET_MIX_SSE_I387
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
@ -2222,7 +2222,7 @@
(define_insn "*pushsf"
[(set (match_operand:SF 0 "push_operand" "=<,<,<")
(match_operand:SF 1 "general_no_elim_operand" "f#rx,rFm#fx,x#rf"))]
(match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
"!TARGET_64BIT"
{
/* Anything else should be already split before reg-stack. */
@ -2235,7 +2235,7 @@
(define_insn "*pushsf_rex64"
[(set (match_operand:SF 0 "push_operand" "=X,X,X")
(match_operand:SF 1 "nonmemory_no_elim_operand" "f#rx,rF#fx,x#rf"))]
(match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
"TARGET_64BIT"
{
/* Anything else should be already split before reg-stack. */
@ -2274,9 +2274,9 @@
(define_insn "*movsf_1"
[(set (match_operand:SF 0 "nonimmediate_operand"
"=f#xr,m ,f#xr,r#xf ,m ,x#rf,x#rf,x#rf ,m ,!*y,!rm,!*y")
"=f,m ,f,r,m ,x,x,x,m ,!*y,!rm,!*y")
(match_operand:SF 1 "general_operand"
"fm#rx,f#rx,G ,rmF#fx,Fr#fx,C ,x ,xm#rf,x#rf,rm ,*y ,*y"))]
"fm,f,G ,rmF,Fr,C ,x ,xm,x,rm ,*y ,*y"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (reload_in_progress || reload_completed
|| (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
@ -2389,7 +2389,7 @@
(define_insn "*pushdf_nointeger"
[(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
(match_operand:DF 1 "general_no_elim_operand" "f#Y,Fo#fY,*r#fY,Y#f"))]
(match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))]
"!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
{
/* This insn should be already split before reg-stack. */
@ -2401,7 +2401,7 @@
(define_insn "*pushdf_integer"
[(set (match_operand:DF 0 "push_operand" "=<,<,<")
(match_operand:DF 1 "general_no_elim_operand" "f#rY,rFo#fY,Y#rf"))]
(match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))]
"TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
{
/* This insn should be already split before reg-stack. */
@ -2441,9 +2441,9 @@
(define_insn "*movdf_nointeger"
[(set (match_operand:DF 0 "nonimmediate_operand"
"=f#Y,m ,f#Y,*r ,o ,Y*x#f,Y*x#f,Y*x#f ,m ")
"=f,m ,f,*r ,o ,Y*x,Y*x,Y*x,m ")
(match_operand:DF 1 "general_operand"
"fm#Y,f#Y,G ,*roF,F*r,C ,Y*x#f,mY*x#f,Y*x#f"))]
"fm,f,G ,*roF,F*r,C ,Y*x,mY*x,Y*x"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
&& (reload_in_progress || reload_completed
@ -2561,9 +2561,9 @@
(define_insn "*movdf_integer"
[(set (match_operand:DF 0 "nonimmediate_operand"
"=f#Yr,m ,f#Yr,r#Yf ,o ,Y*x#rf,Y*x#rf,Y*x#rf,m")
"=f,m ,f,r,o ,Y*x,Y*x,Y*x,m")
(match_operand:DF 1 "general_operand"
"fm#Yr,f#Yr,G ,roF#Yf,Fr#Yf,C ,Y*x#rf,m ,Y*x#rf"))]
"fm,f,G ,roF,Fr,C ,Y*x,m ,Y*x"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
&& (reload_in_progress || reload_completed
@ -2736,7 +2736,7 @@
(define_insn "*pushxf_integer"
[(set (match_operand:XF 0 "push_operand" "=<,<")
(match_operand:XF 1 "general_no_elim_operand" "f#r,ro#f"))]
(match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
"!optimize_size"
{
/* This insn should be already split before reg-stack. */
@ -2808,8 +2808,8 @@
(set_attr "mode" "XF,XF,XF,SI,SI")])
(define_insn "*movxf_integer"
[(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
(match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
(match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
"!optimize_size
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& (reload_in_progress || reload_completed
@ -3538,8 +3538,8 @@
})
(define_insn "*extendsfdf2_mixed"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,m#fY,Y#f")
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm#Y,f#Y,mY#f")))]
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y")
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))]
"TARGET_SSE2 && TARGET_MIX_SSE_I387
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
{
@ -3872,7 +3872,7 @@
})
(define_insn "*truncxfsf2_mixed"
[(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf")
[(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "f,f,f,f")))
(clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
@ -3899,7 +3899,7 @@
(set_attr "mode" "SF")])
(define_insn "*truncxfsf2_i387"
[(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#r,?r#f")
[(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "f,f,f")))
(clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
@ -3970,7 +3970,7 @@
})
(define_insn "*truncxfdf2_mixed"
[(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf")
[(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "f,f,f,f")))
(clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
@ -3997,7 +3997,7 @@
(set_attr "mode" "DF")])
(define_insn "*truncxfdf2_i387"
[(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#r,?r#f")
[(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "f,f,f")))
(clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
@ -4471,7 +4471,7 @@
"")
(define_insn "*floatsisf2_mixed"
[(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f")
[(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
"TARGET_MIX_SSE_I387"
"@
@ -4514,7 +4514,7 @@
"")
(define_insn "*floatdisf2_mixed"
[(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f")
[(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
"TARGET_64BIT && TARGET_MIX_SSE_I387"
"@
@ -4582,7 +4582,7 @@
"")
(define_insn "*floatsidf2_mixed"
[(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f")
[(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
"TARGET_SSE2 && TARGET_MIX_SSE_I387"
"@
@ -4625,7 +4625,7 @@
"")
(define_insn "*floatdidf2_mixed"
[(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f")
[(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
"TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
"@
@ -9545,9 +9545,9 @@
"ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
(define_insn "*absnegsf2_mixed"
[(set (match_operand:SF 0 "nonimmediate_operand" "=x#f,x#f,f#x,rm")
[(set (match_operand:SF 0 "nonimmediate_operand" "=x,x,f,rm")
(match_operator:SF 3 "absneg_operator"
[(match_operand:SF 1 "nonimmediate_operand" "0 ,x#f,0 ,0")]))
[(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0 ,0")]))
(use (match_operand:V4SF 2 "nonimmediate_operand" "xm ,0 ,X ,X"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE_MATH && TARGET_MIX_SSE_I387
@ -9641,9 +9641,9 @@
"ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
(define_insn "*absnegdf2_mixed"
[(set (match_operand:DF 0 "nonimmediate_operand" "=Y#f,Y#f,f#Y,rm")
[(set (match_operand:DF 0 "nonimmediate_operand" "=Y,Y,f,rm")
(match_operator:DF 3 "absneg_operator"
[(match_operand:DF 1 "nonimmediate_operand" "0 ,Y#f,0 ,0")]))
[(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ,0")]))
(use (match_operand:V2DF 2 "nonimmediate_operand" "Ym ,0 ,X ,X"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
@ -13170,8 +13170,8 @@
(define_insn "*fp_jcc_1_mixed"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f#x,x#f")
(match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
[(match_operand 1 "register_operand" "f,x")
(match_operand 2 "nonimmediate_operand" "f,xm")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:CCFP FPSR_REG))
@ -13215,8 +13215,8 @@
(define_insn "*fp_jcc_2_mixed"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f#x,x#f")
(match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
[(match_operand 1 "register_operand" "f,x")
(match_operand 2 "nonimmediate_operand" "f,xm")])
(pc)
(label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP FPSR_REG))
@ -14535,10 +14535,10 @@
;; so use special patterns for add and mull.
(define_insn "*fop_sf_comm_mixed"
[(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
[(set (match_operand:SF 0 "register_operand" "=f,x")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "nonimmediate_operand" "%0,0")
(match_operand:SF 2 "nonimmediate_operand" "fm#x,xm#f")]))]
(match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))]
"TARGET_MIX_SSE_I387
&& COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
@ -14587,7 +14587,7 @@
[(set (match_operand:SF 0 "register_operand" "=f,f,x")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
(match_operand:SF 2 "nonimmediate_operand" "fm,0,xm#f")]))]
(match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))]
"TARGET_MIX_SSE_I387
&& !COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
@ -14681,10 +14681,10 @@
(set_attr "mode" "<MODE>")])
(define_insn "*fop_df_comm_mixed"
[(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
[(set (match_operand:DF 0 "register_operand" "=f,Y")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "nonimmediate_operand" "fm#Y,Ym#f")]))]
(match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))]
"TARGET_SSE2 && TARGET_MIX_SSE_I387
&& COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
@ -14730,10 +14730,10 @@
(set_attr "mode" "DF")])
(define_insn "*fop_df_1_mixed"
[(set (match_operand:DF 0 "register_operand" "=f#Y,f#Y,Y#f")
[(set (match_operand:DF 0 "register_operand" "=f,f,Y")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
(match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym#f")]))]
(match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))]
"TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
&& !COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
@ -15048,8 +15048,8 @@
})
(define_insn "*sqrtsf2_mixed"
[(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0#x,xm#f")))]
[(set (match_operand:SF 0 "register_operand" "=f,x")
(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))]
"TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
"@
fsqrt
@ -15086,8 +15086,8 @@
})
(define_insn "*sqrtdf2_mixed"
[(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0#Y,Ym#f")))]
[(set (match_operand:DF 0 "register_operand" "=f,Y")
(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))]
"TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
"@
fsqrt
@ -18584,11 +18584,11 @@
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
(define_insn "*movsfcc_1_387"
[(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f")
[(set (match_operand:SF 0 "register_operand" "=f,f,r,r")
(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
[(reg FLAGS_REG) (const_int 0)])
(match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
(match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
(match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0")
(match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))]
"TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@
@ -18608,11 +18608,11 @@
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
(define_insn "*movdfcc_1"
[(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f")
[(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
[(reg FLAGS_REG) (const_int 0)])
(match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
(match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
(match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
(match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
"!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@
@ -18624,11 +18624,11 @@
(set_attr "mode" "DF")])
(define_insn "*movdfcc_1_rex64"
[(set (match_operand:DF 0 "register_operand" "=f#r,f#r,r#f,r#f")
[(set (match_operand:DF 0 "register_operand" "=f,f,r,r")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
[(reg FLAGS_REG) (const_int 0)])
(match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f")
(match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))]
(match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
(match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
"TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@

View File

@ -2404,12 +2404,22 @@ register, so @code{PREFERRED_RELOAD_CLASS} returns @code{NO_REGS} when
into any kind of register, code generation will be better if
@code{LEGITIMATE_CONSTANT_P} makes the constant illegitimate instead
of using @code{PREFERRED_RELOAD_CLASS}.
If an insn has pseudos in it after register allocation, reload will go
through the alternatives and call repeatedly @code{PREFERRED_RELOAD_CLASS}
to find the best one. Returning @code{NO_REGS}, in this case, makes
reload add a @code{!} in front of the constraint: the x86 back-end uses
this feature to discourage usage of 387 registers when math is done in
the SSE registers (and vice versa).
@end defmac
@defmac PREFERRED_OUTPUT_RELOAD_CLASS (@var{x}, @var{class})
Like @code{PREFERRED_RELOAD_CLASS}, but for output reloads instead of
input reloads. If you don't define this macro, the default is to use
@var{class}, unchanged.
You can also use @code{PREFERRED_OUTPUT_RELOAD_CLASS} to discourage
reload from using some alternatives, like @code{PREFERRED_RELOAD_CLASS}.
@end defmac
@defmac LIMIT_RELOAD_CLASS (@var{mode}, @var{class})

View File

@ -811,7 +811,8 @@ struct costs
/* Structure used to record preferences of given pseudo. */
struct reg_pref
{
/* (enum reg_class) prefclass is the preferred class. */
/* (enum reg_class) prefclass is the preferred class. May be
NO_REGS if no class is better than memory. */
char prefclass;
/* altclass is a register class that we should use for allocating
@ -1314,6 +1315,10 @@ regclass (rtx f, int nregs)
best = reg_class_subunion[(int) best][class];
}
/* If no register class is better than memory, use memory. */
if (p->mem_cost < best_cost)
best = NO_REGS;
/* Record the alternate register class; i.e., a class for which
every register in it is better than using memory. If adding a
class would make a smaller class (i.e., no union of just those
@ -1524,7 +1529,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
to what we would add if this register were not in the
appropriate class. */
if (reg_pref)
if (reg_pref && reg_pref[REGNO (op)].prefclass != NO_REGS)
alt_cost
+= (may_move_in_cost[mode]
[(unsigned char) reg_pref[REGNO (op)].prefclass]
@ -1750,7 +1755,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
to what we would add if this register were not in the
appropriate class. */
if (reg_pref)
if (reg_pref && reg_pref[REGNO (op)].prefclass != NO_REGS)
alt_cost
+= (may_move_in_cost[mode]
[(unsigned char) reg_pref[REGNO (op)].prefclass]
@ -1836,7 +1841,8 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
int class;
unsigned int nr;
if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0)
if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0
&& reg_pref[regno].prefclass != NO_REGS)
{
enum reg_class pref = reg_pref[regno].prefclass;

View File

@ -1184,15 +1184,24 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/* Narrow down the class of register wanted if that is
desirable on this machine for efficiency. */
if (in != 0)
class = PREFERRED_RELOAD_CLASS (in, class);
{
enum reg_class preferred_class = class;
if (in != 0)
preferred_class = PREFERRED_RELOAD_CLASS (in, class);
/* Output reloads may need analogous treatment, different in detail. */
#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
if (out != 0)
class = PREFERRED_OUTPUT_RELOAD_CLASS (out, class);
if (out != 0)
preferred_class = PREFERRED_OUTPUT_RELOAD_CLASS (out, preferred_class);
#endif
/* Discard what the target said if we cannot do it. */
if (preferred_class != NO_REGS
|| (optional && type == RELOAD_FOR_OUTPUT))
class = preferred_class;
}
/* Make sure we use a class that can handle the actual pseudo
inside any subreg. For example, on the 386, QImode regs
can appear within SImode subregs. Although GENERAL_REGS
@ -1885,7 +1894,11 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
/* Narrow down the reg class, the same way push_reload will;
otherwise we might find a dummy now, but push_reload won't. */
class = PREFERRED_RELOAD_CLASS (in, class);
{
enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, class);
if (class != NO_REGS)
class = preferred_class;
}
/* See if OUT will do. */
if (REG_P (out)
@ -3401,22 +3414,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
losers++;
}
/* If we can't reload this value at all, reject this
alternative. Note that we could also lose due to
LIMIT_RELOAD_RELOAD_CLASS, but we don't check that
here. */
if (! CONSTANT_P (operand)
&& (enum reg_class) this_alternative[i] != NO_REGS
&& (PREFERRED_RELOAD_CLASS (operand,
(enum reg_class) this_alternative[i])
== NO_REGS))
bad = 1;
/* Alternative loses if it requires a type of reload not
permitted for this insn. We can always reload SCRATCH
and objects with a REG_UNUSED note. */
else if (GET_CODE (operand) != SCRATCH
if (GET_CODE (operand) != SCRATCH
&& modified[i] != RELOAD_READ && no_output_reloads
&& ! find_reg_note (insn, REG_UNUSED, operand))
bad = 1;
@ -3424,6 +3425,28 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
&& ! const_to_mem)
bad = 1;
/* If we can't reload this value at all, reject this
alternative. Note that we could also lose due to
LIMIT_RELOAD_CLASS, but we don't check that
here. */
if (! CONSTANT_P (operand)
&& (enum reg_class) this_alternative[i] != NO_REGS)
{
if (PREFERRED_RELOAD_CLASS
(operand, (enum reg_class) this_alternative[i])
== NO_REGS)
reject = 600;
#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
if (operand_type[i] == RELOAD_FOR_OUTPUT
&& PREFERRED_OUTPUT_RELOAD_CLASS
(operand, (enum reg_class) this_alternative[i])
== NO_REGS)
reject = 600;
#endif
}
/* We prefer to reload pseudos over reloading other things,
since such reloads may be able to be eliminated later.
If we are reloading a SCRATCH, we won't be generating any