From: bonzini Date: Mon, 3 Apr 2006 11:20:07 +0000 (+0000) Subject: 2005-08-08 Paolo Bonzini X-Git-Url: http://git.sourceforge.jp/view?a=commitdiff_plain;ds=sidebyside;h=897f76b247c2985b4861f463a65403301884eaa5;p=pf3gnuchains%2Fgcc-fork.git 2005-08-08 Paolo Bonzini Dale Johannesen 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@112637 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 97507f1f55f..ebf0227b0db 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2005-08-08 Paolo Bonzini + Dale Johannesen + + 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 PR bootstrap/26992 diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index ed9d4f3d62e..315487e8fd4 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -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); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index da4b1350a0f..84b19b9dac2 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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. diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index fc8f62661b5..b7839138065 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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) \ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 827bf4e4da1..ef3f36b6964 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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" "")]) (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)" "@ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index b1dae1151a5..2e7632e5a3a 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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}) diff --git a/gcc/regclass.c b/gcc/regclass.c index f76fdcd77cf..1f1e6c24166 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -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; diff --git a/gcc/reload.c b/gcc/reload.c index 9bfb74854ca..f3023ae78b4 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -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