If the target only has integer registers, we don't have to go through delicately tuned alternatives, balanced between x87 regs, SSE regs and integer regs. Attached patch introduces simple and effective alternatives in this case.
Testcases will be provided later by HJ. 2015-07-17 Uros Bizjak <ubiz...@gmail.com> PR target/66824 * config/i386/i386.h (TARGET_HARD_SF_REGS): New define. (TARGET_HARD_DF_REGS): Ditto. (TARGET_HARD_XF_REGS): Ditto. * config/i386/i386.md (*movxf_internal): Add alternatives 9 and 10. Enable alternatives 9 and 10 only for !TARGET_HARD_XF_REG target. (*movdf_internal): Add alternatives 22, 23, 24 and 25. Enable alternatives 22, 23, 24 and 25 only for !TARGET_HARD_DF_REG target. (*movsf_internal): Add alternatives 16 and 17. Enable alternatives 16 and 17 only for !TARGET_HARD_SF_REG target. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32} and committed to mainline. Uros.
Index: config/i386/i386.h =================================================================== --- config/i386/i386.h (revision 225857) +++ config/i386/i386.h (working copy) @@ -524,6 +524,10 @@ #define TARGET_MIX_SSE_I387 \ ((ix86_fpmath & (FPMATH_SSE | FPMATH_387)) == (FPMATH_SSE | FPMATH_387)) +#define TARGET_HARD_SF_REGS (TARGET_80387 || TARGET_MMX || TARGET_SSE) +#define TARGET_HARD_DF_REGS (TARGET_80387 || TARGET_SSE) +#define TARGET_HARD_XF_REGS (TARGET_80387) + #define TARGET_GNU_TLS (ix86_tls_dialect == TLS_DIALECT_GNU) #define TARGET_GNU2_TLS (ix86_tls_dialect == TLS_DIALECT_GNU2) #define TARGET_ANY_GNU_TLS (TARGET_GNU_TLS || TARGET_GNU2_TLS) Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 225857) +++ config/i386/i386.md (working copy) @@ -3087,9 +3087,9 @@ ;; in alternatives 4, 6, 7 and 8. (define_insn "*movxf_internal" [(set (match_operand:XF 0 "nonimmediate_operand" - "=f,m,f,?r ,!o,?*r ,!o,!o,!o") + "=f,m,f,?r ,!o,?*r ,!o,!o,!o,r ,o") (match_operand:XF 1 "general_operand" - "fm,f,G,roF,r , *roF,*r,F ,C"))] + "fm,f,G,roF,r , *roF,*r,F ,C,roF,rF"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) @@ -3098,7 +3098,8 @@ && standard_80387_constant_p (operands[1]) > 0 && !memory_operand (operands[0], XFmode)) || (!TARGET_MEMORY_MISMATCH_STALL - && memory_operand (operands[0], XFmode)))" + && memory_operand (operands[0], XFmode)) + || !TARGET_HARD_XF_REGS)" { switch (get_attr_type (insn)) { @@ -3122,12 +3123,12 @@ ] (const_string "*"))) (set (attr "type") - (cond [(eq_attr "alternative" "3,4,5,6,7,8") + (cond [(eq_attr "alternative" "3,4,5,6,7,8,9,10") (const_string "multi") ] (const_string "fmov"))) (set (attr "mode") - (cond [(eq_attr "alternative" "3,4,5,6,7,8") + (cond [(eq_attr "alternative" "3,4,5,6,7,8,9,10") (if_then_else (match_test "TARGET_64BIT") (const_string "DI") (const_string "SI")) @@ -3136,14 +3137,24 @@ (set (attr "preferred_for_size") (cond [(eq_attr "alternative" "3,4") (symbol_ref "false")] - (symbol_ref "true")))]) + (symbol_ref "true"))) + (set (attr "enabled") + (cond [(eq_attr "alternative" "9,10") + (if_then_else + (match_test "TARGET_HARD_XF_REGS") + (symbol_ref "false") + (const_string "*")) + (not (match_test "TARGET_HARD_XF_REGS")) + (symbol_ref "false") + ] + (const_string "*")))]) ;; Possible store forwarding (partial memory) stall in alternatives 4, 6 and 7. (define_insn "*movdf_internal" [(set (match_operand:DF 0 "nonimmediate_operand" - "=Yf*f,m ,Yf*f,?r ,!o,?*r ,!o,!o,?r,?m,?r,?r,v,v,v,m,*x,*x,*x,m ,r ,Yi") + "=Yf*f,m ,Yf*f,?r ,!o,?*r ,!o,!o,?r,?m,?r,?r,v,v,v,m,*x,*x,*x,m ,r ,Yi,r ,o ,r ,m") (match_operand:DF 1 "general_operand" - "Yf*fm,Yf*f,G ,roF,r ,*roF,*r,F ,rm,rC,C ,F ,C,v,m,v,C ,*x,m ,*x,Yj,r"))] + "Yf*fm,Yf*f,G ,roF,r ,*roF,*r,F ,rm,rC,C ,F ,C,v,m,v,C ,*x,m ,*x,Yj,r ,roF,rF,rmF,rC"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) @@ -3155,7 +3166,8 @@ && standard_sse_constant_p (operands[1]))) && !memory_operand (operands[0], DFmode)) || ((TARGET_64BIT || !TARGET_MEMORY_MISMATCH_STALL) - && memory_operand (operands[0], DFmode)))" + && memory_operand (operands[0], DFmode)) + || !TARGET_HARD_DF_REGS)" { switch (get_attr_type (insn)) { @@ -3216,9 +3228,9 @@ } } [(set (attr "isa") - (cond [(eq_attr "alternative" "3,4,5,6,7") + (cond [(eq_attr "alternative" "3,4,5,6,7,22,23") (const_string "nox64") - (eq_attr "alternative" "8,9,10,11,20,21") + (eq_attr "alternative" "8,9,10,11,20,21,24,25") (const_string "x64") (eq_attr "alternative" "12,13,14,15") (const_string "sse2") @@ -3227,9 +3239,9 @@ (set (attr "type") (cond [(eq_attr "alternative" "0,1,2") (const_string "fmov") - (eq_attr "alternative" "3,4,5,6,7") + (eq_attr "alternative" "3,4,5,6,7,22,23") (const_string "multi") - (eq_attr "alternative" "8,9,10,11") + (eq_attr "alternative" "8,9,10,11,24,25") (const_string "imov") (eq_attr "alternative" "12,16") (const_string "sselog1") @@ -3254,9 +3266,9 @@ (const_string "1") (const_string "*"))) (set (attr "mode") - (cond [(eq_attr "alternative" "3,4,5,6,7,10") + (cond [(eq_attr "alternative" "3,4,5,6,7,10,22,23") (const_string "SI") - (eq_attr "alternative" "8,9,11,20,21") + (eq_attr "alternative" "8,9,11,20,21,24,25") (const_string "DI") /* xorps is one byte shorter for non-AVX targets. */ @@ -3320,13 +3332,23 @@ (set (attr "preferred_for_speed") (cond [(eq_attr "alternative" "3,4") (symbol_ref "TARGET_INTEGER_DFMODE_MOVES")] - (symbol_ref "true")))]) + (symbol_ref "true"))) + (set (attr "enabled") + (cond [(eq_attr "alternative" "22,23,24,25") + (if_then_else + (match_test "TARGET_HARD_DF_REGS") + (symbol_ref "false") + (const_string "*")) + (not (match_test "TARGET_HARD_DF_REGS")) + (symbol_ref "false") + ] + (const_string "*")))]) (define_insn "*movsf_internal" [(set (match_operand:SF 0 "nonimmediate_operand" - "=Yf*f,m ,Yf*f,?r ,?m,v,v,v,m,?r,?Yi,!*y,!*y,!m,!r ,!*Ym") + "=Yf*f,m ,Yf*f,?r ,?m,v,v,v,m,?r,?Yi,!*y,!*y,!m,!r ,!*Ym,r ,m") (match_operand:SF 1 "general_operand" - "Yf*fm,Yf*f,G ,rmF,rF,C,v,m,v,Yj,r ,*y ,m ,*y,*Yn,r"))] + "Yf*fm,Yf*f,G ,rmF,rF,C,v,m,v,Yj,r ,*y ,m ,*y,*Yn,r ,rmF,rF"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) @@ -3336,7 +3358,8 @@ && standard_80387_constant_p (operands[1]) > 0) || (TARGET_SSE_MATH && standard_sse_constant_p (operands[1])))) - || memory_operand (operands[0], SFmode))" + || memory_operand (operands[0], SFmode) + || !TARGET_HARD_SF_REGS)" { switch (get_attr_type (insn)) { @@ -3390,7 +3413,7 @@ [(set (attr "type") (cond [(eq_attr "alternative" "0,1,2") (const_string "fmov") - (eq_attr "alternative" "3,4") + (eq_attr "alternative" "3,4,16,17") (const_string "imov") (eq_attr "alternative" "5") (const_string "sselog1") @@ -3407,7 +3430,7 @@ (const_string "1") (const_string "*"))) (set (attr "mode") - (cond [(eq_attr "alternative" "3,4,9,10,12,13,14,15") + (cond [(eq_attr "alternative" "3,4,9,10,12,13,14,15,16,17") (const_string "SI") (eq_attr "alternative" "11") (const_string "DI") @@ -3445,7 +3468,17 @@ ] (const_string "SF")) ] - (const_string "SF")))]) + (const_string "SF"))) + (set (attr "enabled") + (cond [(eq_attr "alternative" "16,17") + (if_then_else + (match_test "TARGET_HARD_SF_REGS") + (symbol_ref "false") + (const_string "*")) + (not (match_test "TARGET_HARD_SF_REGS")) + (symbol_ref "false") + ] + (const_string "*")))]) (define_split [(set (match_operand 0 "any_fp_register_operand")