diff options
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r-- | gcc/config/i386/i386.md | 774 |
1 files changed, 224 insertions, 550 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 24d1012d5ce..e7eaabb333c 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"))] @@ -1758,10 +1794,11 @@ ] (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) { @@ -1793,12 +1830,14 @@ gcc_unreachable (); } } - [(set_attr "type" "*,*,sselog1,ssemov,ssemov") + [(set_attr "isa" "x64,x64,*,*,*") + (set_attr "type" "*,*,sselog1,ssemov,ssemov") (set_attr "prefix" "*,*,maybe_vex,maybe_vex,maybe_vex") (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,81 +1857,20 @@ [(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,m*y,*y,?*y,?r ,?*Ym,*x,m ,*x,*x,?r ,?*Yi,?*x,?*Ym") (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 ,m ,*Ym,r ,C ,*x,*x,m ,*Yi,r ,*Ym,*x"))] + "!(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: /* Handle broken assemblers that require movd instead of movq. */ @@ -1904,8 +1882,27 @@ 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: + return "%vmovq\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_V2SF: + gcc_assert (!TARGET_AVX); + return "movlps\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}"; @@ -1914,7 +1911,7 @@ 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}"; @@ -1922,16 +1919,27 @@ return "mov{q}\t{%1, %0|%0, %1}"; } } - [(set (attr "type") - (cond [(eq_attr "alternative" "4") + [(set (attr "isa") + (cond [(eq_attr "alternative" "0,1,8") + (const_string "nox64") + (eq_attr "alternative" "2,3,4,5,9,10,11,16,17") + (const_string "x64") + (eq_attr "alternative" "18,19") + (const_string "sse2") + ] + (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,159 +1947,43 @@ (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") (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,14") + (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") - ] - (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")) + (and (eq_attr "alternative" "13,15") + (not (match_test "TARGET_SSE2"))) + (const_string "V2SF") ] (const_string "DI")))]) @@ -2184,6 +2076,7 @@ (const_string "V4SF") ] (const_string "TI")) + (and (eq_attr "alternative" "8,9,10,11") (not (match_test "TARGET_SSE2"))) (const_string "SF") @@ -2582,16 +2475,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 +2497,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 +2522,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 +2558,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 +2602,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 +2610,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 @@ -2792,7 +2656,8 @@ gcc_unreachable (); } } - [(set_attr "type" "sselog1,ssemov,ssemov,*,*") + [(set_attr "isa" "*,*,*,x64,x64") + (set_attr "type" "sselog1,ssemov,ssemov,*,*") (set_attr "prefix" "maybe_vex,maybe_vex,maybe_vex,*,*") (set (attr "mode") (cond [(eq_attr "alternative" "3,4") @@ -2810,101 +2675,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 @@ -2925,166 +2702,30 @@ case 3: case 4: + case 5: 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 ,Yi,r") (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,r ,Yi"))] + "!(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,7 +2735,7 @@ || (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) @@ -3111,15 +2752,25 @@ return "#"; case 5: - case 9: - return standard_sse_constant_opcode (insn, operands[1]); - case 6: + return "mov{q}\t{%1, %0|%0, %1}"; + case 7: + return "mov{l}\t{%1, %k0|%k0, %1}"; + case 8: + return "movabs{q}\t{%1, %0|%0, %1}"; + + case 9: + case 13: + return standard_sse_constant_opcode (insn, operands[1]); + case 10: case 11: case 12: + case 14: + case 15: + case 16: switch (get_attr_mode (insn)) { case MODE_V2DF: @@ -3136,30 +2787,51 @@ case MODE_V1DF: return "%vmovlpd\t{%1, %d0|%d0, %1}"; case MODE_V2SF: - return "%vmovlps\t{%1, %d0|%d0, %1}"; + gcc_assert (!TARGET_AVX); + return "movlps\t{%1, %0|%0, %1}"; default: gcc_unreachable (); } + case 17: + case 18: + /* Handle broken assemblers that require movd instead of movq. */ + return "%vmovd\t{%1, %0|%0, %1}"; + default: gcc_unreachable (); } } [(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") + (if_then_else (eq_attr "alternative" "0,1,2,3,4,5,6,7,8") (const_string "orig") (const_string "maybe_vex"))) (set (attr "prefix_data16") @@ -3167,21 +2839,16 @@ (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") - - /* 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")) + (eq_attr "alternative" "5,6,8,17,18") + (const_string "DI") /* xorps is one byte shorter for !TARGET_AVX. */ - (eq_attr "alternative" "5,9") - (cond [(match_test "TARGET_AVX") + (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") @@ -3195,8 +2862,9 @@ 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") + (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") @@ -3210,11 +2878,17 @@ /* 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") + (eq_attr "alternative" "11,15") + (cond [(not (match_test "TARGET_SSE2")) + (const_string "V2SF") + (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")))]) |