X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fconfig%2Fi386%2Fi386.md;h=f6e0f4b12b2f67ddde949b6ec32bcff45482e5d6;hp=4090ead27a0f72f631906fd18eb825298cb95c9c;hb=28bfa791d44b30fa96cc852ad093b0bcf3e9c168;hpb=470195a47342c21702a19b427b5a31c015f0756a diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 4090ead27a0..f6e0f4b12b2 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -95,7 +95,6 @@ (UNSPEC_RCP 45) (UNSPEC_RSQRT 46) (UNSPEC_SFENCE 47) - (UNSPEC_NOP 48) ; prevents combiner cleverness (UNSPEC_PFRCP 49) (UNSPEC_PFRCPIT1 40) (UNSPEC_PFRCPIT2 41) @@ -182,11 +181,20 @@ (UNSPEC_SSE5_UNSIGNED_CMP 151) (UNSPEC_SSE5_TRUEFALSE 152) (UNSPEC_SSE5_PERMUTE 153) - (UNSPEC_SSE5_ASHIFT 154) - (UNSPEC_SSE5_LSHIFT 155) - (UNSPEC_FRCZ 156) - (UNSPEC_CVTPH2PS 157) - (UNSPEC_CVTPS2PH 158) + (UNSPEC_FRCZ 154) + (UNSPEC_CVTPH2PS 155) + (UNSPEC_CVTPS2PH 156) + + ; For AES support + (UNSPEC_AESENC 159) + (UNSPEC_AESENCLAST 160) + (UNSPEC_AESDEC 161) + (UNSPEC_AESDECLAST 162) + (UNSPEC_AESIMC 163) + (UNSPEC_AESKEYGENASSIST 164) + + ; For PCLMUL support + (UNSPEC_PCLMUL 165) ]) (define_constants @@ -205,6 +213,7 @@ (UNSPECV_XCHG 12) (UNSPECV_LOCK 13) (UNSPECV_PROLOGUE_USE 14) + (UNSPECV_CLD 15) ]) ;; Constants to represent pcomtrue/pcomfalse variants @@ -217,6 +226,20 @@ (COM_TRUE_P 5) ]) +;; Constants used in the SSE5 pperm instruction +(define_constants + [(PPERM_SRC 0x00) /* copy source */ + (PPERM_INVERT 0x20) /* invert source */ + (PPERM_REVERSE 0x40) /* bit reverse source */ + (PPERM_REV_INV 0x60) /* bit reverse & invert src */ + (PPERM_ZERO 0x80) /* all 0's */ + (PPERM_ONES 0xa0) /* all 1's */ + (PPERM_SIGN 0xc0) /* propagate sign bit */ + (PPERM_INV_SIGN 0xe0) /* invert & propagate sign */ + (PPERM_SRC1 0x00) /* use first source byte */ + (PPERM_SRC2 0x10) /* use second source byte */ + ]) + ;; Registers by name. (define_constants [(AX_REG 0) @@ -516,13 +539,53 @@ [(set_attr "length" "128") (set_attr "type" "multi")]) +;; All integer comparison codes. +(define_code_iterator int_cond [ne eq ge gt le lt geu gtu leu ltu ]) + +;; All floating-point comparison codes. +(define_code_iterator fp_cond [unordered ordered + uneq unge ungt unle unlt ltgt ]) + (define_code_iterator plusminus [plus minus]) -;; Base name for define_insn and insn mnemonic. -(define_code_attr addsub [(plus "add") (minus "sub")]) +(define_code_iterator sat_plusminus [ss_plus us_plus ss_minus us_minus]) + +;; Base name for define_insn +(define_code_attr plusminus_insn + [(plus "add") (ss_plus "ssadd") (us_plus "usadd") + (minus "sub") (ss_minus "sssub") (us_minus "ussub")]) + +;; Base name for insn mnemonic. +(define_code_attr plusminus_mnemonic + [(plus "add") (ss_plus "adds") (us_plus "addus") + (minus "sub") (ss_minus "subs") (us_minus "subus")]) ;; Mark commutative operators as such in constraints. -(define_code_attr comm [(plus "%") (minus "")]) +(define_code_attr comm [(plus "%") (ss_plus "%") (us_plus "%") + (minus "") (ss_minus "") (us_minus "")]) + +;; Mapping of signed max and min +(define_code_iterator smaxmin [smax smin]) + +;; Mapping of unsigned max and min +(define_code_iterator umaxmin [umax umin]) + +;; Base name for integer and FP insn mnemonic +(define_code_attr maxminiprefix [(smax "maxs") (smin "mins") + (umax "maxu") (umin "minu")]) +(define_code_attr maxminfprefix [(smax "max") (smin "min")]) + +;; Mapping of parallel logic operators +(define_code_iterator plogic [and ior xor]) + +;; Base name for insn mnemonic. +(define_code_attr plogicprefix [(and "and") (ior "or") (xor "xor")]) + +;; Mapping of abs neg operators +(define_code_iterator absneg [abs neg]) + +;; Base name for x87 insn mnemonic. +(define_code_attr absnegprefix [(abs "abs") (neg "chs")]) ;; All single word integer modes. (define_mode_iterator SWI [QI HI SI (DI "TARGET_64BIT")]) @@ -564,6 +627,14 @@ ;; SSE vector mode corresponding to a scalar mode (define_mode_attr ssevecmode [(QI "V16QI") (HI "V8HI") (SI "V4SI") (DI "V2DI") (SF "V4SF") (DF "V2DF")]) + +;; Instruction suffix for REX 64bit operators. +(define_mode_attr rex64suffix [(SI "") (DI "{q}")]) + +;; This mode iterator allows :P to be used for patterns that operate on +;; pointer-sized quantities. Exactly one of the two alternatives will match. +(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) + ;; Scheduling descriptions @@ -1103,7 +1174,7 @@ [(match_operand:X87MODEI12 2 "memory_operand" "m")]))] UNSPEC_FNSTSW))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) - && TARGET_USE_MODE_FIOP + && (TARGET_USE_MODE_FIOP || optimize_size) && (GET_MODE (operands [3]) == GET_MODE (operands[1]))" "* return output_fp_compare (insn, operands, 0, 0);" [(set_attr "type" "multi") @@ -1120,7 +1191,7 @@ (clobber (match_operand:HI 0 "register_operand" "=a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && TARGET_SAHF && !TARGET_CMOVE - && TARGET_USE_MODE_FIOP + && (TARGET_USE_MODE_FIOP || optimize_size) && (GET_MODE (operands [3]) == GET_MODE (operands[1]))" "#" "&& reload_completed" @@ -1745,25 +1816,6 @@ ] (const_string "QI")))]) -(define_expand "reload_outqi" - [(parallel [(match_operand:QI 0 "" "=m") - (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "register_operand" "=&q")])] - "" -{ - rtx op0, op1, op2; - op0 = operands[0]; op1 = operands[1]; op2 = operands[2]; - - gcc_assert (!reg_overlap_mentioned_p (op2, op0)); - if (! q_regs_operand (op1, QImode)) - { - emit_insn (gen_movqi (op2, op1)); - op1 = op2; - } - emit_insn (gen_movqi (op0, op1)); - DONE; -}) - (define_insn "*swapqi_1" [(set (match_operand:QI 0 "register_operand" "+r") (match_operand:QI 1 "register_operand" "+r")) @@ -2084,7 +2136,7 @@ && !x86_64_immediate_operand (operands[1], DImode) && 1" [(set (match_dup 0) (match_dup 1)) (set (match_dup 2) (match_dup 3))] - "split_di (operands + 1, 1, operands + 2, operands + 3); + "split_di (&operands[1], 1, &operands[2], &operands[3]); operands[1] = gen_lowpart (DImode, operands[2]); operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, GEN_INT (4))); @@ -2099,7 +2151,7 @@ && !x86_64_immediate_operand (operands[1], DImode)" [(set (match_dup 0) (match_dup 1)) (set (match_dup 2) (match_dup 3))] - "split_di (operands + 1, 1, operands + 2, operands + 3); + "split_di (&operands[1], 1, &operands[2], &operands[3]); operands[1] = gen_lowpart (DImode, operands[2]); operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, GEN_INT (4))); @@ -2324,7 +2376,7 @@ && !x86_64_immediate_operand (operands[1], DImode) && 1" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] - "split_di (operands, 2, operands + 2, operands + 4);") + "split_di (&operands[0], 2, &operands[2], &operands[4]);") (define_split [(set (match_operand:DI 0 "memory_operand" "") @@ -2335,7 +2387,7 @@ && !x86_64_immediate_operand (operands[1], DImode)" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] - "split_di (operands, 2, operands + 2, operands + 4);") + "split_di (&operands[0], 2, &operands[2], &operands[4]);") (define_insn "*swapdi_rex64" [(set (match_operand:DI 0 "register_operand" "+r") @@ -2379,10 +2431,23 @@ return "pxor\t%0, %0"; case 1: case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; + /* 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 "movups\t{%1, %0|%0, %1}"; + else + return "movdqu\t{%1, %0|%0, %1}"; + } else - return "movdqa\t{%1, %0|%0, %1}"; + { + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + } default: gcc_unreachable (); } @@ -2416,10 +2481,23 @@ return "pxor\t%0, %0"; case 3: case 4: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; + /* 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 "movups\t{%1, %0|%0, %1}"; + else + return "movdqu\t{%1, %0|%0, %1}"; + } else - return "movdqa\t{%1, %0|%0, %1}"; + { + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + } default: gcc_unreachable (); } @@ -2662,17 +2740,9 @@ (define_split [(set (match_operand:DF 0 "push_operand" "") (match_operand:DF 1 "any_fp_register_operand" ""))] - "!TARGET_64BIT && reload_completed" - [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8))) - (set (mem:DF (reg:SI SP_REG)) (match_dup 1))] - "") - -(define_split - [(set (match_operand:DF 0 "push_operand" "") - (match_operand:DF 1 "any_fp_register_operand" ""))] - "TARGET_64BIT && reload_completed" - [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8))) - (set (mem:DF (reg:DI SP_REG)) (match_dup 1))] + "reload_completed" + [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -8))) + (set (mem:DF (reg:P SP_REG)) (match_dup 1))] "") (define_split @@ -2690,15 +2760,19 @@ [(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,F*r,C ,Y2*x,mY2*x,Y2*x"))] + "fm,f,G,*roF,*Fr,C ,Y2*x,mY2*x,Y2*x"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT) && (reload_in_progress || reload_completed || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || (!(TARGET_SSE2 && TARGET_SSE_MATH) && optimize_size + && !memory_operand (operands[0], DFmode) && standard_80387_constant_p (operands[1])) || GET_CODE (operands[1]) != CONST_DOUBLE - || memory_operand (operands[0], DFmode))" + || ((optimize_size + || !TARGET_MEMORY_MISMATCH_STALL + || reload_in_progress || reload_completed) + && memory_operand (operands[0], DFmode)))" { switch (which_alternative) { @@ -3121,17 +3195,9 @@ (define_split [(set (match_operand:XF 0 "push_operand" "") (match_operand:XF 1 "any_fp_register_operand" ""))] - "!TARGET_64BIT" - [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2))) - (set (mem:XF (reg:SI SP_REG)) (match_dup 1))] - "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") - -(define_split - [(set (match_operand:XF 0 "push_operand" "") - (match_operand:XF 1 "any_fp_register_operand" ""))] - "TARGET_64BIT" - [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2))) - (set (mem:XF (reg:DI SP_REG)) (match_dup 1))] + "" + [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2))) + (set (mem:XF (reg:P SP_REG)) (match_dup 1))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") ;; Do not use integer registers when optimizing for size @@ -3874,16 +3940,9 @@ (define_split [(set (match_operand:DF 0 "push_operand" "") (float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))] - "!TARGET_64BIT" - [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8))) - (set (mem:DF (reg:SI SP_REG)) (float_extend:DF (match_dup 1)))]) - -(define_split - [(set (match_operand:DF 0 "push_operand" "") - (float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))] - "TARGET_64BIT" - [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8))) - (set (mem:DF (reg:DI SP_REG)) (float_extend:DF (match_dup 1)))]) + "" + [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -8))) + (set (mem:DF (reg:P SP_REG)) (float_extend:DF (match_dup 1)))]) (define_insn "*dummy_extendsfxf2" [(set (match_operand:XF 0 "push_operand" "=<") @@ -3895,32 +3954,16 @@ [(set (match_operand:XF 0 "push_operand" "") (float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))] "" - [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2))) - (set (mem:XF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))] - "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") - -(define_split - [(set (match_operand:XF 0 "push_operand" "") - (float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))] - "TARGET_64BIT" - [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2))) - (set (mem:DF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))] + [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2))) + (set (mem:XF (reg:P SP_REG)) (float_extend:XF (match_dup 1)))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split [(set (match_operand:XF 0 "push_operand" "") (float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))] "" - [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2))) - (set (mem:DF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))] - "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") - -(define_split - [(set (match_operand:XF 0 "push_operand" "") - (float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))] - "TARGET_64BIT" - [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2))) - (set (mem:XF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))] + [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2))) + (set (mem:DF (reg:P SP_REG)) (float_extend:XF (match_dup 1)))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_expand "extendsfdf2" @@ -4133,23 +4176,22 @@ "") (define_insn "*truncdfsf_fast_mixed" - [(set (match_operand:SF 0 "nonimmediate_operand" "=m,f,x") + [(set (match_operand:SF 0 "nonimmediate_operand" "=fm,x") (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "f ,f,xm")))] + (match_operand:DF 1 "nonimmediate_operand" "f ,xm")))] "TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations" { switch (which_alternative) { case 0: - case 1: return output_387_reg_move (insn, operands); - case 2: + case 1: return "cvtsd2ss\t{%1, %0|%0, %1}"; default: gcc_unreachable (); } } - [(set_attr "type" "fmov,fmov,ssecvt") + [(set_attr "type" "fmov,ssecvt") (set_attr "mode" "SF")]) ;; Yes, this one doesn't depend on flag_unsafe_math_optimizations, @@ -4567,7 +4609,7 @@ (define_insn "fix_trunc_i387_fisttp_with_temp" [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r") (fix:X87MODEI (match_operand 1 "register_operand" "f,f"))) - (clobber (match_operand:X87MODEI 2 "memory_operand" "=m,m")) + (clobber (match_operand:X87MODEI 2 "memory_operand" "=X,m")) (clobber (match_scratch:XF 3 "=&1f,&1f"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && TARGET_FISTTP @@ -4656,7 +4698,7 @@ (fix:DI (match_operand 1 "register_operand" "f,f"))) (use (match_operand:HI 2 "memory_operand" "m,m")) (use (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:DI 4 "memory_operand" "=m,m")) + (clobber (match_operand:DI 4 "memory_operand" "=X,m")) (clobber (match_scratch:XF 5 "=&1f,&1f"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && !TARGET_FISTTP @@ -4713,7 +4755,7 @@ (fix:X87MODEI12 (match_operand 1 "register_operand" "f,f"))) (use (match_operand:HI 2 "memory_operand" "m,m")) (use (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))] + (clobber (match_operand:X87MODEI12 4 "memory_operand" "=X,m"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && !TARGET_FISTTP && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))" @@ -4773,553 +4815,626 @@ ;; wants to be able to do this between registers. (define_expand "floathi2" - [(set (match_operand:MODEF 0 "register_operand" "") - (float:MODEF (match_operand:HI 1 "nonimmediate_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" -{ - if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) - { - emit_insn - (gen_floatsi2 (operands[0], - convert_to_mode (SImode, operands[1], 0))); - DONE; - } -}) + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:HI 1 "nonimmediate_operand" "")))] + "TARGET_80387 + && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387)" + "") -(define_insn "*floathi2_i387" - [(set (match_operand:MODEF 0 "register_operand" "=f,f") - (float:MODEF - (match_operand:HI 1 "nonimmediate_operand" "m,?r")))] +;; Pre-reload splitter to add memory clobber to the pattern. +(define_insn_and_split "*floathi2_1" + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:HI 1 "register_operand" "")))] + "TARGET_80387 + && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387) + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(parallel [(set (match_dup 0) + (float:X87MODEF (match_dup 1))) + (clobber (match_dup 2))])] + "operands[2] = assign_386_stack_local (HImode, SLOT_TEMP);") + +(define_insn "*floathi2_i387_with_temp" + [(set (match_operand:X87MODEF 0 "register_operand" "=f,f") + (float:X87MODEF (match_operand:HI 1 "nonimmediate_operand" "m,?r"))) + (clobber (match_operand:HI 2 "memory_operand" "=m,m"))] "TARGET_80387 && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)" - "@ - fild%z1\t%1 - #" + "#" [(set_attr "type" "fmov,multi") (set_attr "mode" "") (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) -(define_expand "floatsi2" - [(set (match_operand:MODEF 0 "register_operand" "") - (float:MODEF (match_operand:SI 1 "nonimmediate_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" - " - /* When we use vector converts, we can't have input in memory. */ - if (GET_MODE (operands[0]) == DFmode - && TARGET_USE_VECTOR_CONVERTS && !optimize_size && TARGET_SSE_MATH - && SSE_FLOAT_MODE_P (DFmode)) - operands[1] = force_reg (SImode, operands[1]); - else if (GET_MODE (operands[0]) == SFmode - && !optimize_size && TARGET_USE_VECTOR_CONVERTS && TARGET_SSE_MATH - && SSE_FLOAT_MODE_P (SFmode)) - { - /* When !flag_trapping_math, we handle SImode->SFmode vector - conversions same way as SImode->DFmode. - - For flat_trapping_math we can't safely use vector conversion without - clearing upper half, otherwise precision exception might occur. - However we can still generate the common sequence converting value - from general register to XMM register as: - - mov reg32, mem32 - movd mem32, xmm - cvtdq2pd xmm,xmm - - because we know that movd clears the upper half. - - Sadly in this case we can't rely on reload moving the value to XMM - register, since we need to know if upper half is OK, so we need - to do reloading by hand. We force operand to memory unless target - supports inter unit moves. */ - if (!flag_trapping_math) - operands[1] = force_reg (SImode, operands[1]); - else if (!MEM_P (operands[1])) - { - int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; - rtx tmp = assign_386_stack_local (SImode, slot); - emit_move_insn (tmp, operands[1]); - operands[1] = tmp; - } - } - /* Offload operand of cvtsi2ss and cvtsi2sd into memory for - !TARGET_INTER_UNIT_CONVERSIONS - It is necessary for the patterns to not accept nonmemory operands - as we would optimize out later. */ - else if (!TARGET_INTER_UNIT_CONVERSIONS - && TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) - && !optimize_size - && !MEM_P (operands[1])) - { - int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; - rtx tmp = assign_386_stack_local (GET_MODE (operands[1]), slot); - emit_move_insn (tmp, operands[1]); - operands[1] = tmp; - } - ") - -(define_insn "*floatsisf2_mixed_vector" - [(set (match_operand:SF 0 "register_operand" "=x,f,?f") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "x,m,r")))] - "TARGET_MIX_SSE_I387 && !flag_trapping_math - && TARGET_USE_VECTOR_CONVERTS && !optimize_size" - "@ - cvtdq2ps\t{%1, %0|%0, %1} - fild%z1\t%1 - #" - [(set_attr "type" "sseicvt,fmov,multi") - (set_attr "mode" "SF") - (set_attr "unit" "*,i387,*") - (set_attr "athlon_decode" "double,*,*") - (set_attr "amdfam10_decode" "double,*,*") - (set_attr "fp_int_src" "false,true,true")]) - -(define_insn "*floatsisf2_mixed" - [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,m")))] - "TARGET_MIX_SSE_I387 - && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS) - || optimize_size)" - "@ - fild%z1\t%1 - # - cvtsi2ss\t{%1, %0|%0, %1} - cvtsi2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,sseicvt,sseicvt") - (set_attr "mode" "SF") - (set_attr "unit" "*,i387,*,*") - (set_attr "athlon_decode" "*,*,vector,double") - (set_attr "amdfam10_decode" "*,*,vector,double") - (set_attr "fp_int_src" "true")]) - -(define_insn "*floatsisf2_mixed_memory" - [(set (match_operand:SF 0 "register_operand" "=f,x") - (float:SF (match_operand:SI 1 "memory_operand" "m,m")))] - "TARGET_MIX_SSE_I387 - && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size" - "@ - fild%z1\t%1 - cvtsi2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "*,double") - (set_attr "amdfam10_decode" "*,double") +(define_insn "*floathi2_i387" + [(set (match_operand:X87MODEF 0 "register_operand" "=f") + (float:X87MODEF (match_operand:HI 1 "memory_operand" "m")))] + "TARGET_80387 + && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387)" + "fild%z1\t%1" + [(set_attr "type" "fmov") + (set_attr "mode" "") (set_attr "fp_int_src" "true")]) -(define_insn "*floatsisf2_sse_vector_nointernunit" - [(set (match_operand:SF 0 "register_operand" "=x") - (float:SF (match_operand:SI 1 "memory_operand" "m")))] - "TARGET_SSE_MATH && flag_trapping_math - && TARGET_USE_VECTOR_CONVERTS && !optimize_size - && !TARGET_INTER_UNIT_MOVES" - "#" - [(set_attr "type" "multi")]) - -(define_insn "*floatsisf2_sse_vector_internunit" - [(set (match_operand:SF 0 "register_operand" "=x,x") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm,x")))] - "TARGET_SSE_MATH && flag_trapping_math - && TARGET_USE_VECTOR_CONVERTS && !optimize_size - && TARGET_INTER_UNIT_MOVES" - "#" - [(set_attr "type" "multi")]) - (define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))] - "flag_trapping_math - && TARGET_USE_VECTOR_CONVERTS && reload_completed - && (TARGET_INTER_UNIT_MOVES || MEM_P (operands[1])) - && !SSE_REG_P (operands[1]) && SSE_REG_P (operands[0])" - [(set (match_dup 0) - (float:V4SF (match_dup 2)))] -{ - operands[2] = simplify_gen_subreg (V4SImode, operands[0], SFmode, 0); - operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - emit_insn (gen_sse2_loadld (operands[2], CONST0_RTX (V4SImode), operands[1])); -}) + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:HI 1 "register_operand" ""))) + (clobber (match_operand:HI 2 "memory_operand" ""))] + "TARGET_80387 + && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387) + && reload_completed" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (float:X87MODEF (match_dup 2)))] + "") (define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:SI 1 "register_operand" "")))] - "flag_trapping_math - && TARGET_USE_VECTOR_CONVERTS && reload_completed - && SSE_REG_P (operands[1]) && SSE_REG_P (operands[0])" - [(set (match_dup 2) (vec_duplicate:V4SI (match_dup 1))) - (set (match_dup 0) - (float:V4SF (match_dup 2)))] -{ - operands[2] = simplify_gen_subreg (V4SImode, operands[0], SFmode, 0); - operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); -}) + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:HI 1 "memory_operand" ""))) + (clobber (match_operand:HI 2 "memory_operand" ""))] + "TARGET_80387 + && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387) + && reload_completed" + [(set (match_dup 0) (float:X87MODEF (match_dup 1)))] + "") -(define_insn "*floatsisf2_sse_vector" - [(set (match_operand:SF 0 "register_operand" "=x") - (float:SF (match_operand:SI 1 "register_operand" "x")))] - "TARGET_SSE_MATH && !flag_trapping_math - && TARGET_USE_VECTOR_CONVERTS && !optimize_size - && !TARGET_INTER_UNIT_MOVES" - "cvtdq2ps\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "double") - (set_attr "amdfam10_decode" "double") - (set_attr "fp_int_src" "true")]) +(define_expand "float2" + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF + (match_operand:SSEMODEI24 1 "nonimmediate_operand" "")))] + "TARGET_80387 + || ((mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" + "") -(define_insn "*floatsisf2_sse" - [(set (match_operand:SF 0 "register_operand" "=x,x") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "r,m")))] - "TARGET_SSE_MATH - && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS) - || optimize_size)" - "cvtsi2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "vector,double") - (set_attr "amdfam10_decode" "vector,double") - (set_attr "fp_int_src" "true")]) +;; Pre-reload splitter to add memory clobber to the pattern. +(define_insn_and_split "*float2_1" + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:SSEMODEI24 1 "register_operand" "")))] + "((TARGET_80387 + && (!((mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387)) + || ((mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH + && ((mode == SImode + && TARGET_SSE2 && TARGET_USE_VECTOR_CONVERTS && !optimize_size + && flag_trapping_math) + || !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size)))) + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(parallel [(set (match_dup 0) (float:X87MODEF (match_dup 1))) + (clobber (match_dup 2))])] +{ + operands[2] = assign_386_stack_local (mode, SLOT_TEMP); -(define_insn "*floatsisf2_sse_memory" - [(set (match_operand:SF 0 "register_operand" "=x") - (float:SF (match_operand:SI 1 "memory_operand" "m")))] - "TARGET_SSE_MATH - && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size" - "cvtsi2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "double") - (set_attr "amdfam10_decode" "double") - (set_attr "fp_int_src" "true")]) + /* Avoid store forwarding (partial memory) stall penalty + by passing DImode value through XMM registers. */ + if (mode == DImode && !TARGET_64BIT + && TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + && !optimize_size) + { + emit_insn (gen_floatdi2_i387_with_xmm (operands[0], + operands[1], + operands[2])); + DONE; + } +}) -(define_insn "*floatsidf2_mixed_vector" - [(set (match_operand:DF 0 "register_operand" "=x,f,f") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "x,m,r")))] +(define_insn "*floatsi2_vector_mixed_with_temp" + [(set (match_operand:MODEF 0 "register_operand" "=f,f,x,x,x") + (float:MODEF + (match_operand:SI 1 "nonimmediate_operand" "m,?r,r,m,!x"))) + (clobber (match_operand:SI 2 "memory_operand" "=X,m,m,X,m"))] "TARGET_SSE2 && TARGET_MIX_SSE_I387 && TARGET_USE_VECTOR_CONVERTS && !optimize_size" - "@ - cvtdq2pd\t{%1, %0|%0, %1} - fild%z1\t%1 - #" - [(set_attr "type" "sseicvt,fmov,multi") - (set_attr "mode" "V2DF,DF,DF") - (set_attr "unit" "*,*,i387") - (set_attr "athlon_decode" "double,*,*") - (set_attr "amdfam10_decode" "double,*,*") - (set_attr "fp_int_src" "false,true,true")]) - -(define_insn "*floatsidf2_mixed" - [(set (match_operand:DF 0 "register_operand" "=f,?f,x,x,!x") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,m,x")))] - "TARGET_SSE2 && TARGET_MIX_SSE_I387 - && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS) - || optimize_size)" - "@ - fild%z1\t%1 - # - cvtsi2sd\t{%1, %0|%0, %1} - cvtsi2sd\t{%1, %0|%0, %1} - cvtdq2pd\t{%1, %0|%0, %1}" + "#" [(set_attr "type" "fmov,multi,sseicvt,sseicvt,sseicvt") - (set_attr "mode" "DF,DF,DF,DF,V2DF") + (set_attr "mode" ",,,,") (set_attr "unit" "*,i387,*,*,*") (set_attr "athlon_decode" "*,*,double,direct,double") (set_attr "amdfam10_decode" "*,*,vector,double,double") - (set_attr "fp_int_src" "true,true,true,true,false")]) + (set_attr "fp_int_src" "true")]) -(define_insn "*floatsidf2_mixed_memory" - [(set (match_operand:DF 0 "register_operand" "=f,x") - (float:DF (match_operand:SI 1 "memory_operand" "m,m")))] +(define_insn "*floatsi2_vector_mixed" + [(set (match_operand:MODEF 0 "register_operand" "=f,x") + (float:MODEF (match_operand:SI 1 "memory_operand" "m,m")))] "TARGET_SSE2 && TARGET_MIX_SSE_I387 - && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size" + && TARGET_USE_VECTOR_CONVERTS && !optimize_size" "@ fild%z1\t%1 - cvtsi2sd\t{%1, %0|%0, %1}" + #" [(set_attr "type" "fmov,sseicvt") - (set_attr "mode" "DF") + (set_attr "mode" ",") + (set_attr "unit" "i387,*") (set_attr "athlon_decode" "*,direct") (set_attr "amdfam10_decode" "*,double") (set_attr "fp_int_src" "true")]) -(define_insn "*floatsidf2_sse_vector" - [(set (match_operand:DF 0 "register_operand" "=x") - (float:DF (match_operand:SI 1 "register_operand" "x")))] - "TARGET_SSE2 && TARGET_SSE_MATH - && TARGET_USE_VECTOR_CONVERTS && !optimize_size" - "cvtdq2pd\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "V2DF") - (set_attr "athlon_decode" "double") - (set_attr "amdfam10_decode" "double") +(define_insn "*float2_mixed_with_temp" + [(set (match_operand:MODEF 0 "register_operand" "=f,f,x,x") + (float:MODEF + (match_operand:SSEMODEI24 1 "nonimmediate_operand" "m,?r,r,m"))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" "=X,m,m,X"))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387" + "#" + [(set_attr "type" "fmov,multi,sseicvt,sseicvt") + (set_attr "mode" "") + (set_attr "unit" "*,i387,*,*") + (set_attr "athlon_decode" "*,*,double,direct") + (set_attr "amdfam10_decode" "*,*,vector,double") (set_attr "fp_int_src" "true")]) (define_split - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:SI 1 "memory_operand" "")))] - "TARGET_USE_VECTOR_CONVERTS && reload_completed - && SSE_REG_P (operands[0])" - [(set (match_dup 0) - (float:V2DF - (vec_select:V2SI - (match_dup 2) - (parallel [(const_int 0) (const_int 1)]))))] -{ - operands[2] = simplify_gen_subreg (V4SImode, operands[0], DFmode, 0); - operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); - emit_insn (gen_sse2_loadld (operands[2], CONST0_RTX (V4SImode), operands[1])); -}) + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SSEMODEI24 1 "register_operand" ""))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387 + && TARGET_INTER_UNIT_CONVERSIONS + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(set (match_dup 0) (float:MODEF (match_dup 1)))] + "") -(define_insn "*floatsidf2_sse" - [(set (match_operand:DF 0 "register_operand" "=x,x,!x") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "r,m,x")))] - "TARGET_SSE2 && TARGET_SSE_MATH - && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS) - || optimize_size)" +(define_split + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SSEMODEI24 1 "register_operand" ""))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387 + && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size) + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (float:MODEF (match_dup 2)))] + "") + +(define_insn "*float2_mixed_interunit" + [(set (match_operand:MODEF 0 "register_operand" "=f,x,x") + (float:MODEF + (match_operand:SSEMODEI24 1 "nonimmediate_operand" "m,r,m")))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387 + && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)" + "@ + fild%z1\t%1 + cvtsi2s\t{%1, %0|%0, %1} + cvtsi2s\t{%1, %0|%0, %1}" + [(set_attr "type" "fmov,sseicvt,sseicvt") + (set_attr "mode" "") + (set_attr "unit" "i387,*,*") + (set_attr "athlon_decode" "*,double,direct") + (set_attr "amdfam10_decode" "*,vector,double") + (set_attr "fp_int_src" "true")]) + +(define_insn "*float2_mixed_nointerunit" + [(set (match_operand:MODEF 0 "register_operand" "=f,x") + (float:MODEF + (match_operand:SSEMODEI24 1 "memory_operand" "m,m")))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387 + && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size)" "@ - cvtsi2sd\t{%1, %0|%0, %1} - cvtsi2sd\t{%1, %0|%0, %1} - cvtdq2pd\t{%1, %0|%0, %1}" + fild%z1\t%1 + cvtsi2s\t{%1, %0|%0, %1}" + [(set_attr "type" "fmov,sseicvt") + (set_attr "mode" "") + (set_attr "athlon_decode" "*,direct") + (set_attr "amdfam10_decode" "*,double") + (set_attr "fp_int_src" "true")]) + +(define_insn "*floatsi2_vector_sse_with_temp" + [(set (match_operand:MODEF 0 "register_operand" "=x,x,x") + (float:MODEF + (match_operand:SI 1 "nonimmediate_operand" "r,m,!x"))) + (clobber (match_operand:SI 2 "memory_operand" "=m,X,m"))] + "TARGET_SSE2 && TARGET_SSE_MATH + && TARGET_USE_VECTOR_CONVERTS && !optimize_size" + "#" [(set_attr "type" "sseicvt") - (set_attr "mode" "DF,DF,V2DF") + (set_attr "mode" ",,") (set_attr "athlon_decode" "double,direct,double") (set_attr "amdfam10_decode" "vector,double,double") (set_attr "fp_int_src" "true")]) -(define_insn "*floatsidf2_memory" - [(set (match_operand:DF 0 "register_operand" "=x") - (float:DF (match_operand:SI 1 "memory_operand" "x")))] +(define_insn "*floatsi2_vector_sse" + [(set (match_operand:MODEF 0 "register_operand" "=x") + (float:MODEF (match_operand:SI 1 "memory_operand" "m")))] "TARGET_SSE2 && TARGET_SSE_MATH - && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS) - || optimize_size)" - "cvtsi2sd\t{%1, %0|%0, %1}" + && TARGET_USE_VECTOR_CONVERTS && !optimize_size" + "#" [(set_attr "type" "sseicvt") - (set_attr "mode" "DF") + (set_attr "mode" "") (set_attr "athlon_decode" "direct") (set_attr "amdfam10_decode" "double") (set_attr "fp_int_src" "true")]) -(define_insn "*floatsi2_i387" - [(set (match_operand:MODEF 0 "register_operand" "=f,f") - (float:MODEF - (match_operand:SI 1 "nonimmediate_operand" "m,?r")))] - "TARGET_80387 - && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))" - "@ - fild%z1\t%1 - #" - [(set_attr "type" "fmov,multi") - (set_attr "mode" "") - (set_attr "unit" "*,i387") - (set_attr "fp_int_src" "true")]) - -(define_expand "floatdisf2" - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))] - "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)" +(define_split + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SI 1 "register_operand" ""))) + (clobber (match_operand:SI 2 "memory_operand" ""))] + "TARGET_SSE2 && TARGET_SSE_MATH + && TARGET_USE_VECTOR_CONVERTS && !optimize_size + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(const_int 0)] { - if (!TARGET_INTER_UNIT_CONVERSIONS && TARGET_64BIT - && TARGET_SSE_MATH && SSE_FLOAT_MODE_P (SFmode) - && !optimize_size - && !MEM_P (operands[1])) + rtx op1 = operands[1]; + + operands[3] = simplify_gen_subreg (mode, operands[0], + mode, 0); + if (GET_CODE (op1) == SUBREG) + op1 = SUBREG_REG (op1); + + if (GENERAL_REG_P (op1) && TARGET_INTER_UNIT_MOVES) { - int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; - rtx tmp = assign_386_stack_local (GET_MODE (operands[1]), slot); - emit_move_insn (tmp, operands[1]); - operands[1] = tmp; + operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0); + emit_insn (gen_sse2_loadld (operands[4], + CONST0_RTX (V4SImode), operands[1])); + } + /* We can ignore possible trapping value in the + high part of SSE register for non-trapping math. */ + else if (SSE_REG_P (op1) && !flag_trapping_math) + operands[4] = simplify_gen_subreg (V4SImode, operands[1], SImode, 0); + else + { + operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0); + emit_move_insn (operands[2], operands[1]); + emit_insn (gen_sse2_loadld (operands[4], + CONST0_RTX (V4SImode), operands[2])); } + emit_insn + (gen_sse2_cvtdq2p (operands[3], operands[4])); + DONE; }) -(define_insn "*floatdisf2_mixed" - [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,m")))] - "TARGET_64BIT && TARGET_MIX_SSE_I387 - && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)" - "@ - fild%z1\t%1 - # - cvtsi2ss{q}\t{%1, %0|%0, %1} - cvtsi2ss{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,sseicvt,sseicvt") - (set_attr "mode" "SF") - (set_attr "unit" "*,i387,*,*") - (set_attr "athlon_decode" "*,*,vector,double") - (set_attr "amdfam10_decode" "*,*,vector,double") - (set_attr "fp_int_src" "true")]) +(define_split + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SI 1 "memory_operand" ""))) + (clobber (match_operand:SI 2 "memory_operand" ""))] + "TARGET_SSE2 && TARGET_SSE_MATH + && TARGET_USE_VECTOR_CONVERTS && !optimize_size + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(const_int 0)] +{ + operands[3] = simplify_gen_subreg (mode, operands[0], + mode, 0); + operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0); -(define_insn "*floatdisf2_mixed" - [(set (match_operand:SF 0 "register_operand" "=f,x") - (float:SF (match_operand:DI 1 "memory_operand" "m,m")))] - "TARGET_64BIT && TARGET_MIX_SSE_I387 - && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size" - "@ - fild%z1\t%1 - cvtsi2ss{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "*,double") - (set_attr "amdfam10_decode" "*,double") - (set_attr "fp_int_src" "true")]) + emit_insn (gen_sse2_loadld (operands[4], + CONST0_RTX (V4SImode), operands[1])); + emit_insn + (gen_sse2_cvtdq2p (operands[3], operands[4])); + DONE; +}) -(define_insn "*floatdisf2_sse" - [(set (match_operand:SF 0 "register_operand" "=x,x") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "r,m")))] - "TARGET_64BIT && TARGET_SSE_MATH - && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)" - "cvtsi2ss{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "vector,double") - (set_attr "amdfam10_decode" "vector,double") - (set_attr "fp_int_src" "true")]) +(define_split + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SI 1 "register_operand" "")))] + "TARGET_SSE2 && TARGET_SSE_MATH + && TARGET_USE_VECTOR_CONVERTS && !optimize_size + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(const_int 0)] +{ + rtx op1 = operands[1]; -(define_insn "*floatdisf2_memory" - [(set (match_operand:SF 0 "register_operand" "=x") - (float:SF (match_operand:DI 1 "memory_operand" "m")))] - "TARGET_64BIT && TARGET_SSE_MATH - && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size" - "cvtsi2ss{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "double") - (set_attr "amdfam10_decode" "double") - (set_attr "fp_int_src" "true")]) + operands[3] = simplify_gen_subreg (mode, operands[0], + mode, 0); + if (GET_CODE (op1) == SUBREG) + op1 = SUBREG_REG (op1); -(define_expand "floatdidf2" - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))] - "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" -{ - if (!TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH) - { - ix86_expand_convert_sign_didf_sse (operands[0], operands[1]); - DONE; - } - if (!TARGET_INTER_UNIT_CONVERSIONS && TARGET_64BIT - && TARGET_SSE_MATH && SSE_FLOAT_MODE_P (DFmode) - && !optimize_size - && !MEM_P (operands[1])) + if (GENERAL_REG_P (op1) && TARGET_INTER_UNIT_MOVES) { - int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; - rtx tmp = assign_386_stack_local (GET_MODE (operands[1]), slot); - emit_move_insn (tmp, operands[1]); - operands[1] = tmp; + operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0); + emit_insn (gen_sse2_loadld (operands[4], + CONST0_RTX (V4SImode), operands[1])); } + /* We can ignore possible trapping value in the + high part of SSE register for non-trapping math. */ + else if (SSE_REG_P (op1) && !flag_trapping_math) + operands[4] = simplify_gen_subreg (V4SImode, operands[1], SImode, 0); + else + gcc_unreachable (); }) -(define_insn "*floatdidf2_mixed" - [(set (match_operand:DF 0 "register_operand" "=f,?f,x,x") - (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,m")))] - "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387 - && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)" - "@ - fild%z1\t%1 - # - cvtsi2sd{q}\t{%1, %0|%0, %1} - cvtsi2sd{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,sseicvt,sseicvt") - (set_attr "mode" "DF") - (set_attr "unit" "*,i387,*,*") - (set_attr "athlon_decode" "*,*,double,direct") - (set_attr "amdfam10_decode" "*,*,vector,double") - (set_attr "fp_int_src" "true")]) +(define_split + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SI 1 "memory_operand" "")))] + "TARGET_SSE2 && TARGET_SSE_MATH + && TARGET_USE_VECTOR_CONVERTS && !optimize_size + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(const_int 0)] +{ + operands[3] = simplify_gen_subreg (mode, operands[0], + mode, 0); + operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0); -(define_insn "*floatdidf2_mixed_memory" - [(set (match_operand:DF 0 "register_operand" "=f,x") - (float:DF (match_operand:DI 1 "memory_operand" "m,m")))] - "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387 - && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size" - "@ - fild%z1\t%1 - cvtsi2sd{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,sseicvt") - (set_attr "mode" "DF") - (set_attr "athlon_decode" "*,direct") - (set_attr "amdfam10_decode" "*,double") + emit_insn (gen_sse2_loadld (operands[4], + CONST0_RTX (V4SImode), operands[1])); + emit_insn + (gen_sse2_cvtdq2p (operands[3], operands[4])); + DONE; +}) + +(define_insn "*float2_sse_with_temp" + [(set (match_operand:MODEF 0 "register_operand" "=x,x") + (float:MODEF + (match_operand:SSEMODEI24 1 "nonimmediate_operand" "r,m"))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" "=m,X"))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" + "#" + [(set_attr "type" "sseicvt") + (set_attr "mode" "") + (set_attr "athlon_decode" "double,direct") + (set_attr "amdfam10_decode" "vector,double") (set_attr "fp_int_src" "true")]) -(define_insn "*floatdidf2_sse" - [(set (match_operand:DF 0 "register_operand" "=x,x") - (float:DF (match_operand:DI 1 "nonimmediate_operand" "r,m")))] - "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH +(define_insn "*float2_sse_interunit" + [(set (match_operand:MODEF 0 "register_operand" "=x,x") + (float:MODEF + (match_operand:SSEMODEI24 1 "nonimmediate_operand" "r,m")))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)" - "cvtsi2sd{q}\t{%1, %0|%0, %1}" + "cvtsi2s\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") - (set_attr "mode" "DF") + (set_attr "mode" "") (set_attr "athlon_decode" "double,direct") (set_attr "amdfam10_decode" "vector,double") (set_attr "fp_int_src" "true")]) -(define_insn "*floatdidf2_sse_memory" - [(set (match_operand:DF 0 "register_operand" "=x") - (float:DF (match_operand:DI 1 "memory_operand" "m")))] - "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH - && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size" - "cvtsi2sd{q}\t{%1, %0|%0, %1}" +(define_split + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SSEMODEI24 1 "nonimmediate_operand" ""))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH + && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size) + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(set (match_dup 0) (float:MODEF (match_dup 1)))] + "") + +(define_insn "*float2_sse_nointerunit" + [(set (match_operand:MODEF 0 "register_operand" "=x") + (float:MODEF + (match_operand:SSEMODEI24 1 "memory_operand" "m")))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH + && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size)" + "cvtsi2s\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") - (set_attr "mode" "DF") + (set_attr "mode" "") (set_attr "athlon_decode" "direct") (set_attr "amdfam10_decode" "double") (set_attr "fp_int_src" "true")]) -(define_insn "*floatdi2_i387" - [(set (match_operand:MODEF 0 "register_operand" "=f,f") - (float:MODEF - (match_operand:DI 1 "nonimmediate_operand" "m,?r")))] - "TARGET_80387 - && (!TARGET_SSE_MATH || !TARGET_64BIT - || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))" +(define_split + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SSEMODEI24 1 "register_operand" ""))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH + && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size) + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (float:MODEF (match_dup 2)))] + "") + +(define_split + [(set (match_operand:MODEF 0 "register_operand" "") + (float:MODEF (match_operand:SSEMODEI24 1 "memory_operand" ""))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] + "(mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH + && reload_completed + && (SSE_REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && SSE_REG_P (operands[0])))" + [(set (match_dup 0) (float:MODEF (match_dup 1)))] + "") + +(define_insn "*float2_i387_with_temp" + [(set (match_operand:X87MODEF 0 "register_operand" "=f,f") + (float:X87MODEF + (match_operand:SSEMODEI24 1 "nonimmediate_operand" "m,?r"))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" "=X,m"))] + "TARGET_80387" "@ fild%z1\t%1 #" [(set_attr "type" "fmov,multi") - (set_attr "mode" "") + (set_attr "mode" "") (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) -(define_insn "floatxf2" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:X87MODEI 1 "nonimmediate_operand" "m,?r")))] +(define_insn "*float2_i387" + [(set (match_operand:X87MODEF 0 "register_operand" "=f") + (float:X87MODEF + (match_operand:SSEMODEI24 1 "memory_operand" "m")))] "TARGET_80387" - "@ - fild%z1\t%1 - #" - [(set_attr "type" "fmov,multi") - (set_attr "mode" "XF") - (set_attr "unit" "*,i387") + "fild%z1\t%1" + [(set_attr "type" "fmov") + (set_attr "mode" "") (set_attr "fp_int_src" "true")]) -;; %%% Kill these when reload knows how to do it. (define_split - [(set (match_operand 0 "fp_register_operand" "") - (float (match_operand 1 "register_operand" "")))] - "reload_completed - && X87_FLOAT_MODE_P (GET_MODE (operands[0]))" - [(const_int 0)] + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:SSEMODEI24 1 "register_operand" ""))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] + "TARGET_80387 + && reload_completed + && FP_REG_P (operands[0])" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (float:X87MODEF (match_dup 2)))] + "") + +(define_split + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:SSEMODEI24 1 "memory_operand" ""))) + (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] + "TARGET_80387 + && reload_completed + && FP_REG_P (operands[0])" + [(set (match_dup 0) (float:X87MODEF (match_dup 1)))] + "") + +;; Avoid store forwarding (partial memory) stall penalty +;; by passing DImode value through XMM registers. */ + +(define_insn "floatdi2_i387_with_xmm" + [(set (match_operand:X87MODEF 0 "register_operand" "=f,f") + (float:X87MODEF + (match_operand:DI 1 "nonimmediate_operand" "m,?r"))) + (clobber (match_scratch:V4SI 3 "=X,x")) + (clobber (match_scratch:V4SI 4 "=X,x")) + (clobber (match_operand:DI 2 "memory_operand" "=X,m"))] + "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + && !TARGET_64BIT && !optimize_size" + "#" + [(set_attr "type" "multi") + (set_attr "mode" "") + (set_attr "unit" "i387") + (set_attr "fp_int_src" "true")]) + +(define_split + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:DI 1 "register_operand" ""))) + (clobber (match_scratch:V4SI 3 "")) + (clobber (match_scratch:V4SI 4 "")) + (clobber (match_operand:DI 2 "memory_operand" ""))] + "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + && !TARGET_64BIT && !optimize_size + && reload_completed + && FP_REG_P (operands[0])" + [(set (match_dup 2) (match_dup 3)) + (set (match_dup 0) (float:X87MODEF (match_dup 2)))] { - operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]); - operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[2])); - ix86_free_from_memory (GET_MODE (operands[1])); - DONE; + /* The DImode arrived in a pair of integral registers (e.g. %edx:%eax). + Assemble the 64-bit DImode value in an xmm register. */ + emit_insn (gen_sse2_loadld (operands[3], CONST0_RTX (V4SImode), + gen_rtx_SUBREG (SImode, operands[1], 0))); + emit_insn (gen_sse2_loadld (operands[4], CONST0_RTX (V4SImode), + gen_rtx_SUBREG (SImode, operands[1], 4))); + emit_insn (gen_sse2_punpckldq (operands[3], operands[3], operands[4])); + + operands[3] = gen_rtx_REG (DImode, REGNO (operands[3])); }) -(define_expand "floatunssisf2" - [(use (match_operand:SF 0 "register_operand" "")) - (use (match_operand:SI 1 "nonimmediate_operand" ""))] - "!TARGET_64BIT && TARGET_SSE_MATH" +(define_split + [(set (match_operand:X87MODEF 0 "register_operand" "") + (float:X87MODEF (match_operand:DI 1 "memory_operand" ""))) + (clobber (match_scratch:V4SI 3 "")) + (clobber (match_scratch:V4SI 4 "")) + (clobber (match_operand:DI 2 "memory_operand" ""))] + "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + && !TARGET_64BIT && !optimize_size + && reload_completed + && FP_REG_P (operands[0])" + [(set (match_dup 0) (float:X87MODEF (match_dup 1)))] + "") + +;; Avoid store forwarding (partial memory) stall penalty by extending +;; SImode value to DImode through XMM register instead of pushing two +;; SImode values to stack. Note that even !TARGET_INTER_UNIT_MOVES +;; targets benefit from this optimization. Also note that fild +;; loads from memory only. + +(define_insn "*floatunssi2_1" + [(set (match_operand:X87MODEF 0 "register_operand" "=f,f") + (unsigned_float:X87MODEF + (match_operand:SI 1 "nonimmediate_operand" "x,m"))) + (clobber (match_operand:DI 2 "memory_operand" "=m,m")) + (clobber (match_scratch:SI 3 "=X,x"))] + "!TARGET_64BIT + && TARGET_80387 && TARGET_SSE" + "#" + [(set_attr "type" "multi") + (set_attr "mode" "")]) + +(define_split + [(set (match_operand:X87MODEF 0 "register_operand" "") + (unsigned_float:X87MODEF + (match_operand:SI 1 "register_operand" ""))) + (clobber (match_operand:DI 2 "memory_operand" "")) + (clobber (match_scratch:SI 3 ""))] + "!TARGET_64BIT + && TARGET_80387 && TARGET_SSE + && reload_completed" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) + (float:X87MODEF (match_dup 2)))] + "operands[1] = simplify_gen_subreg (DImode, operands[1], SImode, 0);") + +(define_split + [(set (match_operand:X87MODEF 0 "register_operand" "") + (unsigned_float:X87MODEF + (match_operand:SI 1 "memory_operand" ""))) + (clobber (match_operand:DI 2 "memory_operand" "")) + (clobber (match_scratch:SI 3 ""))] + "!TARGET_64BIT + && TARGET_80387 && TARGET_SSE + && reload_completed" + [(set (match_dup 2) (match_dup 3)) + (set (match_dup 0) + (float:X87MODEF (match_dup 2)))] { - if (TARGET_SSE2) - ix86_expand_convert_uns_sisf_sse (operands[0], operands[1]); - else - x86_emit_floatuns (operands); - DONE; + emit_move_insn (operands[3], operands[1]); + operands[3] = simplify_gen_subreg (DImode, operands[3], SImode, 0); }) -(define_expand "floatunssidf2" - [(use (match_operand:DF 0 "register_operand" "")) - (use (match_operand:SI 1 "nonimmediate_operand" ""))] - "!TARGET_64BIT && TARGET_SSE_MATH && TARGET_SSE2" - "ix86_expand_convert_uns_sidf_sse (operands[0], operands[1]); DONE;") +(define_expand "floatunssi2" + [(parallel + [(set (match_operand:X87MODEF 0 "register_operand" "") + (unsigned_float:X87MODEF + (match_operand:SI 1 "nonimmediate_operand" ""))) + (clobber (match_dup 2)) + (clobber (match_scratch:SI 3 ""))])] + "!TARGET_64BIT + && ((TARGET_80387 && TARGET_SSE) + || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))" +{ + if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + { + ix86_expand_convert_uns_si_sse (operands[0], operands[1]); + DONE; + } + else + { + int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + operands[2] = assign_386_stack_local (DImode, slot); + } +}) (define_expand "floatunsdisf2" [(use (match_operand:SF 0 "register_operand" "")) @@ -5330,8 +5445,8 @@ (define_expand "floatunsdidf2" [(use (match_operand:DF 0 "register_operand" "")) (use (match_operand:DI 1 "nonimmediate_operand" ""))] - "TARGET_SSE_MATH && TARGET_SSE2 - && (TARGET_64BIT || TARGET_KEEPS_VECTOR_ALIGNED_STACK)" + "(TARGET_64BIT || TARGET_KEEPS_VECTOR_ALIGNED_STACK) + && TARGET_SSE2 && TARGET_SSE_MATH" { if (TARGET_64BIT) x86_emit_floatuns (operands); @@ -5374,9 +5489,7 @@ (match_dup 4)) (match_dup 5))) (clobber (reg:CC FLAGS_REG))])] - "split_ti (operands+0, 1, operands+0, operands+3); - split_ti (operands+1, 1, operands+1, operands+4); - split_ti (operands+2, 1, operands+2, operands+5);") + "split_ti (&operands[0], 3, &operands[0], &operands[3]);") ;; %%% splits for addsidi3 ; [(set (match_operand:DI 0 "nonimmediate_operand" "") @@ -5413,9 +5526,7 @@ (match_dup 4)) (match_dup 5))) (clobber (reg:CC FLAGS_REG))])] - "split_di (operands+0, 1, operands+0, operands+3); - split_di (operands+1, 1, operands+1, operands+4); - split_di (operands+2, 1, operands+2, operands+5);") + "split_di (&operands[0], 3, &operands[0], &operands[3]);") (define_insn "adddi3_carry_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") @@ -5441,7 +5552,7 @@ [(set_attr "type" "alu") (set_attr "mode" "DI")]) -(define_insn "*3_cc_overflow" +(define_insn "*3_cc_overflow" [(set (reg:CCC FLAGS_REG) (compare:CCC (plusminus:SWI @@ -5451,7 +5562,7 @@ (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (plusminus:SWI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (, mode, operands)" - "{}\t{%2, %0|%0, %2}" + "{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "")]) @@ -5478,7 +5589,7 @@ [(set_attr "type" "icmp") (set_attr "mode" "")]) -(define_insn "*si3_zext_cc_overflow" +(define_insn "*si3_zext_cc_overflow" [(set (reg:CCC FLAGS_REG) (compare:CCC (plusminus:SI (match_operand:SI 1 "nonimmediate_operand" "0") @@ -5487,7 +5598,7 @@ (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))] "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" - "{l}\t{%2, %k0|%k0, %2}" + "{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) @@ -7150,9 +7261,7 @@ (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) (match_dup 5)))) (clobber (reg:CC FLAGS_REG))])] - "split_ti (operands+0, 1, operands+0, operands+3); - split_ti (operands+1, 1, operands+1, operands+4); - split_ti (operands+2, 1, operands+2, operands+5);") + "split_ti (&operands[0], 3, &operands[0], &operands[3]);") ;; %%% splits for subsidi3 @@ -7185,9 +7294,7 @@ (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) (match_dup 5)))) (clobber (reg:CC FLAGS_REG))])] - "split_di (operands+0, 1, operands+0, operands+3); - split_di (operands+1, 1, operands+1, operands+4); - split_di (operands+2, 1, operands+2, operands+5);") + "split_di (&operands[0], 3, &operands[0], &operands[3]);") (define_insn "subdi3_carry_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") @@ -9600,11 +9707,9 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (XOR, DImode, operands)" - "@ - xor{q}\t{%2, %0|%0, %2} - xor{q}\t{%2, %0|%0, %2}" + "xor{q}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "DI,DI")]) + (set_attr "mode" "DI")]) (define_insn "*xordi_2_rex64" [(set (reg FLAGS_REG) @@ -9616,11 +9721,9 @@ "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) && ix86_binary_operator_ok (XOR, DImode, operands)" - "@ - xor{q}\t{%2, %0|%0, %2} - xor{q}\t{%2, %0|%0, %2}" + "xor{q}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "DI,DI")]) + (set_attr "mode" "DI")]) (define_insn "*xordi_3_rex64" [(set (reg FLAGS_REG) @@ -10045,20 +10148,19 @@ "TARGET_64BIT && reload_completed" [(parallel [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (neg:DI (match_dup 2)) (const_int 0))) - (set (match_dup 0) (neg:DI (match_dup 2)))]) + (compare:CCZ (neg:DI (match_dup 1)) (const_int 0))) + (set (match_dup 0) (neg:DI (match_dup 1)))]) (parallel - [(set (match_dup 1) + [(set (match_dup 2) (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) (match_dup 3)) (const_int 0))) (clobber (reg:CC FLAGS_REG))]) (parallel - [(set (match_dup 1) - (neg:DI (match_dup 1))) + [(set (match_dup 2) + (neg:DI (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] - "split_ti (operands+1, 1, operands+2, operands+3); - split_ti (operands+0, 1, operands+0, operands+1);") + "split_ti (&operands[0], 2, &operands[0], &operands[2]);") (define_expand "negdi2" [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") @@ -10082,20 +10184,19 @@ "!TARGET_64BIT && reload_completed" [(parallel [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (neg:SI (match_dup 2)) (const_int 0))) - (set (match_dup 0) (neg:SI (match_dup 2)))]) + (compare:CCZ (neg:SI (match_dup 1)) (const_int 0))) + (set (match_dup 0) (neg:SI (match_dup 1)))]) (parallel - [(set (match_dup 1) + [(set (match_dup 2) (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) (match_dup 3)) (const_int 0))) (clobber (reg:CC FLAGS_REG))]) (parallel - [(set (match_dup 1) - (neg:SI (match_dup 1))) + [(set (match_dup 2) + (neg:SI (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] - "split_di (operands+1, 1, operands+2, operands+3); - split_di (operands+0, 1, operands+0, operands+1);") + "split_di (&operands[0], 2, &operands[0], &operands[2]);"); (define_insn "*negdi2_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") @@ -10238,17 +10339,11 @@ ;; Changing of sign for FP values is doable using integer unit too. -(define_expand "neg2" - [(set (match_operand:X87MODEF 0 "register_operand" "") - (neg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" - "ix86_expand_fp_absneg_operator (NEG, mode, operands); DONE;") - -(define_expand "abs2" +(define_expand "2" [(set (match_operand:X87MODEF 0 "register_operand" "") - (abs:X87MODEF (match_operand:X87MODEF 1 "register_operand" "")))] + (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "")))] "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" - "ix86_expand_fp_absneg_operator (ABS, mode, operands); DONE;") + "ix86_expand_fp_absneg_operator (, mode, operands); DONE;") (define_insn "*absneg2_mixed" [(set (match_operand:MODEF 0 "register_operand" "=x,x,f,!r") @@ -10277,17 +10372,11 @@ "TARGET_80387 && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" "#") -(define_expand "negtf2" - [(set (match_operand:TF 0 "register_operand" "") - (neg:TF (match_operand:TF 1 "register_operand" "")))] - "TARGET_64BIT" - "ix86_expand_fp_absneg_operator (NEG, TFmode, operands); DONE;") - -(define_expand "abstf2" +(define_expand "tf2" [(set (match_operand:TF 0 "register_operand" "") - (abs:TF (match_operand:TF 1 "register_operand" "")))] + (absneg:TF (match_operand:TF 1 "register_operand" "")))] "TARGET_64BIT" - "ix86_expand_fp_absneg_operator (ABS, TFmode, operands); DONE;") + "ix86_expand_fp_absneg_operator (, TFmode, operands); DONE;") (define_insn "*absnegtf2_sse" [(set (match_operand:TF 0 "register_operand" "=x,x") @@ -10427,75 +10516,40 @@ ;; Conditionalize these after reload. If they match before reload, we ;; lose the clobber and ability to use integer instructions. -(define_insn "*neg2_1" - [(set (match_operand:X87MODEF 0 "register_operand" "=f") - (neg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))] - "TARGET_80387 - && (reload_completed || !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "")]) - -(define_insn "*abs2_1" +(define_insn "*2_1" [(set (match_operand:X87MODEF 0 "register_operand" "=f") - (abs:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))] + (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))] "TARGET_80387 - && (reload_completed || !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))" - "fabs" + && (reload_completed + || !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))" + "f" [(set_attr "type" "fsgn") (set_attr "mode" "")]) -(define_insn "*negextendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (float_extend:DF - (match_operand:SF 1 "register_operand" "0"))))] - "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "DF")]) - -(define_insn "*negextenddfxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (float_extend:XF - (match_operand:DF 1 "register_operand" "0"))))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF")]) - -(define_insn "*negextendsfxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (float_extend:XF - (match_operand:SF 1 "register_operand" "0"))))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF")]) - -(define_insn "*absextendsfdf2" +(define_insn "*extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (float_extend:DF - (match_operand:SF 1 "register_operand" "0"))))] + (absneg:DF (float_extend:DF + (match_operand:SF 1 "register_operand" "0"))))] "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)" - "fabs" + "f" [(set_attr "type" "fsgn") (set_attr "mode" "DF")]) -(define_insn "*absextenddfxf2" +(define_insn "*extendsfxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (float_extend:XF - (match_operand:DF 1 "register_operand" "0"))))] + (absneg:XF (float_extend:XF + (match_operand:SF 1 "register_operand" "0"))))] "TARGET_80387" - "fabs" + "f" [(set_attr "type" "fsgn") (set_attr "mode" "XF")]) -(define_insn "*absextendsfxf2" +(define_insn "*extenddfxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (float_extend:XF - (match_operand:SF 1 "register_operand" "0"))))] + (absneg:XF (float_extend:XF + (match_operand:DF 1 "register_operand" "0"))))] "TARGET_80387" - "fabs" + "f" [(set_attr "type" "fsgn") (set_attr "mode" "XF")]) @@ -13124,7 +13178,7 @@ (lshiftrt:SI (match_dup 3) (minus:QI (const_int 32) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))])] - "split_di (operands, 1, operands + 4, operands + 5);") + "split_di (&operands[0], 1, &operands[4], &operands[5]);") (define_insn "*rotlsi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") @@ -13360,7 +13414,7 @@ (ashift:SI (match_dup 3) (minus:QI (const_int 32) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))])] - "split_di (operands, 1, operands + 4, operands + 5);") + "split_di (&operands[0], 1, &operands[4], &operands[5]);") (define_insn "*rotrdi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") @@ -13637,7 +13691,7 @@ (const_int 1)) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" - "bts{q} %1,%0" + "bts{q}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1")]) (define_insn "*btrq" @@ -13647,7 +13701,7 @@ (const_int 0)) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" - "btr{q} %1,%0" + "btr{q}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1")]) (define_insn "*btcq" @@ -13657,7 +13711,7 @@ (not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1)))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" - "btc{q} %1,%0" + "btc{q}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1")]) ;; Allow Nocona to avoid these instructions if a register is available. @@ -13758,6 +13812,30 @@ emit_insn (gen_xordi3 (operands[0], operands[0], op1)); DONE; }) + +(define_insn "*btdi_rex64" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:DI + (match_operand:DI 0 "register_operand" "r") + (const_int 1) + (match_operand:DI 1 "nonmemory_operand" "rN")) + (const_int 0)))] + "TARGET_64BIT && (TARGET_USE_BT || optimize_size)" + "bt{q}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1")]) + +(define_insn "*btsi" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:SI + (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand:SI 1 "nonmemory_operand" "rN")) + (const_int 0)))] + "TARGET_USE_BT || optimize_size" + "bt{l}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1")]) ;; Store-flag instructions. @@ -13768,113 +13846,17 @@ ;; to avoid partial register stalls. Otherwise do things the setcc+movzx ;; way, which can later delete the movzx if only QImode is needed. -(define_expand "seq" - [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;") - -(define_expand "sne" - [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;") - -(define_expand "sgt" - [(set (match_operand:QI 0 "register_operand" "") - (gt:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;") - -(define_expand "sgtu" - [(set (match_operand:QI 0 "register_operand" "") - (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;") - -(define_expand "slt" +(define_expand "s" [(set (match_operand:QI 0 "register_operand" "") - (lt:QI (reg:CC FLAGS_REG) (const_int 0)))] + (int_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] "" - "if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;") + "if (ix86_expand_setcc (, operands[0])) DONE; else FAIL;") -(define_expand "sltu" +(define_expand "s" [(set (match_operand:QI 0 "register_operand" "") - (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;") - -(define_expand "sge" - [(set (match_operand:QI 0 "register_operand" "") - (ge:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;") - -(define_expand "sgeu" - [(set (match_operand:QI 0 "register_operand" "") - (geu:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;") - -(define_expand "sle" - [(set (match_operand:QI 0 "register_operand" "") - (le:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;") - -(define_expand "sleu" - [(set (match_operand:QI 0 "register_operand" "") - (leu:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;") - -(define_expand "sunordered" - [(set (match_operand:QI 0 "register_operand" "") - (unordered:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;") - -(define_expand "sordered" - [(set (match_operand:QI 0 "register_operand" "") - (ordered:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387" - "if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;") - -(define_expand "suneq" - [(set (match_operand:QI 0 "register_operand" "") - (uneq:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;") - -(define_expand "sunge" - [(set (match_operand:QI 0 "register_operand" "") - (unge:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;") - -(define_expand "sungt" - [(set (match_operand:QI 0 "register_operand" "") - (ungt:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;") - -(define_expand "sunle" - [(set (match_operand:QI 0 "register_operand" "") - (unle:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;") - -(define_expand "sunlt" - [(set (match_operand:QI 0 "register_operand" "") - (unlt:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;") - -(define_expand "sltgt" - [(set (match_operand:QI 0 "register_operand" "") - (ltgt:QI (reg:CC FLAGS_REG) (const_int 0)))] + (fp_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;") + "if (ix86_expand_setcc (, operands[0])) DONE; else FAIL;") (define_insn "*setcc_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") @@ -13969,25 +13951,15 @@ ;; 0xffffffff is NaN, but not in normalized form, so we can't represent ;; it directly. -(define_insn "*sse_setccsf" - [(set (match_operand:SF 0 "register_operand" "=x") - (match_operator:SF 1 "sse_comparison_operator" - [(match_operand:SF 2 "register_operand" "0") - (match_operand:SF 3 "nonimmediate_operand" "xm")]))] - "TARGET_SSE && !TARGET_SSE5" - "cmp%D1ss\t{%3, %0|%0, %3}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "SF")]) - -(define_insn "*sse_setccdf" - [(set (match_operand:DF 0 "register_operand" "=x") - (match_operator:DF 1 "sse_comparison_operator" - [(match_operand:DF 2 "register_operand" "0") - (match_operand:DF 3 "nonimmediate_operand" "xm")]))] - "TARGET_SSE2 && !TARGET_SSE5" - "cmp%D1sd\t{%3, %0|%0, %3}" +(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")]))] + "SSE_FLOAT_MODE_P (mode) && !TARGET_SSE5" + "cmp%D1s\t{%3, %0|%0, %3}" [(set_attr "type" "ssecmp") - (set_attr "mode" "DF")]) + (set_attr "mode" "")]) (define_insn "*sse5_setcc" [(set (match_operand:MODEF 0 "register_operand" "=x") @@ -14006,149 +13978,23 @@ ;; For all bCOND expanders, also expand the compare or test insn that ;; generates reg FLAGS_REG. Generate an equality comparison if `beq' or `bne'. -(define_expand "beq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (EQ, operands[0]); DONE;") - -(define_expand "bne" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (NE, operands[0]); DONE;") - -(define_expand "bgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (GT, operands[0]); DONE;") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (GTU, operands[0]); DONE;") - -(define_expand "blt" +(define_expand "b" [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (LT, operands[0]); DONE;") - -(define_expand "bltu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (LTU, operands[0]); DONE;") - -(define_expand "bge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (GE, operands[0]); DONE;") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) + (if_then_else (int_cond:CC (reg:CC FLAGS_REG) + (const_int 0)) + (label_ref (match_operand 0 "")) (pc)))] "" - "ix86_expand_branch (GEU, operands[0]); DONE;") - -(define_expand "ble" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (LE, operands[0]); DONE;") - -(define_expand "bleu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "ix86_expand_branch (LEU, operands[0]); DONE;") - -(define_expand "bunordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (UNORDERED, operands[0]); DONE;") - -(define_expand "bordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (ORDERED, operands[0]); DONE;") - -(define_expand "buneq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (UNEQ, operands[0]); DONE;") - -(define_expand "bunge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (UNGE, operands[0]); DONE;") - -(define_expand "bungt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (UNGT, operands[0]); DONE;") - -(define_expand "bunle" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (UNLE, operands[0]); DONE;") + "ix86_expand_branch (, operands[0]); DONE;") -(define_expand "bunlt" +(define_expand "b" [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (UNLT, operands[0]); DONE;") - -(define_expand "bltgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) + (if_then_else (fp_cond:CC (reg:CC FLAGS_REG) + (const_int 0)) + (label_ref (match_operand 0 "")) (pc)))] "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (LTGT, operands[0]); DONE;") + "ix86_expand_branch (, operands[0]); DONE;") (define_insn "*jcc_1" [(set (pc) @@ -14186,6 +14032,76 @@ (const_int 2) (const_int 6)))]) +;; ??? Handle alignment requirements for compare and branch fused macro-op; +;; the branch instruction does not start at a 16-byte boundary or cross +;; a 16-byte boundary. + +(define_insn "*jcc_fused_1" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(match_operand:SWI 2 "register_operand" "") + (match_operand:SWI 3 "const0_operand" "n")]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT" +{ + return "test{}\t%2, %2\n\t" + "%+j%E1\t%l0\t" ASM_COMMENT_START " fused"; +} + [(set_attr "type" "multi") + (set_attr "mode" "")]) + +(define_insn "*jcc_fused_2" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(match_operand:SWI 2 "register_operand" "") + (match_operand:SWI 3 "const0_operand" "n")]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT" +{ + return "test{}\t%2, %2\n\t" + "%+j%e1\t%l0\t" ASM_COMMENT_START " fused"; +} + [(set_attr "type" "multi") + (set_attr "mode" "")]) + +(define_insn "*jcc_fused_3" + [(set (pc) + (if_then_else + (match_operator 1 "ix86_comparison_uns_operator" + [(match_operand:SWI 2 "nonimmediate_operand" ",m,") + (match_operand:SWI 3 "" ",,m")]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT + && !(MEM_P (operands[2]) + && (MEM_P (operands[3]) || CONST_INT_P (operands[3])))" +{ + return "cmp{}\t{%3, %2|%2, %3}\n\t" + "%+j%E1\t%l0\t" ASM_COMMENT_START " fused"; +} + [(set_attr "type" "multi") + (set_attr "mode" "")]) + +(define_insn "*jcc_fused_4" + [(set (pc) + (if_then_else + (match_operator 1 "ix86_comparison_uns_operator" + [(match_operand:SWI 2 "nonimmediate_operand" ",m,") + (match_operand:SWI 3 "" ",,m")]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT + && !(MEM_P (operands[2]) + && (MEM_P (operands[3]) || CONST_INT_P (operands[3])))" +{ + return "cmp{}\t{%3, %2|%2, %3}\n\t" + "%+j%e1\t%l0\t" ASM_COMMENT_START " fused"; +} + [(set_attr "type" "multi") + (set_attr "mode" "")]) + ;; In general it is not safe to assume too much about CCmode registers, ;; so simplify-rtx stops when it sees a second one. Under certain ;; conditions this is safe on x86, so help combine not create @@ -14235,6 +14151,199 @@ FAIL; }) +;; zero_extend in SImode is correct, since this is what combine pass +;; generates from shift insn with QImode operand. Actually, the mode of +;; operand 2 (bit offset operand) doesn't matter since bt insn takes +;; appropriate modulo of the bit offset value. + +(define_insn_and_split "*jcc_btdi_rex64" + [(set (pc) + (if_then_else (match_operator 0 "bt_comparison_operator" + [(zero_extract:DI + (match_operand:DI 1 "register_operand" "r") + (const_int 1) + (zero_extend:SI + (match_operand:QI 2 "register_operand" "r"))) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_64BIT && (TARGET_USE_BT || optimize_size)" + "#" + "&& 1" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:DI + (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] +{ + operands[2] = simplify_gen_subreg (DImode, operands[2], QImode, 0); + + PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0]))); +}) + +;; avoid useless masking of bit offset operand +(define_insn_and_split "*jcc_btdi_mask_rex64" + [(set (pc) + (if_then_else (match_operator 0 "bt_comparison_operator" + [(zero_extract:DI + (match_operand:DI 1 "register_operand" "r") + (const_int 1) + (and:SI + (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "const_int_operand" "n")))]) + (label_ref (match_operand 4 "" "")) + (pc)))] + "TARGET_64BIT && (TARGET_USE_BT || optimize_size) + && (INTVAL (operands[3]) & 0x3f) == 0x3f" + "#" + "&& 1" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:DI + (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)]) + (label_ref (match_dup 4)) + (pc)))] +{ + operands[2] = simplify_gen_subreg (DImode, operands[2], SImode, 0); + + PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0]))); +}) + +(define_insn_and_split "*jcc_btsi" + [(set (pc) + (if_then_else (match_operator 0 "bt_comparison_operator" + [(zero_extract:SI + (match_operand:SI 1 "register_operand" "r") + (const_int 1) + (zero_extend:SI + (match_operand:QI 2 "register_operand" "r"))) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_USE_BT || optimize_size" + "#" + "&& 1" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:SI + (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] +{ + operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0); + + PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0]))); +}) + +;; avoid useless masking of bit offset operand +(define_insn_and_split "*jcc_btsi_mask" + [(set (pc) + (if_then_else (match_operator 0 "bt_comparison_operator" + [(zero_extract:SI + (match_operand:SI 1 "register_operand" "r") + (const_int 1) + (and:SI + (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "const_int_operand" "n")))]) + (label_ref (match_operand 4 "" "")) + (pc)))] + "(TARGET_USE_BT || optimize_size) + && (INTVAL (operands[3]) & 0x1f) == 0x1f" + "#" + "&& 1" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:SI + (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)]) + (label_ref (match_dup 4)) + (pc)))] + "PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));") + +(define_insn_and_split "*jcc_btsi_1" + [(set (pc) + (if_then_else (match_operator 0 "bt_comparison_operator" + [(and:SI + (lshiftrt:SI + (match_operand:SI 1 "register_operand" "r") + (match_operand:QI 2 "register_operand" "r")) + (const_int 1)) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_USE_BT || optimize_size" + "#" + "&& 1" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:SI + (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] +{ + operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0); + + PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0]))); +}) + +;; avoid useless masking of bit offset operand +(define_insn_and_split "*jcc_btsi_mask_1" + [(set (pc) + (if_then_else + (match_operator 0 "bt_comparison_operator" + [(and:SI + (lshiftrt:SI + (match_operand:SI 1 "register_operand" "r") + (subreg:QI + (and:SI + (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "const_int_operand" "n")) 0)) + (const_int 1)) + (const_int 0)]) + (label_ref (match_operand 4 "" "")) + (pc)))] + "(TARGET_USE_BT || optimize_size) + && (INTVAL (operands[3]) & 0x1f) == 0x1f" + "#" + "&& 1" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:SI + (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)]) + (label_ref (match_dup 4)) + (pc)))] + "PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));") + ;; Define combination compare-and-branch fp compare instructions to use ;; during early optimization. Splitting the operation apart early makes ;; for bad code when we want to reverse the operation. @@ -14432,7 +14541,7 @@ (clobber (reg:CCFP FLAGS_REG)) (clobber (match_scratch:HI 5 "=a,a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[3])) - && TARGET_USE_MODE_FIOP + && (TARGET_USE_MODE_FIOP || optimize_size) && GET_MODE (operands[1]) == GET_MODE (operands[3]) && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0]))) && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode @@ -14541,15 +14650,8 @@ "") (define_insn "*indirect_jump" - [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))] - "!TARGET_64BIT" - "jmp\t%A0" - [(set_attr "type" "ibr") - (set_attr "length_immediate" "0")]) - -(define_insn "*indirect_jump_rtx64" - [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))] - "TARGET_64BIT" + [(set (pc) (match_operand:P 0 "nonimmediate_operand" "rm"))] + "" "jmp\t%A0" [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) @@ -14593,17 +14695,9 @@ }) (define_insn "*tablejump_1" - [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm")) - (use (label_ref (match_operand 1 "" "")))] - "!TARGET_64BIT" - "jmp\t%A0" - [(set_attr "type" "ibr") - (set_attr "length_immediate" "0")]) - -(define_insn "*tablejump_1_rtx64" - [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm")) + [(set (pc) (match_operand:P 0 "nonimmediate_operand" "rm")) (use (label_ref (match_operand 1 "" "")))] - "TARGET_64BIT" + "" "jmp\t%A0" [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) @@ -14852,7 +14946,10 @@ ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387 ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL), - operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1), + operands[0], const0_rtx, + GEN_INT ((DEFAULT_ABI == SYSV_ABI ? X86_64_SSE_REGPARM_MAX + : X64_SSE_REGPARM_MAX) + - 1), NULL, 0); for (i = 0; i < XVECLEN (operands[2], 0); i++) @@ -14897,9 +14994,9 @@ [(return)] "ix86_can_use_return_insn_p ()" { - if (current_function_pops_args) + if (crtl->args.pops_args) { - rtx popc = GEN_INT (current_function_pops_args); + rtx popc = GEN_INT (crtl->args.pops_args); emit_jump_insn (gen_return_pop_internal (popc)); DONE; } @@ -15051,21 +15148,11 @@ DONE; }) -(define_insn_and_split "eh_return_si" +(define_insn_and_split "eh_return_" [(set (pc) - (unspec [(match_operand:SI 0 "register_operand" "c")] + (unspec [(match_operand:P 0 "register_operand" "c")] UNSPEC_EH_RETURN))] - "!TARGET_64BIT" - "#" - "reload_completed" - [(const_int 0)] - "ix86_expand_epilogue (2); DONE;") - -(define_insn_and_split "eh_return_di" - [(set (pc) - (unspec [(match_operand:DI 0 "register_operand" "c")] - UNSPEC_EH_RETURN))] - "TARGET_64BIT" + "" "#" "reload_completed" [(const_int 0)] @@ -15445,7 +15532,7 @@ (define_expand "paritydi2" [(set (match_operand:DI 0 "register_operand" "") - (parity:DI (match_operand:DI 1 "nonimmediate_operand" "")))] + (parity:DI (match_operand:DI 1 "register_operand" "")))] "! TARGET_POPCNT" { rtx scratch = gen_reg_rtx (QImode); @@ -15473,10 +15560,10 @@ (define_insn_and_split "paritydi2_cmp" [(set (reg:CC FLAGS_REG) - (parity:CC (match_operand:DI 3 "nonimmediate_operand" "0,m"))) - (clobber (match_scratch:DI 0 "=r,X")) - (clobber (match_scratch:SI 1 "=r,r")) - (clobber (match_scratch:HI 2 "=Q,Q"))] + (parity:CC (match_operand:DI 3 "register_operand" "0"))) + (clobber (match_scratch:DI 0 "=r")) + (clobber (match_scratch:SI 1 "=&r")) + (clobber (match_scratch:HI 2 "=Q"))] "! TARGET_POPCNT" "#" "&& reload_completed" @@ -15491,21 +15578,19 @@ (clobber (match_dup 2))])] { operands[4] = gen_lowpart (SImode, operands[3]); - - if (MEM_P (operands[3])) - emit_move_insn (operands[1], gen_highpart (SImode, operands[3])); - else if (! TARGET_64BIT) - operands[1] = gen_highpart (SImode, operands[3]); - else + + if (TARGET_64BIT) { emit_move_insn (operands[1], gen_lowpart (SImode, operands[3])); emit_insn (gen_lshrdi3 (operands[3], operands[3], GEN_INT (32))); } + else + operands[1] = gen_highpart (SImode, operands[3]); }) (define_expand "paritysi2" [(set (match_operand:SI 0 "register_operand" "") - (parity:SI (match_operand:SI 1 "nonimmediate_operand" "")))] + (parity:SI (match_operand:SI 1 "register_operand" "")))] "! TARGET_POPCNT" { rtx scratch = gen_reg_rtx (QImode); @@ -15524,9 +15609,9 @@ (define_insn_and_split "paritysi2_cmp" [(set (reg:CC FLAGS_REG) - (parity:CC (match_operand:SI 2 "nonimmediate_operand" "0,m"))) - (clobber (match_scratch:SI 0 "=r,X")) - (clobber (match_scratch:HI 1 "=Q,Q"))] + (parity:CC (match_operand:SI 2 "register_operand" "0"))) + (clobber (match_scratch:SI 0 "=r")) + (clobber (match_scratch:HI 1 "=&Q"))] "! TARGET_POPCNT" "#" "&& reload_completed" @@ -15541,13 +15626,8 @@ { operands[3] = gen_lowpart (HImode, operands[2]); - if (MEM_P (operands[2])) - emit_move_insn (operands[1], gen_highpart (HImode, operands[2])); - else - { - emit_move_insn (operands[1], gen_lowpart (HImode, operands[2])); - emit_insn (gen_lshrsi3 (operands[2], operands[2], GEN_INT (16))); - } + emit_move_insn (operands[1], gen_lowpart (HImode, operands[2])); + emit_insn (gen_lshrsi3 (operands[2], operands[2], GEN_INT (16))); }) (define_insn "*parityhi2_cmp" @@ -15949,80 +16029,80 @@ ;; Gcc is slightly more smart about handling normal two address instructions ;; so use special patterns for add and mull. -(define_insn "*fop_sf_comm_mixed" - [(set (match_operand:SF 0 "register_operand" "=f,x") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "nonimmediate_operand" "%0,0") - (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))] - "TARGET_MIX_SSE_I387 +(define_insn "*fop__comm_mixed" + [(set (match_operand:MODEF 0 "register_operand" "=f,x") + (match_operator:MODEF 3 "binary_fp_operator" + [(match_operand:MODEF 1 "nonimmediate_operand" "%0,0") + (match_operand:MODEF 2 "nonimmediate_operand" "fm,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 (match_operand:SF 3 "mult_operator" "") + (if_then_else (match_operand:MODEF 3 "mult_operator" "") (const_string "ssemul") (const_string "sseadd")) - (if_then_else (match_operand:SF 3 "mult_operator" "") + (if_then_else (match_operand:MODEF 3 "mult_operator" "") (const_string "fmul") (const_string "fop")))) - (set_attr "mode" "SF")]) + (set_attr "mode" "")]) -(define_insn "*fop_sf_comm_sse" - [(set (match_operand:SF 0 "register_operand" "=x") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "nonimmediate_operand" "%0") - (match_operand:SF 2 "nonimmediate_operand" "xm")]))] - "TARGET_SSE_MATH +(define_insn "*fop__comm_sse" + [(set (match_operand:MODEF 0 "register_operand" "=x") + (match_operator:MODEF 3 "binary_fp_operator" + [(match_operand:MODEF 1 "nonimmediate_operand" "%0") + (match_operand:MODEF 2 "nonimmediate_operand" "xm")]))] + "SSE_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:SF 3 "mult_operator" "") + (if_then_else (match_operand:MODEF 3 "mult_operator" "") (const_string "ssemul") (const_string "sseadd"))) - (set_attr "mode" "SF")]) + (set_attr "mode" "")]) -(define_insn "*fop_sf_comm_i387" - [(set (match_operand:SF 0 "register_operand" "=f") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "nonimmediate_operand" "%0") - (match_operand:SF 2 "nonimmediate_operand" "fm")]))] +(define_insn "*fop__comm_i387" + [(set (match_operand:MODEF 0 "register_operand" "=f") + (match_operator:MODEF 3 "binary_fp_operator" + [(match_operand:MODEF 1 "nonimmediate_operand" "%0") + (match_operand:MODEF 2 "nonimmediate_operand" "fm")]))] "TARGET_80387 && 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:SF 3 "mult_operator" "") + (if_then_else (match_operand:MODEF 3 "mult_operator" "") (const_string "fmul") (const_string "fop"))) - (set_attr "mode" "SF")]) + (set_attr "mode" "")]) -(define_insn "*fop_sf_1_mixed" - [(set (match_operand:SF 0 "register_operand" "=f,f,x") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "nonimmediate_operand" "0,fm,0") - (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))] - "TARGET_MIX_SSE_I387 +(define_insn "*fop__1_mixed" + [(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,0") + (match_operand:MODEF 2 "nonimmediate_operand" "fm,0,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") - (match_operand:SF 3 "mult_operator" "")) + (match_operand:MODEF 3 "mult_operator" "")) (const_string "ssemul") (and (eq_attr "alternative" "2") - (match_operand:SF 3 "div_operator" "")) + (match_operand:MODEF 3 "div_operator" "")) (const_string "ssediv") (eq_attr "alternative" "2") (const_string "sseadd") - (match_operand:SF 3 "mult_operator" "") + (match_operand:MODEF 3 "mult_operator" "") (const_string "fmul") - (match_operand:SF 3 "div_operator" "") + (match_operand:MODEF 3 "div_operator" "") (const_string "fdiv") ] (const_string "fop"))) - (set_attr "mode" "SF")]) + (set_attr "mode" "")]) (define_insn "*rcpsf2_sse" [(set (match_operand:SF 0 "register_operand" "=x") @@ -16033,219 +16113,75 @@ [(set_attr "type" "sse") (set_attr "mode" "SF")]) -(define_insn "*fop_sf_1_sse" - [(set (match_operand:SF 0 "register_operand" "=x") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "register_operand" "0") - (match_operand:SF 2 "nonimmediate_operand" "xm")]))] - "TARGET_SSE_MATH +(define_insn "*fop__1_sse" + [(set (match_operand:MODEF 0 "register_operand" "=x") + (match_operator:MODEF 3 "binary_fp_operator" + [(match_operand:MODEF 1 "register_operand" "0") + (match_operand:MODEF 2 "nonimmediate_operand" "xm")]))] + "SSE_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:SF 3 "mult_operator" "") + (cond [(match_operand:MODEF 3 "mult_operator" "") (const_string "ssemul") - (match_operand:SF 3 "div_operator" "") + (match_operand:MODEF 3 "div_operator" "") (const_string "ssediv") ] (const_string "sseadd"))) - (set_attr "mode" "SF")]) - -;; This pattern is not fully shadowed by the pattern above. -(define_insn "*fop_sf_1_i387" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "nonimmediate_operand" "0,fm") - (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] - "TARGET_80387 && !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") - (cond [(match_operand:SF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:SF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "mode" "SF")]) - -;; ??? Add SSE splitters for these! -(define_insn "*fop_sf_2_i387" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (match_operator:SF 3 "binary_fp_operator" - [(float:SF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) - (match_operand:SF 2 "register_operand" "0,0")]))] - "TARGET_80387 && TARGET_USE_MODE_FIOP && !TARGET_SSE_MATH" - "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:SF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:SF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "fp_int_src" "true") - (set_attr "mode" "")]) - -(define_insn "*fop_sf_3_i387" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "register_operand" "0,0") - (float:SF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && TARGET_USE_MODE_FIOP && !TARGET_SSE_MATH" - "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:SF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:SF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "fp_int_src" "true") (set_attr "mode" "")]) -(define_insn "*fop_df_comm_mixed" - [(set (match_operand:DF 0 "register_operand" "=f,x") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "%0,0") - (match_operand:DF 2 "nonimmediate_operand" "fm,xm")]))] - "TARGET_SSE2 && 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:DF 3 "mult_operator" "") - (const_string "ssemul") - (const_string "sseadd")) - (if_then_else (match_operand:DF 3 "mult_operator" "") - (const_string "fmul") - (const_string "fop")))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_df_comm_sse" - [(set (match_operand:DF 0 "register_operand" "=x") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "%0") - (match_operand:DF 2 "nonimmediate_operand" "xm")]))] - "TARGET_SSE2 && 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:DF 3 "mult_operator" "") - (const_string "ssemul") - (const_string "sseadd"))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_df_comm_i387" - [(set (match_operand:DF 0 "register_operand" "=f") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "%0") - (match_operand:DF 2 "nonimmediate_operand" "fm")]))] - "TARGET_80387 - && 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:DF 3 "mult_operator" "") - (const_string "fmul") - (const_string "fop"))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_df_1_mixed" - [(set (match_operand:DF 0 "register_operand" "=f,f,x") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "0,fm,0") - (match_operand:DF 2 "nonimmediate_operand" "fm,0,xm")]))] - "TARGET_SSE2 && TARGET_SSE_MATH && 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:DF 3 "mult_operator" "")) - (const_string "ssemul") - (and (eq_attr "alternative" "2") - (match_operand:DF 3 "div_operator" "")) - (const_string "ssediv") - (eq_attr "alternative" "2") - (const_string "sseadd") - (match_operand:DF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:DF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_df_1_sse" - [(set (match_operand:DF 0 "register_operand" "=x") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "register_operand" "0") - (match_operand:DF 2 "nonimmediate_operand" "xm")]))] - "TARGET_SSE2 && TARGET_SSE_MATH - && !COMMUTATIVE_ARITH_P (operands[3])" - "* return output_387_binary_op (insn, operands);" - [(set_attr "mode" "DF") - (set (attr "type") - (cond [(match_operand:DF 3 "mult_operator" "") - (const_string "ssemul") - (match_operand:DF 3 "div_operator" "") - (const_string "ssediv") - ] - (const_string "sseadd")))]) - ;; This pattern is not fully shadowed by the pattern above. -(define_insn "*fop_df_1_i387" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "0,fm") - (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] - "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH) +(define_insn "*fop__1_i387" + [(set (match_operand:MODEF 0 "register_operand" "=f,f") + (match_operator:MODEF 3 "binary_fp_operator" + [(match_operand:MODEF 1 "nonimmediate_operand" "0,fm") + (match_operand:MODEF 2 "nonimmediate_operand" "fm,0")]))] + "TARGET_80387 && !(SSE_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") - (cond [(match_operand:DF 3 "mult_operator" "") + (cond [(match_operand:MODEF 3 "mult_operator" "") (const_string "fmul") - (match_operand:DF 3 "div_operator" "") + (match_operand:MODEF 3 "div_operator" "") (const_string "fdiv") ] (const_string "fop"))) - (set_attr "mode" "DF")]) + (set_attr "mode" "")]) ;; ??? Add SSE splitters for these! -(define_insn "*fop_df_2_i387" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (match_operator:DF 3 "binary_fp_operator" - [(float:DF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) - (match_operand:DF 2 "register_operand" "0,0")]))] - "TARGET_80387 && TARGET_USE_MODE_FIOP - && !(TARGET_SSE2 && TARGET_SSE_MATH)" +(define_insn "*fop__2_i387" + [(set (match_operand:MODEF 0 "register_operand" "=f,f") + (match_operator:MODEF 3 "binary_fp_operator" + [(float:MODEF + (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) + (match_operand:MODEF 2 "register_operand" "0,0")]))] + "TARGET_80387 && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + && (TARGET_USE_MODE_FIOP || optimize_size)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") - (cond [(match_operand:DF 3 "mult_operator" "") + (cond [(match_operand:MODEF 3 "mult_operator" "") (const_string "fmul") - (match_operand:DF 3 "div_operator" "") + (match_operand:MODEF 3 "div_operator" "") (const_string "fdiv") ] (const_string "fop"))) (set_attr "fp_int_src" "true") - (set_attr "mode" "")]) + (set_attr "mode" "")]) -(define_insn "*fop_df_3_i387" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "register_operand" "0,0") - (float:DF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && TARGET_USE_MODE_FIOP - && !(TARGET_SSE2 && TARGET_SSE_MATH)" +(define_insn "*fop__3_i387" + [(set (match_operand:MODEF 0 "register_operand" "=f,f") + (match_operator:MODEF 3 "binary_fp_operator" + [(match_operand:MODEF 1 "register_operand" "0,0") + (float:MODEF + (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] + "TARGET_80387 && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + && (TARGET_USE_MODE_FIOP || optimize_size)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") - (cond [(match_operand:DF 3 "mult_operator" "") + (cond [(match_operand:MODEF 3 "mult_operator" "") (const_string "fmul") - (match_operand:DF 3 "div_operator" "") + (match_operand:MODEF 3 "div_operator" "") (const_string "fdiv") ] (const_string "fop"))) @@ -16255,7 +16191,8 @@ (define_insn "*fop_df_4_i387" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_fp_operator" - [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) + [(float_extend:DF + (match_operand:SF 1 "nonimmediate_operand" "fm,0")) (match_operand:DF 2 "register_operand" "0,f")]))] "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" @@ -16335,12 +16272,13 @@ (const_string "fop"))) (set_attr "mode" "XF")]) -(define_insn "*fop_xf_2_i387" +(define_insn "*fop_xf_2_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" - [(float:XF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) - (match_operand:XF 2 "register_operand" "0,0")]))] - "TARGET_80387 && TARGET_USE_MODE_FIOP" + [(float:XF + (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) + (match_operand:XF 2 "register_operand" "0,0")]))] + "TARGET_80387 && (TARGET_USE_MODE_FIOP || optimize_size)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -16352,12 +16290,13 @@ (set_attr "fp_int_src" "true") (set_attr "mode" "")]) -(define_insn "*fop_xf_3_i387" +(define_insn "*fop_xf_3_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" [(match_operand:XF 1 "register_operand" "0,0") - (float:XF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && TARGET_USE_MODE_FIOP" + (float:XF + (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] + "TARGET_80387 && (TARGET_USE_MODE_FIOP || optimize_size)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -16384,7 +16323,7 @@ (const_string "fdiv") ] (const_string "fop"))) - (set_attr "mode" "SF")]) + (set_attr "mode" "")]) (define_insn "*fop_xf_5_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") @@ -16401,7 +16340,7 @@ (const_string "fdiv") ] (const_string "fop"))) - (set_attr "mode" "SF")]) + (set_attr "mode" "")]) (define_insn "*fop_xf_6_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") @@ -16419,7 +16358,7 @@ (const_string "fdiv") ] (const_string "fop"))) - (set_attr "mode" "SF")]) + (set_attr "mode" "")]) (define_split [(set (match_operand 0 "register_operand" "") @@ -16572,28 +16511,24 @@ (define_expand "fmodxf3" [(use (match_operand:XF 0 "register_operand" "")) - (use (match_operand:XF 1 "register_operand" "")) - (use (match_operand:XF 2 "register_operand" ""))] + (use (match_operand:XF 1 "general_operand" "")) + (use (match_operand:XF 2 "general_operand" ""))] "TARGET_USE_FANCY_MATH_387" { rtx label = gen_label_rtx (); - rtx op2; + rtx op1 = gen_reg_rtx (XFmode); + rtx op2 = gen_reg_rtx (XFmode); - if (rtx_equal_p (operands[1], operands[2])) - { - op2 = gen_reg_rtx (XFmode); - emit_move_insn (op2, operands[2]); - } - else - op2 = operands[2]; + emit_move_insn (op2, operands[2]); + emit_move_insn (op1, operands[1]); emit_label (label); - emit_insn (gen_fpremxf4_i387 (operands[1], op2, operands[1], op2)); + emit_insn (gen_fpremxf4_i387 (op1, op2, op1, op2)); ix86_emit_fp_unordered_jump (label); LABEL_NUSES (label) = 1; - emit_move_insn (operands[0], operands[1]); + emit_move_insn (operands[0], op1); DONE; }) @@ -16608,8 +16543,8 @@ rtx op1 = gen_reg_rtx (XFmode); rtx op2 = gen_reg_rtx (XFmode); - emit_insn (gen_extendxf2 (op1, operands[1])); emit_insn (gen_extendxf2 (op2, operands[2])); + emit_insn (gen_extendxf2 (op1, operands[1])); emit_label (label); emit_insn (gen_fpremxf4_i387 (op1, op2, op1, op2)); @@ -16644,28 +16579,24 @@ (define_expand "remainderxf3" [(use (match_operand:XF 0 "register_operand" "")) - (use (match_operand:XF 1 "register_operand" "")) - (use (match_operand:XF 2 "register_operand" ""))] + (use (match_operand:XF 1 "general_operand" "")) + (use (match_operand:XF 2 "general_operand" ""))] "TARGET_USE_FANCY_MATH_387" { rtx label = gen_label_rtx (); - rtx op2; + rtx op1 = gen_reg_rtx (XFmode); + rtx op2 = gen_reg_rtx (XFmode); - if (rtx_equal_p (operands[1], operands[2])) - { - op2 = gen_reg_rtx (XFmode); - emit_move_insn (op2, operands[2]); - } - else - op2 = operands[2]; + emit_move_insn (op2, operands[2]); + emit_move_insn (op1, operands[1]); emit_label (label); - emit_insn (gen_fprem1xf4_i387 (operands[1], op2, operands[1], op2)); + emit_insn (gen_fprem1xf4_i387 (op1, op2, op1, op2)); ix86_emit_fp_unordered_jump (label); LABEL_NUSES (label) = 1; - emit_move_insn (operands[0], operands[1]); + emit_move_insn (operands[0], op1); DONE; }) @@ -16680,8 +16611,8 @@ rtx op1 = gen_reg_rtx (XFmode); rtx op2 = gen_reg_rtx (XFmode); - emit_insn (gen_extendxf2 (op1, operands[1])); emit_insn (gen_extendxf2 (op2, operands[2])); + emit_insn (gen_extendxf2 (op1, operands[1])); emit_label (label); @@ -17686,7 +17617,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r") (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")] UNSPEC_FIST)) - (clobber (match_operand:DI 2 "memory_operand" "=m,m")) + (clobber (match_operand:DI 2 "memory_operand" "=X,m")) (clobber (match_scratch:XF 3 "=&1f,&1f"))] "TARGET_USE_FANCY_MATH_387" "#" @@ -17936,7 +17867,7 @@ UNSPEC_FIST_FLOOR)) (use (match_operand:HI 2 "memory_operand" "m,m")) (use (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:DI 4 "memory_operand" "=m,m")) + (clobber (match_operand:DI 4 "memory_operand" "=X,m")) (clobber (match_scratch:XF 5 "=&1f,&1f"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" @@ -17995,7 +17926,7 @@ UNSPEC_FIST_FLOOR)) (use (match_operand:HI 2 "memory_operand" "m,m")) (use (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))] + (clobber (match_operand:X87MODEI12 4 "memory_operand" "=X,m"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" "#" @@ -18201,7 +18132,7 @@ UNSPEC_FIST_CEIL)) (use (match_operand:HI 2 "memory_operand" "m,m")) (use (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:DI 4 "memory_operand" "=m,m")) + (clobber (match_operand:DI 4 "memory_operand" "=X,m")) (clobber (match_scratch:XF 5 "=&1f,&1f"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" @@ -18260,7 +18191,7 @@ UNSPEC_FIST_CEIL)) (use (match_operand:HI 2 "memory_operand" "m,m")) (use (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))] + (clobber (match_operand:X87MODEI12 4 "memory_operand" "=X,m"))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" "#" @@ -18534,6 +18465,14 @@ ;; Block operation instructions +(define_insn "cld" + [(unspec_volatile [(const_int 0)] UNSPECV_CLD)] + "" + "cld" + [(set_attr "length" "1") + (set_attr "length_immediate" "0") + (set_attr "modrm" "0")]) + (define_expand "movmemsi" [(use (match_operand:BLK 0 "memory_operand" "")) (use (match_operand:BLK 1 "memory_operand" "")) @@ -18606,7 +18545,7 @@ (set (match_operand 2 "register_operand" "") (match_operand 5 "" ""))])] "TARGET_SINGLE_STRINGOP || optimize_size" - "") + "ix86_current_function_needs_cld = 1;") (define_insn "*strmovdi_rex_1" [(set (mem:DI (match_operand:DI 2 "register_operand" "0")) @@ -18633,7 +18572,7 @@ (plus:SI (match_dup 3) (const_int 4)))] "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" - "{movsl|movsd}" + "movs{l|d}" [(set_attr "type" "str") (set_attr "mode" "SI") (set_attr "memory" "both")]) @@ -18648,7 +18587,7 @@ (plus:DI (match_dup 3) (const_int 4)))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" - "{movsl|movsd}" + "movs{l|d}" [(set_attr "type" "str") (set_attr "mode" "SI") (set_attr "memory" "both")]) @@ -18723,7 +18662,7 @@ (match_operand 3 "memory_operand" "")) (use (match_dup 4))])] "" - "") + "ix86_current_function_needs_cld = 1;") (define_insn "*rep_movdi_rex64" [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0)) @@ -18883,7 +18822,7 @@ (set (match_operand 0 "register_operand" "") (match_operand 3 "" ""))])] "TARGET_SINGLE_STRINGOP || optimize_size" - "") + "ix86_current_function_needs_cld = 1;") (define_insn "*strsetdi_rex_1" [(set (mem:DI (match_operand:DI 1 "register_operand" "0")) @@ -18904,7 +18843,7 @@ (plus:SI (match_dup 1) (const_int 4)))] "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" - "{stosl|stosd}" + "stos{l|d}" [(set_attr "type" "str") (set_attr "memory" "store") (set_attr "mode" "SI")]) @@ -18916,7 +18855,7 @@ (plus:DI (match_dup 1) (const_int 4)))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" - "{stosl|stosd}" + "stos{l|d}" [(set_attr "type" "str") (set_attr "memory" "store") (set_attr "mode" "SI")]) @@ -18977,7 +18916,7 @@ (use (match_operand 3 "register_operand" "")) (use (match_dup 1))])] "" - "") + "ix86_current_function_needs_cld = 1;") (define_insn "*rep_stosdi_rex64" [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0)) @@ -19153,7 +19092,7 @@ (clobber (match_operand 1 "register_operand" "")) (clobber (match_dup 2))])] "" - "") + "ix86_current_function_needs_cld = 1;") (define_insn "*cmpstrnqi_nz_1" [(set (reg:CC FLAGS_REG) @@ -19200,7 +19139,7 @@ (clobber (match_operand 1 "register_operand" "")) (clobber (match_dup 2))])] "" - "") + "ix86_current_function_needs_cld = 1;") (define_insn "*cmpstrnqi_1" [(set (reg:CC FLAGS_REG) @@ -19269,7 +19208,7 @@ (clobber (match_operand 1 "register_operand" "")) (clobber (reg:CC FLAGS_REG))])] "" - "") + "ix86_current_function_needs_cld = 1;") (define_insn "*strlenqi_1" [(set (match_operand:SI 0 "register_operand" "=&c") @@ -19388,7 +19327,7 @@ (match_operand:DI 2 "general_operand" "") (match_operand:DI 3 "general_operand" "")))] "TARGET_64BIT" - "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;") + "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") (define_insn "x86_movdicc_0_m1_rex64" [(set (match_operand:DI 0 "register_operand" "=r") @@ -19407,6 +19346,21 @@ (set_attr "mode" "DI") (set_attr "length_immediate" "0")]) +(define_insn "*x86_movdicc_0_m1_se" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extract:DI (match_operand 1 "ix86_carry_flag_operator" "") + (const_int 1) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))] + "" + "sbb{q}\t%0, %0" + [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") + (set_attr "memory" "none") + (set_attr "imm_disp" "false") + (set_attr "mode" "DI") + (set_attr "length_immediate" "0")]) + (define_insn "*movdicc_c_rex64" [(set (match_operand:DI 0 "register_operand" "=r,r") (if_then_else:DI (match_operator 1 "ix86_comparison_operator" @@ -19427,7 +19381,7 @@ (match_operand:SI 2 "general_operand" "") (match_operand:SI 3 "general_operand" "")))] "" - "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;") + "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") ;; Data flow gets confused by our desire for `sbbl reg,reg', and clearing ;; the register first winds up with `sbbl $0,reg', which is also weird. @@ -19450,6 +19404,21 @@ (set_attr "mode" "SI") (set_attr "length_immediate" "0")]) +(define_insn "*x86_movsicc_0_m1_se" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extract:SI (match_operand 1 "ix86_carry_flag_operator" "") + (const_int 1) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))] + "" + "sbb{l}\t%0, %0" + [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") + (set_attr "memory" "none") + (set_attr "imm_disp" "false") + (set_attr "mode" "SI") + (set_attr "length_immediate" "0")]) + (define_insn "*movsicc_noc" [(set (match_operand:SI 0 "register_operand" "=r,r") (if_then_else:SI (match_operator 1 "ix86_comparison_operator" @@ -19470,7 +19439,7 @@ (match_operand:HI 2 "general_operand" "") (match_operand:HI 3 "general_operand" "")))] "TARGET_HIMODE_MATH" - "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;") + "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") (define_insn "*movhicc_noc" [(set (match_operand:HI 0 "register_operand" "=r,r") @@ -19492,7 +19461,7 @@ (match_operand:QI 2 "general_operand" "") (match_operand:QI 3 "general_operand" "")))] "TARGET_QIMODE_MATH" - "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;") + "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") (define_insn_and_split "*movqicc_noc" [(set (match_operand:QI 0 "register_operand" "=r,r") @@ -19514,13 +19483,15 @@ [(set_attr "type" "icmov") (set_attr "mode" "SI")]) -(define_expand "movsfcc" - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operand 1 "comparison_operator" "") - (match_operand:SF 2 "register_operand" "") - (match_operand:SF 3 "register_operand" "")))] - "(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH" - "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") +(define_expand "movcc" + [(set (match_operand:X87MODEF 0 "register_operand" "") + (if_then_else:X87MODEF + (match_operand 1 "comparison_operator" "") + (match_operand:X87MODEF 2 "register_operand" "") + (match_operand:X87MODEF 3 "register_operand" "")))] + "(TARGET_80387 && TARGET_CMOVE) + || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" + "if (ix86_expand_fp_movcc (operands)) DONE; else FAIL;") (define_insn "*movsfcc_1_387" [(set (match_operand:SF 0 "register_operand" "=f,f,r,r") @@ -19538,14 +19509,6 @@ [(set_attr "type" "fcmov,fcmov,icmov,icmov") (set_attr "mode" "SF,SF,SI,SI")]) -(define_expand "movdfcc" - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_operand 1 "comparison_operator" "") - (match_operand:DF 2 "register_operand" "") - (match_operand:DF 3 "register_operand" "")))] - "(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)" - "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") - (define_insn "*movdfcc_1" [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" @@ -19589,22 +19552,13 @@ [(set (match_dup 2) (if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)]) (match_dup 5) - (match_dup 7))) + (match_dup 6))) (set (match_dup 3) (if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)]) - (match_dup 6) + (match_dup 7) (match_dup 8)))] - "split_di (operands+2, 1, operands+5, operands+6); - split_di (operands+3, 1, operands+7, operands+8); - split_di (operands, 1, operands+2, operands+3);") - -(define_expand "movxfcc" - [(set (match_operand:XF 0 "register_operand" "") - (if_then_else:XF (match_operand 1 "comparison_operator" "") - (match_operand:XF 2 "register_operand" "") - (match_operand:XF 3 "register_operand" "")))] - "TARGET_80387 && TARGET_CMOVE" - "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") + "split_di (&operands[2], 2, &operands[5], &operands[7]); + split_di (&operands[0], 1, &operands[2], &operands[3]);") (define_insn "*movxfcc_1" [(set (match_operand:XF 0 "register_operand" "=f,f") @@ -19638,41 +19592,15 @@ ;; 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 "sminsf3" - [(set (match_operand:SF 0 "register_operand" "=x") - (smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0") - (match_operand:SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE_MATH" - "minss\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "SF")]) - -(define_insn "smaxsf3" - [(set (match_operand:SF 0 "register_operand" "=x") - (smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0") - (match_operand:SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE_MATH" - "maxss\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "SF")]) - -(define_insn "smindf3" - [(set (match_operand:DF 0 "register_operand" "=x") - (smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0") - (match_operand:DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 && TARGET_SSE_MATH" - "minsd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "DF")]) - -(define_insn "smaxdf3" - [(set (match_operand:DF 0 "register_operand" "=x") - (smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0") - (match_operand:DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 && TARGET_SSE_MATH" - "maxsd\t{%2, %0|%0, %2}" +(define_insn "3" + [(set (match_operand:MODEF 0 "register_operand" "=x") + (smaxmin:MODEF + (match_operand:MODEF 1 "nonimmediate_operand" "%0") + (match_operand:MODEF 2 "nonimmediate_operand" "xm")))] + "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" + "s\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") - (set_attr "mode" "DF")]) + (set_attr "mode" "")]) ;; These versions of the min/max patterns implement exactly the operations ;; min = (op1 < op2 ? op1 : op2) @@ -19680,45 +19608,27 @@ ;; Their operands are not commutative, and thus they may be used in the ;; presence of -0.0 and NaN. -(define_insn "*ieee_sminsf3" - [(set (match_operand:SF 0 "register_operand" "=x") - (unspec:SF [(match_operand:SF 1 "register_operand" "0") - (match_operand:SF 2 "nonimmediate_operand" "xm")] - UNSPEC_IEEE_MIN))] - "TARGET_SSE_MATH" - "minss\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "SF")]) - -(define_insn "*ieee_smaxsf3" - [(set (match_operand:SF 0 "register_operand" "=x") - (unspec:SF [(match_operand:SF 1 "register_operand" "0") - (match_operand:SF 2 "nonimmediate_operand" "xm")] - UNSPEC_IEEE_MAX))] - "TARGET_SSE_MATH" - "maxss\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "SF")]) - -(define_insn "*ieee_smindf3" - [(set (match_operand:DF 0 "register_operand" "=x") - (unspec:DF [(match_operand:DF 1 "register_operand" "0") - (match_operand:DF 2 "nonimmediate_operand" "xm")] - UNSPEC_IEEE_MIN))] - "TARGET_SSE2 && TARGET_SSE_MATH" - "minsd\t{%2, %0|%0, %2}" +(define_insn "*ieee_smin3" + [(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_MIN))] + "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" + "mins\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") - (set_attr "mode" "DF")]) + (set_attr "mode" "")]) -(define_insn "*ieee_smaxdf3" - [(set (match_operand:DF 0 "register_operand" "=x") - (unspec:DF [(match_operand:DF 1 "register_operand" "0") - (match_operand:DF 2 "nonimmediate_operand" "xm")] - UNSPEC_IEEE_MAX))] - "TARGET_SSE2 && TARGET_SSE_MATH" - "maxsd\t{%2, %0|%0, %2}" +(define_insn "*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))] + "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" + "maxs\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") - (set_attr "mode" "DF")]) + (set_attr "mode" "")]) ;; Make two stack loads independent: ;; fld aa fld aa @@ -19747,37 +19657,13 @@ operands[1], operands[0]);") ;; Conditional addition patterns -(define_expand "addqicc" - [(match_operand:QI 0 "register_operand" "") - (match_operand 1 "comparison_operator" "") - (match_operand:QI 2 "register_operand" "") - (match_operand:QI 3 "const_int_operand" "")] - "" - "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") - -(define_expand "addhicc" - [(match_operand:HI 0 "register_operand" "") - (match_operand 1 "comparison_operator" "") - (match_operand:HI 2 "register_operand" "") - (match_operand:HI 3 "const_int_operand" "")] - "" - "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") - -(define_expand "addsicc" - [(match_operand:SI 0 "register_operand" "") +(define_expand "addcc" + [(match_operand:SWI 0 "register_operand" "") (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "const_int_operand" "")] + (match_operand:SWI 2 "register_operand" "") + (match_operand:SWI 3 "const_int_operand" "")] "" - "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") - -(define_expand "adddicc" - [(match_operand:DI 0 "register_operand" "") - (match_operand 1 "comparison_operator" "") - (match_operand:DI 2 "register_operand" "") - (match_operand:DI 3 "const_int_operand" "")] - "TARGET_64BIT" - "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") + "if (ix86_expand_int_addcc (operands)) DONE; else FAIL;") ;; Misc patterns (?) @@ -19906,12 +19792,12 @@ (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0))) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_STACK_PROBE" - "call\t__alloca" + "call\t___chkstk" [(set_attr "type" "multi") (set_attr "length" "5")]) (define_insn "allocate_stack_worker_64" - [(set (match_operand:DI 0 "register_operand" "=a") + [(set (match_operand:DI 0 "register_operand" "+a") (unspec_volatile:DI [(match_dup 0)] UNSPECV_STACK_PROBE)) (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0))) (clobber (reg:DI R10_REG)) @@ -21191,32 +21077,30 @@ (use (match_operand:DI 2 "const_int_operand" "i")) (use (label_ref:DI (match_operand 3 "" "X")))] "TARGET_64BIT - && INTVAL (operands[4]) + SSE_REGPARM_MAX * 16 - 16 < 128 + && INTVAL (operands[4]) + X86_64_SSE_REGPARM_MAX * 16 - 16 < 128 && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128" - "* { int i; operands[0] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, operands[0], operands[4])); - output_asm_insn (\"jmp\\t%A1\", operands); - for (i = SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--) + output_asm_insn ("jmp\t%A1", operands); + for (i = X86_64_SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--) { operands[4] = adjust_address (operands[0], DImode, i*16); operands[5] = gen_rtx_REG (TImode, SSE_REGNO (i)); PUT_MODE (operands[4], TImode); if (GET_CODE (XEXP (operands[0], 0)) != PLUS) - output_asm_insn (\"rex\", operands); - output_asm_insn (\"movaps\\t{%5, %4|%4, %5}\", operands); + output_asm_insn ("rex", operands); + output_asm_insn ("movaps\t{%5, %4|%4, %5}", operands); } - (*targetm.asm_out.internal_label) (asm_out_file, \"L\", - CODE_LABEL_NUMBER (operands[3])); - return \"\"; + (*targetm.asm_out.internal_label) (asm_out_file, "L", + CODE_LABEL_NUMBER (operands[3])); + return ""; } - " [(set_attr "type" "other") (set_attr "length_immediate" "0") (set_attr "length_address" "0") - (set_attr "length" "135") + (set_attr "length" "34") (set_attr "memory" "store") (set_attr "modrm" "0") (set_attr "mode" "DI")])