diff options
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r-- | gcc/config/i386/i386.md | 1055 |
1 files changed, 380 insertions, 675 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 24d1012d5ce..475da37cb9b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -651,12 +651,14 @@ (define_attr "movu" "0,1" (const_string "0")) ;; Used to control the "enabled" attribute on a per-instruction basis. -(define_attr "isa" "base,sse2,sse2_noavx,sse3,sse4,sse4_noavx,noavx,avx, - avx2,noavx2,bmi2,fma4,fma" +(define_attr "isa" "base,x64,nox64,sse2,sse2_noavx,sse3,sse4,sse4_noavx, + noavx,avx,avx2,noavx2,bmi2,fma4,fma" (const_string "base")) (define_attr "enabled" "" - (cond [(eq_attr "isa" "sse2") (symbol_ref "TARGET_SSE2") + (cond [(eq_attr "isa" "x64") (symbol_ref "TARGET_64BIT") + (eq_attr "isa" "nox64") (symbol_ref "!TARGET_64BIT") + (eq_attr "isa" "sse2") (symbol_ref "TARGET_SSE2") (eq_attr "isa" "sse2_noavx") (symbol_ref "TARGET_SSE2 && !TARGET_AVX") (eq_attr "isa" "sse3") (symbol_ref "TARGET_SSE3") @@ -1654,6 +1656,40 @@ ;; Move instructions. +;; Reload patterns to support multi-word load/store +;; with non-offsetable address. +(define_expand "reload_noff_store" + [(parallel [(match_operand 0 "memory_operand" "=m") + (match_operand 1 "register_operand" "r") + (match_operand:DI 2 "register_operand" "=&r")])] + "TARGET_64BIT" +{ + rtx mem = operands[0]; + rtx addr = XEXP (mem, 0); + + emit_move_insn (operands[2], addr); + mem = replace_equiv_address_nv (mem, operands[2]); + + emit_insn (gen_rtx_SET (VOIDmode, mem, operands[1])); + DONE; +}) + +(define_expand "reload_noff_load" + [(parallel [(match_operand 0 "register_operand" "=r") + (match_operand 1 "memory_operand" "m") + (match_operand:DI 2 "register_operand" "=r")])] + "TARGET_64BIT" +{ + rtx mem = operands[1]; + rtx addr = XEXP (mem, 0); + + emit_move_insn (operands[2], addr); + mem = replace_equiv_address_nv (mem, operands[2]); + + emit_insn (gen_rtx_SET (VOIDmode, operands[0], mem)); + DONE; +}) + (define_expand "movoi" [(set (match_operand:OI 0 "nonimmediate_operand") (match_operand:OI 1 "general_operand"))] @@ -1722,12 +1758,12 @@ (match_operand:OI 1 "vector_move_operand" "C ,xm,x"))] "TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))" { - switch (which_alternative) + switch (get_attr_type (insn)) { - case 0: + case TYPE_SSELOG1: return standard_sse_constant_opcode (insn, operands[1]); - case 1: - case 2: + + case TYPE_SSEMOV: if (misaligned_operand (operands[0], OImode) || misaligned_operand (operands[1], OImode)) { @@ -1743,6 +1779,7 @@ else return "vmovdqa\t{%1, %0|%0, %1}"; } + default: gcc_unreachable (); } @@ -1758,20 +1795,21 @@ ] (const_string "OI")))]) -(define_insn "*movti_internal_rex64" +(define_insn "*movti_internal" [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,x,x ,m") (match_operand:TI 1 "general_operand" "riFo,re,C,xm,x"))] - "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "(TARGET_64BIT || TARGET_SSE) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" { - switch (which_alternative) + switch (get_attr_type (insn)) { - case 0: - case 1: + case TYPE_MULTI: return "#"; - case 2: + + case TYPE_SSELOG1: return standard_sse_constant_opcode (insn, operands[1]); - case 3: - case 4: + + case TYPE_SSEMOV: /* TDmode values are passed as TImode on the stack. Moving them to stack may result in unaligned memory access. */ if (misaligned_operand (operands[0], TImode) @@ -1789,16 +1827,22 @@ else return "%vmovdqa\t{%1, %0|%0, %1}"; } + default: gcc_unreachable (); } } - [(set_attr "type" "*,*,sselog1,ssemov,ssemov") - (set_attr "prefix" "*,*,maybe_vex,maybe_vex,maybe_vex") + [(set_attr "isa" "x64,x64,*,*,*") + (set_attr "type" "multi,multi,sselog1,ssemov,ssemov") + (set (attr "prefix") + (if_then_else (eq_attr "type" "sselog1,ssemov") + (const_string "maybe_vex") + (const_string "orig"))) (set (attr "mode") (cond [(eq_attr "alternative" "0,1") (const_string "DI") - (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") + (ior (not (match_test "TARGET_SSE2")) + (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")) (const_string "V4SF") (and (eq_attr "alternative" "4") (match_test "TARGET_SSE_TYPELESS_STORES")) @@ -1818,120 +1862,98 @@ [(const_int 0)] "ix86_split_long_move (operands); DONE;") -(define_insn "*movti_internal_sse" - [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x ,m") - (match_operand:TI 1 "vector_move_operand" "C ,xm,x"))] - "TARGET_SSE && !TARGET_64BIT - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" -{ - switch (which_alternative) - { - case 0: - return standard_sse_constant_opcode (insn, operands[1]); - case 1: - case 2: - /* TDmode values are passed as TImode on the stack. Moving them - to stack may result in unaligned memory access. */ - if (misaligned_operand (operands[0], TImode) - || misaligned_operand (operands[1], TImode)) - { - if (get_attr_mode (insn) == MODE_V4SF) - return "%vmovups\t{%1, %0|%0, %1}"; - else - return "%vmovdqu\t{%1, %0|%0, %1}"; - } - else - { - if (get_attr_mode (insn) == MODE_V4SF) - return "%vmovaps\t{%1, %0|%0, %1}"; - else - return "%vmovdqa\t{%1, %0|%0, %1}"; - } - default: - gcc_unreachable (); - } -} - [(set_attr "type" "sselog1,ssemov,ssemov") - (set_attr "prefix" "maybe_vex") - (set (attr "mode") - (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") - (const_string "V4SF") - (and (eq_attr "alternative" "2") - (match_test "TARGET_SSE_TYPELESS_STORES")) - (const_string "V4SF") - (match_test "TARGET_AVX") - (const_string "TI") - (ior (not (match_test "TARGET_SSE2")) - (match_test "optimize_function_for_size_p (cfun)")) - (const_string "V4SF") - ] - (const_string "TI")))]) - -(define_insn "*movdi_internal_rex64" +(define_insn "*movdi_internal" [(set (match_operand:DI 0 "nonimmediate_operand" - "=r,r ,r,m ,*y,m*y,?*y,?r ,?*Ym,*x,m ,*x,*x,?r ,?*Yi,?*x,?*Ym") + "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r ,?*Ym,*x,*x,*x,m ,?r ,?*Yi,?*Ym,?*Yi") (match_operand:DI 1 "general_operand" - "Z ,rem,i,re,C ,*y ,m ,*Ym,r ,C ,*x,*x,m ,*Yi,r ,*Ym,*x"))] - "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*Ym,r ,C ,*x,m ,*x,*Yi,r ,*Yi ,*Ym"))] + "!(MEM_P (operands[0]) && MEM_P (operands[1]))" { switch (get_attr_type (insn)) { - case TYPE_SSECVT: - if (SSE_REG_P (operands[0])) - return "movq2dq\t{%1, %0|%0, %1}"; - else - return "movdq2q\t{%1, %0|%0, %1}"; - - case TYPE_SSEMOV: - if (get_attr_mode (insn) == MODE_V4SF) - return "%vmovaps\t{%1, %0|%0, %1}"; - else if (get_attr_mode (insn) == MODE_TI) - return "%vmovdqa\t{%1, %0|%0, %1}"; + case TYPE_MULTI: + return "#"; - /* Handle broken assemblers that require movd instead of movq. */ - if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) - return "%vmovd\t{%1, %0|%0, %1}"; - else - return "%vmovq\t{%1, %0|%0, %1}"; + case TYPE_MMX: + return "pxor\t%0, %0"; case TYPE_MMXMOV: +#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ /* Handle broken assemblers that require movd instead of movq. */ if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) return "movd\t{%1, %0|%0, %1}"; - else - return "movq\t{%1, %0|%0, %1}"; +#endif + return "movq\t{%1, %0|%0, %1}"; case TYPE_SSELOG1: return standard_sse_constant_opcode (insn, operands[1]); - case TYPE_MMX: - return "pxor\t%0, %0"; + case TYPE_SSEMOV: + switch (get_attr_mode (insn)) + { + case MODE_DI: +#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ + /* Handle broken assemblers that require movd instead of movq. */ + if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) + return "%vmovd\t{%1, %0|%0, %1}"; +#endif + return "%vmovq\t{%1, %0|%0, %1}"; + case MODE_TI: + return "%vmovdqa\t{%1, %0|%0, %1}"; + + case MODE_V2SF: + gcc_assert (!TARGET_AVX); + return "movlps\t{%1, %0|%0, %1}"; + case MODE_V4SF: + return "%vmovaps\t{%1, %0|%0, %1}"; + + default: + gcc_unreachable (); + } + + case TYPE_SSECVT: + if (SSE_REG_P (operands[0])) + return "movq2dq\t{%1, %0|%0, %1}"; + else + return "movdq2q\t{%1, %0|%0, %1}"; case TYPE_LEA: return "lea{q}\t{%E1, %0|%0, %E1}"; - default: + case TYPE_IMOV: gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); if (get_attr_mode (insn) == MODE_SI) return "mov{l}\t{%k1, %k0|%k0, %k1}"; - else if (which_alternative == 2) + else if (which_alternative == 4) return "movabs{q}\t{%1, %0|%0, %1}"; else if (ix86_use_lea_for_mov (insn, operands)) return "lea{q}\t{%E1, %0|%0, %E1}"; else return "mov{q}\t{%1, %0|%0, %1}"; + + default: + gcc_unreachable (); } } - [(set (attr "type") - (cond [(eq_attr "alternative" "4") + [(set (attr "isa") + (cond [(eq_attr "alternative" "0,1") + (const_string "nox64") + (eq_attr "alternative" "2,3,4,5,10,11,16,17") + (const_string "x64") + ] + (const_string "*"))) + (set (attr "type") + (cond [(eq_attr "alternative" "0,1") + (const_string "multi") + (eq_attr "alternative" "6") (const_string "mmx") - (eq_attr "alternative" "5,6,7,8") + (eq_attr "alternative" "7,8,9,10,11") (const_string "mmxmov") - (eq_attr "alternative" "9") + (eq_attr "alternative" "12") (const_string "sselog1") - (eq_attr "alternative" "10,11,12,13,14") + (eq_attr "alternative" "13,14,15,16,17") (const_string "ssemov") - (eq_attr "alternative" "15,16") + (eq_attr "alternative" "18,19") (const_string "ssecvt") (match_operand 1 "pic_32bit_operand") (const_string "lea") @@ -1939,161 +1961,45 @@ (const_string "imov"))) (set (attr "modrm") (if_then_else - (and (eq_attr "alternative" "2") (eq_attr "type" "imov")) + (and (eq_attr "alternative" "4") (eq_attr "type" "imov")) (const_string "0") (const_string "*"))) (set (attr "length_immediate") (if_then_else - (and (eq_attr "alternative" "2") (eq_attr "type" "imov")) + (and (eq_attr "alternative" "4") (eq_attr "type" "imov")) (const_string "8") (const_string "*"))) (set (attr "prefix_rex") - (if_then_else (eq_attr "alternative" "7,8") - (const_string "1") - (const_string "*"))) - (set (attr "prefix_data16") - (if_then_else (eq_attr "alternative" "10") + (if_then_else (eq_attr "alternative" "10,11,16,17") (const_string "1") (const_string "*"))) (set (attr "prefix") - (if_then_else (eq_attr "alternative" "9,10,11,12,13,14") + (if_then_else (eq_attr "type" "sselog1,ssemov") (const_string "maybe_vex") (const_string "orig"))) + (set (attr "prefix_data16") + (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "DI")) + (const_string "1") + (const_string "*"))) (set (attr "mode") - (cond [(eq_attr "alternative" "0") - (const_string "SI") - (eq_attr "alternative" "9,11") - (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") - (const_string "V4SF") - (match_test "TARGET_AVX") - (const_string "TI") - (match_test "optimize_function_for_size_p (cfun)") - (const_string "V4SF") - ] - (const_string "TI")) - ] - (const_string "DI")))]) - -;; Reload patterns to support multi-word load/store -;; with non-offsetable address. -(define_expand "reload_noff_store" - [(parallel [(match_operand 0 "memory_operand" "=m") - (match_operand 1 "register_operand" "r") - (match_operand:DI 2 "register_operand" "=&r")])] - "TARGET_64BIT" -{ - rtx mem = operands[0]; - rtx addr = XEXP (mem, 0); - - emit_move_insn (operands[2], addr); - mem = replace_equiv_address_nv (mem, operands[2]); - - emit_insn (gen_rtx_SET (VOIDmode, mem, operands[1])); - DONE; -}) - -(define_expand "reload_noff_load" - [(parallel [(match_operand 0 "register_operand" "=r") - (match_operand 1 "memory_operand" "m") - (match_operand:DI 2 "register_operand" "=r")])] - "TARGET_64BIT" -{ - rtx mem = operands[1]; - rtx addr = XEXP (mem, 0); - - emit_move_insn (operands[2], addr); - mem = replace_equiv_address_nv (mem, operands[2]); - - emit_insn (gen_rtx_SET (VOIDmode, operands[0], mem)); - DONE; -}) - -(define_insn "*movdi_internal" - [(set (match_operand:DI 0 "nonimmediate_operand" - "=r ,o ,*y,m*y,*y,*x,m ,*x,*x,*x,m ,*x,*x,?*x,?*Ym") - (match_operand:DI 1 "general_operand" - "riFo,riF,C ,*y ,m ,C ,*x,*x,m ,C ,*x,*x,m ,*Ym,*x"))] - "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))" -{ - switch (get_attr_type (insn)) - { - case TYPE_SSECVT: - if (SSE_REG_P (operands[0])) - return "movq2dq\t{%1, %0|%0, %1}"; - else - return "movdq2q\t{%1, %0|%0, %1}"; - - case TYPE_SSEMOV: - switch (get_attr_mode (insn)) - { - case MODE_TI: - return "%vmovdqa\t{%1, %0|%0, %1}"; - case MODE_DI: - return "%vmovq\t{%1, %0|%0, %1}"; - case MODE_V4SF: - return "%vmovaps\t{%1, %0|%0, %1}"; - case MODE_V2SF: - return "movlps\t{%1, %0|%0, %1}"; - default: - gcc_unreachable (); - } - - case TYPE_MMXMOV: - return "movq\t{%1, %0|%0, %1}"; - - case TYPE_SSELOG1: - return standard_sse_constant_opcode (insn, operands[1]); - - case TYPE_MMX: - return "pxor\t%0, %0"; - - case TYPE_MULTI: - return "#"; + (cond [(eq_attr "alternative" "2") + (const_string "SI") + (eq_attr "alternative" "12,13") + (cond [(ior (not (match_test "TARGET_SSE2")) + (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")) + (const_string "V4SF") + (match_test "TARGET_AVX") + (const_string "TI") + (match_test "optimize_function_for_size_p (cfun)") + (const_string "V4SF") + ] + (const_string "TI")) - default: - gcc_unreachable (); - } -} - [(set (attr "isa") - (cond [(eq_attr "alternative" "5,6,7,8,13,14") - (const_string "sse2") - (eq_attr "alternative" "9,10,11,12") - (const_string "noavx") + (and (eq_attr "alternative" "14,15") + (not (match_test "TARGET_SSE2"))) + (const_string "V2SF") ] - (const_string "*"))) - (set (attr "type") - (cond [(eq_attr "alternative" "0,1") - (const_string "multi") - (eq_attr "alternative" "2") - (const_string "mmx") - (eq_attr "alternative" "3,4") - (const_string "mmxmov") - (eq_attr "alternative" "5,9") - (const_string "sselog1") - (eq_attr "alternative" "13,14") - (const_string "ssecvt") - ] - (const_string "ssemov"))) - (set (attr "prefix") - (if_then_else (eq_attr "alternative" "5,6,7,8") - (const_string "maybe_vex") - (const_string "orig"))) - (set (attr "mode") - (cond [(eq_attr "alternative" "9,11") - (const_string "V4SF") - (eq_attr "alternative" "10,12") - (const_string "V2SF") - (eq_attr "alternative" "5,7") - (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") - (const_string "V4SF") - (match_test "TARGET_AVX") - (const_string "TI") - (match_test "optimize_function_for_size_p (cfun)") - (const_string "V4SF") - ] - (const_string "TI")) - ] - (const_string "DI")))]) + (const_string "DI")))]) (define_split [(set (match_operand:DI 0 "nonimmediate_operand") @@ -2106,9 +2012,9 @@ (define_insn "*movsi_internal" [(set (match_operand:SI 0 "nonimmediate_operand" - "=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x") + "=r,m ,*y,*y,?rm,?*y,*x,*x,*x,m ,?r ,?*Yi") (match_operand:SI 1 "general_operand" - "g ,re,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m"))] + "g ,re,C ,*y,*y ,rm ,C ,*x,m ,*x,*Yi,r"))] "!(MEM_P (operands[0]) && MEM_P (operands[1]))" { switch (get_attr_type (insn)) @@ -2119,14 +2025,18 @@ case TYPE_SSEMOV: switch (get_attr_mode (insn)) { + case MODE_SI: + return "%vmovd\t{%1, %0|%0, %1}"; case MODE_TI: return "%vmovdqa\t{%1, %0|%0, %1}"; + case MODE_V4SF: return "%vmovaps\t{%1, %0|%0, %1}"; - case MODE_SI: - return "%vmovd\t{%1, %0|%0, %1}"; + case MODE_SF: - return "%vmovss\t{%1, %0|%0, %1}"; + gcc_assert (!TARGET_AVX); + return "movss\t{%1, %0|%0, %1}"; + default: gcc_unreachable (); } @@ -2135,19 +2045,29 @@ return "pxor\t%0, %0"; case TYPE_MMXMOV: - if (get_attr_mode (insn) == MODE_DI) - return "movq\t{%1, %0|%0, %1}"; - return "movd\t{%1, %0|%0, %1}"; + switch (get_attr_mode (insn)) + { + case MODE_DI: + return "movq\t{%1, %0|%0, %1}"; + case MODE_SI: + return "movd\t{%1, %0|%0, %1}"; + + default: + gcc_unreachable (); + } case TYPE_LEA: return "lea{l}\t{%E1, %0|%0, %E1}"; - default: + case TYPE_IMOV: gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); if (ix86_use_lea_for_mov (insn, operands)) return "lea{l}\t{%E1, %0|%0, %E1}"; else return "mov{l}\t{%1, %0|%0, %1}"; + + default: + gcc_unreachable (); } } [(set (attr "type") @@ -2164,9 +2084,9 @@ ] (const_string "imov"))) (set (attr "prefix") - (if_then_else (eq_attr "alternative" "0,1,2,3,4,5") - (const_string "orig") - (const_string "maybe_vex"))) + (if_then_else (eq_attr "type" "sselog1,ssemov") + (const_string "maybe_vex") + (const_string "orig"))) (set (attr "prefix_data16") (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI")) (const_string "1") @@ -2175,16 +2095,17 @@ (cond [(eq_attr "alternative" "2,3") (const_string "DI") (eq_attr "alternative" "6,7") - (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") + (cond [(ior (not (match_test "TARGET_SSE2")) + (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")) (const_string "V4SF") (match_test "TARGET_AVX") (const_string "TI") - (ior (not (match_test "TARGET_SSE2")) - (match_test "optimize_function_for_size_p (cfun)")) + (match_test "optimize_function_for_size_p (cfun)") (const_string "V4SF") ] (const_string "TI")) - (and (eq_attr "alternative" "8,9,10,11") + + (and (eq_attr "alternative" "8,9") (not (match_test "TARGET_SSE2"))) (const_string "SF") ] @@ -2582,16 +2503,17 @@ ;; Floating point push instructions. (define_insn "*pushtf" - [(set (match_operand:TF 0 "push_operand" "=<,<,<") - (match_operand:TF 1 "general_no_elim_operand" "x,Fo,*r"))] - "TARGET_SSE" + [(set (match_operand:TF 0 "push_operand" "=<,<") + (match_operand:TF 1 "general_no_elim_operand" "x,*roF"))] + "TARGET_64BIT || TARGET_SSE" { /* This insn should be already split before reg-stack. */ gcc_unreachable (); } - [(set_attr "type" "multi") - (set_attr "unit" "sse,*,*") - (set_attr "mode" "TF,SI,SI")]) + [(set_attr "isa" "*,x64") + (set_attr "type" "multi") + (set_attr "unit" "sse,*") + (set_attr "mode" "TF,DI")]) ;; %%% Kill this when call knows how to work this out. (define_split @@ -2603,33 +2525,21 @@ (define_insn "*pushxf" [(set (match_operand:XF 0 "push_operand" "=<,<") - (match_operand:XF 1 "general_no_elim_operand" "f,ro"))] - "optimize_function_for_speed_p (cfun)" -{ - /* This insn should be already split before reg-stack. */ - gcc_unreachable (); -} - [(set_attr "type" "multi") - (set_attr "unit" "i387,*") - (set_attr "mode" "XF,SI")]) - -;; Size of pushxf is 3 (for sub) + 2 (for fstp) + memory operand size. -;; Size of pushxf using integer instructions is 3+3*memory operand size -;; Pushing using integer instructions is longer except for constants -;; and direct memory references (assuming that any given constant is pushed -;; only once, but this ought to be handled elsewhere). - -(define_insn "*pushxf_nointeger" - [(set (match_operand:XF 0 "push_operand" "=<,<") - (match_operand:XF 1 "general_no_elim_operand" "f,*rFo"))] - "optimize_function_for_size_p (cfun)" + (match_operand:XF 1 "general_no_elim_operand" "f,Yx*roF"))] + "" { /* This insn should be already split before reg-stack. */ gcc_unreachable (); } [(set_attr "type" "multi") (set_attr "unit" "i387,*") - (set_attr "mode" "XF,SI")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "1") + (if_then_else (match_test "TARGET_64BIT") + (const_string "DI") + (const_string "SI")) + ] + (const_string "XF")))]) ;; %%% Kill this when call knows how to work this out. (define_split @@ -2640,34 +2550,18 @@ (set (mem:XF (reg:P SP_REG)) (match_dup 1))] "operands[2] = GEN_INT (-GET_MODE_SIZE (XFmode));") -(define_insn "*pushdf_rex64" - [(set (match_operand:DF 0 "push_operand" "=<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFm,x"))] - "TARGET_64BIT" -{ - /* This insn should be already split before reg-stack. */ - gcc_unreachable (); -} - [(set_attr "type" "multi") - (set_attr "unit" "i387,*,*") - (set_attr "mode" "DF,DI,DF")]) - -;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size. -;; Size of pushdf using integer instructions is 2+2*memory operand size -;; On the average, pushdf using integers can be still shorter. - (define_insn "*pushdf" - [(set (match_operand:DF 0 "push_operand" "=<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFo,x"))] - "!TARGET_64BIT" + [(set (match_operand:DF 0 "push_operand" "=<,<,<,<") + (match_operand:DF 1 "general_no_elim_operand" "f,Yd*roF,rmF,x"))] + "" { /* This insn should be already split before reg-stack. */ gcc_unreachable (); } - [(set_attr "isa" "*,*,sse2") + [(set_attr "isa" "*,nox64,x64,sse2") (set_attr "type" "multi") - (set_attr "unit" "i387,*,*") - (set_attr "mode" "DF,DI,DF")]) + (set_attr "unit" "i387,*,*,sse") + (set_attr "mode" "DF,SI,DI,DF")]) ;; %%% Kill this when call knows how to work this out. (define_split @@ -2692,7 +2586,7 @@ (define_insn "*pushsf" [(set (match_operand:SF 0 "push_operand" "=<,<,<") - (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))] + (match_operand:SF 1 "general_no_elim_operand" "f,rmF,x"))] "!TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ @@ -2736,10 +2630,7 @@ [(set (match_operand:TF 0 "nonimmediate_operand") (match_operand:TF 1 "nonimmediate_operand"))] "TARGET_64BIT || TARGET_SSE" -{ - ix86_expand_move (TFmode, operands); - DONE; -}) + "ix86_expand_move (TFmode, operands); DONE;") (define_expand "mov<mode>" [(set (match_operand:X87MODEF 0 "nonimmediate_operand") @@ -2747,10 +2638,11 @@ "" "ix86_expand_move (<MODE>mode, operands); DONE;") -(define_insn "*movtf_internal_rex64" +(define_insn "*movtf_internal" [(set (match_operand:TF 0 "nonimmediate_operand" "=x,x ,m,?*r ,!o") (match_operand:TF 1 "general_operand" "C ,xm,x,*roF,*rC"))] - "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) + "(TARGET_64BIT || TARGET_SSE) + && !(MEM_P (operands[0]) && MEM_P (operands[1])) && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || GET_CODE (operands[1]) != CONST_DOUBLE @@ -2760,12 +2652,12 @@ || (!TARGET_MEMORY_MISMATCH_STALL && memory_operand (operands[0], TFmode)))" { - switch (which_alternative) + switch (get_attr_type (insn)) { - case 0: + case TYPE_SSELOG1: return standard_sse_constant_opcode (insn, operands[1]); - case 1: - case 2: + + case TYPE_SSEMOV: /* Handle misaligned load/store since we don't have movmisaligntf pattern. */ if (misaligned_operand (operands[0], TFmode) @@ -2784,16 +2676,19 @@ return "%vmovdqa\t{%1, %0|%0, %1}"; } - case 3: - case 4: + case TYPE_MULTI: return "#"; default: gcc_unreachable (); } } - [(set_attr "type" "sselog1,ssemov,ssemov,*,*") - (set_attr "prefix" "maybe_vex,maybe_vex,maybe_vex,*,*") + [(set_attr "isa" "*,*,*,x64,x64") + (set_attr "type" "sselog1,ssemov,ssemov,multi,multi") + (set (attr "prefix") + (if_then_else (eq_attr "type" "sselog1,ssemov") + (const_string "maybe_vex") + (const_string "orig"))) (set (attr "mode") (cond [(eq_attr "alternative" "3,4") (const_string "DI") @@ -2810,101 +2705,13 @@ ] (const_string "TI")))]) -(define_insn "*movtf_internal_sse" - [(set (match_operand:TF 0 "nonimmediate_operand" "=x,x ,m") - (match_operand:TF 1 "general_operand" "C ,xm,x"))] - "TARGET_SSE && !TARGET_64BIT - && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (!can_create_pseudo_p () - || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || GET_CODE (operands[1]) != CONST_DOUBLE - || (optimize_function_for_size_p (cfun) - && standard_sse_constant_p (operands[1]) - && !memory_operand (operands[0], TFmode)) - || (!TARGET_MEMORY_MISMATCH_STALL - && memory_operand (operands[0], TFmode)))" -{ - switch (which_alternative) - { - case 0: - return standard_sse_constant_opcode (insn, operands[1]); - case 1: - case 2: - /* Handle misaligned load/store since we - don't have movmisaligntf pattern. */ - if (misaligned_operand (operands[0], TFmode) - || misaligned_operand (operands[1], TFmode)) - { - if (get_attr_mode (insn) == MODE_V4SF) - return "%vmovups\t{%1, %0|%0, %1}"; - else - return "%vmovdqu\t{%1, %0|%0, %1}"; - } - else - { - if (get_attr_mode (insn) == MODE_V4SF) - return "%vmovaps\t{%1, %0|%0, %1}"; - else - return "%vmovdqa\t{%1, %0|%0, %1}"; - } - default: - gcc_unreachable (); - } -} - [(set_attr "type" "sselog1,ssemov,ssemov") - (set_attr "prefix" "maybe_vex") - (set (attr "mode") - (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") - (const_string "V4SF") - (and (eq_attr "alternative" "2") - (match_test "TARGET_SSE_TYPELESS_STORES")) - (const_string "V4SF") - (match_test "TARGET_AVX") - (const_string "TI") - (ior (not (match_test "TARGET_SSE2")) - (match_test "optimize_function_for_size_p (cfun)")) - (const_string "V4SF") - ] - (const_string "TI")))]) - -(define_insn "*movxf_internal_rex64" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,?Yx*r ,!o") - (match_operand:XF 1 "general_operand" "fm,f,G,Yx*roF,Yx*rC"))] - "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (!can_create_pseudo_p () - || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || GET_CODE (operands[1]) != CONST_DOUBLE - || (optimize_function_for_size_p (cfun) - && standard_80387_constant_p (operands[1]) > 0 - && !memory_operand (operands[0], XFmode)) - || (!TARGET_MEMORY_MISMATCH_STALL - && memory_operand (operands[0], XFmode)))" -{ - switch (which_alternative) - { - case 0: - case 1: - return output_387_reg_move (insn, operands); - - case 2: - return standard_80387_constant_opcode (operands[1]); - - case 3: - case 4: - return "#"; - - default: - gcc_unreachable (); - } -} - [(set_attr "type" "fmov,fmov,fmov,multi,multi") - (set_attr "mode" "XF,XF,XF,SI,SI")]) - -;; Possible store forwarding (partial memory) stall in alternative 4. +;; Possible store forwarding (partial memory) stall in alternatives 4 and 5. (define_insn "*movxf_internal" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,?Yx*r ,!o") - (match_operand:XF 1 "general_operand" "fm,f,G,Yx*roF,Yx*rF"))] - "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) + [(set (match_operand:XF 0 "nonimmediate_operand" + "=f,m,f,?Yx*r ,!o ,!o") + (match_operand:XF 1 "general_operand" + "fm,f,G,Yx*roF,Yx*rF,Yx*rC"))] + "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || GET_CODE (operands[1]) != CONST_DOUBLE @@ -2914,177 +2721,37 @@ || (!TARGET_MEMORY_MISMATCH_STALL && memory_operand (operands[0], XFmode)))" { - switch (which_alternative) + switch (get_attr_type (insn)) { - case 0: - case 1: + case TYPE_FMOV: + if (which_alternative == 2) + return standard_80387_constant_opcode (operands[1]); return output_387_reg_move (insn, operands); - case 2: - return standard_80387_constant_opcode (operands[1]); - - case 3: - case 4: + case TYPE_MULTI: return "#"; default: gcc_unreachable (); } } - [(set_attr "type" "fmov,fmov,fmov,multi,multi") - (set_attr "mode" "XF,XF,XF,SI,SI")]) - -(define_insn "*movdf_internal_rex64" - [(set (match_operand:DF 0 "nonimmediate_operand" - "=Yf*f,m ,Yf*f,?r,?m,?r,?r,x,x,x,m,Yi,r") - (match_operand:DF 1 "general_operand" - "Yf*fm,Yf*f,G ,rm,rC,C ,F ,C,x,m,x,r ,Yi"))] - "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (!can_create_pseudo_p () - || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || GET_CODE (operands[1]) != CONST_DOUBLE - || (optimize_function_for_size_p (cfun) - && ((!(TARGET_SSE2 && TARGET_SSE_MATH) - && standard_80387_constant_p (operands[1]) > 0) - || (TARGET_SSE2 && TARGET_SSE_MATH - && standard_sse_constant_p (operands[1])))) - || memory_operand (operands[0], DFmode))" -{ - switch (which_alternative) - { - case 0: - case 1: - return output_387_reg_move (insn, operands); - - case 2: - return standard_80387_constant_opcode (operands[1]); - - case 3: - case 4: - return "mov{q}\t{%1, %0|%0, %1}"; - - case 5: - return "mov{l}\t{%1, %k0|%k0, %1}"; - - case 6: - return "movabs{q}\t{%1, %0|%0, %1}"; - - case 7: - return standard_sse_constant_opcode (insn, operands[1]); - - case 8: - case 9: - case 10: - switch (get_attr_mode (insn)) - { - case MODE_V2DF: - return "%vmovapd\t{%1, %0|%0, %1}"; - case MODE_V4SF: - return "%vmovaps\t{%1, %0|%0, %1}"; - - case MODE_DI: - return "%vmovq\t{%1, %0|%0, %1}"; - case MODE_DF: - if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1])) - return "vmovsd\t{%1, %0, %0|%0, %0, %1}"; - return "%vmovsd\t{%1, %0|%0, %1}"; - case MODE_V1DF: - return "%vmovlpd\t{%1, %d0|%d0, %1}"; - case MODE_V2SF: - return "%vmovlps\t{%1, %d0|%d0, %1}"; - default: - gcc_unreachable (); - } - - case 11: - case 12: - /* Handle broken assemblers that require movd instead of movq. */ - return "%vmovd\t{%1, %0|%0, %1}"; - - default: - gcc_unreachable(); - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "0,1,2") - (const_string "fmov") - (eq_attr "alternative" "3,4,5,6") - (const_string "imov") - (eq_attr "alternative" "7") - (const_string "sselog1") - ] - (const_string "ssemov"))) - (set (attr "modrm") - (if_then_else - (and (eq_attr "alternative" "6") (eq_attr "type" "imov")) - (const_string "0") - (const_string "*"))) - (set (attr "length_immediate") - (if_then_else - (and (eq_attr "alternative" "6") (eq_attr "type" "imov")) - (const_string "8") - (const_string "*"))) - (set (attr "prefix") - (if_then_else (eq_attr "alternative" "0,1,2,3,4,5,6") - (const_string "orig") - (const_string "maybe_vex"))) - (set (attr "prefix_data16") - (if_then_else (eq_attr "mode" "V1DF") - (const_string "1") - (const_string "*"))) + [(set_attr "isa" "*,*,*,*,nox64,x64") + (set_attr "type" "fmov,fmov,fmov,multi,multi,multi") (set (attr "mode") - (cond [(eq_attr "alternative" "0,1,2") - (const_string "DF") - (eq_attr "alternative" "3,4,6,11,12") - (const_string "DI") - (eq_attr "alternative" "5") - (const_string "SI") - - /* xorps is one byte shorter for !TARGET_AVX. */ - (eq_attr "alternative" "7") - (cond [(match_test "TARGET_AVX") - (const_string "V2DF") - (match_test "optimize_function_for_size_p (cfun)") - (const_string "V4SF") - (match_test "TARGET_SSE_LOAD0_BY_PXOR") - (const_string "TI") - ] - (const_string "V2DF")) - - /* For architectures resolving dependencies on - whole SSE registers use APD move to break dependency - chains, otherwise use short move to avoid extra work. - - movaps encodes one byte shorter for !TARGET_AVX. */ - (eq_attr "alternative" "8") - (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") - (const_string "V4SF") - (match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY") - (const_string "V2DF") - (match_test "TARGET_AVX") - (const_string "DF") - (match_test "optimize_function_for_size_p (cfun)") - (const_string "V4SF") - ] - (const_string "DF")) - /* For architectures resolving dependencies on register - parts we may avoid extra work to zero out upper part - of register. */ - (eq_attr "alternative" "9") - (if_then_else - (match_test "TARGET_SSE_SPLIT_REGS") - (const_string "V1DF") - (const_string "DF")) + (cond [(eq_attr "alternative" "3,4,5") + (if_then_else (match_test "TARGET_64BIT") + (const_string "DI") + (const_string "SI")) ] - (const_string "DF")))]) + (const_string "XF")))]) ;; Possible store forwarding (partial memory) stall in alternative 4. (define_insn "*movdf_internal" [(set (match_operand:DF 0 "nonimmediate_operand" - "=Yf*f,m ,Yf*f,?Yd*r ,!o ,x,x,x,m,*x,*x,*x,m") + "=Yf*f,m ,Yf*f,?Yd*r ,!o ,?r,?m,?r,?r,x,x,x,m,*x,*x,*x,m ,r ,Yi") (match_operand:DF 1 "general_operand" - "Yf*fm,Yf*f,G ,Yd*roF,Yd*rF,C,x,m,x,C ,*x,m ,*x"))] - "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) + "Yf*fm,Yf*f,G ,Yd*roF,Yd*rF,rm,rC,C ,F ,C,x,m,x,C ,*x,m ,*x,Yi,r"))] + "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || GET_CODE (operands[1]) != CONST_DOUBLE @@ -3094,49 +2761,58 @@ || (TARGET_SSE2 && TARGET_SSE_MATH && standard_sse_constant_p (operands[1]))) && !memory_operand (operands[0], DFmode)) - || (!TARGET_MEMORY_MISMATCH_STALL + || ((TARGET_64BIT || !TARGET_MEMORY_MISMATCH_STALL) && memory_operand (operands[0], DFmode)))" { - switch (which_alternative) + switch (get_attr_type (insn)) { - case 0: - case 1: + case TYPE_FMOV: + if (which_alternative == 2) + return standard_80387_constant_opcode (operands[1]); return output_387_reg_move (insn, operands); - case 2: - return standard_80387_constant_opcode (operands[1]); - - case 3: - case 4: + case TYPE_MULTI: return "#"; - case 5: - case 9: + case TYPE_IMOV: + if (get_attr_mode (insn) == MODE_SI) + return "mov{l}\t{%1, %k0|%k0, %1}"; + else if (which_alternative == 8) + return "movabs{q}\t{%1, %0|%0, %1}"; + else + return "mov{q}\t{%1, %0|%0, %1}"; + + case TYPE_SSELOG1: return standard_sse_constant_opcode (insn, operands[1]); - case 6: - case 7: - case 8: - case 10: - case 11: - case 12: + case TYPE_SSEMOV: switch (get_attr_mode (insn)) { - case MODE_V2DF: - return "%vmovapd\t{%1, %0|%0, %1}"; - case MODE_V4SF: - return "%vmovaps\t{%1, %0|%0, %1}"; - - case MODE_DI: - return "%vmovq\t{%1, %0|%0, %1}"; case MODE_DF: if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1])) return "vmovsd\t{%1, %0, %0|%0, %0, %1}"; return "%vmovsd\t{%1, %0|%0, %1}"; - case MODE_V1DF: - return "%vmovlpd\t{%1, %d0|%d0, %1}"; + + case MODE_V4SF: + return "%vmovaps\t{%1, %0|%0, %1}"; + case MODE_V2DF: + return "%vmovapd\t{%1, %0|%0, %1}"; + case MODE_V2SF: - return "%vmovlps\t{%1, %d0|%d0, %1}"; + gcc_assert (!TARGET_AVX); + return "movlps\t{%1, %0|%0, %1}"; + case MODE_V1DF: + gcc_assert (!TARGET_AVX); + return "movlpd\t{%1, %0|%0, %1}"; + + case MODE_DI: +#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ + /* Handle broken assemblers that require movd instead of movq. */ + if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) + return "%vmovd\t{%1, %0|%0, %1}"; +#endif + return "%vmovq\t{%1, %0|%0, %1}"; + default: gcc_unreachable (); } @@ -3146,42 +2822,54 @@ } } [(set (attr "isa") - (if_then_else (eq_attr "alternative" "5,6,7,8") - (const_string "sse2") - (const_string "*"))) + (cond [(eq_attr "alternative" "3,4") + (const_string "nox64") + (eq_attr "alternative" "5,6,7,8,17,18") + (const_string "x64") + (eq_attr "alternative" "9,10,11,12") + (const_string "sse2") + ] + (const_string "*"))) (set (attr "type") (cond [(eq_attr "alternative" "0,1,2") (const_string "fmov") (eq_attr "alternative" "3,4") (const_string "multi") - (eq_attr "alternative" "5,9") + (eq_attr "alternative" "5,6,7,8") + (const_string "imov") + (eq_attr "alternative" "9,13") (const_string "sselog1") ] (const_string "ssemov"))) + (set (attr "modrm") + (if_then_else (eq_attr "alternative" "8") + (const_string "0") + (const_string "*"))) + (set (attr "length_immediate") + (if_then_else (eq_attr "alternative" "8") + (const_string "8") + (const_string "*"))) (set (attr "prefix") - (if_then_else (eq_attr "alternative" "0,1,2,3,4") - (const_string "orig") - (const_string "maybe_vex"))) + (if_then_else (eq_attr "type" "sselog1,ssemov") + (const_string "maybe_vex") + (const_string "orig"))) (set (attr "prefix_data16") - (if_then_else (eq_attr "mode" "V1DF") + (if_then_else + (ior (and (eq_attr "type" "ssemov") (eq_attr "mode" "DI")) + (eq_attr "mode" "V1DF")) (const_string "1") (const_string "*"))) (set (attr "mode") - (cond [(eq_attr "alternative" "0,1,2") - (const_string "DF") - (eq_attr "alternative" "3,4") + (cond [(eq_attr "alternative" "3,4,7") (const_string "SI") + (eq_attr "alternative" "5,6,8,17,18") + (const_string "DI") - /* For SSE1, we have many fewer alternatives. */ - (not (match_test "TARGET_SSE2")) - (if_then_else - (eq_attr "alternative" "5,6,9,10") - (const_string "V4SF") - (const_string "V2SF")) - - /* xorps is one byte shorter for !TARGET_AVX. */ - (eq_attr "alternative" "5,9") - (cond [(match_test "TARGET_AVX") + /* xorps is one byte shorter for non-AVX targets. */ + (eq_attr "alternative" "9,13") + (cond [(not (match_test "TARGET_SSE2")) + (const_string "V4SF") + (match_test "TARGET_AVX") (const_string "V2DF") (match_test "optimize_function_for_size_p (cfun)") (const_string "V4SF") @@ -3191,12 +2879,13 @@ (const_string "V2DF")) /* For architectures resolving dependencies on - whole SSE registers use APD move to break dependency - chains, otherwise use short move to avoid extra work. + whole SSE registers use movapd to break dependency + chains, otherwise use short move to avoid extra work. */ - movaps encodes one byte shorter for !TARGET_AVX. */ - (eq_attr "alternative" "6,10") - (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL") + /* movaps is one byte shorter for non-AVX targets. */ + (eq_attr "alternative" "10,14") + (cond [(ior (not (match_test "TARGET_SSE2")) + (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")) (const_string "V4SF") (match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY") (const_string "V2DF") @@ -3204,25 +2893,33 @@ (const_string "DF") (match_test "optimize_function_for_size_p (cfun)") (const_string "V4SF") - ] - (const_string "DF")) + ] + (const_string "DF")) /* For architectures resolving dependencies on register parts we may avoid extra work to zero out upper part of register. */ - (eq_attr "alternative" "7,11") - (if_then_else - (match_test "TARGET_SSE_SPLIT_REGS") - (const_string "V1DF") - (const_string "DF")) + (eq_attr "alternative" "11,15") + (cond [(not (match_test "TARGET_SSE2")) + (const_string "V2SF") + (match_test "TARGET_AVX") + (const_string "DF") + (match_test "TARGET_SSE_SPLIT_REGS") + (const_string "V1DF") + ] + (const_string "DF")) + + (and (eq_attr "alternative" "12,16") + (not (match_test "TARGET_SSE2"))) + (const_string "V2SF") ] (const_string "DF")))]) (define_insn "*movsf_internal" [(set (match_operand:SF 0 "nonimmediate_operand" - "=Yf*f,m ,Yf*f,?r ,?m,x,x,x,m,!*y,!m,!*y,?Yi,?r,!*Ym,!r") + "=Yf*f,m ,Yf*f,?r ,?m,x,x,x,m,?r,?Yi,!*y,!*y,!m,!r ,!*Ym") (match_operand:SF 1 "general_operand" - "Yf*fm,Yf*f,G ,rmF,rF,C,x,m,x,m ,*y,*y ,r ,Yi,r ,*Ym"))] + "Yf*fm,Yf*f,G ,rmF,rF,C,x,m,x,Yi,r ,*y ,m ,*y,*Ym,r"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) @@ -3234,44 +2931,48 @@ && standard_sse_constant_p (operands[1])))) || memory_operand (operands[0], SFmode))" { - switch (which_alternative) + switch (get_attr_type (insn)) { - case 0: - case 1: + case TYPE_FMOV: + if (which_alternative == 2) + return standard_80387_constant_opcode (operands[1]); return output_387_reg_move (insn, operands); - case 2: - return standard_80387_constant_opcode (operands[1]); - - case 3: - case 4: + case TYPE_IMOV: return "mov{l}\t{%1, %0|%0, %1}"; - case 5: + case TYPE_SSELOG1: return standard_sse_constant_opcode (insn, operands[1]); - case 6: - if (get_attr_mode (insn) == MODE_V4SF) - return "%vmovaps\t{%1, %0|%0, %1}"; - if (TARGET_AVX) - return "vmovss\t{%1, %0, %0|%0, %0, %1}"; + case TYPE_SSEMOV: + switch (get_attr_mode (insn)) + { + case MODE_SF: + if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1])) + return "vmovss\t{%1, %0, %0|%0, %0, %1}"; + return "%vmovss\t{%1, %0|%0, %1}"; - case 7: - case 8: - return "%vmovss\t{%1, %0|%0, %1}"; + case MODE_V4SF: + return "%vmovaps\t{%1, %0|%0, %1}"; - case 9: - case 10: - case 14: - case 15: - return "movd\t{%1, %0|%0, %1}"; + case MODE_SI: + return "%vmovd\t{%1, %0|%0, %1}"; - case 11: - return "movq\t{%1, %0|%0, %1}"; + default: + gcc_unreachable (); + } - case 12: - case 13: - return "%vmovd\t{%1, %0|%0, %1}"; + case TYPE_MMXMOV: + switch (get_attr_mode (insn)) + { + case MODE_DI: + return "movq\t{%1, %0|%0, %1}"; + case MODE_SI: + return "movd\t{%1, %0|%0, %1}"; + + default: + gcc_unreachable (); + } default: gcc_unreachable (); @@ -3281,27 +2982,34 @@ (cond [(eq_attr "alternative" "0,1,2") (const_string "fmov") (eq_attr "alternative" "3,4") - (const_string "multi") + (const_string "imov") (eq_attr "alternative" "5") (const_string "sselog1") - (eq_attr "alternative" "9,10,11,14,15") + (eq_attr "alternative" "11,12,13,14,15") (const_string "mmxmov") ] (const_string "ssemov"))) (set (attr "prefix") - (if_then_else (eq_attr "alternative" "5,6,7,8,12,13") + (if_then_else (eq_attr "type" "sselog1,ssemov") (const_string "maybe_vex") (const_string "orig"))) + (set (attr "prefix_data16") + (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI")) + (const_string "1") + (const_string "*"))) (set (attr "mode") - (cond [(eq_attr "alternative" "3,4,9,10") + (cond [(eq_attr "alternative" "3,4,9,10,14,15") (const_string "SI") + (eq_attr "alternative" "11") + (const_string "DI") (eq_attr "alternative" "5") - (cond [(match_test "TARGET_AVX") - (const_string "V4SF") - (ior (not (match_test "TARGET_SSE2")) - (match_test "optimize_function_for_size_p (cfun)")) + (cond [(not (match_test "TARGET_SSE2")) (const_string "V4SF") - (match_test "TARGET_SSE_LOAD0_BY_PXOR") + (match_test "TARGET_AVX") + (const_string "V4SF") + (match_test "optimize_function_for_size_p (cfun)") + (const_string "V4SF") + (match_test "TARGET_SSE_LOAD0_BY_PXOR") (const_string "TI") ] (const_string "V4SF")) @@ -3316,15 +3024,12 @@ of instructions to load just part of the register. It is better to maintain the whole registers in single format to avoid problems on using packed logical operations. */ - (eq_attr "alternative" "6") - (if_then_else - (ior (match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY") - (match_test "TARGET_SSE_SPLIT_REGS")) - (const_string "V4SF") - (const_string "SF")) - (eq_attr "alternative" "11") - (const_string "DI")] - (const_string "SF")))]) + (and (eq_attr "alternative" "6") + (ior (match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY") + (match_test "TARGET_SSE_SPLIT_REGS"))) + (const_string "V4SF") + ] + (const_string "SF")))]) (define_split [(set (match_operand 0 "any_fp_register_operand") |