X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fi386%2Fi386.md;h=2e7633dfc7de9afdf193b8def5c5837abfdeca75;hb=04a4c50efa63213eddc3d99a1022116e6e253910;hp=b74136368ae41fabce162c06367830df56ed431e;hpb=a23f3c3cdcda948154f4533b7b65e07bc5f5d7ea;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b74136368ae..2e7633dfc7d 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -53,6 +53,7 @@ ;; d -- print duplicated register operand for AVX instruction. ;; D -- print condition for SSE cmp instruction. ;; P -- if PIC, print an @PLT suffix. +;; p -- print raw symbol name. ;; X -- don't print any sort of PIC '@' suffix for a symbol. ;; & -- print some in-use local-dynamic symbol name. ;; H -- print a memory address offset by 8; used for sse high-parts @@ -108,6 +109,7 @@ UNSPEC_TRUNC_NOOP UNSPEC_DIV_ALREADY_SPLIT UNSPEC_CALL_NEEDS_VZEROUPPER + UNSPEC_PAUSE ;; For SSE/MMX support: UNSPEC_FIX_NOTRUNC @@ -224,8 +226,6 @@ UNSPEC_VPERMIL UNSPEC_VPERMIL2 UNSPEC_VPERMIL2F128 - UNSPEC_MASKLOAD - UNSPEC_MASKSTORE UNSPEC_CAST UNSPEC_VTESTP UNSPEC_VCVTPH2PS @@ -416,9 +416,9 @@ (const_int 0) (eq_attr "type" "alu,alu1,negnot,imovx,ishift,rotate,ishift1,rotate1, imul,icmp,push,pop") - (symbol_ref "ix86_attr_length_immediate_default(insn,1)") + (symbol_ref "ix86_attr_length_immediate_default (insn, true)") (eq_attr "type" "imov,test") - (symbol_ref "ix86_attr_length_immediate_default(insn,0)") + (symbol_ref "ix86_attr_length_immediate_default (insn, false)") (eq_attr "type" "call") (if_then_else (match_operand 0 "constant_call_address_operand" "") (const_int 4) @@ -526,11 +526,11 @@ (if_then_else (and (eq_attr "prefix_0f" "1") (eq_attr "prefix_extra" "0")) (if_then_else (eq_attr "prefix_vex_w" "1") - (symbol_ref "ix86_attr_length_vex_default (insn, 1, 1)") - (symbol_ref "ix86_attr_length_vex_default (insn, 1, 0)")) + (symbol_ref "ix86_attr_length_vex_default (insn, true, true)") + (symbol_ref "ix86_attr_length_vex_default (insn, true, false)")) (if_then_else (eq_attr "prefix_vex_w" "1") - (symbol_ref "ix86_attr_length_vex_default (insn, 0, 1)") - (symbol_ref "ix86_attr_length_vex_default (insn, 0, 0)")))) + (symbol_ref "ix86_attr_length_vex_default (insn, false, true)") + (symbol_ref "ix86_attr_length_vex_default (insn, false, false)")))) ;; Set when modrm byte is used. (define_attr "modrm" "" @@ -698,6 +698,16 @@ ;; Define attribute to indicate unaligned ssemov insns (define_attr "movu" "0,1" (const_string "0")) +;; Used to control the "enabled" attribute on a per-instruction basis. +(define_attr "isa" "base,noavx,avx" + (const_string "base")) + +(define_attr "enabled" "" + (cond [(eq_attr "isa" "noavx") (symbol_ref "!TARGET_AVX") + (eq_attr "isa" "avx") (symbol_ref "TARGET_AVX") + ] + (const_int 1))) + ;; Describe a user's asm statement. (define_asm_attributes [(set_attr "length" "128") @@ -926,8 +936,16 @@ ;; All integer modes handled by SSE cvtts?2si* operators. (define_mode_iterator SSEMODEI24 [SI DI]) -;; SSE asm suffix for floating point modes -(define_mode_attr ssemodefsuffix [(SF "s") (DF "d")]) +;; SSE instruction suffix for various modes +(define_mode_attr ssemodesuffix + [(SF "ss") (DF "sd") + (V8SF "ps") (V4DF "pd") + (V4SF "ps") (V2DF "pd") + (V16QI "b") (V8HI "w") (V4SI "d") (V2DI "q") + (V8SI "si")]) + +;; SSE vector suffix for floating point modes +(define_mode_attr ssevecmodesuffix [(SF "ps") (DF "pd")]) ;; SSE vector mode corresponding to a scalar mode (define_mode_attr ssevecmode @@ -1246,7 +1264,7 @@ UNSPEC_FNSTSW))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2])" - "* return output_fp_compare (insn, operands, 0, 0);" + "* return output_fp_compare (insn, operands, false, false);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set (attr "mode") @@ -1293,7 +1311,7 @@ (match_operand:XF 2 "register_operand" "f"))] UNSPEC_FNSTSW))] "TARGET_80387" - "* return output_fp_compare (insn, operands, 0, 0);" + "* return output_fp_compare (insn, operands, false, false);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set_attr "mode" "XF")]) @@ -1327,7 +1345,7 @@ (match_operand:MODEF 2 "nonimmediate_operand" "fm"))] UNSPEC_FNSTSW))] "TARGET_80387" - "* return output_fp_compare (insn, operands, 0, 0);" + "* return output_fp_compare (insn, operands, false, false);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set_attr "mode" "")]) @@ -1362,7 +1380,7 @@ UNSPEC_FNSTSW))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2])" - "* return output_fp_compare (insn, operands, 0, 1);" + "* return output_fp_compare (insn, operands, false, true);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set (attr "mode") @@ -1412,7 +1430,7 @@ "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && (TARGET_USE_MODE_FIOP || optimize_function_for_size_p (cfun)) && (GET_MODE (operands [3]) == GET_MODE (operands[1]))" - "* return output_fp_compare (insn, operands, 0, 0);" + "* return output_fp_compare (insn, operands, false, false);" [(set_attr "type" "multi") (set_attr "unit" "i387") (set_attr "fp_int_src" "true") @@ -1488,7 +1506,7 @@ "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 0);" + "* return output_fp_compare (insn, operands, true, false);" [(set_attr "type" "fcmp,ssecomi") (set_attr "prefix" "orig,maybe_vex") (set (attr "mode") @@ -1517,7 +1535,7 @@ "TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 0);" + "* return output_fp_compare (insn, operands, true, false);" [(set_attr "type" "ssecomi") (set_attr "prefix" "maybe_vex") (set (attr "mode") @@ -1541,7 +1559,7 @@ && TARGET_CMOVE && !(SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && TARGET_SSE_MATH) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 0);" + "* return output_fp_compare (insn, operands, true, false);" [(set_attr "type" "fcmp") (set (attr "mode") (cond [(match_operand:SF 1 "" "") @@ -1561,7 +1579,7 @@ "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 1);" + "* return output_fp_compare (insn, operands, true, true);" [(set_attr "type" "fcmp,ssecomi") (set_attr "prefix" "orig,maybe_vex") (set (attr "mode") @@ -1590,7 +1608,7 @@ "TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 1);" + "* return output_fp_compare (insn, operands, true, true);" [(set_attr "type" "ssecomi") (set_attr "prefix" "maybe_vex") (set (attr "mode") @@ -1614,7 +1632,7 @@ && TARGET_CMOVE && !(SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && TARGET_SSE_MATH) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 1);" + "* return output_fp_compare (insn, operands, true, true);" [(set_attr "type" "fcmp") (set (attr "mode") (cond [(match_operand:SF 1 "" "") @@ -1877,15 +1895,15 @@ { if (get_attr_mode (insn) == MODE_V4SF) return "%vmovups\t{%1, %0|%0, %1}"; - else - return "%vmovdqu\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}"; + else + return "%vmovdqa\t{%1, %0|%0, %1}"; } default: gcc_unreachable (); @@ -1940,15 +1958,15 @@ { if (get_attr_mode (insn) == MODE_V4SF) return "%vmovups\t{%1, %0|%0, %1}"; - else - return "%vmovdqu\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}"; + else + return "%vmovdqa\t{%1, %0|%0, %1}"; } default: gcc_unreachable (); @@ -1983,24 +2001,20 @@ return "movdq2q\t{%1, %0|%0, %1}"; case TYPE_SSEMOV: - if (TARGET_AVX) - { - if (get_attr_mode (insn) == MODE_TI) - return "vmovdqa\t{%1, %0|%0, %1}"; - else - return "vmovq\t{%1, %0|%0, %1}"; - } - if (get_attr_mode (insn) == MODE_TI) - return "movdqa\t{%1, %0|%0, %1}"; - /* FALLTHRU */ + return "%vmovdqa\t{%1, %0|%0, %1}"; + /* 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_MMXMOV: - /* Moves from and into integer register is done using movd - opcode with REX prefix. */ + /* 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}"; - return "movq\t{%1, %0|%0, %1}"; + else + return "movq\t{%1, %0|%0, %1}"; case TYPE_SSELOG1: return "%vpxor\t%0, %d0"; @@ -2114,10 +2128,14 @@ movlps\t{%1, %0|%0, %1} movaps\t{%1, %0|%0, %1} movlps\t{%1, %0|%0, %1}" - [(set_attr "type" "*,*,mmx,mmxmov,mmxmov,sselog1,ssemov,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov") + [(set (attr "isa") + (if_then_else (eq_attr "alternative" "9,10,11,12") + (const_string "noavx") + (const_string "base"))) + (set_attr "type" "*,*,mmx,mmxmov,mmxmov,sselog1,ssemov,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov") (set (attr "prefix") (if_then_else (eq_attr "alternative" "5,6,7,8") - (const_string "vex") + (const_string "maybe_vex") (const_string "orig"))) (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")]) @@ -2417,6 +2435,9 @@ { if (TARGET_PARTIAL_REG_STALL && optimize_function_for_speed_p (cfun)) FAIL; + if (GET_CODE (operands[0]) == SUBREG + && GET_MODE_CLASS (GET_MODE (SUBREG_REG (operands[0]))) != MODE_INT) + FAIL; /* Don't generate memory->memory moves, go through a register */ if (MEM_P (operands[0]) && MEM_P (operands[1])) operands[1] = force_reg (mode, operands[1]); @@ -2468,10 +2489,9 @@ } } [(set (attr "type") - (if_then_else (and (match_operand:QI 0 "register_operand" "") - (ior (not (match_operand:QI 0 "q_regs_operand" "")) - (ne (symbol_ref "TARGET_MOVX") - (const_int 0)))) + (if_then_else (ior (not (match_operand:QI 0 "QIreg_operand" "")) + (ne (symbol_ref "TARGET_MOVX") + (const_int 0))) (const_string "imovx") (const_string "imov"))) (set (attr "mode") @@ -2496,7 +2516,7 @@ } [(set (attr "type") (if_then_else (and (match_operand:QI 0 "register_operand" "") - (ior (not (match_operand:QI 0 "q_regs_operand" "")) + (ior (not (match_operand:QI 0 "QIreg_operand" "")) (ne (symbol_ref "TARGET_MOVX") (const_int 0)))) (const_string "imovx") @@ -2533,7 +2553,7 @@ } } [(set (attr "type") - (if_then_else (ior (not (match_operand:QI 0 "q_regs_operand" "")) + (if_then_else (ior (not (match_operand:QI 0 "QIreg_operand" "")) (ne (symbol_ref "TARGET_MOVX") (const_int 0))) (const_string "imovx") @@ -2561,7 +2581,7 @@ } [(set (attr "type") (if_then_else (and (match_operand:QI 0 "register_operand" "") - (ior (not (match_operand:QI 0 "q_regs_operand" "")) + (ior (not (match_operand:QI 0 "QIreg_operand" "")) (ne (symbol_ref "TARGET_MOVX") (const_int 0)))) (const_string "imovx") @@ -2683,10 +2703,14 @@ [(const_int 0)] "ix86_split_long_move (operands); DONE;") +;; 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,rFo,Y2"))] - "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES" + (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFo,Y2"))] + "" { /* This insn should be already split before reg-stack. */ gcc_unreachable (); @@ -2695,23 +2719,6 @@ (set_attr "unit" "i387,*,*") (set_attr "mode" "DF,SI,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. Allow this -;; pattern for optimize_size too. - -(define_insn "*pushdf_nointeger" - [(set (match_operand:DF 0 "push_operand" "=<,<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y2"))] - "!(TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES)" -{ - /* This insn should be already split before reg-stack. */ - gcc_unreachable (); -} - [(set_attr "type" "multi") - (set_attr "unit" "i387,*,*,*") - (set_attr "mode" "DF,SI,SI,DF")]) - ;; %%% Kill this when call knows how to work this out. (define_split [(set (match_operand:DF 0 "push_operand" "") @@ -2803,14 +2810,14 @@ return "%vmovaps\t{%1, %0|%0, %1}"; else return "%vmovdqa\t{%1, %0|%0, %1}"; + case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "%vxorps\t%0, %d0"; - else - return "%vpxor\t%0, %d0"; + return standard_sse_constant_opcode (insn, operands[1]); + case 3: case 4: return "#"; + default: gcc_unreachable (); } @@ -2843,42 +2850,14 @@ "ix86_split_long_move (operands); DONE;") (define_insn "*movxf_internal" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o") - (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))] - "optimize_function_for_speed_p (cfun) - && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (reload_in_progress || reload_completed - || GET_CODE (operands[1]) != CONST_DOUBLE - || 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")]) - -;; Do not use integer registers when optimizing for size -(define_insn "*movxf_internal_nointeger" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o") - (match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))] - "optimize_function_for_size_p (cfun) - && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (reload_in_progress || reload_completed - || standard_80387_constant_p (operands[1]) + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,Yx*r ,o") + (match_operand:XF 1 "general_operand" "fm,f,G,Yx*roF,FYx*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 + || (optimize_function_for_size_p (cfun) + && standard_80387_constant_p (operands[1]) > 0) || memory_operand (operands[0], XFmode))" { switch (which_alternative) @@ -2919,12 +2898,14 @@ (match_operand:DF 1 "general_operand" "fm,f,G,rm,r,F ,F ,C ,Y2*x,m ,Y2*x,r ,Yi"))] "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (reload_in_progress || reload_completed + && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || (!(TARGET_SSE2 && TARGET_SSE_MATH) - && optimize_function_for_size_p (cfun) - && standard_80387_constant_p (operands[1])) || 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) @@ -2947,23 +2928,8 @@ return "#"; case 7: - switch (get_attr_mode (insn)) - { - case MODE_V4SF: - return "%vxorps\t%0, %d0"; - case MODE_V2DF: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vxorpd\t%0, %d0"; - case MODE_TI: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vpxor\t%0, %d0"; - default: - gcc_unreachable (); - } + return standard_sse_constant_opcode (insn, operands[1]); + case 8: case 9: case 10: @@ -2984,15 +2950,10 @@ case MODE_DI: return "%vmovq\t{%1, %0|%0, %1}"; case MODE_DF: - if (TARGET_AVX) - { - if (REG_P (operands[0]) && REG_P (operands[1])) - return "vmovsd\t{%1, %0, %0|%0, %0, %1}"; - else - return "vmovsd\t{%1, %0|%0, %1}"; - } + if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1])) + return "vmovsd\t{%1, %0, %0|%0, %0, %1}"; else - return "movsd\t{%1, %0|%0, %1}"; + return "%vmovsd\t{%1, %0|%0, %1}"; case MODE_V1DF: return "%vmovlpd\t{%1, %d0|%d0, %1}"; case MODE_V2SF: @@ -3003,7 +2964,8 @@ case 11: case 12: - return "%vmovd\t{%1, %0|%0, %1}"; + /* Handle broken assemblers that require movd instead of movq. */ + return "%vmovd\t{%1, %0|%0, %1}"; default: gcc_unreachable(); @@ -3079,21 +3041,25 @@ ] (const_string "DF")))]) +;; Possible store forwarding (partial memory) stall in alternative 4. (define_insn "*movdf_internal" [(set (match_operand:DF 0 "nonimmediate_operand" - "=f,m,f,r ,o ,Y2*x,Y2*x,Y2*x,m ") + "=f,m,f,Yd*r ,o ,Y2*x,Y2*x,Y2*x,m ") (match_operand:DF 1 "general_operand" - "fm,f,G,roF,Fr,C ,Y2*x,m ,Y2*x"))] + "fm,f,G,Yd*roF,FYd*r,C ,Y2*x,m ,Y2*x"))] "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && optimize_function_for_speed_p (cfun) - && TARGET_INTEGER_DFMODE_MOVES - && (reload_in_progress || reload_completed + && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || (!(TARGET_SSE2 && TARGET_SSE_MATH) - && optimize_function_for_size_p (cfun) - && standard_80387_constant_p (operands[1])) || GET_CODE (operands[1]) != CONST_DOUBLE - || memory_operand (operands[0], DFmode))" + || (!TARGET_INTEGER_DFMODE_MOVES + && ((!(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)) + || ((TARGET_INTEGER_DFMODE_MOVES + || !TARGET_MEMORY_MISMATCH_STALL) + && memory_operand (operands[0], DFmode)))" { switch (which_alternative) { @@ -3109,167 +3075,8 @@ return "#"; case 5: - switch (get_attr_mode (insn)) - { - case MODE_V4SF: - return "xorps\t%0, %0"; - case MODE_V2DF: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "xorps\t%0, %0"; - else - return "xorpd\t%0, %0"; - case MODE_TI: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "xorps\t%0, %0"; - else - return "pxor\t%0, %0"; - default: - gcc_unreachable (); - } - case 6: - case 7: - case 8: - switch (get_attr_mode (insn)) - { - case MODE_V4SF: - return "movaps\t{%1, %0|%0, %1}"; - case MODE_V2DF: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movapd\t{%1, %0|%0, %1}"; - case MODE_TI: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movdqa\t{%1, %0|%0, %1}"; - case MODE_DI: - return "movq\t{%1, %0|%0, %1}"; - case MODE_DF: - return "movsd\t{%1, %0|%0, %1}"; - case MODE_V1DF: - return "movlpd\t{%1, %0|%0, %1}"; - case MODE_V2SF: - return "movlps\t{%1, %0|%0, %1}"; - default: - gcc_unreachable (); - } - - default: - gcc_unreachable(); - } -} - [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov") - (set (attr "prefix_data16") - (if_then_else (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") - (const_string "SI") - - /* For SSE1, we have many fewer alternatives. */ - (eq (symbol_ref "TARGET_SSE2") (const_int 0)) - (cond [(eq_attr "alternative" "5,6") - (const_string "V4SF") - ] - (const_string "V2SF")) - - /* xorps is one byte shorter. */ - (eq_attr "alternative" "5") - (cond [(ne (symbol_ref "optimize_function_for_size_p (cfun)") - (const_int 0)) - (const_string "V4SF") - (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") - (const_int 0)) - (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. */ - (eq_attr "alternative" "6") - (cond - [(ne (symbol_ref "optimize_function_for_size_p (cfun)") - (const_int 0)) - (const_string "V4SF") - (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") - (const_int 0)) - (const_string "V2DF") - ] - (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") - (if_then_else - (ne (symbol_ref "TARGET_SSE_SPLIT_REGS") - (const_int 0)) - (const_string "V1DF") - (const_string "DF")) - ] - (const_string "DF")))]) - -;; Moving is usually shorter when only FP registers are used. This separate -;; movdf pattern avoids the use of integer registers for FP operations -;; when optimizing for size. - -(define_insn "*movdf_internal_nointeger" - [(set (match_operand:DF 0 "nonimmediate_operand" - "=f,m,f,*r ,o ,Y2*x,Y2*x,Y2*x ,m ") - (match_operand:DF 1 "general_operand" - "fm,f,G,*roF,*Fr,C ,Y2*x,mY2*x,Y2*x"))] - "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1])) - && (optimize_function_for_size_p (cfun) - || !TARGET_INTEGER_DFMODE_MOVES) - && (reload_in_progress || reload_completed - || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || (!(TARGET_SSE2 && TARGET_SSE_MATH) - && optimize_function_for_size_p (cfun) - && !memory_operand (operands[0], DFmode) - && standard_80387_constant_p (operands[1])) - || GET_CODE (operands[1]) != CONST_DOUBLE - || ((optimize_function_for_size_p (cfun) - || !TARGET_MEMORY_MISMATCH_STALL - || reload_in_progress || reload_completed) - && 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 "#"; + return standard_sse_constant_opcode (insn, operands[1]); - case 5: - switch (get_attr_mode (insn)) - { - case MODE_V4SF: - return "%vxorps\t%0, %d0"; - case MODE_V2DF: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vxorpd\t%0, %d0"; - case MODE_TI: - if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) - return "%vxorps\t%0, %d0"; - else - return "%vpxor\t%0, %d0"; - default: - gcc_unreachable (); - } case 6: case 7: case 8: @@ -3290,35 +3097,20 @@ case MODE_DI: return "%vmovq\t{%1, %0|%0, %1}"; case MODE_DF: - if (TARGET_AVX) - { - if (REG_P (operands[0]) && REG_P (operands[1])) - return "vmovsd\t{%1, %0, %0|%0, %0, %1}"; - else - return "vmovsd\t{%1, %0|%0, %1}"; - } + if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1])) + return "vmovsd\t{%1, %0, %0|%0, %0, %1}"; else - return "movsd\t{%1, %0|%0, %1}"; + return "%vmovsd\t{%1, %0|%0, %1}"; case MODE_V1DF: - if (TARGET_AVX) - { - if (REG_P (operands[0])) - return "vmovlpd\t{%1, %0, %0|%0, %0, %1}"; - else - return "vmovlpd\t{%1, %0|%0, %1}"; - } + if (TARGET_AVX && REG_P (operands[0])) + return "vmovlpd\t{%1, %0, %0|%0, %0, %1}"; else - return "movlpd\t{%1, %0|%0, %1}"; + return "%vmovlpd\t{%1, %0|%0, %1}"; case MODE_V2SF: - if (TARGET_AVX) - { - if (REG_P (operands[0])) - return "vmovlps\t{%1, %0, %0|%0, %0, %1}"; - else - return "vmovlps\t{%1, %0|%0, %1}"; - } + if (TARGET_AVX && REG_P (operands[0])) + return "vmovlps\t{%1, %0, %0|%0, %0, %1}"; else - return "movlps\t{%1, %0|%0, %1}"; + return "%vmovlps\t{%1, %0|%0, %1}"; default: gcc_unreachable (); } @@ -3407,11 +3199,14 @@ (match_operand:SF 1 "general_operand" "fm,f,G,rmF,Fr,C,x,xm,x,m ,*y,*y ,r ,Yi,r ,*Ym"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) - && (reload_in_progress || reload_completed + && (!can_create_pseudo_p () || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || (!TARGET_SSE_MATH && optimize_function_for_size_p (cfun) - && standard_80387_constant_p (operands[1])) || GET_CODE (operands[1]) != CONST_DOUBLE + || (optimize_function_for_size_p (cfun) + && ((!TARGET_SSE_MATH + && standard_80387_constant_p (operands[1]) > 0) + || (TARGET_SSE_MATH + && standard_sse_constant_p (operands[1])))) || memory_operand (operands[0], SFmode))" { switch (which_alternative) @@ -3426,33 +3221,32 @@ case 3: case 4: return "mov{l}\t{%1, %0|%0, %1}"; + case 5: - if (get_attr_mode (insn) == MODE_TI) - return "%vpxor\t%0, %d0"; - else - return "%vxorps\t%0, %d0"; + return standard_sse_constant_opcode (insn, operands[1]); + case 6: if (get_attr_mode (insn) == MODE_V4SF) return "%vmovaps\t{%1, %0|%0, %1}"; else return "%vmovss\t{%1, %d0|%d0, %1}"; case 7: - if (TARGET_AVX) - return REG_P (operands[1]) ? "vmovss\t{%1, %0, %0|%0, %0, %1}" - : "vmovss\t{%1, %0|%0, %1}"; + if (TARGET_AVX && REG_P (operands[1])) + return "vmovss\t{%1, %0, %0|%0, %0, %1}"; else - return "movss\t{%1, %0|%0, %1}"; + return "%vmovss\t{%1, %0|%0, %1}"; case 8: return "%vmovss\t{%1, %0|%0, %1}"; case 9: case 10: case 14: case 15: return "movd\t{%1, %0|%0, %1}"; - case 12: case 13: - return "%vmovd\t{%1, %0|%0, %1}"; case 11: return "movq\t{%1, %0|%0, %1}"; + case 12: case 13: + return "%vmovd\t{%1, %0|%0, %1}"; + default: gcc_unreachable (); } @@ -3522,7 +3316,7 @@ } else if (FP_REG_P (r)) { - if (!standard_80387_constant_p (c)) + if (standard_80387_constant_p (c) < 1) FAIL; } else if (MMX_REG_P (r)) @@ -3554,7 +3348,7 @@ } else if (FP_REG_P (r)) { - if (!standard_80387_constant_p (c)) + if (standard_80387_constant_p (c) < 1) FAIL; } else if (MMX_REG_P (r)) @@ -4045,7 +3839,7 @@ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" { /* ??? Needed for compress_float_constant since all fp constants - are LEGITIMATE_CONSTANT_P. */ + are TARGET_LEGITIMATE_CONSTANT_P. */ if (GET_CODE (operands[1]) == CONST_DOUBLE) { if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387) @@ -4151,7 +3945,7 @@ "TARGET_80387" { /* ??? Needed for compress_float_constant since all fp constants - are LEGITIMATE_CONSTANT_P. */ + are TARGET_LEGITIMATE_CONSTANT_P. */ if (GET_CODE (operands[1]) == CONST_DOUBLE) { if (standard_80387_constant_p (operands[1]) > 0) @@ -4599,7 +4393,7 @@ (fix:DI (match_operand:MODEF 1 "nonimmediate_operand" "x,m")))] "TARGET_64BIT && SSE_FLOAT_MODE_P (mode) && (!TARGET_FISTTP || TARGET_SSE_MATH)" - "%vcvtts2si{q}\t{%1, %0|%0, %1}" + "%vcvtt2si{q}\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") (set_attr "prefix" "maybe_vex") (set_attr "prefix_rex" "1") @@ -4613,7 +4407,7 @@ (fix:SI (match_operand:MODEF 1 "nonimmediate_operand" "x,m")))] "SSE_FLOAT_MODE_P (mode) && (!TARGET_FISTTP || TARGET_SSE_MATH)" - "%vcvtts2si\t{%1, %0|%0, %1}" + "%vcvtt2si\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") (set_attr "prefix" "maybe_vex") (set_attr "mode" "") @@ -4685,7 +4479,7 @@ && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && (TARGET_64BIT || mode != DImode)) && TARGET_SSE_MATH)" - "* return output_fix_trunc (insn, operands, 1);" + "* return output_fix_trunc (insn, operands, true);" [(set_attr "type" "fisttp") (set_attr "mode" "")]) @@ -4769,7 +4563,7 @@ "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && !TARGET_FISTTP && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "trunc") (set_attr "mode" "DI")]) @@ -4824,7 +4618,7 @@ "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && !TARGET_FISTTP && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "trunc") (set_attr "mode" "")]) @@ -5113,8 +4907,8 @@ && (TARGET_INTER_UNIT_CONVERSIONS || optimize_function_for_size_p (cfun))" "@ fild%Z1\t%1 - %vcvtsi2s\t{%1, %d0|%d0, %1} - %vcvtsi2s\t{%1, %d0|%d0, %1}" + %vcvtsi2\t{%1, %d0|%d0, %1} + %vcvtsi2\t{%1, %d0|%d0, %1}" [(set_attr "type" "fmov,sseicvt,sseicvt") (set_attr "prefix" "orig,maybe_vex,maybe_vex") (set_attr "mode" "") @@ -5139,7 +4933,7 @@ && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_function_for_size_p (cfun))" "@ fild%Z1\t%1 - %vcvtsi2s\t{%1, %d0|%d0, %1}" + %vcvtsi2\t{%1, %d0|%d0, %1}" [(set_attr "type" "fmov,sseicvt") (set_attr "prefix" "orig,maybe_vex") (set_attr "mode" "") @@ -5219,7 +5013,7 @@ CONST0_RTX (V4SImode), operands[2])); } emit_insn - (gen_sse2_cvtdq2p (operands[3], operands[4])); + (gen_sse2_cvtdq2 (operands[3], operands[4])); DONE; }) @@ -5242,7 +5036,7 @@ emit_insn (gen_sse2_loadld (operands[4], CONST0_RTX (V4SImode), operands[1])); emit_insn - (gen_sse2_cvtdq2p (operands[3], operands[4])); + (gen_sse2_cvtdq2 (operands[3], operands[4])); DONE; }) @@ -5277,7 +5071,7 @@ else gcc_unreachable (); emit_insn - (gen_sse2_cvtdq2p (operands[3], operands[4])); + (gen_sse2_cvtdq2 (operands[3], operands[4])); DONE; }) @@ -5299,7 +5093,7 @@ emit_insn (gen_sse2_loadld (operands[4], CONST0_RTX (V4SImode), operands[1])); emit_insn - (gen_sse2_cvtdq2p (operands[3], operands[4])); + (gen_sse2_cvtdq2 (operands[3], operands[4])); DONE; }) @@ -5325,7 +5119,7 @@ "(mode != DImode || TARGET_64BIT) && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH && (TARGET_INTER_UNIT_CONVERSIONS || optimize_function_for_size_p (cfun))" - "%vcvtsi2s\t{%1, %d0|%d0, %1}" + "%vcvtsi2\t{%1, %d0|%d0, %1}" [(set_attr "type" "sseicvt") (set_attr "prefix" "maybe_vex") (set_attr "mode" "") @@ -5360,7 +5154,7 @@ "(mode != DImode || TARGET_64BIT) && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_function_for_size_p (cfun))" - "%vcvtsi2s\t{%1, %d0|%d0, %1}" + "%vcvtsi2\t{%1, %d0|%d0, %1}" [(set_attr "type" "sseicvt") (set_attr "prefix" "maybe_vex") (set_attr "mode" "") @@ -6065,7 +5859,7 @@ ;; Convert lea to the lea pattern to avoid flags dependency. ;; ??? This pattern handles immediate operands that do not satisfy immediate -;; operand predicate (LEGITIMATE_CONSTANT_P) in the previous pattern. +;; operand predicate (TARGET_LEGITIMATE_CONSTANT_P) in the previous pattern. (define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") @@ -7921,7 +7715,7 @@ (if_then_else (and (eq_attr "type" "imovx") (and (ne (symbol_ref "INTVAL (operands[2]) == 0xff") (const_int 0)) - (match_operand 1 "ext_QIreg_nomode_operand" ""))) + (match_operand 1 "ext_QIreg_operand" ""))) (const_string "1") (const_string "*"))) (set_attr "mode" "SI,DI,DI,SI")]) @@ -7965,7 +7759,7 @@ (if_then_else (and (eq_attr "type" "imovx") (and (ne (symbol_ref "INTVAL (operands[2]) == 0xff") (const_int 0)) - (match_operand 1 "ext_QIreg_nomode_operand" ""))) + (match_operand 1 "ext_QIreg_operand" ""))) (const_string "1") (const_string "*"))) (set_attr "length_immediate" "*,*,0") @@ -8008,7 +7802,7 @@ (set (attr "prefix_rex") (if_then_else (and (eq_attr "type" "imovx") - (match_operand 1 "ext_QIreg_nomode_operand" "")) + (match_operand 1 "ext_QIreg_operand" "")) (const_string "1") (const_string "*"))) (set_attr "mode" "HI,HI,SI")]) @@ -10382,14 +10176,17 @@ }) (define_expand "insv" - [(set (zero_extract (match_operand 0 "ext_register_operand" "") - (match_operand 1 "const8_operand" "") - (match_operand 2 "const8_operand" "")) + [(set (zero_extract (match_operand 0 "register_operand" "") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")) (match_operand 3 "register_operand" ""))] "" { rtx (*gen_mov_insv_1) (rtx, rtx); + if (ix86_expand_pinsr (operands)) + DONE; + /* Handle insertions to %ah et al. */ if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8) FAIL; @@ -10708,27 +10505,19 @@ ;; 0xffffffff is NaN, but not in normalized form, so we can't represent ;; it directly. -(define_insn "*avx_setcc" - [(set (match_operand:MODEF 0 "register_operand" "=x") - (match_operator:MODEF 1 "avx_comparison_float_operator" - [(match_operand:MODEF 2 "register_operand" "x") - (match_operand:MODEF 3 "nonimmediate_operand" "xm")]))] - "TARGET_AVX" - "vcmp%D1s\t{%3, %2, %0|%0, %2, %3}" - [(set_attr "type" "ssecmp") - (set_attr "prefix" "vex") - (set_attr "length_immediate" "1") - (set_attr "mode" "")]) - -(define_insn "*sse_setcc" - [(set (match_operand:MODEF 0 "register_operand" "=x") - (match_operator:MODEF 1 "sse_comparison_operator" - [(match_operand:MODEF 2 "register_operand" "0") - (match_operand:MODEF 3 "nonimmediate_operand" "xm")]))] +(define_insn "setcc__sse" + [(set (match_operand:MODEF 0 "register_operand" "=x,x") + (match_operator:MODEF 3 "sse_comparison_operator" + [(match_operand:MODEF 1 "register_operand" "0,x") + (match_operand:MODEF 2 "nonimmediate_operand" "xm,xm")]))] "SSE_FLOAT_MODE_P (mode)" - "cmp%D1s\t{%3, %0|%0, %3}" - [(set_attr "type" "ssecmp") + "@ + cmp%D3\t{%2, %0|%0, %2} + vcmp%D3\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "type" "ssecmp") (set_attr "length_immediate" "1") + (set_attr "prefix" "orig,vex") (set_attr "mode" "")]) ;; Basic conditional jump instructions. @@ -11276,56 +11065,134 @@ ;; P6 processors will jump to the address after the decrement when %esp ;; is used as a call operand, so they will execute return address as a code. ;; See Pentium Pro errata 70, Pentium 2 errata A33 and Pentium 3 errata E17. - + +;; Register constraint for call instruction. +(define_mode_attr c [(SI "l") (DI "r")]) + ;; Call subroutine returning no value. -(define_expand "call_pop" - [(parallel [(call (match_operand:QI 0 "" "") - (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "" "")))])] - "!TARGET_64BIT" +(define_expand "call" + [(call (match_operand:QI 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" ""))] + "" { ix86_expand_call (NULL, operands[0], operands[1], - operands[2], operands[3], 0); + operands[2], NULL, false); DONE; }) -(define_insn_and_split "*call_pop_0_vzeroupper" - [(parallel - [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" "")) - (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "")))]) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT" - "#" - "&& reload_completed" +(define_expand "sibcall" + [(call (match_operand:QI 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" ""))] + "" +{ + ix86_expand_call (NULL, operands[0], operands[1], + operands[2], NULL, true); + DONE; +}) + +(define_insn_and_split "*call_vzeroupper" + [(call (mem:QI (match_operand:P 0 "call_insn_operand" "zm")) + (match_operand 1 "" "")) + (unspec [(match_operand 2 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && !SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" + "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" [(set_attr "type" "call")]) -(define_insn "*call_pop_0" - [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" "")) - (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "")))] +(define_insn "*call" + [(call (mem:QI (match_operand:P 0 "call_insn_operand" "zm")) + (match_operand 1 "" ""))] + "!SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[0]);" + [(set_attr "type" "call")]) + +(define_insn_and_split "*call_rex64_ms_sysv_vzeroupper" + [(parallel + [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzm")) + (match_operand 1 "" "")) + (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) + (clobber (reg:TI XMM6_REG)) + (clobber (reg:TI XMM7_REG)) + (clobber (reg:TI XMM8_REG)) + (clobber (reg:TI XMM9_REG)) + (clobber (reg:TI XMM10_REG)) + (clobber (reg:TI XMM11_REG)) + (clobber (reg:TI XMM12_REG)) + (clobber (reg:TI XMM13_REG)) + (clobber (reg:TI XMM14_REG)) + (clobber (reg:TI XMM15_REG)) + (clobber (reg:DI SI_REG)) + (clobber (reg:DI DI_REG))]) + (unspec [(match_operand 2 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" + [(set_attr "type" "call")]) + +(define_insn "*call_rex64_ms_sysv" + [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzm")) + (match_operand 1 "" "")) + (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) + (clobber (reg:TI XMM6_REG)) + (clobber (reg:TI XMM7_REG)) + (clobber (reg:TI XMM8_REG)) + (clobber (reg:TI XMM9_REG)) + (clobber (reg:TI XMM10_REG)) + (clobber (reg:TI XMM11_REG)) + (clobber (reg:TI XMM12_REG)) + (clobber (reg:TI XMM13_REG)) + (clobber (reg:TI XMM14_REG)) + (clobber (reg:TI XMM15_REG)) + (clobber (reg:DI SI_REG)) + (clobber (reg:DI DI_REG))] + "TARGET_64BIT && !SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[0]);" + [(set_attr "type" "call")]) + +(define_insn_and_split "*sibcall_vzeroupper" + [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" "")) + (unspec [(match_operand 2 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" + [(set_attr "type" "call")]) + +(define_insn "*sibcall" + [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" ""))] + "SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[0]);" + [(set_attr "type" "call")]) + +(define_expand "call_pop" + [(parallel [(call (match_operand:QI 0 "" "") + (match_operand:SI 1 "" "")) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "" "")))])] "!TARGET_64BIT" { - if (SIBLING_CALL_P (insn)) - return "jmp\t%P0"; - else - return "call\t%P0"; -} - [(set_attr "type" "call")]) + ix86_expand_call (NULL, operands[0], operands[1], + operands[2], operands[3], false); + DONE; +}) -(define_insn_and_split "*call_pop_1_vzeroupper" +(define_insn_and_split "*call_pop_vzeroupper" [(parallel - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) + [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm")) (match_operand:SI 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) @@ -11339,27 +11206,23 @@ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" [(set_attr "type" "call")]) -(define_insn "*call_pop_1" - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) - (match_operand:SI 1 "" "")) +(define_insn "*call_pop" + [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm")) + (match_operand 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 2 "immediate_operand" "i")))] "!TARGET_64BIT && !SIBLING_CALL_P (insn)" -{ - if (constant_call_address_operand (operands[0], Pmode)) - return "call\t%P0"; - return "call\t%A0"; -} + "* return ix86_output_call_insn (insn, operands[0]);" [(set_attr "type" "call")]) -(define_insn_and_split "*sibcall_pop_1_vzeroupper" +(define_insn_and_split "*sibcall_pop_vzeroupper" [(parallel - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) - (match_operand:SI 1 "" "")) + [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "i,i")))]) + (match_operand:SI 2 "immediate_operand" "i")))]) (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" @@ -11369,120 +11232,89 @@ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" [(set_attr "type" "call")]) -(define_insn "*sibcall_pop_1" - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) - (match_operand:SI 1 "" "")) +(define_insn "*sibcall_pop" + [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" "")) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "i,i")))] + (match_operand:SI 2 "immediate_operand" "i")))] "!TARGET_64BIT && SIBLING_CALL_P (insn)" - "@ - jmp\t%P0 - jmp\t%A0" + "* return ix86_output_call_insn (insn, operands[0]);" [(set_attr "type" "call")]) -(define_expand "call" - [(call (match_operand:QI 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" ""))] +;; Call subroutine, returning value in operand 0 + +(define_expand "call_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "" "") + (match_operand 2 "" ""))) + (use (match_operand 3 "" ""))] "" { - ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 0); + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], NULL, false); DONE; }) -(define_expand "sibcall" - [(call (match_operand:QI 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" ""))] +(define_expand "sibcall_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "" "") + (match_operand 2 "" ""))) + (use (match_operand 3 "" ""))] "" { - ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 1); + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], NULL, true); DONE; }) -(define_insn_and_split "*call_0_vzeroupper" - [(call (mem:QI (match_operand 0 "constant_call_address_operand" "")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) - -(define_insn "*call_0" - [(call (mem:QI (match_operand 0 "constant_call_address_operand" "")) - (match_operand 1 "" ""))] - "" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) - -(define_insn_and_split "*call_1_vzeroupper" - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) - -(define_insn "*call_1" - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) - (match_operand 1 "" ""))] - "!TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) - -(define_insn_and_split "*sibcall_1_vzeroupper" - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] +(define_insn_and_split "*call_value_vzeroupper" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:P 1 "call_insn_operand" "zm")) + (match_operand 2 "" ""))) + (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" + "TARGET_VZEROUPPER && !SIBLING_CALL_P (insn)" "#" "&& reload_completed" [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) + "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" + [(set_attr "type" "callv")]) -(define_insn "*sibcall_1" - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) - (match_operand 1 "" ""))] - "!TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) +(define_insn "*call_value" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:P 1 "call_insn_operand" "zm")) + (match_operand 2 "" "")))] + "!SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) -(define_insn_and_split "*call_1_rex64_vzeroupper" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] +(define_insn_and_split "*sibcall_value_vzeroupper" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:P 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" ""))) + (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn) - && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" + "TARGET_VZEROUPPER && SIBLING_CALL_P (insn)" "#" "&& reload_completed" [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) + "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" + [(set_attr "type" "callv")]) -(define_insn "*call_1_rex64" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) - (match_operand 1 "" ""))] - "TARGET_64BIT && !SIBLING_CALL_P (insn) - && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) +(define_insn "*sibcall_value" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:P 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" "")))] + "SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) -(define_insn_and_split "*call_1_rex64_ms_sysv_vzeroupper" +(define_insn_and_split "*call_value_rex64_ms_sysv_vzeroupper" [(parallel - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) - (match_operand 1 "" "")) + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzm")) + (match_operand 2 "" ""))) (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) (clobber (reg:TI XMM6_REG)) (clobber (reg:TI XMM7_REG)) @@ -11496,18 +11328,19 @@ (clobber (reg:TI XMM15_REG)) (clobber (reg:DI SI_REG)) (clobber (reg:DI DI_REG))]) - (unspec [(match_operand 2 "const_int_operand" "")] + (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" "#" "&& reload_completed" [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) + "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" + [(set_attr "type" "callv")]) -(define_insn "*call_1_rex64_ms_sysv" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) - (match_operand 1 "" "")) +(define_insn "*call_value_rex64_ms_sysv" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzm")) + (match_operand 2 "" ""))) (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) (clobber (reg:TI XMM6_REG)) (clobber (reg:TI XMM7_REG)) @@ -11522,48 +11355,9 @@ (clobber (reg:DI SI_REG)) (clobber (reg:DI DI_REG))] "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) - -(define_insn_and_split "*call_1_rex64_large_vzeroupper" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) - -(define_insn "*call_1_rex64_large" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm")) - (match_operand 1 "" ""))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) - -(define_insn_and_split "*sibcall_1_rex64_vzeroupper" - [(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U")) - (match_operand 1 "" "")) - (unspec [(match_operand 2 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;" - [(set_attr "type" "call")]) - -(define_insn "*sibcall_1_rex64" - [(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U")) - (match_operand 1 "" ""))] - "TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[0], 0); } - [(set_attr "type" "call")]) + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) -;; Call subroutine, returning value in operand 0 (define_expand "call_value_pop" [(parallel [(set (match_operand 0 "" "") (call (match_operand:QI 1 "" "") @@ -11574,35 +11368,65 @@ "!TARGET_64BIT" { ix86_expand_call (operands[0], operands[1], operands[2], - operands[3], operands[4], 0); + operands[3], operands[4], false); DONE; }) -(define_expand "call_value" +(define_insn_and_split "*call_value_pop_vzeroupper" + [(parallel + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))]) + (unspec [(match_operand 4 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" + [(set_attr "type" "callv")]) + +(define_insn "*call_value_pop" [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "" "") - (match_operand:SI 2 "" ""))) - (use (match_operand:SI 3 "" ""))] - ;; Operand 3 is not used on the i386. - "" -{ - ix86_expand_call (operands[0], operands[1], operands[2], - operands[3], NULL, 0); - DONE; -}) + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))] + "!TARGET_64BIT && !SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) -(define_expand "sibcall_value" +(define_insn_and_split "*sibcall_value_pop_vzeroupper" + [(parallel + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))]) + (unspec [(match_operand 4 "const_int_operand" "")] + UNSPEC_CALL_NEEDS_VZEROUPPER)] + "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" + [(set_attr "type" "callv")]) + +(define_insn "*sibcall_value_pop" [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "" "") - (match_operand:SI 2 "" ""))) - (use (match_operand:SI 3 "" ""))] - ;; Operand 3 is not used on the i386. - "" -{ - ix86_expand_call (operands[0], operands[1], operands[2], - operands[3], NULL, 1); - DONE; -}) + (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))] + "!TARGET_64BIT && SIBLING_CALL_P (insn)" + "* return ix86_output_call_insn (insn, operands[1]);" + [(set_attr "type" "callv")]) ;; Call subroutine returning any type. @@ -11632,7 +11456,7 @@ : X86_64_MS_SSE_REGPARM_MAX) : X86_32_SSE_REGPARM_MAX) - 1), - NULL, 0); + NULL, false); for (i = 0; i < XVECLEN (operands[2], 0); i++) { @@ -12532,164 +12356,160 @@ (define_insn "*tls_global_dynamic_32_gnu" [(set (match_operand:SI 0 "register_operand" "=a") - (unspec:SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "tls_symbolic_operand" "") - (match_operand:SI 3 "call_insn_operand" "")] - UNSPEC_TLS_GD)) + (unspec:SI + [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "tls_symbolic_operand" "") + (match_operand:SI 3 "constant_call_address_operand" "z")] + UNSPEC_TLS_GD)) (clobber (match_scratch:SI 4 "=d")) (clobber (match_scratch:SI 5 "=c")) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_GNU_TLS" - "lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}\;call\t%P3" +{ + output_asm_insn + ("lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}", operands); + if (TARGET_SUN_TLS) +#ifdef HAVE_AS_IX86_TLSGDPLT + return "call\t%a2@tlsgdplt"; +#else + return "call\t%p3@plt"; +#endif + return "call\t%P3"; +} [(set_attr "type" "multi") (set_attr "length" "12")]) (define_expand "tls_global_dynamic_32" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (unspec:SI - [(match_dup 2) - (match_operand:SI 1 "tls_symbolic_operand" "") - (match_dup 3)] - UNSPEC_TLS_GD)) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 "")) - (clobber (reg:CC FLAGS_REG))])] - "" -{ - if (flag_pic) - operands[2] = pic_offset_table_rtx; - else - { - operands[2] = gen_reg_rtx (Pmode); - emit_insn (gen_set_got (operands[2])); - } - if (TARGET_GNU2_TLS) - { - emit_insn (gen_tls_dynamic_gnu2_32 - (operands[0], operands[1], operands[2])); - DONE; - } - operands[3] = ix86_tls_get_addr (); -}) + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 1 "tls_symbolic_operand" "") + (match_operand:SI 3 "constant_call_address_operand" "")] + UNSPEC_TLS_GD)) + (clobber (match_scratch:SI 4 "")) + (clobber (match_scratch:SI 5 "")) + (clobber (reg:CC FLAGS_REG))])]) (define_insn "*tls_global_dynamic_64" [(set (match_operand:DI 0 "register_operand" "=a") - (call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" "")) - (match_operand:DI 3 "" ""))) + (call:DI + (mem:QI (match_operand:DI 2 "constant_call_address_operand" "z")) + (match_operand:DI 3 "" ""))) (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)] "TARGET_64BIT" - { return ASM_BYTE "0x66\n\tlea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}\n" ASM_SHORT "0x6666\n\trex64\n\tcall\t%P2"; } +{ + fputs (ASM_BYTE "0x66\n", asm_out_file); + output_asm_insn + ("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands); + fputs (ASM_SHORT "0x6666\n", asm_out_file); + fputs ("\trex64\n", asm_out_file); + if (TARGET_SUN_TLS) + return "call\t%p2@plt"; + return "call\t%P2"; +} [(set_attr "type" "multi") (set_attr "length" "16")]) (define_expand "tls_global_dynamic_64" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (call:DI (mem:QI (match_dup 2)) (const_int 0))) - (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] - UNSPEC_TLS_GD)])] - "" -{ - if (TARGET_GNU2_TLS) - { - emit_insn (gen_tls_dynamic_gnu2_64 - (operands[0], operands[1])); - DONE; - } - operands[2] = ix86_tls_get_addr (); -}) + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (call:DI + (mem:QI (match_operand:DI 2 "constant_call_address_operand" "")) + (const_int 0))) + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_TLS_GD)])]) (define_insn "*tls_local_dynamic_base_32_gnu" [(set (match_operand:SI 0 "register_operand" "=a") - (unspec:SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "call_insn_operand" "")] - UNSPEC_TLS_LD_BASE)) + (unspec:SI + [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "constant_call_address_operand" "z")] + UNSPEC_TLS_LD_BASE)) (clobber (match_scratch:SI 3 "=d")) (clobber (match_scratch:SI 4 "=c")) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_GNU_TLS" - "lea{l}\t{%&@tlsldm(%1), %0|%0, %&@tlsldm[%1]}\;call\t%P2" +{ + output_asm_insn + ("lea{l}\t{%&@tlsldm(%1), %0|%0, %&@tlsldm[%1]}", operands); + if (TARGET_SUN_TLS) +#ifdef HAVE_AS_IX86_TLSLDMPLT + return "call\t%&@tlsldmplt"; +#else + return "call\t%p2@plt"; +#endif + return "call\t%P2"; +} [(set_attr "type" "multi") (set_attr "length" "11")]) (define_expand "tls_local_dynamic_base_32" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (unspec:SI [(match_dup 1) (match_dup 2)] - UNSPEC_TLS_LD_BASE)) - (clobber (match_scratch:SI 3 "")) - (clobber (match_scratch:SI 4 "")) - (clobber (reg:CC FLAGS_REG))])] - "" -{ - if (flag_pic) - operands[1] = pic_offset_table_rtx; - else - { - operands[1] = gen_reg_rtx (Pmode); - emit_insn (gen_set_got (operands[1])); - } - if (TARGET_GNU2_TLS) - { - emit_insn (gen_tls_dynamic_gnu2_32 - (operands[0], ix86_tls_module_base (), operands[1])); - DONE; - } - operands[2] = ix86_tls_get_addr (); -}) + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "constant_call_address_operand" "")] + UNSPEC_TLS_LD_BASE)) + (clobber (match_scratch:SI 3 "")) + (clobber (match_scratch:SI 4 "")) + (clobber (reg:CC FLAGS_REG))])]) (define_insn "*tls_local_dynamic_base_64" [(set (match_operand:DI 0 "register_operand" "=a") - (call:DI (mem:QI (match_operand:DI 1 "call_insn_operand" "")) - (match_operand:DI 2 "" ""))) + (call:DI + (mem:QI (match_operand:DI 1 "constant_call_address_operand" "z")) + (match_operand:DI 2 "" ""))) (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)] "TARGET_64BIT" - "lea{q}\t{%&@tlsld(%%rip), %%rdi|rdi, %&@tlsld[rip]}\;call\t%P1" +{ + output_asm_insn + ("lea{q}\t{%&@tlsld(%%rip), %%rdi|rdi, %&@tlsld[rip]}", operands); + if (TARGET_SUN_TLS) + return "call\t%p1@plt"; + return "call\t%P1"; +} [(set_attr "type" "multi") (set_attr "length" "12")]) (define_expand "tls_local_dynamic_base_64" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (call:DI (mem:QI (match_dup 1)) (const_int 0))) - (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])] - "" -{ - if (TARGET_GNU2_TLS) - { - emit_insn (gen_tls_dynamic_gnu2_64 - (operands[0], ix86_tls_module_base ())); - DONE; - } - operands[1] = ix86_tls_get_addr (); -}) + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (call:DI + (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) + (const_int 0))) + (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]) ;; Local dynamic of a single variable is a lose. Show combine how ;; to convert that back to global dynamic. (define_insn_and_split "*tls_local_dynamic_32_once" [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "call_insn_operand" "")] - UNSPEC_TLS_LD_BASE) - (const:SI (unspec:SI - [(match_operand:SI 3 "tls_symbolic_operand" "")] - UNSPEC_DTPOFF)))) + (plus:SI + (unspec:SI [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "constant_call_address_operand" "z")] + UNSPEC_TLS_LD_BASE) + (const:SI (unspec:SI + [(match_operand:SI 3 "tls_symbolic_operand" "")] + UNSPEC_DTPOFF)))) (clobber (match_scratch:SI 4 "=d")) (clobber (match_scratch:SI 5 "=c")) (clobber (reg:CC FLAGS_REG))] "" "#" "" - [(parallel [(set (match_dup 0) - (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)] - UNSPEC_TLS_GD)) - (clobber (match_dup 4)) - (clobber (match_dup 5)) - (clobber (reg:CC FLAGS_REG))])]) + [(parallel + [(set (match_dup 0) + (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)] + UNSPEC_TLS_GD)) + (clobber (match_dup 4)) + (clobber (match_dup 5)) + (clobber (reg:CC FLAGS_REG))])]) ;; Segment register for the thread base ptr load (define_mode_attr tp_seg [(SI "gs") (DI "fs")]) -;; Load and add the thread base pointer from %gs:0. +;; Load and add the thread base pointer from %:0. (define_insn "*load_tp_" [(set (match_operand:P 0 "register_operand" "=r") (unspec:P [(const_int 0)] UNSPEC_TP))] @@ -12723,7 +12543,11 @@ UNSPEC_TLS_IE_SUN)) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && TARGET_SUN_TLS" - "mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}\n\tadd{q}\t{%a1@gottpoff(%%rip), %0|%0, %a1@gottpoff[rip]}" +{ + output_asm_insn + ("mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}", operands); + return "add{q}\t{%a1@gottpoff(%%rip), %0|%0, %a1@gottpoff[rip]}"; +} [(set_attr "type" "multi")]) ;; GNU2 TLS patterns can be split. @@ -12865,66 +12689,32 @@ ;; Gcc is slightly more smart about handling normal two address instructions ;; so use special patterns for add and mull. -(define_insn "*fop__comm_mixed_avx" - [(set (match_operand:MODEF 0 "register_operand" "=f,x") - (match_operator:MODEF 3 "binary_fp_operator" - [(match_operand:MODEF 1 "nonimmediate_operand" "%0,x") - (match_operand:MODEF 2 "nonimmediate_operand" "fm,xm")]))] - "AVX_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387 - && COMMUTATIVE_ARITH_P (operands[3]) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (if_then_else (eq_attr "alternative" "1") - (if_then_else (match_operand:MODEF 3 "mult_operator" "") - (const_string "ssemul") - (const_string "sseadd")) - (if_then_else (match_operand:MODEF 3 "mult_operator" "") - (const_string "fmul") - (const_string "fop")))) - (set_attr "prefix" "orig,maybe_vex") - (set_attr "mode" "")]) - (define_insn "*fop__comm_mixed" - [(set (match_operand:MODEF 0 "register_operand" "=f,x") + [(set (match_operand:MODEF 0 "register_operand" "=f,x,x") (match_operator:MODEF 3 "binary_fp_operator" - [(match_operand:MODEF 1 "nonimmediate_operand" "%0,0") - (match_operand:MODEF 2 "nonimmediate_operand" "fm,xm")]))] + [(match_operand:MODEF 1 "nonimmediate_operand" "%0,0,x") + (match_operand:MODEF 2 "nonimmediate_operand" "fm,xm,xm")]))] "SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387 && COMMUTATIVE_ARITH_P (operands[3]) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (if_then_else (eq_attr "alternative" "1") + (if_then_else (eq_attr "alternative" "1,2") (if_then_else (match_operand:MODEF 3 "mult_operator" "") (const_string "ssemul") (const_string "sseadd")) (if_then_else (match_operand:MODEF 3 "mult_operator" "") (const_string "fmul") (const_string "fop")))) - (set_attr "mode" "")]) - -(define_insn "*fop__comm_avx" - [(set (match_operand:MODEF 0 "register_operand" "=x") - (match_operator:MODEF 3 "binary_fp_operator" - [(match_operand:MODEF 1 "nonimmediate_operand" "%x") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")]))] - "AVX_FLOAT_MODE_P (mode) && TARGET_SSE_MATH - && COMMUTATIVE_ARITH_P (operands[3]) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (if_then_else (match_operand:MODEF 3 "mult_operator" "") - (const_string "ssemul") - (const_string "sseadd"))) - (set_attr "prefix" "vex") + (set_attr "isa" "base,noavx,avx") + (set_attr "prefix" "orig,orig,vex") (set_attr "mode" "")]) (define_insn "*fop__comm_sse" - [(set (match_operand:MODEF 0 "register_operand" "=x") + [(set (match_operand:MODEF 0 "register_operand" "=x,x") (match_operator:MODEF 3 "binary_fp_operator" - [(match_operand:MODEF 1 "nonimmediate_operand" "%0") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")]))] + [(match_operand:MODEF 1 "nonimmediate_operand" "%0,x") + (match_operand:MODEF 2 "nonimmediate_operand" "xm,xm")]))] "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH && COMMUTATIVE_ARITH_P (operands[3]) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" @@ -12933,6 +12723,8 @@ (if_then_else (match_operand:MODEF 3 "mult_operator" "") (const_string "ssemul") (const_string "sseadd"))) + (set_attr "isa" "noavx,avx") + (set_attr "prefix" "orig,vex") (set_attr "mode" "")]) (define_insn "*fop__comm_i387" @@ -12950,50 +12742,23 @@ (const_string "fop"))) (set_attr "mode" "")]) -(define_insn "*fop__1_mixed_avx" - [(set (match_operand:MODEF 0 "register_operand" "=f,f,x") - (match_operator:MODEF 3 "binary_fp_operator" - [(match_operand:MODEF 1 "nonimmediate_operand" "0,fm,x") - (match_operand:MODEF 2 "nonimmediate_operand" "fm,0,xm")]))] - "AVX_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387 - && !COMMUTATIVE_ARITH_P (operands[3]) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(and (eq_attr "alternative" "2") - (match_operand:MODEF 3 "mult_operator" "")) - (const_string "ssemul") - (and (eq_attr "alternative" "2") - (match_operand:MODEF 3 "div_operator" "")) - (const_string "ssediv") - (eq_attr "alternative" "2") - (const_string "sseadd") - (match_operand:MODEF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:MODEF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "prefix" "orig,orig,maybe_vex") - (set_attr "mode" "")]) - (define_insn "*fop__1_mixed" - [(set (match_operand:MODEF 0 "register_operand" "=f,f,x") + [(set (match_operand:MODEF 0 "register_operand" "=f,f,x,x") (match_operator:MODEF 3 "binary_fp_operator" - [(match_operand:MODEF 1 "nonimmediate_operand" "0,fm,0") - (match_operand:MODEF 2 "nonimmediate_operand" "fm,0,xm")]))] + [(match_operand:MODEF 1 "nonimmediate_operand" "0,fm,0,x") + (match_operand:MODEF 2 "nonimmediate_operand" "fm,0,xm,xm")]))] "SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387 && !COMMUTATIVE_ARITH_P (operands[3]) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (cond [(and (eq_attr "alternative" "2") + (cond [(and (eq_attr "alternative" "2,3") (match_operand:MODEF 3 "mult_operator" "")) (const_string "ssemul") - (and (eq_attr "alternative" "2") + (and (eq_attr "alternative" "2,3") (match_operand:MODEF 3 "div_operator" "")) (const_string "ssediv") - (eq_attr "alternative" "2") + (eq_attr "alternative" "2,3") (const_string "sseadd") (match_operand:MODEF 3 "mult_operator" "") (const_string "fmul") @@ -13001,6 +12766,8 @@ (const_string "fdiv") ] (const_string "fop"))) + (set_attr "isa" "base,base,noavx,avx") + (set_attr "prefix" "orig,orig,orig,vex") (set_attr "mode" "")]) (define_insn "*rcpsf2_sse" @@ -13014,29 +12781,11 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "SF")]) -(define_insn "*fop__1_avx" - [(set (match_operand:MODEF 0 "register_operand" "=x") - (match_operator:MODEF 3 "binary_fp_operator" - [(match_operand:MODEF 1 "register_operand" "x") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")]))] - "AVX_FLOAT_MODE_P (mode) && TARGET_SSE_MATH - && !COMMUTATIVE_ARITH_P (operands[3])" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:MODEF 3 "mult_operator" "") - (const_string "ssemul") - (match_operand:MODEF 3 "div_operator" "") - (const_string "ssediv") - ] - (const_string "sseadd"))) - (set_attr "prefix" "vex") - (set_attr "mode" "")]) - (define_insn "*fop__1_sse" - [(set (match_operand:MODEF 0 "register_operand" "=x") + [(set (match_operand:MODEF 0 "register_operand" "=x,x") (match_operator:MODEF 3 "binary_fp_operator" - [(match_operand:MODEF 1 "register_operand" "0") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")]))] + [(match_operand:MODEF 1 "register_operand" "0,x") + (match_operand:MODEF 2 "nonimmediate_operand" "xm,xm")]))] "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH && !COMMUTATIVE_ARITH_P (operands[3])" "* return output_387_binary_op (insn, operands);" @@ -13047,6 +12796,8 @@ (const_string "ssediv") ] (const_string "sseadd"))) + (set_attr "isa" "noavx,avx") + (set_attr "prefix" "orig,vex") (set_attr "mode" "")]) ;; This pattern is not fully shadowed by the pattern above. @@ -13391,7 +13142,7 @@ (sqrt:MODEF (match_operand:MODEF 1 "nonimmediate_operand" "xm")))] "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "%vsqrts\t{%1, %d0|%d0, %1}" + "%vsqrt\t{%1, %d0|%d0, %1}" [(set_attr "type" "sse") (set_attr "atom_sse_attr" "sqrt") (set_attr "prefix" "maybe_vex") @@ -13639,7 +13390,7 @@ (set (match_operand:XF 1 "register_operand" "") (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))] "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))]) (define_split @@ -13649,7 +13400,7 @@ (set (match_operand:XF 1 "register_operand" "") (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))] "find_regno_note (insn, REG_UNUSED, REGNO (operands[1])) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))]) (define_insn "sincos_extendxf3_i387" @@ -13675,7 +13426,7 @@ (set (match_operand:XF 1 "register_operand" "") (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SINCOS_SIN))] "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" [(set (match_dup 1) (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SIN))]) @@ -13687,7 +13438,7 @@ (set (match_operand:XF 1 "register_operand" "") (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SINCOS_SIN))] "find_regno_note (insn, REG_UNUSED, REGNO (operands[1])) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" [(set (match_dup 0) (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_COS))]) @@ -14565,7 +14316,7 @@ (match_operand:SI 2 "const_0_to_15_operand" "n")] UNSPEC_ROUND))] "TARGET_ROUND" - "%vrounds\t{%2, %1, %d0|%d0, %1, %2}" + "%vround\t{%2, %1, %d0|%d0, %1, %2}" [(set_attr "type" "ssecvt") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_vex") @@ -14659,7 +14410,7 @@ UNSPEC_FIST)) (clobber (match_scratch:XF 2 "=&1f"))] "TARGET_USE_FANCY_MATH_387" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fpspc") (set_attr "mode" "DI")]) @@ -14718,7 +14469,7 @@ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] UNSPEC_FIST))] "TARGET_USE_FANCY_MATH_387" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fpspc") (set_attr "mode" "")]) @@ -14908,7 +14659,7 @@ (clobber (match_scratch:XF 4 "=&1f"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "floor") (set_attr "mode" "DI")]) @@ -14965,7 +14716,7 @@ (use (match_operand:HI 3 "memory_operand" "m"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "floor") (set_attr "mode" "")]) @@ -15165,7 +14916,7 @@ (clobber (match_scratch:XF 4 "=&1f"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "ceil") (set_attr "mode" "DI")]) @@ -15222,7 +14973,7 @@ (use (match_operand:HI 3 "memory_operand" "m"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "* return output_fix_trunc (insn, operands, 0);" + "* return output_fix_trunc (insn, operands, false);" [(set_attr "type" "fistp") (set_attr "i387_cw" "ceil") (set_attr "mode" "")]) @@ -16473,25 +16224,18 @@ ;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator ;; are undefined in this condition, we're certain this is correct. -(define_insn "*avx_3" - [(set (match_operand:MODEF 0 "register_operand" "=x") - (smaxmin:MODEF - (match_operand:MODEF 1 "nonimmediate_operand" "%x") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")))] - "AVX_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "vs\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "sseadd") - (set_attr "prefix" "vex") - (set_attr "mode" "")]) - (define_insn "3" - [(set (match_operand:MODEF 0 "register_operand" "=x") + [(set (match_operand:MODEF 0 "register_operand" "=x,x") (smaxmin:MODEF - (match_operand:MODEF 1 "nonimmediate_operand" "%0") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")))] + (match_operand:MODEF 1 "nonimmediate_operand" "%0,x") + (match_operand:MODEF 2 "nonimmediate_operand" "xm,xm")))] "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "s\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") + "@ + \t{%2, %0|%0, %2} + v\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "prefix" "orig,vex") + (set_attr "type" "sseadd") (set_attr "mode" "")]) ;; These versions of the min/max patterns implement exactly the operations @@ -16500,50 +16244,34 @@ ;; Their operands are not commutative, and thus they may be used in the ;; presence of -0.0 and NaN. -(define_insn "*avx_ieee_smin3" - [(set (match_operand:MODEF 0 "register_operand" "=x") - (unspec:MODEF - [(match_operand:MODEF 1 "register_operand" "x") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")] - UNSPEC_IEEE_MIN))] - "AVX_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "vmins\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "sseadd") - (set_attr "prefix" "vex") - (set_attr "mode" "")]) - (define_insn "*ieee_smin3" - [(set (match_operand:MODEF 0 "register_operand" "=x") + [(set (match_operand:MODEF 0 "register_operand" "=x,x") (unspec:MODEF - [(match_operand:MODEF 1 "register_operand" "0") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")] + [(match_operand:MODEF 1 "register_operand" "0,x") + (match_operand:MODEF 2 "nonimmediate_operand" "xm,xm")] UNSPEC_IEEE_MIN))] "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "mins\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "")]) - -(define_insn "*avx_ieee_smax3" - [(set (match_operand:MODEF 0 "register_operand" "=x") - (unspec:MODEF - [(match_operand:MODEF 1 "register_operand" "0") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")] - UNSPEC_IEEE_MAX))] - "AVX_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "vmaxs\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "sseadd") - (set_attr "prefix" "vex") + "@ + min\t{%2, %0|%0, %2} + vmin\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "prefix" "orig,vex") + (set_attr "type" "sseadd") (set_attr "mode" "")]) (define_insn "*ieee_smax3" - [(set (match_operand:MODEF 0 "register_operand" "=x") + [(set (match_operand:MODEF 0 "register_operand" "=x,x") (unspec:MODEF - [(match_operand:MODEF 1 "register_operand" "0") - (match_operand:MODEF 2 "nonimmediate_operand" "xm")] + [(match_operand:MODEF 1 "register_operand" "0,x") + (match_operand:MODEF 2 "nonimmediate_operand" "xm,xm")] UNSPEC_IEEE_MAX))] "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "maxs\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") + "@ + max\t{%2, %0|%0, %2} + vmax\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "prefix" "orig,vex") + (set_attr "type" "sseadd") (set_attr "mode" "")]) ;; Make two stack loads independent: @@ -17517,338 +17245,6 @@ operands[0] = dest; }) -;; Call-value patterns last so that the wildcard operand does not -;; disrupt insn-recog's switch tables. - -(define_insn_and_split "*call_value_pop_0_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "")))]) - (unspec [(match_operand 4 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_pop_0" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "")))] - "!TARGET_64BIT" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_pop_1_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i")))]) - (unspec [(match_operand 4 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_pop_1" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i")))] - "!TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*sibcall_value_pop_1_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i,i")))]) - (unspec [(match_operand 4 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*sibcall_value_pop_1" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) - (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i,i")))] - "!TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_0_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) - (match_operand:SI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_0" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) - (match_operand:SI 2 "" "")))] - "!TARGET_64BIT" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_0_rex64_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) - (match_operand:DI 2 "const_int_operand" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_0_rex64" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) - (match_operand:DI 2 "const_int_operand" "")))] - "TARGET_64BIT" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_0_rex64_ms_sysv_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) - (match_operand:DI 2 "const_int_operand" ""))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))]) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_0_rex64_ms_sysv" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) - (match_operand:DI 2 "const_int_operand" ""))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_1_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) - (match_operand:SI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_1" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) - (match_operand:SI 2 "" "")))] - "!TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*sibcall_value_1_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) - (match_operand:SI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*sibcall_value_1" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) - (match_operand:SI 2 "" "")))] - "!TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_1_rex64_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) - (match_operand:DI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn) - && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_1_rex64" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) - (match_operand:DI 2 "" "")))] - "TARGET_64BIT && !SIBLING_CALL_P (insn) - && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_1_rex64_ms_sysv_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) - (match_operand:DI 2 "" ""))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))]) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_1_rex64_ms_sysv" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) - (match_operand:DI 2 "" ""))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*call_value_1_rex64_large_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm")) - (match_operand:DI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*call_value_1_rex64_large" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm")) - (match_operand:DI 2 "" "")))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - -(define_insn_and_split "*sibcall_value_1_rex64_vzeroupper" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U")) - (match_operand:DI 2 "" ""))) - (unspec [(match_operand 3 "const_int_operand" "")] - UNSPEC_CALL_NEEDS_VZEROUPPER)] - "TARGET_VZEROUPPER && TARGET_64BIT && SIBLING_CALL_P (insn)" - "#" - "&& reload_completed" - [(const_int 0)] - "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;" - [(set_attr "type" "callv")]) - -(define_insn "*sibcall_value_1_rex64" - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U")) - (match_operand:DI 2 "" "")))] - "TARGET_64BIT && SIBLING_CALL_P (insn)" - { return ix86_output_call_insn (insn, operands[1], 1); } - [(set_attr "type" "callv")]) - ;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5. ;; That, however, is usually mapped by the OS to SIGSEGV, which is often ;; caught for use by garbage collectors and the like. Using an insn that @@ -18337,6 +17733,25 @@ [(set_attr "type" "other") (set_attr "prefix_extra" "1")]) +(define_expand "pause" + [(set (match_dup 0) + (unspec:BLK [(match_dup 0)] UNSPEC_PAUSE))] + "" +{ + operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); + MEM_VOLATILE_P (operands[0]) = 1; +}) + +;; Use "rep; nop", instead of "pause", to support older assemblers. +;; They have the same encoding. +(define_insn "*pause" + [(set (match_operand:BLK 0 "" "") + (unspec:BLK [(match_dup 0)] UNSPEC_PAUSE))] + "" + "rep; nop" + [(set_attr "length" "2") + (set_attr "memory" "unknown")]) + (include "mmx.md") (include "sse.md") (include "sync.md")