X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fi386%2Fi386.md;h=b98bce3ff98c4f21ad2649371cef22d230ef2a29;hb=359a1a93d8ee75957b9e61f1175a141e315b7184;hp=408787b8ab4a8aa373ab01823ca31eb4b5c6ee79;hpb=b861eae354492368477773098d6dfc9710de7015;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 408787b8ab4..b98bce3ff98 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1,6 +1,6 @@ ;; GCC machine description for IA-32 and x86-64. ;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 ;; Free Software Foundation, Inc. ;; Mostly by William Schelter. ;; x86_64 support added by Jan Hubicka @@ -30,7 +30,6 @@ ;; L,W,B,Q,S,T -- print the opcode suffix for specified size of operand. ;; C -- print opcode suffix for set/cmov insn. ;; c -- like C, but print reversed condition -;; E,e -- likewise, but for compare-and-branch fused insn. ;; F,f -- likewise, but for floating-point. ;; O -- if HAVE_AS_IX86_CMOV_SUN_SYNTAX, expand to "w.", "l." or "q.", ;; otherwise nothing @@ -57,6 +56,7 @@ ;; X -- don't print any sort of PIC '@' suffix for a symbol. ;; & -- print some in-use local-dynamic symbol name. ;; H -- print a memory address offset by 8; used for sse high-parts +;; Y -- print condition for XOP pcom* instruction. ;; + -- print a branch hint as 'cs' or 'ds' prefix ;; ; -- print a semicolon (after prefixes due to bug in older gas). @@ -85,6 +85,7 @@ (UNSPEC_SET_RIP 16) (UNSPEC_SET_GOT_OFFSET 17) (UNSPEC_MEMORY_BLOCKAGE 18) + (UNSPEC_SSE_PROLOGUE_SAVE_LOW 19) ; TLS support (UNSPEC_TP 20) @@ -199,6 +200,11 @@ (UNSPEC_FMA4_INTRINSIC 150) (UNSPEC_FMA4_FMADDSUB 151) (UNSPEC_FMA4_FMSUBADD 152) + (UNSPEC_XOP_UNSIGNED_CMP 151) + (UNSPEC_XOP_TRUEFALSE 152) + (UNSPEC_XOP_PERMUTE 153) + (UNSPEC_FRCZ 154) + ; For AES support (UNSPEC_AESENC 159) (UNSPEC_AESENCLAST 160) @@ -213,11 +219,12 @@ ; For AVX support (UNSPEC_PCMP 166) (UNSPEC_VPERMIL 167) - (UNSPEC_VPERMIL2F128 168) - (UNSPEC_MASKLOAD 169) - (UNSPEC_MASKSTORE 170) - (UNSPEC_CAST 171) - (UNSPEC_VTESTP 172) + (UNSPEC_VPERMIL2 168) + (UNSPEC_VPERMIL2F128 169) + (UNSPEC_MASKLOAD 170) + (UNSPEC_MASKSTORE 171) + (UNSPEC_CAST 172) + (UNSPEC_VTESTP 173) ]) (define_constants @@ -241,7 +248,11 @@ (UNSPECV_RDTSC 18) (UNSPECV_RDTSCP 19) (UNSPECV_RDPMC 20) - (UNSPECV_VSWAPMOV 21) + (UNSPECV_VSWAPMOV 21) + (UNSPECV_LLWP_INTRINSIC 22) + (UNSPECV_SLWP_INTRINSIC 23) + (UNSPECV_LWPVAL_INTRINSIC 24) + (UNSPECV_LWPINS_INTRINSIC 25) ]) ;; Constants to represent pcomtrue/pcomfalse variants @@ -254,6 +265,20 @@ (COM_TRUE_P 5) ]) +;; Constants used in the XOP 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) @@ -318,7 +343,7 @@ ;; Processor type. (define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,atom, - generic64,amdfam10" + generic64,amdfam10,bdver1" (const (symbol_ref "ix86_schedule"))) ;; A basic instruction type. Refinements due to arguments to be @@ -333,7 +358,7 @@ fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint, sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul, sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,ssediv,sseins, - ssemuladd,sse4arg, + ssemuladd,sse4arg,lwp, mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft" (const_string "other")) @@ -554,7 +579,7 @@ ;; if the instruction is complex. (define_attr "memory" "none,load,store,both,unknown" - (cond [(eq_attr "type" "other,multi,str") + (cond [(eq_attr "type" "other,multi,str,lwp") (const_string "unknown") (eq_attr "type" "lea,fcmov,fpspc") (const_string "none") @@ -653,11 +678,11 @@ (set_attr "type" "multi")]) ;; All integer comparison codes. -(define_code_iterator int_cond [ne eq ge gt le lt geu gtu leu ltu ]) +(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 ]) + uneq unge ungt unle unlt ltgt]) (define_code_iterator plusminus [plus minus]) @@ -672,6 +697,8 @@ (define_code_attr plusminus_mnemonic [(plus "add") (ss_plus "adds") (us_plus "addus") (minus "sub") (ss_minus "subs") (us_minus "subus")]) +(define_code_attr plusminus_carry_mnemonic + [(plus "adc") (minus "sbb")]) ;; Mark commutative operators as such in constraints. (define_code_attr comm [(plus "%") (ss_plus "%") (us_plus "%") @@ -687,33 +714,52 @@ (define_code_iterator maxmin [smax smin 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")]) +(define_code_attr maxmin_int [(smax "maxs") (smin "mins") + (umax "maxu") (umin "minu")]) +(define_code_attr maxmin_float [(smax "max") (smin "min")]) + +;; Mapping of logic operators +(define_code_iterator any_logic [and ior xor]) +(define_code_iterator any_or [ior xor]) + +;; Base name for insn mnemonic. +(define_code_attr logic [(and "and") (ior "or") (xor "xor")]) + +;; Mapping of shift-right operators +(define_code_iterator any_shiftrt [lshiftrt ashiftrt]) + +;; Base name for define_insn +(define_code_attr shiftrt_insn [(lshiftrt "lshr") (ashiftrt "ashr")]) + +;; Base name for insn mnemonic. +(define_code_attr shiftrt [(lshiftrt "shr") (ashiftrt "sar")]) + +;; Mapping of rotate operators +(define_code_iterator any_rotate [rotate rotatert]) -;; Mapping of parallel logic operators -(define_code_iterator plogic [and ior xor]) +;; Base name for define_insn +(define_code_attr rotate_insn [(rotate "rotl") (rotatert "rotr")]) ;; Base name for insn mnemonic. -(define_code_attr plogicprefix [(and "and") (ior "or") (xor "xor")]) +(define_code_attr rotate [(rotate "rol") (rotatert "ror")]) ;; 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")]) +(define_code_attr absneg_mnemonic [(abs "abs") (neg "chs")]) ;; Used in signed and unsigned widening multiplications. (define_code_iterator any_extend [sign_extend zero_extend]) -;; Used in signed and unsigned divisions. -(define_code_iterator any_div [div udiv]) - ;; Various insn prefixes for signed and unsigned operations. (define_code_attr u [(sign_extend "") (zero_extend "u") (div "") (udiv "u")]) (define_code_attr s [(sign_extend "s") (zero_extend "u")]) +;; Used in signed and unsigned divisions. +(define_code_iterator any_div [div udiv]) + ;; Instruction prefix for signed and unsigned operations. (define_code_attr sgnprefix [(sign_extend "i") (zero_extend "") (div "i") (udiv "")]) @@ -721,6 +767,9 @@ ;; All single word integer modes. (define_mode_iterator SWI [QI HI SI (DI "TARGET_64BIT")]) +;; Single word integer modes without DImode. +(define_mode_iterator SWI124 [QI HI SI]) + ;; Single word integer modes without QImode. (define_mode_iterator SWI248 [HI SI (DI "TARGET_64BIT")]) @@ -737,18 +786,27 @@ (HI "TARGET_HIMODE_MATH") SI (DI "TARGET_64BIT")]) +;; Math-dependant single word integer modes without DImode. +(define_mode_iterator SWIM124 [(QI "TARGET_QIMODE_MATH") + (HI "TARGET_HIMODE_MATH") + SI]) + ;; Math-dependant single word integer modes without QImode. (define_mode_iterator SWIM248 [(HI "TARGET_HIMODE_MATH") SI (DI "TARGET_64BIT")]) -;; Half mode for double word integer modes. -(define_mode_iterator DWIH [(SI "!TARGET_64BIT") - (DI "TARGET_64BIT")]) - ;; Double word integer modes. +(define_mode_iterator DWI [(DI "!TARGET_64BIT") + (TI "TARGET_64BIT")]) + +;; Double word integer modes as mode attribute. (define_mode_attr DWI [(SI "DI") (DI "TI")]) (define_mode_attr dwi [(SI "di") (DI "ti")]) +;; Half mode for double word integer modes. +(define_mode_iterator DWIH [(SI "!TARGET_64BIT") + (DI "TARGET_64BIT")]) + ;; Instruction suffix for integer modes. (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")]) @@ -759,11 +817,14 @@ (define_mode_attr i [(QI "n") (HI "n") (SI "i") (DI "e")]) ;; General operand constraint for word modes. -(define_mode_attr g [(SI "g") (DI "rme")]) +(define_mode_attr g [(QI "qmn") (HI "rmn") (SI "g") (DI "rme")]) ;; Immediate operand constraint for double integer modes. (define_mode_attr di [(SI "iF") (DI "e")]) +;; Immediate operand constraint for shifts. +(define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")]) + ;; General operand predicate for integer modes. (define_mode_attr general_operand [(QI "general_operand") @@ -772,6 +833,36 @@ (DI "x86_64_general_operand") (TI "x86_64_general_operand")]) +;; General sign/zero extend operand predicate for integer modes. +(define_mode_attr general_szext_operand + [(QI "general_operand") + (HI "general_operand") + (SI "general_operand") + (DI "x86_64_szext_general_operand")]) + +;; Operand predicate for shifts. +(define_mode_attr shift_operand + [(QI "nonimmediate_operand") + (HI "nonimmediate_operand") + (SI "nonimmediate_operand") + (DI "shiftdi_operand") + (TI "register_operand")]) + +;; Operand predicate for shift argument. +(define_mode_attr shift_immediate_operand + [(QI "const_1_to_31_operand") + (HI "const_1_to_31_operand") + (SI "const_1_to_31_operand") + (DI "const_1_to_63_operand")]) + +;; Input operand predicate for arithmetic left shifts. +(define_mode_attr ashl_input_operand + [(QI "nonimmediate_operand") + (HI "nonimmediate_operand") + (SI "nonimmediate_operand") + (DI "ashldi_input_operand") + (TI "reg_or_pm1_operand")]) + ;; SSE and x87 SFmode and DFmode floating point modes (define_mode_iterator MODEF [SF DF]) @@ -819,322 +910,80 @@ ;; Compare and branch/compare and store instructions. -(define_expand "cbranchti4" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" ""))) - (set (pc) (if_then_else - (match_operator 0 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "TARGET_64BIT" -{ - if (MEM_P (operands[1]) && MEM_P (operands[2])) - operands[1] = force_reg (TImode, operands[1]); - ix86_compare_op0 = operands[1]; - ix86_compare_op1 = operands[2]; - ix86_expand_branch (GET_CODE (operands[0]), operands[3]); - DONE; -}) - -(define_expand "cbranchdi4" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "x86_64_general_operand" ""))) - (set (pc) (if_then_else - (match_operator 0 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "" -{ - if (MEM_P (operands[1]) && MEM_P (operands[2])) - operands[1] = force_reg (DImode, operands[1]); - ix86_compare_op0 = operands[1]; - ix86_compare_op1 = operands[2]; - ix86_expand_branch (GET_CODE (operands[0]), operands[3]); - DONE; -}) - -(define_expand "cstoredi4" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:DI 2 "nonimmediate_operand" "") - (match_operand:DI 3 "x86_64_general_operand" ""))) - (set (match_operand:QI 0 "register_operand" "") - (match_operator 1 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]))] - "TARGET_64BIT" -{ - if (MEM_P (operands[2]) && MEM_P (operands[3])) - operands[2] = force_reg (DImode, operands[2]); - ix86_compare_op0 = operands[2]; - ix86_compare_op1 = operands[3]; - ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); - DONE; -}) - -(define_expand "cbranchsi4" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:SI 1 "cmpsi_operand" "") - (match_operand:SI 2 "general_operand" ""))) - (set (pc) (if_then_else - (match_operator 0 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "" -{ - if (MEM_P (operands[1]) && MEM_P (operands[2])) - operands[1] = force_reg (SImode, operands[1]); - ix86_compare_op0 = operands[1]; - ix86_compare_op1 = operands[2]; - ix86_expand_branch (GET_CODE (operands[0]), operands[3]); - DONE; -}) - -(define_expand "cstoresi4" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:SI 2 "cmpsi_operand" "") - (match_operand:SI 3 "general_operand" ""))) - (set (match_operand:QI 0 "register_operand" "") - (match_operator 1 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]))] - "" -{ - if (MEM_P (operands[2]) && MEM_P (operands[3])) - operands[2] = force_reg (SImode, operands[2]); - ix86_compare_op0 = operands[2]; - ix86_compare_op1 = operands[3]; - ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); - DONE; -}) - -(define_expand "cbranchhi4" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (pc) (if_then_else - (match_operator 0 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "" -{ - if (MEM_P (operands[1]) && MEM_P (operands[2])) - operands[1] = force_reg (HImode, operands[1]); - ix86_compare_op0 = operands[1]; - ix86_compare_op1 = operands[2]; - ix86_expand_branch (GET_CODE (operands[0]), operands[3]); - DONE; -}) - -(define_expand "cstorehi4" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:HI 2 "nonimmediate_operand" "") - (match_operand:HI 3 "general_operand" ""))) - (set (match_operand:QI 0 "register_operand" "") - (match_operator 1 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]))] - "" -{ - if (MEM_P (operands[2]) && MEM_P (operands[3])) - operands[2] = force_reg (HImode, operands[2]); - ix86_compare_op0 = operands[2]; - ix86_compare_op1 = operands[3]; - ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); - DONE; -}) - - -(define_expand "cbranchqi4" +(define_expand "cbranch4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" ""))) + (compare:CC (match_operand:SDWIM 1 "nonimmediate_operand" "") + (match_operand:SDWIM 2 "" ""))) (set (pc) (if_then_else - (match_operator 0 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { if (MEM_P (operands[1]) && MEM_P (operands[2])) - operands[1] = force_reg (QImode, operands[1]); + operands[1] = force_reg (mode, operands[1]); ix86_compare_op0 = operands[1]; ix86_compare_op1 = operands[2]; ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) - -(define_expand "cstoreqi4" +(define_expand "cstore4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:QI 2 "nonimmediate_operand" "") - (match_operand:QI 3 "general_operand" ""))) + (compare:CC (match_operand:SWIM 2 "nonimmediate_operand" "") + (match_operand:SWIM 3 "" ""))) (set (match_operand:QI 0 "register_operand" "") - (match_operator 1 "comparison_operator" - [(reg:CC FLAGS_REG) - (const_int 0)]))] + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) (const_int 0)]))] "" { if (MEM_P (operands[2]) && MEM_P (operands[3])) - operands[2] = force_reg (QImode, operands[2]); + operands[2] = force_reg (mode, operands[2]); ix86_compare_op0 = operands[2]; ix86_compare_op1 = operands[3]; ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) - -(define_insn "cmpdi_ccno_1_rex64" - [(set (reg FLAGS_REG) - (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr") - (match_operand:DI 1 "const0_operand" "")))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" - "@ - test{q}\t%0, %0 - cmp{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "test,icmp") - (set_attr "length_immediate" "0,1") - (set_attr "mode" "DI")]) - -(define_insn "*cmpdi_minus_1_rex64" - [(set (reg FLAGS_REG) - (compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r") - (match_operand:DI 1 "x86_64_general_operand" "re,mr")) - (const_int 0)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)" - "cmp{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "DI")]) - -(define_expand "cmpdi_1_rex64" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" "")))] - "TARGET_64BIT" - "") - -(define_insn "cmpdi_1_insn_rex64" - [(set (reg FLAGS_REG) - (compare (match_operand:DI 0 "nonimmediate_operand" "mr,r") - (match_operand:DI 1 "x86_64_general_operand" "re,mr")))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)" - "cmp{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "DI")]) - - -(define_insn "*cmpsi_ccno_1" - [(set (reg FLAGS_REG) - (compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr") - (match_operand:SI 1 "const0_operand" "")))] - "ix86_match_ccmode (insn, CCNOmode)" - "@ - test{l}\t%0, %0 - cmp{l}\t{%1, %0|%0, %1}" - [(set_attr "type" "test,icmp") - (set_attr "length_immediate" "0,1") - (set_attr "mode" "SI")]) - -(define_insn "*cmpsi_minus_1" - [(set (reg FLAGS_REG) - (compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r") - (match_operand:SI 1 "general_operand" "ri,mr")) - (const_int 0)))] - "ix86_match_ccmode (insn, CCGOCmode)" - "cmp{l}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "SI")]) - -(define_expand "cmpsi_1" +(define_expand "cmp_1" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" "")))] + (compare:CC (match_operand:SWI48 0 "nonimmediate_operand" "") + (match_operand:SWI48 1 "" "")))] "" "") -(define_insn "*cmpsi_1_insn" - [(set (reg FLAGS_REG) - (compare (match_operand:SI 0 "nonimmediate_operand" "rm,r") - (match_operand:SI 1 "general_operand" "ri,mr")))] - "!(MEM_P (operands[0]) && MEM_P (operands[1])) - && ix86_match_ccmode (insn, CCmode)" - "cmp{l}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "SI")]) - -(define_insn "*cmphi_ccno_1" - [(set (reg FLAGS_REG) - (compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr") - (match_operand:HI 1 "const0_operand" "")))] - "ix86_match_ccmode (insn, CCNOmode)" - "@ - test{w}\t%0, %0 - cmp{w}\t{%1, %0|%0, %1}" - [(set_attr "type" "test,icmp") - (set_attr "length_immediate" "0,1") - (set_attr "mode" "HI")]) - -(define_insn "*cmphi_minus_1" - [(set (reg FLAGS_REG) - (compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r") - (match_operand:HI 1 "general_operand" "rn,mr")) - (const_int 0)))] - "ix86_match_ccmode (insn, CCGOCmode)" - "cmp{w}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "HI")]) - -(define_insn "*cmphi_1" - [(set (reg FLAGS_REG) - (compare (match_operand:HI 0 "nonimmediate_operand" "rm,r") - (match_operand:HI 1 "general_operand" "rn,mr")))] - "!(MEM_P (operands[0]) && MEM_P (operands[1])) - && ix86_match_ccmode (insn, CCmode)" - "cmp{w}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "HI")]) - -(define_insn "*cmpqi_ccno_1" +(define_insn "*cmp_ccno_1" [(set (reg FLAGS_REG) - (compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq") - (match_operand:QI 1 "const0_operand" "")))] + (compare (match_operand:SWI 0 "nonimmediate_operand" ",?m") + (match_operand:SWI 1 "const0_operand" "")))] "ix86_match_ccmode (insn, CCNOmode)" "@ - test{b}\t%0, %0 - cmp{b}\t{$0, %0|%0, 0}" + test{}\t%0, %0 + cmp{}\t{%1, %0|%0, %1}" [(set_attr "type" "test,icmp") (set_attr "length_immediate" "0,1") - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) -(define_insn "*cmpqi_1" +(define_insn "*cmp_1" [(set (reg FLAGS_REG) - (compare (match_operand:QI 0 "nonimmediate_operand" "qm,q") - (match_operand:QI 1 "general_operand" "qn,mq")))] - "!(MEM_P (operands[0]) && MEM_P (operands[1])) - && ix86_match_ccmode (insn, CCmode)" - "cmp{b}\t{%1, %0|%0, %1}" + (compare (match_operand:SWI 0 "nonimmediate_operand" "m,") + (match_operand:SWI 1 "" ",m")))] + "ix86_match_ccmode (insn, CCmode)" + "cmp{}\t{%1, %0|%0, %1}" [(set_attr "type" "icmp") - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) -(define_insn "*cmpqi_minus_1" +(define_insn "*cmp_minus_1" [(set (reg FLAGS_REG) - (compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "qm,q") - (match_operand:QI 1 "general_operand" "qn,mq")) - (const_int 0)))] + (compare + (minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "m,") + (match_operand:SWI 1 "" ",m")) + (const_int 0)))] "ix86_match_ccmode (insn, CCGOCmode)" - "cmp{b}\t{%1, %0|%0, %1}" + "cmp{}\t{%1, %0|%0, %1}" [(set_attr "type" "icmp") - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) (define_insn "*cmpqi_ext_1" [(set (reg FLAGS_REG) @@ -1187,11 +1036,11 @@ (match_operand 0 "ext_register_operand" "") (const_int 8) (const_int 8)) 0) - (match_operand:QI 1 "general_operand" "")))] + (match_operand:QI 1 "immediate_operand" "")))] "" "") -(define_insn "cmpqi_ext_3_insn" +(define_insn "*cmpqi_ext_3_insn" [(set (reg FLAGS_REG) (compare (subreg:QI @@ -1206,7 +1055,7 @@ (set_attr "modrm" "1") (set_attr "mode" "QI")]) -(define_insn "cmpqi_ext_3_insn_rex64" +(define_insn "*cmpqi_ext_3_insn_rex64" [(set (reg FLAGS_REG) (compare (subreg:QI @@ -2531,11 +2380,13 @@ && !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]); - operands[1] = gen_lowpart (DImode, operands[2]); - operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, - GEN_INT (4))); - ") +{ + 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))); +}) (define_split [(set (match_operand:DI 0 "push_operand" "") @@ -2546,11 +2397,13 @@ && !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]); - operands[1] = gen_lowpart (DImode, operands[2]); - operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, - GEN_INT (4))); - ") +{ + 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))); +}) (define_insn "*pushdi2_prologue_rex64" [(set (match_operand:DI 0 "push_operand" "=<") @@ -3260,9 +3113,15 @@ case MODE_V4SF: return "%vxorps\t%0, %d0"; case MODE_V2DF: - return "%vxorpd\t%0, %d0"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "%vxorps\t%0, %d0"; + else + return "%vxorpd\t%0, %d0"; case MODE_TI: - return "%vpxor\t%0, %d0"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "%vxorps\t%0, %d0"; + else + return "%vpxor\t%0, %d0"; default: gcc_unreachable (); } @@ -3274,9 +3133,15 @@ case MODE_V4SF: return "%vmovaps\t{%1, %0|%0, %1}"; case MODE_V2DF: - return "%vmovapd\t{%1, %0|%0, %1}"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "%vmovaps\t{%1, %0|%0, %1}"; + else + return "%vmovapd\t{%1, %0|%0, %1}"; case MODE_TI: - return "%vmovdqa\t{%1, %0|%0, %1}"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "%vmovaps\t{%1, %0|%0, %1}"; + else + return "%vmovdqa\t{%1, %0|%0, %1}"; case MODE_DI: return "%vmovq\t{%1, %0|%0, %1}"; case MODE_DF: @@ -3410,9 +3275,15 @@ case MODE_V4SF: return "%vxorps\t%0, %d0"; case MODE_V2DF: - return "%vxorpd\t%0, %d0"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "%vxorps\t%0, %d0"; + else + return "%vxorpd\t%0, %d0"; case MODE_TI: - return "%vpxor\t%0, %d0"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "%vxorps\t%0, %d0"; + else + return "%vpxor\t%0, %d0"; default: gcc_unreachable (); } @@ -3424,9 +3295,15 @@ case MODE_V4SF: return "%vmovaps\t{%1, %0|%0, %1}"; case MODE_V2DF: - return "%vmovapd\t{%1, %0|%0, %1}"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "%vmovaps\t{%1, %0|%0, %1}"; + else + return "%vmovapd\t{%1, %0|%0, %1}"; case MODE_TI: - return "%vmovdqa\t{%1, %0|%0, %1}"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "%vmovaps\t{%1, %0|%0, %1}"; + else + return "%vmovdqa\t{%1, %0|%0, %1}"; case MODE_DI: return "%vmovq\t{%1, %0|%0, %1}"; case MODE_DF: @@ -3550,9 +3427,15 @@ case MODE_V4SF: return "xorps\t%0, %0"; case MODE_V2DF: - return "xorpd\t%0, %0"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "xorps\t%0, %0"; + else + return "xorpd\t%0, %0"; case MODE_TI: - return "pxor\t%0, %0"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; default: gcc_unreachable (); } @@ -3564,9 +3447,15 @@ case MODE_V4SF: return "movaps\t{%1, %0|%0, %1}"; case MODE_V2DF: - return "movapd\t{%1, %0|%0, %1}"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movapd\t{%1, %0|%0, %1}"; case MODE_TI: - return "movdqa\t{%1, %0|%0, %1}"; + if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; case MODE_DI: return "movq\t{%1, %0|%0, %1}"; case MODE_DF: @@ -4352,12 +4241,12 @@ && true_regnum (operands[1]) == AX_REG && true_regnum (operands[2]) == DX_REG) { - emit_insn (gen_ashrsi3_31 (operands[2], operands[1], GEN_INT (31))); + emit_insn (gen_ashrsi3_cvt (operands[2], operands[1], GEN_INT (31))); } else { emit_move_insn (operands[2], operands[1]); - emit_insn (gen_ashrsi3_31 (operands[2], operands[2], GEN_INT (31))); + emit_insn (gen_ashrsi3_cvt (operands[2], operands[2], GEN_INT (31))); } emit_move_insn (operands[4], operands[2]); DONE; @@ -4380,16 +4269,17 @@ /* Generate a cltd if possible and doing so it profitable. */ if ((optimize_function_for_size_p (cfun) || TARGET_USE_CLTD) - && true_regnum (operands[3]) == AX_REG) + && true_regnum (operands[3]) == AX_REG + && true_regnum (operands[4]) == DX_REG) { - emit_insn (gen_ashrsi3_31 (operands[4], operands[3], GEN_INT (31))); + emit_insn (gen_ashrsi3_cvt (operands[4], operands[3], GEN_INT (31))); DONE; } if (true_regnum (operands[4]) != true_regnum (operands[1])) emit_move_insn (operands[4], operands[1]); - emit_insn (gen_ashrsi3_31 (operands[4], operands[4], GEN_INT (31))); + emit_insn (gen_ashrsi3_cvt (operands[4], operands[4], GEN_INT (31))); DONE; }) @@ -4588,7 +4478,8 @@ } else operands[3] = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); - emit_insn (gen_sse_unpcklps (operands[3], operands[3], operands[3])); + emit_insn (gen_vec_interleave_lowv4sf (operands[3], operands[3], + operands[3])); } else emit_insn (gen_vec_setv4sf_0 (operands[3], @@ -5469,7 +5360,6 @@ "TARGET_80387 || ((mode != DImode || TARGET_64BIT) && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" - " { if (!((mode != DImode || TARGET_64BIT) && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) @@ -5490,7 +5380,7 @@ emit_insn (insn); DONE; } -}") +}) ;; Pre-reload splitter to add memory clobber to the pattern. (define_insn_and_split "*float2_1" @@ -5985,7 +5875,8 @@ 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])); + emit_insn (gen_vec_interleave_lowv4si (operands[3], operands[3], + operands[4])); operands[3] = gen_rtx_REG (DImode, REGNO (operands[3])); }) @@ -6126,42 +6017,13 @@ (plus:DWIH (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) (plus:DWIH + (match_dup 4) (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 4)) - (match_dup 5))) + (match_dup 5)))) (clobber (reg:CC FLAGS_REG))])] "split_ (&operands[0], 3, &operands[0], &operands[3]);") -(define_insn "add3_carry" - [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,") - (plus:SWI - (plus:SWI (match_operand:SWI 3 "ix86_carry_flag_operator" "") - (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) - (match_operand:SWI 2 "" ",m"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, mode, operands)" - "adc{}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "")]) - -(define_insn "*addsi3_carry_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (plus:SI - (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") - (match_operand:SI 1 "nonimmediate_operand" "%0")) - (match_operand:SI 2 "general_operand" "g")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" - "adc{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - (define_insn "*add3_cc" [(set (reg:CC FLAGS_REG) (unspec:CC @@ -6188,19 +6050,6 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) -(define_insn "*add3_cconly_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (plus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "%0") - (match_operand:SWI 2 "" "m")) - (match_dup 1))) - (clobber (match_scratch:SWI 0 "="))] - "ix86_binary_operator_ok (PLUS, mode, operands)" - "add{}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "")]) - (define_insn "*lea_1" [(set (match_operand:DWIH 0 "register_operand" "=r") (match_operand:DWIH 1 "no_seg_address_operand" "p"))] @@ -6256,20 +6105,9 @@ return "add{}\t{%1, %0|%0, %1}"; gcc_assert (rtx_equal_p (operands[0], operands[1])); + if (x86_maybe_negate_const_int (&operands[2], mode)) + return "sub{}\t{%2, %0|%0, %2}"; - /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - /* Avoid overflows. */ - && (mode != DImode - || ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{}\t{%2, %0|%0, %2}"; - } return "add{}\t{%2, %0|%0, %2}"; } } @@ -6324,16 +6162,9 @@ } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %k0|%k0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], SImode)) + return "sub{l}\t{%2, %k0|%k0, %2}"; + return "add{l}\t{%2, %k0|%k0, %2}"; } } @@ -6375,16 +6206,9 @@ } default: - /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], HImode)) + return "sub{w}\t{%2, %0|%0, %2}"; + return "add{w}\t{%2, %0|%0, %2}"; } } @@ -6425,16 +6249,9 @@ } default: - /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], HImode)) + return "sub{w}\t{%2, %0|%0, %2}"; + return "add{w}\t{%2, %0|%0, %2}"; } } @@ -6472,14 +6289,8 @@ } default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) + if (x86_maybe_negate_const_int (&operands[2], QImode)) { - operands[2] = GEN_INT (-INTVAL (operands[2])); if (widen) return "sub{l}\t{%2, %k0|%k0, %2}"; else @@ -6526,14 +6337,8 @@ } default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) + if (x86_maybe_negate_const_int (&operands[2], QImode)) { - operands[2] = GEN_INT (-INTVAL (operands[2])); if (widen) return "sub{l}\t{%2, %k0|%k0, %2}"; else @@ -6578,13 +6383,9 @@ } default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. */ - if (CONST_INT_P (operands[1]) - && INTVAL (operands[1]) < 0) - { - operands[1] = GEN_INT (-INTVAL (operands[1])); - return "sub{b}\t{%1, %0|%0, %1}"; - } + if (x86_maybe_negate_const_int (&operands[1], QImode)) + return "sub{b}\t{%1, %0|%0, %1}"; + return "add{b}\t{%1, %0|%0, %1}"; } } @@ -6629,19 +6430,9 @@ gcc_assert (rtx_equal_p (operands[0], operands[1])); /* ???? In DImode, we ought to handle there the 32bit case too - do we need new constraint? */ - /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - /* Avoid overflows. */ - && (mode != DImode - || ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], mode)) + return "sub{}\t{%2, %0|%0, %2}"; + return "add{}\t{%2, %0|%0, %2}"; } } @@ -6683,16 +6474,9 @@ } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %k0|%k0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], SImode)) + return "sub{l}\t{%2, %k0|%k0, %2}"; + return "add{l}\t{%2, %k0|%k0, %2}"; } } @@ -6730,16 +6514,9 @@ } default: - /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], HImode)) + return "sub{w}\t{%2, %0|%0, %2}"; + return "add{w}\t{%2, %0|%0, %2}"; } } @@ -6779,13 +6556,9 @@ } default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. */ - if (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) < 0) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{b}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], QImode)) + return "sub{b}\t{%2, %0|%0, %2}"; + return "add{b}\t{%2, %0|%0, %2}"; } } @@ -6823,19 +6596,9 @@ gcc_assert (rtx_equal_p (operands[0], operands[1])); /* ???? In DImode, we ought to handle there the 32bit case too - do we need new constraint? */ - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - /* Avoid overflows. */ - && (mode != DImode - || ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], mode)) + return "sub{}\t{%2, %0|%0, %2}"; + return "add{}\t{%2, %0|%0, %2}"; } } @@ -6876,16 +6639,9 @@ } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %k0|%k0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], SImode)) + return "sub{l}\t{%2, %k0|%k0, %2}"; + return "add{l}\t{%2, %k0|%k0, %2}"; } } @@ -6921,16 +6677,9 @@ } default: - /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], HImode)) + return "sub{w}\t{%2, %0|%0, %2}"; + return "add{w}\t{%2, %0|%0, %2}"; } } @@ -6968,13 +6717,9 @@ } default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. */ - if (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) < 0) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{b}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], QImode)) + return "sub{b}\t{%2, %0|%0, %2}"; + return "add{b}\t{%2, %0|%0, %2}"; } } @@ -6988,8 +6733,6 @@ ; by converting cmp to add, inc or dec as done by peephole2. This pattern ; is matched then. We can't accept general immediate, because for ; case of overflows, the result is messed up. -; This pattern also don't hold of 0x8000000000000000, since the value -; overflows when negated. ; Also carry flag is reversed compared to cmp, so this conversion is valid ; only for comparisons not depending on it. @@ -7015,16 +6758,10 @@ default: gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if ((INTVAL (operands[2]) == -128 - || (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) != 128)) - /* Avoid overflows. */ - && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) - return "sub{q}\t{%2, %0|%0, %2}"; - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "add{q}\t{%2, %0|%0, %2}"; + if (x86_maybe_negate_const_int (&operands[2], DImode)) + return "add{q}\t{%2, %0|%0, %2}"; + + return "sub{q}\t{%2, %0|%0, %2}"; } } [(set (attr "type") @@ -7042,8 +6779,6 @@ ; by converting cmp to add, inc or dec as done by peephole2. This pattern ; is matched then. We can't accept general immediate, because for ; case of overflows, the result is messed up. -; This pattern also don't hold of 0x80000000, since the value overflows -; when negated. ; Also carry flag is reversed compared to cmp, so this conversion is valid ; only for comparisons not depending on it. @@ -7053,8 +6788,7 @@ (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "const_int_operand" "n"))) (clobber (match_scratch:SI 0 "=rm"))] - "ix86_match_ccmode (insn, CCGCmode) - && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000" + "ix86_match_ccmode (insn, CCGCmode)" { switch (get_attr_type (insn)) { @@ -7069,14 +6803,10 @@ default: gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if ((INTVAL (operands[2]) == -128 - || (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) != 128))) - return "sub{l}\t{%2, %0|%0, %2}"; - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "add{l}\t{%2, %0|%0, %2}"; + if (x86_maybe_negate_const_int (&operands[2], SImode)) + return "add{l}\t{%2, %0|%0, %2}"; + + return "sub{l}\t{%2, %0|%0, %2}"; } } [(set (attr "type") @@ -7098,8 +6828,7 @@ (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "const_int_operand" "n"))) (clobber (match_scratch:HI 0 "=rm"))] - "ix86_match_ccmode (insn, CCGCmode) - && (INTVAL (operands[2]) & 0xffff) != 0x8000" + "ix86_match_ccmode (insn, CCGCmode)" { switch (get_attr_type (insn)) { @@ -7114,14 +6843,10 @@ default: gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if ((INTVAL (operands[2]) == -128 - || (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) != 128))) - return "sub{w}\t{%2, %0|%0, %2}"; - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "add{w}\t{%2, %0|%0, %2}"; + if (x86_maybe_negate_const_int (&operands[2], HImode)) + return "add{w}\t{%2, %0|%0, %2}"; + + return "sub{w}\t{%2, %0|%0, %2}"; } } [(set (attr "type") @@ -7143,8 +6868,7 @@ (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const_int_operand" "n"))) (clobber (match_scratch:QI 0 "=qm"))] - "ix86_match_ccmode (insn, CCGCmode) - && (INTVAL (operands[2]) & 0xff) != 0x80" + "ix86_match_ccmode (insn, CCGCmode)" { switch (get_attr_type (insn)) { @@ -7161,11 +6885,9 @@ default: gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (INTVAL (operands[2]) < 0) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "add{b}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], QImode)) + return "add{b}\t{%2, %0|%0, %2}"; + return "sub{b}\t{%2, %0|%0, %2}"; } } @@ -7203,19 +6925,9 @@ default: gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - /* Avoid overflows. */ - && (mode != DImode - || ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], mode)) + return "sub{}\t{%2, %0|%0, %2}"; + return "add{}\t{%2, %0|%0, %2}"; } } @@ -7252,16 +6964,9 @@ } default: - /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], HImode)) + return "sub{w}\t{%2, %0|%0, %2}"; + return "add{w}\t{%2, %0|%0, %2}"; } } @@ -7300,13 +7005,9 @@ } default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. */ - if (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) < 0) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{b}\t{%2, %0|%0, %2}"; - } + if (x86_maybe_negate_const_int (&operands[2], QImode)) + return "sub{b}\t{%2, %0|%0, %2}"; + return "add{b}\t{%2, %0|%0, %2}"; } } @@ -7658,46 +7359,6 @@ (clobber (reg:CC FLAGS_REG))])] "split_ (&operands[0], 3, &operands[0], &operands[3]);") -(define_insn "sub3_carry" - [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,") - (minus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "0,0") - (plus:SWI - (match_operand:SWI 3 "ix86_carry_flag_operator" "") - (match_operand:SWI 2 "" ",m")))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, mode, operands)" - "sbb{}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "")]) - -(define_insn "*subsi3_carry_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (minus:SI (match_operand:SI 1 "register_operand" "0") - (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") - (match_operand:SI 2 "general_operand" "g"))))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sbb{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - -(define_insn "*sub3_cconly_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (minus:SWI - (match_operand:SWI 0 "nonimmediate_operand" "m,") - (match_operand:SWI 1 "" ",m")) - (match_dup 0)))] - "" - "cmp{}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "")]) - (define_insn "*sub_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (minus:SWI @@ -7787,7 +7448,93 @@ "sub{l}\t{%2, %1|%1, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) + +;; Add with carry and subtract with borrow + +(define_expand "3_carry" + [(parallel + [(set (match_operand:SWI 0 "nonimmediate_operand" "") + (plusminus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "") + (plus:SWI (match_operator:SWI 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand" "") + (const_int 0)]) + (match_operand:SWI 2 "" "")))) + (clobber (reg:CC FLAGS_REG))])] + "ix86_binary_operator_ok (, mode, operands)" + "") + +(define_insn "*3_carry" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,") + (plusminus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (plus:SWI + (match_operator 3 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:SWI 2 "" ",m")))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (PLUS, mode, operands)" + "{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "")]) + +(define_insn "*addsi3_carry_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0") + (plus:SI (match_operator 3 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:SI 2 "general_operand" "g"))))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" + "adc{l}\t{%2, %k0|%k0, %2}" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "SI")]) + +(define_insn "*subsi3_carry_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (minus:SI (match_operand:SI 1 "register_operand" "0") + (plus:SI (match_operator 3 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:SI 2 "general_operand" "g"))))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" + "sbb{l}\t{%2, %k0|%k0, %2}" + [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") + (set_attr "mode" "SI")]) + +;; Overflow setting add and subtract instructions + +(define_insn "*add3_cconly_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0") + (match_operand:SWI 2 "" "m")) + (match_dup 1))) + (clobber (match_scratch:SWI 0 "="))] + "ix86_binary_operator_ok (PLUS, mode, operands)" + "add{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) +(define_insn "*sub3_cconly_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (minus:SWI + (match_operand:SWI 0 "nonimmediate_operand" "m,") + (match_operand:SWI 1 "" ",m")) + (match_dup 0)))] + "" + "cmp{}\t{%1, %0|%0, %1}" + [(set_attr "type" "icmp") + (set_attr "mode" "")]) (define_insn "*3_cc_overflow" [(set (reg:CCC FLAGS_REG) @@ -8209,7 +7956,7 @@ (clobber (reg:CC FLAGS_REG))] "" "#" - "&& reload_completed" + "reload_completed" [(parallel [(set (match_dup 1) (ashiftrt:SWIM248 (match_dup 4) (match_dup 5))) (clobber (reg:CC FLAGS_REG))]) @@ -8220,7 +7967,7 @@ (use (match_dup 1)) (clobber (reg:CC FLAGS_REG))])] { - operands[5] = GEN_INT (GET_MODE_BITSIZE (mode) - 1); + operands[5] = GEN_INT (GET_MODE_BITSIZE (mode)-1); if (mode != HImode && (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD)) @@ -8268,7 +8015,7 @@ (clobber (reg:CC FLAGS_REG))] "" "#" - "&& reload_completed" + "reload_completed" [(set (match_dup 1) (const_int 0)) (parallel [(set (match_dup 0) (udiv:SWIM248 (match_dup 2) (match_dup 3))) @@ -8317,39 +8064,6 @@ ;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al. ;; Note that this excludes ah. -(define_insn "*testdi_1_rex64" - [(set (reg FLAGS_REG) - (compare - (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm") - (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re")) - (const_int 0)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "@ - test{l}\t{%k1, %k0|%k0, %k1} - test{l}\t{%k1, %k0|%k0, %k1} - test{q}\t{%1, %0|%0, %1} - test{q}\t{%1, %0|%0, %1} - test{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "test") - (set_attr "modrm" "0,1,0,1,1") - (set_attr "mode" "SI,SI,DI,DI,DI") - (set_attr "pent_pair" "uv,np,uv,np,uv")]) - -(define_insn "testsi_1" - [(set (reg FLAGS_REG) - (compare - (and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm") - (match_operand:SI 1 "general_operand" "i,i,ri")) - (const_int 0)))] - "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "test{l}\t{%1, %0|%0, %1}" - [(set_attr "type" "test") - (set_attr "modrm" "0,1,1") - (set_attr "mode" "SI") - (set_attr "pent_pair" "uv,np,uv")]) - (define_expand "testsi_ccno_1" [(set (reg:CCNO FLAGS_REG) (compare:CCNO @@ -8359,19 +8073,6 @@ "" "") -(define_insn "*testhi_1" - [(set (reg FLAGS_REG) - (compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%!*a,r,rm") - (match_operand:HI 1 "general_operand" "n,n,rn")) - (const_int 0)))] - "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "test{w}\t{%1, %0|%0, %1}" - [(set_attr "type" "test") - (set_attr "modrm" "0,1,1") - (set_attr "mode" "HI") - (set_attr "pent_pair" "uv,np,uv")]) - (define_expand "testqi_ccz_1" [(set (reg:CCZ FLAGS_REG) (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "") @@ -8380,6 +8081,25 @@ "" "") +(define_insn "*testdi_1" + [(set (reg FLAGS_REG) + (compare + (and:DI + (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm") + (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re")) + (const_int 0)))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "@ + test{l}\t{%k1, %k0|%k0, %k1} + test{l}\t{%k1, %k0|%k0, %k1} + test{q}\t{%1, %0|%0, %1} + test{q}\t{%1, %0|%0, %1} + test{q}\t{%1, %0|%0, %1}" + [(set_attr "type" "test") + (set_attr "modrm" "0,1,0,1,1") + (set_attr "mode" "SI,SI,DI,DI,DI")]) + (define_insn "*testqi_1_maybe_si" [(set (reg FLAGS_REG) (compare @@ -8405,19 +8125,19 @@ (set_attr "mode" "QI,QI,QI,SI") (set_attr "pent_pair" "uv,np,uv,np")]) -(define_insn "*testqi_1" +(define_insn "*test_1" [(set (reg FLAGS_REG) - (compare - (and:QI - (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm") - (match_operand:QI 1 "general_operand" "n,n,qn")) - (const_int 0)))] - "!(MEM_P (operands[0]) && MEM_P (operands[1])) - && ix86_match_ccmode (insn, CCNOmode)" - "test{b}\t{%1, %0|%0, %1}" + (compare + (and:SWI124 + (match_operand:SWI124 0 "nonimmediate_operand" "%!*a,,m") + (match_operand:SWI124 1 "general_operand" ",,")) + (const_int 0)))] + "ix86_match_ccmode (insn, CCNOmode) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "test{}\t{%1, %0|%0, %1}" [(set_attr "type" "test") (set_attr "modrm" "0,1,1") - (set_attr "mode" "QI") + (set_attr "mode" "") (set_attr "pent_pair" "uv,np,uv")]) (define_expand "testqi_ext_ccno_0" @@ -8451,7 +8171,7 @@ (set_attr "modrm" "1") (set_attr "pent_pair" "np")]) -(define_insn "*testqi_ext_1" +(define_insn "*testqi_ext_1_rex64" [(set (reg FLAGS_REG) (compare (and:SI @@ -8460,15 +8180,14 @@ (const_int 8) (const_int 8)) (zero_extend:SI - (match_operand:QI 1 "general_operand" "Qm"))) + (match_operand:QI 1 "register_operand" "Q"))) (const_int 0)))] - "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" "test{b}\t{%1, %h0|%h0, %1}" [(set_attr "type" "test") (set_attr "mode" "QI")]) -(define_insn "*testqi_ext_1_rex64" +(define_insn "*testqi_ext_1" [(set (reg FLAGS_REG) (compare (and:SI @@ -8477,9 +8196,9 @@ (const_int 8) (const_int 8)) (zero_extend:SI - (match_operand:QI 1 "register_operand" "Q"))) + (match_operand:QI 1 "general_operand" "Qm"))) (const_int 0)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" + "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" "test{b}\t{%1, %h0|%h0, %1}" [(set_attr "type" "test") (set_attr "mode" "QI")]) @@ -8502,24 +8221,6 @@ [(set_attr "type" "test") (set_attr "mode" "QI")]) -;; Combine likes to form bit extractions for some tests. Humor it. -(define_insn "*testqi_ext_3" - [(set (reg FLAGS_REG) - (compare (zero_extract:SI - (match_operand 0 "nonimmediate_operand" "rm") - (match_operand:SI 1 "const_int_operand" "") - (match_operand:SI 2 "const_int_operand" "")) - (const_int 0)))] - "ix86_match_ccmode (insn, CCNOmode) - && INTVAL (operands[1]) > 0 - && INTVAL (operands[2]) >= 0 - && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32 - && (GET_MODE (operands[0]) == SImode - || (TARGET_64BIT && GET_MODE (operands[0]) == DImode) - || GET_MODE (operands[0]) == HImode - || GET_MODE (operands[0]) == QImode)" - "#") - (define_insn "*testqi_ext_3_rex64" [(set (reg FLAGS_REG) (compare (zero_extract:DI @@ -8541,6 +8242,24 @@ || GET_MODE (operands[0]) == QImode)" "#") +;; Combine likes to form bit extractions for some tests. Humor it. +(define_insn "*testqi_ext_3" + [(set (reg FLAGS_REG) + (compare (zero_extract:SI + (match_operand 0 "nonimmediate_operand" "rm") + (match_operand:SI 1 "const_int_operand" "") + (match_operand:SI 2 "const_int_operand" "")) + (const_int 0)))] + "ix86_match_ccmode (insn, CCNOmode) + && INTVAL (operands[1]) > 0 + && INTVAL (operands[2]) >= 0 + && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32 + && (GET_MODE (operands[0]) == SImode + || (TARGET_64BIT && GET_MODE (operands[0]) == DImode) + || GET_MODE (operands[0]) == HImode + || GET_MODE (operands[0]) == QImode)" + "#") + (define_split [(set (match_operand 0 "flags_reg_operand" "") (match_operator 1 "compare_operator" @@ -8640,22 +8359,22 @@ "operands[2] = gen_lowpart (QImode, operands[2]); operands[3] = gen_lowpart (QImode, operands[3]);") - ;; %%% This used to optimize known byte-wide and operations to memory, ;; and sometimes to QImode registers. If this is considered useful, ;; it should be done with splitters. -(define_expand "anddi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (and:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "x86_64_szext_general_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (AND, DImode, operands); DONE;") +(define_expand "and3" + [(set (match_operand:SWIM 0 "nonimmediate_operand" "") + (and:SWIM (match_operand:SWIM 1 "nonimmediate_operand" "") + (match_operand:SWIM 2 "" "")))] + "" + "ix86_expand_binary_operator (AND, mode, operands); DONE;") -(define_insn "*anddi_1_rex64" +(define_insn "*anddi_1" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r") - (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm") - (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L"))) + (and:DI + (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm") + (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L"))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)" { @@ -8700,29 +8419,6 @@ (const_string "*"))) (set_attr "mode" "SI,DI,DI,SI")]) -(define_insn "*anddi_2" - [(set (reg FLAGS_REG) - (compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm") - (and:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (AND, DImode, operands)" - "@ - and{l}\t{%k2, %k0|%k0, %k2} - and{q}\t{%2, %0|%0, %2} - and{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI,DI,DI")]) - -(define_expand "andsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (and:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "ix86_expand_binary_operator (AND, SImode, operands); DONE;") - (define_insn "*andsi_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r") (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm") @@ -8768,43 +8464,6 @@ (set_attr "length_immediate" "*,*,0") (set_attr "mode" "SI")]) -(define_split - [(set (match_operand 0 "register_operand" "") - (and (match_dup 0) - (const_int -65536))) - (clobber (reg:CC FLAGS_REG))] - "optimize_function_for_size_p (cfun) || (TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL)" - [(set (strict_low_part (match_dup 1)) (const_int 0))] - "operands[1] = gen_lowpart (HImode, operands[0]);") - -(define_split - [(set (match_operand 0 "ext_register_operand" "") - (and (match_dup 0) - (const_int -256))) - (clobber (reg:CC FLAGS_REG))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_REG_STALL) && reload_completed" - [(set (strict_low_part (match_dup 1)) (const_int 0))] - "operands[1] = gen_lowpart (QImode, operands[0]);") - -(define_split - [(set (match_operand 0 "ext_register_operand" "") - (and (match_dup 0) - (const_int -65281))) - (clobber (reg:CC FLAGS_REG))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_REG_STALL) && reload_completed" - [(parallel [(set (zero_extract:SI (match_dup 0) - (const_int 8) - (const_int 8)) - (xor:SI - (zero_extract:SI (match_dup 0) - (const_int 8) - (const_int 8)) - (zero_extract:SI (match_dup 0) - (const_int 8) - (const_int 8)))) - (clobber (reg:CC FLAGS_REG))])] - "operands[0] = gen_lowpart (SImode, operands[0]);") - ;; See comment for addsi_1_zext why we do use nonimmediate_operand (define_insn "*andsi_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -8817,40 +8476,6 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*andsi_2" - [(set (reg FLAGS_REG) - (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "g,ri")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm") - (and:SI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (AND, SImode, operands)" - "and{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) - -;; See comment for addsi_1_zext why we do use nonimmediate_operand -(define_insn "*andsi_2_zext" - [(set (reg FLAGS_REG) - (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (AND, SImode, operands)" - "and{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) - -(define_expand "andhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (and:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (AND, HImode, operands); DONE;") - (define_insn "*andhi_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r") (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,qm") @@ -8881,26 +8506,6 @@ (const_string "*"))) (set_attr "mode" "HI,HI,SI")]) -(define_insn "*andhi_2" - [(set (reg FLAGS_REG) - (compare (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "rmn,rn")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm") - (and:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (AND, HImode, operands)" - "and{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_expand "andqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (and:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (AND, QImode, operands); DONE;") - ;; %%% Potential partial reg stall on alternative 2. What to do? (define_insn "*andqi_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") @@ -8920,17 +8525,75 @@ (and:QI (match_dup 0) (match_operand:QI 1 "general_operand" "qn,qmn"))) (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "and{b}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) +(define_split + [(set (match_operand 0 "register_operand" "") + (and (match_dup 0) + (const_int -65536))) + (clobber (reg:CC FLAGS_REG))] + "(TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL) + || optimize_function_for_size_p (cfun)" + [(set (strict_low_part (match_dup 1)) (const_int 0))] + "operands[1] = gen_lowpart (HImode, operands[0]);") + +(define_split + [(set (match_operand 0 "ext_register_operand" "") + (and (match_dup 0) + (const_int -256))) + (clobber (reg:CC FLAGS_REG))] + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && reload_completed" + [(set (strict_low_part (match_dup 1)) (const_int 0))] + "operands[1] = gen_lowpart (QImode, operands[0]);") + +(define_split + [(set (match_operand 0 "ext_register_operand" "") + (and (match_dup 0) + (const_int -65281))) + (clobber (reg:CC FLAGS_REG))] + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && reload_completed" + [(parallel [(set (zero_extract:SI (match_dup 0) + (const_int 8) + (const_int 8)) + (xor:SI + (zero_extract:SI (match_dup 0) + (const_int 8) + (const_int 8)) + (zero_extract:SI (match_dup 0) + (const_int 8) + (const_int 8)))) + (clobber (reg:CC FLAGS_REG))])] + "operands[0] = gen_lowpart (SImode, operands[0]);") + +(define_insn "*anddi_2" + [(set (reg FLAGS_REG) + (compare + (and:DI + (match_operand:DI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re")) + (const_int 0))) + (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm") + (and:DI (match_dup 1) (match_dup 2)))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) + && ix86_binary_operator_ok (AND, DImode, operands)" + "@ + and{l}\t{%k2, %k0|%k0, %k2} + and{q}\t{%2, %0|%0, %2} + and{q}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "SI,DI,DI")]) + (define_insn "*andqi_2_maybe_si" [(set (reg FLAGS_REG) (compare (and:QI - (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "qmn,qn,n")) + (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:QI 2 "general_operand" "qmn,qn,n")) (const_int 0))) (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,*r") (and:QI (match_dup 1) (match_dup 2)))] @@ -8950,19 +8613,34 @@ [(set_attr "type" "alu") (set_attr "mode" "QI,QI,SI")]) -(define_insn "*andqi_2" +(define_insn "*and_2" [(set (reg FLAGS_REG) - (compare (and:QI - (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qmn,qn")) + (compare (and:SWI124 + (match_operand:SWI124 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI124 2 "general_operand" ",")) (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm") - (and:QI (match_dup 1) (match_dup 2)))] + (set (match_operand:SWI124 0 "nonimmediate_operand" "=,m") + (and:SWI124 (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (AND, QImode, operands)" - "and{b}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (AND, mode, operands)" + "and{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) + +;; See comment for addsi_1_zext why we do use nonimmediate_operand +(define_insn "*andsi_2_zext" + [(set (reg FLAGS_REG) + (compare (and:SI + (match_operand:SI 1 "nonimmediate_operand" "%0") + (match_operand:SI 2 "general_operand" "g")) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) + && ix86_binary_operator_ok (AND, SImode, operands)" + "and{l}\t{%2, %k0|%k0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "SI")]) (define_insn "*andqi_2_slp" [(set (reg FLAGS_REG) @@ -8972,7 +8650,7 @@ (const_int 0))) (set (strict_low_part (match_dup 0)) (and:QI (match_dup 0) (match_dup 1)))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && ix86_match_ccmode (insn, CCNOmode) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "and{b}\t{%1, %0|%0, %1}" @@ -8982,7 +8660,6 @@ ;; ??? A bug in recog prevents it from recognizing a const_int as an ;; operand to zero_extend in andqi_ext_1. It was checking explicitly ;; for a QImode operand, which of course failed. - (define_insn "andqi_ext_0" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) @@ -9003,7 +8680,6 @@ ;; Generated by peephole translating test to and. This shows up ;; often in fp comparisons. - (define_insn "*andqi_ext_0_cc" [(set (reg FLAGS_REG) (compare @@ -9030,7 +8706,7 @@ (set_attr "modrm" "1") (set_attr "mode" "QI")]) -(define_insn "*andqi_ext_1" +(define_insn "*andqi_ext_1_rex64" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) @@ -9040,15 +8716,15 @@ (const_int 8) (const_int 8)) (zero_extend:SI - (match_operand:QI 2 "general_operand" "Qm")))) + (match_operand 2 "ext_register_operand" "Q")))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT" + "TARGET_64BIT" "and{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "0") (set_attr "mode" "QI")]) -(define_insn "*andqi_ext_1_rex64" +(define_insn "*andqi_ext_1" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) @@ -9058,9 +8734,9 @@ (const_int 8) (const_int 8)) (zero_extend:SI - (match_operand 2 "ext_register_operand" "Q")))) + (match_operand:QI 2 "general_operand" "Qm")))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" + "!TARGET_64BIT" "and{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "0") @@ -9131,323 +8807,208 @@ operands[1] = gen_lowpart (QImode, operands[1]); operands[2] = gen_lowpart (QImode, operands[2]);") -;; Logical inclusive OR instructions +;; Logical inclusive and exclusive OR instructions ;; %%% This used to optimize known byte-wide and operations to memory. ;; If this is considered useful, it should be done with splitters. -(define_expand "iordi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (ior:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "x86_64_general_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (IOR, DImode, operands); DONE;") +(define_expand "3" + [(set (match_operand:SWIM 0 "nonimmediate_operand" "") + (any_or:SWIM (match_operand:SWIM 1 "nonimmediate_operand" "") + (match_operand:SWIM 2 "" "")))] + "" + "ix86_expand_binary_operator (, mode, operands); DONE;") -(define_insn "*iordi_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rme"))) +(define_insn "*_1" + [(set (match_operand:SWI248 0 "nonimmediate_operand" "=r,rm") + (any_or:SWI248 + (match_operand:SWI248 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI248 2 "" ",r"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && ix86_binary_operator_ok (IOR, DImode, operands)" - "or{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*iordi_2_rex64" - [(set (reg FLAGS_REG) - (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "rem,re")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm") - (ior:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (IOR, DImode, operands)" - "or{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*iordi_3_rex64" - [(set (reg FLAGS_REG) - (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0") - (match_operand:DI 2 "x86_64_general_operand" "rem")) - (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (IOR, DImode, operands)" - "or{q}\t{%2, %0|%0, %2}" + "ix86_binary_operator_ok (, mode, operands)" + "{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - - -(define_expand "iorsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (ior:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "ix86_expand_binary_operator (IOR, SImode, operands); DONE;") + (set_attr "mode" "")]) -(define_insn "*iorsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "ri,g"))) +;; %%% Potential partial reg stall on alternative 2. What to do? +(define_insn "*qi_1" + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r") + (any_or:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:QI 2 "general_operand" "qmn,qn,rn"))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (IOR, SImode, operands)" - "or{l}\t{%2, %0|%0, %2}" + "ix86_binary_operator_ok (, QImode, operands)" + "@ + {b}\t{%2, %0|%0, %2} + {b}\t{%2, %0|%0, %2} + {l}\t{%k2, %k0|%k0, %k2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "QI,QI,SI")]) ;; See comment for addsi_1_zext why we do use nonimmediate_operand -(define_insn "*iorsi_1_zext" +(define_insn "*si_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))) + (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0") + (match_operand:SI 2 "general_operand" "g")))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)" - "or{l}\t{%2, %k0|%k0, %2}" + "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" + "{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*iorsi_1_zext_imm" +(define_insn "*si_1_zext_imm" [(set (match_operand:DI 0 "register_operand" "=r") - (ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) - (match_operand:DI 2 "x86_64_zext_immediate_operand" "Z"))) + (any_or:DI + (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) + (match_operand:DI 2 "x86_64_zext_immediate_operand" "Z"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "or{l}\t{%2, %k0|%k0, %2}" + "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" + "{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*iorsi_2" +(define_insn "*qi_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m")) + (any_or:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "qmn,qn"))) + (clobber (reg:CC FLAGS_REG))] + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "{b}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + +(define_insn "*_2" [(set (reg FLAGS_REG) - (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "g,ri")) + (compare (any_or:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI 2 "" ",")) (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm") - (ior:SI (match_dup 1) (match_dup 2)))] + (set (match_operand:SWI 0 "nonimmediate_operand" "=,m") + (any_or:SWI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (IOR, SImode, operands)" - "or{l}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (, mode, operands)" + "{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) ;; See comment for addsi_1_zext why we do use nonimmediate_operand ;; ??? Special case for immediate operand is missing - it is tricky. -(define_insn "*iorsi_2_zext" +(define_insn "*si_2_zext" [(set (reg FLAGS_REG) - (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) + (compare (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0") + (match_operand:SI 2 "general_operand" "g")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (ior:SI (match_dup 1) (match_dup 2))))] + (zero_extend:DI (any_or:SI (match_dup 1) (match_dup 2))))] "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (IOR, SImode, operands)" - "or{l}\t{%2, %k0|%k0, %2}" + && ix86_binary_operator_ok (, SImode, operands)" + "{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*iorsi_2_zext_imm" +(define_insn "*si_2_zext_imm" [(set (reg FLAGS_REG) - (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand 2 "x86_64_zext_immediate_operand" "Z")) + (compare (any_or:SI + (match_operand:SI 1 "nonimmediate_operand" "%0") + (match_operand:SI 2 "x86_64_zext_immediate_operand" "Z")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") - (ior:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))] + (any_or:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (IOR, SImode, operands)" - "or{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) - -(define_insn "*iorsi_3" - [(set (reg FLAGS_REG) - (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "or{l}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (, SImode, operands)" + "{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_expand "iorhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (ior:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (IOR, HImode, operands); DONE;") - -(define_insn "*iorhi_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m") - (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "rmn,rn"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (IOR, HImode, operands)" - "or{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_insn "*iorhi_2" - [(set (reg FLAGS_REG) - (compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "rmn,rn")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm") - (ior:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (IOR, HImode, operands)" - "or{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_insn "*iorhi_3" - [(set (reg FLAGS_REG) - (compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0") - (match_operand:HI 2 "general_operand" "rmn")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "or{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_expand "iorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ior:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (IOR, QImode, operands); DONE;") - -;; %%% Potential partial reg stall on alternative 2. What to do? -(define_insn "*iorqi_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r") - (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "qmn,qn,rn"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (IOR, QImode, operands)" - "@ - or{b}\t{%2, %0|%0, %2} - or{b}\t{%2, %0|%0, %2} - or{l}\t{%k2, %k0|%k0, %k2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI,QI,SI")]) - -(define_insn "*iorqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m")) - (ior:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qmn,qn"))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "or{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) - -(define_insn "*iorqi_2" - [(set (reg FLAGS_REG) - (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qmn,qn")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm") - (ior:QI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (IOR, QImode, operands)" - "or{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI")]) - -(define_insn "*iorqi_2_slp" +(define_insn "*qi_2_slp" [(set (reg FLAGS_REG) - (compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") - (match_operand:QI 1 "general_operand" "qmn,qn")) + (compare (any_or:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") + (match_operand:QI 1 "general_operand" "qmn,qn")) (const_int 0))) (set (strict_low_part (match_dup 0)) - (ior:QI (match_dup 0) (match_dup 1)))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + (any_or:QI (match_dup 0) (match_dup 1)))] + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && ix86_match_ccmode (insn, CCNOmode) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "or{b}\t{%1, %0|%0, %1}" + "{b}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) -(define_insn "*iorqi_3" +(define_insn "*_3" [(set (reg FLAGS_REG) - (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0") - (match_operand:QI 2 "general_operand" "qmn")) + (compare (any_or:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0") + (match_operand:SWI 2 "" "")) (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] + (clobber (match_scratch:SWI 0 "="))] "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "or{b}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (, mode, operands)" + "{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) -(define_insn "*iorqi_ext_0" +(define_insn "*qi_ext_0" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) - (ior:SI + (any_or:SI (zero_extract:SI (match_operand 1 "ext_register_operand" "0") (const_int 8) (const_int 8)) (match_operand 2 "const_int_operand" "n"))) (clobber (reg:CC FLAGS_REG))] - "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "or{b}\t{%2, %h0|%h0, %2}" + "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" + "{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "1") (set_attr "modrm" "1") (set_attr "mode" "QI")]) -(define_insn "*iorqi_ext_1" +(define_insn "*qi_ext_1_rex64" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) - (ior:SI + (any_or:SI (zero_extract:SI (match_operand 1 "ext_register_operand" "0") (const_int 8) (const_int 8)) (zero_extend:SI - (match_operand:QI 2 "general_operand" "Qm")))) + (match_operand 2 "ext_register_operand" "Q")))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT + "TARGET_64BIT && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "or{b}\t{%2, %h0|%h0, %2}" + "{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "0") (set_attr "mode" "QI")]) -(define_insn "*iorqi_ext_1_rex64" +(define_insn "*qi_ext_1" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) - (ior:SI + (any_or:SI (zero_extract:SI (match_operand 1 "ext_register_operand" "0") (const_int 8) (const_int 8)) (zero_extend:SI - (match_operand 2 "ext_register_operand" "Q")))) + (match_operand:QI 2 "general_operand" "Qm")))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT + "!TARGET_64BIT && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "or{b}\t{%2, %h0|%h0, %2}" + "{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "0") (set_attr "mode" "QI")]) -(define_insn "*iorqi_ext_2" +(define_insn "*qi_ext_2" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) - (ior:SI + (any_or:SI (zero_extract:SI (match_operand 1 "ext_register_operand" "0") (const_int 8) (const_int 8)) @@ -9455,16 +9016,16 @@ (const_int 8) (const_int 8)))) (clobber (reg:CC FLAGS_REG))] - "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "ior{b}\t{%h2, %h0|%h0, %h2}" + "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" + "{b}\t{%h2, %h0|%h0, %h2}" [(set_attr "type" "alu") (set_attr "length_immediate" "0") (set_attr "mode" "QI")]) (define_split [(set (match_operand 0 "register_operand" "") - (ior (match_operand 1 "register_operand" "") - (match_operand 2 "const_int_operand" ""))) + (any_or (match_operand 1 "register_operand" "") + (match_operand 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] "reload_completed && QI_REG_P (operands[0]) @@ -9472,9 +9033,9 @@ && !(INTVAL (operands[2]) & ~(255 << 8)) && GET_MODE (operands[0]) != QImode" [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8)) - (ior:SI (zero_extract:SI (match_dup 1) - (const_int 8) (const_int 8)) - (match_dup 2))) + (any_or:SI (zero_extract:SI (match_dup 1) + (const_int 8) (const_int 8)) + (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]); @@ -9484,8 +9045,8 @@ ;; profitable when 7th bit is set. (define_split [(set (match_operand 0 "register_operand" "") - (ior (match_operand 1 "general_operand" "") - (match_operand 2 "const_int_operand" ""))) + (any_or (match_operand 1 "general_operand" "") + (match_operand 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] "reload_completed && ANY_QI_REG_P (operands[0]) @@ -9494,4047 +9055,1750 @@ && (INTVAL (operands[2]) & 128) && GET_MODE (operands[0]) != QImode" [(parallel [(set (strict_low_part (match_dup 0)) - (ior:QI (match_dup 1) - (match_dup 2))) + (any_or:QI (match_dup 1) + (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (QImode, operands[0]); operands[1] = gen_lowpart (QImode, operands[1]); operands[2] = gen_lowpart (QImode, operands[2]);") - -;; Logical XOR instructions -;; %%% This used to optimize known byte-wide and operations to memory. -;; If this is considered useful, it should be done with splitters. - -(define_expand "xordi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (xor:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "x86_64_general_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (XOR, DImode, operands); DONE;") - -(define_insn "*xordi_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && ix86_binary_operator_ok (XOR, DImode, operands)" - "xor{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) +(define_expand "xorqi_cc_ext_1" + [(parallel [ + (set (reg:CCNO FLAGS_REG) + (compare:CCNO + (xor:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "") + (const_int 8) + (const_int 8)) + (match_operand:QI 2 "general_operand" "")) + (const_int 0))) + (set (zero_extract:SI (match_operand 0 "ext_register_operand" "") + (const_int 8) + (const_int 8)) + (xor:SI + (zero_extract:SI + (match_dup 1) + (const_int 8) + (const_int 8)) + (match_dup 2)))])] + "" + "") -(define_insn "*xordi_2_rex64" +(define_insn "*xorqi_cc_ext_1_rex64" [(set (reg FLAGS_REG) - (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "rem,re")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm") - (xor:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (XOR, DImode, operands)" - "xor{q}\t{%2, %0|%0, %2}" + (compare + (xor:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (match_operand:QI 2 "nonmemory_operand" "Qn")) + (const_int 0))) + (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (xor:SI + (zero_extract:SI + (match_dup 1) + (const_int 8) + (const_int 8)) + (match_dup 2)))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" + "xor{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "DI")]) + (set_attr "modrm" "1") + (set_attr "mode" "QI")]) -(define_insn "*xordi_3_rex64" +(define_insn "*xorqi_cc_ext_1" [(set (reg FLAGS_REG) - (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0") - (match_operand:DI 2 "x86_64_general_operand" "rem")) - (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (XOR, DImode, operands)" - "xor{q}\t{%2, %0|%0, %2}" + (compare + (xor:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (match_operand:QI 2 "general_operand" "qmn")) + (const_int 0))) + (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q") + (const_int 8) + (const_int 8)) + (xor:SI + (zero_extract:SI + (match_dup 1) + (const_int 8) + (const_int 8)) + (match_dup 2)))] + "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" + "xor{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "DI")]) + (set_attr "modrm" "1") + (set_attr "mode" "QI")]) + +;; Negation instructions -(define_expand "xorsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (xor:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] +(define_expand "neg2" + [(set (match_operand:SDWIM 0 "nonimmediate_operand" "") + (neg:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand" "")))] "" - "ix86_expand_binary_operator (XOR, SImode, operands); DONE;") + "ix86_expand_unary_operator (NEG, mode, operands); DONE;") -(define_insn "*xorsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "ri,rm"))) +(define_insn_and_split "*neg2_doubleword" + [(set (match_operand: 0 "nonimmediate_operand" "=ro") + (neg: (match_operand: 1 "nonimmediate_operand" "0"))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (XOR, SImode, operands)" - "xor{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + "ix86_unary_operator_ok (NEG, mode, operands)" + "#" + "reload_completed" + [(parallel + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (neg:DWIH (match_dup 1)) (const_int 0))) + (set (match_dup 0) (neg:DWIH (match_dup 1)))]) + (parallel + [(set (match_dup 2) + (plus:DWIH (match_dup 3) + (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) + (const_int 0)))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 2) + (neg:DWIH (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] + "split_ (&operands[0], 2, &operands[0], &operands[2]);") -;; See comment for addsi_1_zext why we do use nonimmediate_operand -;; Add speccase for immediates -(define_insn "*xorsi_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))) +(define_insn "*neg2_1" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=m") + (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)" - "xor{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + "ix86_unary_operator_ok (NEG, mode, operands)" + "neg{}\t%0" + [(set_attr "type" "negnot") + (set_attr "mode" "")]) -(define_insn "*xorsi_1_zext_imm" +;; Combine is quite creative about this pattern. +(define_insn "*negsi2_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") - (xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) - (match_operand:DI 2 "x86_64_zext_immediate_operand" "Z"))) + (lshiftrt:DI + (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0") + (const_int 32))) + (const_int 32))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)" - "xor{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") + "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)" + "neg{l}\t%k0" + [(set_attr "type" "negnot") (set_attr "mode" "SI")]) -(define_insn "*xorsi_2" - [(set (reg FLAGS_REG) - (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "g,ri")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm") - (xor:SI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (XOR, SImode, operands)" - "xor{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) +;; The problem with neg is that it does not perform (compare x 0), +;; it really performs (compare 0 x), which leaves us with the zero +;; flag being the only useful item. -;; See comment for addsi_1_zext why we do use nonimmediate_operand -;; ??? Special case for immediate operand is missing - it is tricky. -(define_insn "*xorsi_2_zext" - [(set (reg FLAGS_REG) - (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (xor:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (XOR, SImode, operands)" - "xor{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) +(define_insn "*neg2_cmpz" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ + (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=m") + (neg:SWI (match_dup 1)))] + "ix86_unary_operator_ok (NEG, mode, operands)" + "neg{}\t%0" + [(set_attr "type" "negnot") + (set_attr "mode" "")]) -(define_insn "*xorsi_2_zext_imm" - [(set (reg FLAGS_REG) - (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand 2 "x86_64_zext_immediate_operand" "Z")) - (const_int 0))) +(define_insn "*negsi2_cmpz_zext" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ + (lshiftrt:DI + (neg:DI (ashift:DI + (match_operand:DI 1 "register_operand" "0") + (const_int 32))) + (const_int 32)) + (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") - (xor:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (XOR, SImode, operands)" - "xor{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") + (lshiftrt:DI (neg:DI (ashift:DI (match_dup 1) + (const_int 32))) + (const_int 32)))] + "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)" + "neg{l}\t%k0" + [(set_attr "type" "negnot") (set_attr "mode" "SI")]) -(define_insn "*xorsi_3" - [(set (reg FLAGS_REG) - (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "xor{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) +;; Changing of sign for FP values is doable using integer unit too. -(define_expand "xorhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (xor:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (XOR, HImode, operands); DONE;") - -(define_insn "*xorhi_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m") - (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "rmn,rn"))) +(define_expand "2" + [(set (match_operand:X87MODEF 0 "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 (, mode, operands); DONE;") + +(define_insn "*absneg2_mixed" + [(set (match_operand:MODEF 0 "register_operand" "=x,x,f,!r") + (match_operator:MODEF 3 "absneg_operator" + [(match_operand:MODEF 1 "register_operand" "0,x,0,0")])) + (use (match_operand: 2 "nonimmediate_operand" "xm,0,X,X")) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (XOR, HImode, operands)" - "xor{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) + "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (mode)" + "#") -(define_insn "*xorhi_2" - [(set (reg FLAGS_REG) - (compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "rmn,rn")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm") - (xor:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (XOR, HImode, operands)" - "xor{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) +(define_insn "*absneg2_sse" + [(set (match_operand:MODEF 0 "register_operand" "=x,x,!r") + (match_operator:MODEF 3 "absneg_operator" + [(match_operand:MODEF 1 "register_operand" "0 ,x,0")])) + (use (match_operand: 2 "register_operand" "xm,0,X")) + (clobber (reg:CC FLAGS_REG))] + "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" + "#") -(define_insn "*xorhi_3" - [(set (reg FLAGS_REG) - (compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0") - (match_operand:HI 2 "general_operand" "rmn")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "xor{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) +(define_insn "*absneg2_i387" + [(set (match_operand:X87MODEF 0 "register_operand" "=f,!r") + (match_operator:X87MODEF 3 "absneg_operator" + [(match_operand:X87MODEF 1 "register_operand" "0,0")])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_80387 && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" + "#") -(define_expand "xorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (xor:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (XOR, QImode, operands); DONE;") +(define_expand "tf2" + [(set (match_operand:TF 0 "register_operand" "") + (absneg:TF (match_operand:TF 1 "register_operand" "")))] + "TARGET_SSE2" + "ix86_expand_fp_absneg_operator (, TFmode, operands); DONE;") -;; %%% Potential partial reg stall on alternative 2. What to do? -(define_insn "*xorqi_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r") - (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "qmn,qn,rn"))) +(define_insn "*absnegtf2_sse" + [(set (match_operand:TF 0 "register_operand" "=x,x") + (match_operator:TF 3 "absneg_operator" + [(match_operand:TF 1 "register_operand" "0,x")])) + (use (match_operand:TF 2 "nonimmediate_operand" "xm,0")) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (XOR, QImode, operands)" - "@ - xor{b}\t{%2, %0|%0, %2} - xor{b}\t{%2, %0|%0, %2} - xor{l}\t{%k2, %k0|%k0, %k2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI,QI,SI")]) + "TARGET_SSE2" + "#") -(define_insn "*xorqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (xor:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,qmn"))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "xor{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) +;; Splitters for fp abs and neg. -(define_insn "*xorqi_ext_0" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (xor:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "0") - (const_int 8) - (const_int 8)) - (match_operand 2 "const_int_operand" "n"))) +(define_split + [(set (match_operand 0 "fp_register_operand" "") + (match_operator 1 "absneg_operator" [(match_dup 0)])) + (use (match_operand 2 "" "")) (clobber (reg:CC FLAGS_REG))] - "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "xor{b}\t{%2, %h0|%h0, %2}" - [(set_attr "type" "alu") - (set_attr "length_immediate" "1") - (set_attr "modrm" "1") - (set_attr "mode" "QI")]) + "reload_completed" + [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))]) -(define_insn "*xorqi_ext_1" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (xor:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "0") - (const_int 8) - (const_int 8)) - (zero_extend:SI - (match_operand:QI 2 "general_operand" "Qm")))) +(define_split + [(set (match_operand 0 "register_operand" "") + (match_operator 3 "absneg_operator" + [(match_operand 1 "register_operand" "")])) + (use (match_operand 2 "nonimmediate_operand" "")) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT - && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "xor{b}\t{%2, %h0|%h0, %2}" - [(set_attr "type" "alu") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + "reload_completed && SSE_REG_P (operands[0])" + [(set (match_dup 0) (match_dup 3))] +{ + enum machine_mode mode = GET_MODE (operands[0]); + enum machine_mode vmode = GET_MODE (operands[2]); + rtx tmp; -(define_insn "*xorqi_ext_1_rex64" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (xor:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "0") - (const_int 8) - (const_int 8)) - (zero_extend:SI - (match_operand 2 "ext_register_operand" "Q")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "xor{b}\t{%2, %h0|%h0, %2}" - [(set_attr "type" "alu") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + operands[0] = simplify_gen_subreg (vmode, operands[0], mode, 0); + operands[1] = simplify_gen_subreg (vmode, operands[1], mode, 0); + if (operands_match_p (operands[0], operands[2])) + { + tmp = operands[1]; + operands[1] = operands[2]; + operands[2] = tmp; + } + if (GET_CODE (operands[3]) == ABS) + tmp = gen_rtx_AND (vmode, operands[1], operands[2]); + else + tmp = gen_rtx_XOR (vmode, operands[1], operands[2]); + operands[3] = tmp; +}) -(define_insn "*xorqi_ext_2" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (xor:SI - (zero_extract:SI (match_operand 1 "ext_register_operand" "0") - (const_int 8) - (const_int 8)) - (zero_extract:SI (match_operand 2 "ext_register_operand" "Q") - (const_int 8) - (const_int 8)))) +(define_split + [(set (match_operand:SF 0 "register_operand" "") + (match_operator:SF 1 "absneg_operator" [(match_dup 0)])) + (use (match_operand:V4SF 2 "" "")) (clobber (reg:CC FLAGS_REG))] - "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "xor{b}\t{%h2, %h0|%h0, %h2}" - [(set_attr "type" "alu") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + "reload_completed" + [(parallel [(set (match_dup 0) (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] +{ + rtx tmp; + operands[0] = gen_lowpart (SImode, operands[0]); + if (GET_CODE (operands[1]) == ABS) + { + tmp = gen_int_mode (0x7fffffff, SImode); + tmp = gen_rtx_AND (SImode, operands[0], tmp); + } + else + { + tmp = gen_int_mode (0x80000000, SImode); + tmp = gen_rtx_XOR (SImode, operands[0], tmp); + } + operands[1] = tmp; +}) -(define_insn "*xorqi_cc_1" - [(set (reg FLAGS_REG) - (compare - (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qmn,qn")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm") - (xor:QI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_binary_operator_ok (XOR, QImode, operands)" - "xor{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI")]) +(define_split + [(set (match_operand:DF 0 "register_operand" "") + (match_operator:DF 1 "absneg_operator" [(match_dup 0)])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "reload_completed" + [(parallel [(set (match_dup 0) (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] +{ + rtx tmp; + if (TARGET_64BIT) + { + tmp = gen_lowpart (DImode, operands[0]); + tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63)); + operands[0] = tmp; -(define_insn "*xorqi_2_slp" - [(set (reg FLAGS_REG) - (compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") - (match_operand:QI 1 "general_operand" "qmn,qn")) - (const_int 0))) - (set (strict_low_part (match_dup 0)) - (xor:QI (match_dup 0) (match_dup 1)))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "xor{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) - -(define_insn "*xorqi_cc_2" - [(set (reg FLAGS_REG) - (compare - (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0") - (match_operand:QI 2 "general_operand" "qmn")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] - "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "xor{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI")]) - -(define_insn "*xorqi_cc_ext_1" - [(set (reg FLAGS_REG) - (compare - (xor:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "0") - (const_int 8) - (const_int 8)) - (match_operand:QI 2 "general_operand" "qmn")) - (const_int 0))) - (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q") - (const_int 8) - (const_int 8)) - (xor:SI - (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8)) - (match_dup 2)))] - "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" - "xor{b}\t{%2, %h0|%h0, %2}" - [(set_attr "type" "alu") - (set_attr "modrm" "1") - (set_attr "mode" "QI")]) - -(define_insn "*xorqi_cc_ext_1_rex64" - [(set (reg FLAGS_REG) - (compare - (xor:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "0") - (const_int 8) - (const_int 8)) - (match_operand:QI 2 "nonmemory_operand" "Qn")) - (const_int 0))) - (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (xor:SI - (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8)) - (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" - "xor{b}\t{%2, %h0|%h0, %2}" - [(set_attr "type" "alu") - (set_attr "modrm" "1") - (set_attr "mode" "QI")]) - -(define_expand "xorqi_cc_ext_1" - [(parallel [ - (set (reg:CCNO FLAGS_REG) - (compare:CCNO - (xor:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "") - (const_int 8) - (const_int 8)) - (match_operand:QI 2 "general_operand" "")) - (const_int 0))) - (set (zero_extract:SI (match_operand 0 "ext_register_operand" "") - (const_int 8) - (const_int 8)) - (xor:SI - (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8)) - (match_dup 2)))])] - "" - "") - -(define_split - [(set (match_operand 0 "register_operand" "") - (xor (match_operand 1 "register_operand" "") - (match_operand 2 "const_int_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && QI_REG_P (operands[0]) - && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(INTVAL (operands[2]) & ~(255 << 8)) - && GET_MODE (operands[0]) != QImode" - [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8)) - (xor:SI (zero_extract:SI (match_dup 1) - (const_int 8) (const_int 8)) - (match_dup 2))) - (clobber (reg:CC FLAGS_REG))])] - "operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);") - -;; Since XOR can be encoded with sign extended immediate, this is only -;; profitable when 7th bit is set. -(define_split - [(set (match_operand 0 "register_operand" "") - (xor (match_operand 1 "general_operand" "") - (match_operand 2 "const_int_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && ANY_QI_REG_P (operands[0]) - && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(INTVAL (operands[2]) & ~255) - && (INTVAL (operands[2]) & 128) - && GET_MODE (operands[0]) != QImode" - [(parallel [(set (strict_low_part (match_dup 0)) - (xor:QI (match_dup 1) - (match_dup 2))) - (clobber (reg:CC FLAGS_REG))])] - "operands[0] = gen_lowpart (QImode, operands[0]); - operands[1] = gen_lowpart (QImode, operands[1]); - operands[2] = gen_lowpart (QImode, operands[2]);") - -;; Negation instructions - -(define_expand "negti2" - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))] - "TARGET_64BIT" - "ix86_expand_unary_operator (NEG, TImode, operands); DONE;") - -(define_insn "*negti2_1" - [(set (match_operand:TI 0 "nonimmediate_operand" "=ro") - (neg:TI (match_operand:TI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && ix86_unary_operator_ok (NEG, TImode, operands)" - "#") - -(define_split - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (neg:TI (match_operand:TI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed" - [(parallel - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (neg:DI (match_dup 1)) (const_int 0))) - (set (match_dup 0) (neg:DI (match_dup 1)))]) - (parallel - [(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 2) - (neg:DI (match_dup 2))) - (clobber (reg:CC FLAGS_REG))])] - "split_ti (&operands[0], 2, &operands[0], &operands[2]);") - -(define_expand "negdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))] - "" - "ix86_expand_unary_operator (NEG, DImode, operands); DONE;") - -(define_insn "*negdi2_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro") - (neg:DI (match_operand:DI 1 "general_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT - && ix86_unary_operator_ok (NEG, DImode, operands)" - "#") + if (GET_CODE (operands[1]) == ABS) + tmp = const0_rtx; + else + tmp = gen_rtx_NOT (DImode, tmp); + } + else + { + operands[0] = gen_highpart (SImode, operands[0]); + if (GET_CODE (operands[1]) == ABS) + { + tmp = gen_int_mode (0x7fffffff, SImode); + tmp = gen_rtx_AND (SImode, operands[0], tmp); + } + else + { + tmp = gen_int_mode (0x80000000, SImode); + tmp = gen_rtx_XOR (SImode, operands[0], tmp); + } + } + operands[1] = tmp; +}) (define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (neg:DI (match_operand:DI 1 "general_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && reload_completed" - [(parallel - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (neg:SI (match_dup 1)) (const_int 0))) - (set (match_dup 0) (neg:SI (match_dup 1)))]) - (parallel - [(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 2) - (neg:SI (match_dup 2))) - (clobber (reg:CC FLAGS_REG))])] - "split_di (&operands[0], 2, &operands[0], &operands[2]);"); - -(define_insn "*negdi2_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)" - "neg{q}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "DI")]) - -;; The problem with neg is that it does not perform (compare x 0), -;; it really performs (compare 0 x), which leaves us with the zero -;; flag being the only useful item. - -(define_insn "*negdi2_cmpz_rex64" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (neg:DI (match_dup 1)))] - "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)" - "neg{q}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "DI")]) - - -(define_expand "negsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))] - "" - "ix86_expand_unary_operator (NEG, SImode, operands); DONE;") - -(define_insn "*negsi2_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_unary_operator_ok (NEG, SImode, operands)" - "neg{l}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "SI")]) - -;; Combine is quite creative about this pattern. -(define_insn "*negsi2_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0") - (const_int 32))) - (const_int 32))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)" - "neg{l}\t%k0" - [(set_attr "type" "negnot") - (set_attr "mode" "SI")]) - -;; The problem with neg is that it does not perform (compare x 0), -;; it really performs (compare 0 x), which leaves us with the zero -;; flag being the only useful item. - -(define_insn "*negsi2_cmpz" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (neg:SI (match_dup 1)))] - "ix86_unary_operator_ok (NEG, SImode, operands)" - "neg{l}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "SI")]) - -(define_insn "*negsi2_cmpz_zext" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (lshiftrt:DI - (neg:DI (ashift:DI - (match_operand:DI 1 "register_operand" "0") - (const_int 32))) - (const_int 32)) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (neg:DI (ashift:DI (match_dup 1) - (const_int 32))) - (const_int 32)))] - "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)" - "neg{l}\t%k0" - [(set_attr "type" "negnot") - (set_attr "mode" "SI")]) - -(define_expand "neghi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_unary_operator (NEG, HImode, operands); DONE;") - -(define_insn "*neghi2_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_unary_operator_ok (NEG, HImode, operands)" - "neg{w}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "HI")]) - -(define_insn "*neghi2_cmpz" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (neg:HI (match_dup 1)))] - "ix86_unary_operator_ok (NEG, HImode, operands)" - "neg{w}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "HI")]) - -(define_expand "negqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (neg:QI (match_operand:QI 1 "nonimmediate_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_unary_operator (NEG, QImode, operands); DONE;") - -(define_insn "*negqi2_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_unary_operator_ok (NEG, QImode, operands)" - "neg{b}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "QI")]) - -(define_insn "*negqi2_cmpz" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (neg:QI (match_dup 1)))] - "ix86_unary_operator_ok (NEG, QImode, operands)" - "neg{b}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "QI")]) - -;; Changing of sign for FP values is doable using integer unit too. - -(define_expand "2" - [(set (match_operand:X87MODEF 0 "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 (, mode, operands); DONE;") - -(define_insn "*absneg2_mixed" - [(set (match_operand:MODEF 0 "register_operand" "=x,x,f,!r") - (match_operator:MODEF 3 "absneg_operator" - [(match_operand:MODEF 1 "register_operand" "0,x,0,0")])) - (use (match_operand: 2 "nonimmediate_operand" "xm,0,X,X")) - (clobber (reg:CC FLAGS_REG))] - "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (mode)" - "#") - -(define_insn "*absneg2_sse" - [(set (match_operand:MODEF 0 "register_operand" "=x,x,!r") - (match_operator:MODEF 3 "absneg_operator" - [(match_operand:MODEF 1 "register_operand" "0 ,x,0")])) - (use (match_operand: 2 "register_operand" "xm,0,X")) - (clobber (reg:CC FLAGS_REG))] - "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "#") - -(define_insn "*absneg2_i387" - [(set (match_operand:X87MODEF 0 "register_operand" "=f,!r") - (match_operator:X87MODEF 3 "absneg_operator" - [(match_operand:X87MODEF 1 "register_operand" "0,0")])) + [(set (match_operand:XF 0 "register_operand" "") + (match_operator:XF 1 "absneg_operator" [(match_dup 0)])) (use (match_operand 2 "" "")) (clobber (reg:CC FLAGS_REG))] - "TARGET_80387 && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" - "#") - -(define_expand "tf2" - [(set (match_operand:TF 0 "register_operand" "") - (absneg:TF (match_operand:TF 1 "register_operand" "")))] - "TARGET_SSE2" - "ix86_expand_fp_absneg_operator (, TFmode, operands); DONE;") - -(define_insn "*absnegtf2_sse" - [(set (match_operand:TF 0 "register_operand" "=x,x") - (match_operator:TF 3 "absneg_operator" - [(match_operand:TF 1 "register_operand" "0,x")])) - (use (match_operand:TF 2 "nonimmediate_operand" "xm,0")) - (clobber (reg:CC FLAGS_REG))] - "TARGET_SSE2" - "#") - -;; Splitters for fp abs and neg. - -(define_split - [(set (match_operand 0 "fp_register_operand" "") - (match_operator 1 "absneg_operator" [(match_dup 0)])) - (use (match_operand 2 "" "")) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))]) - -(define_split - [(set (match_operand 0 "register_operand" "") - (match_operator 3 "absneg_operator" - [(match_operand 1 "register_operand" "")])) - (use (match_operand 2 "nonimmediate_operand" "")) - (clobber (reg:CC FLAGS_REG))] - "reload_completed && SSE_REG_P (operands[0])" - [(set (match_dup 0) (match_dup 3))] -{ - enum machine_mode mode = GET_MODE (operands[0]); - enum machine_mode vmode = GET_MODE (operands[2]); - rtx tmp; - - operands[0] = simplify_gen_subreg (vmode, operands[0], mode, 0); - operands[1] = simplify_gen_subreg (vmode, operands[1], mode, 0); - if (operands_match_p (operands[0], operands[2])) - { - tmp = operands[1]; - operands[1] = operands[2]; - operands[2] = tmp; - } - if (GET_CODE (operands[3]) == ABS) - tmp = gen_rtx_AND (vmode, operands[1], operands[2]); - else - tmp = gen_rtx_XOR (vmode, operands[1], operands[2]); - operands[3] = tmp; -}) - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (match_operator:SF 1 "absneg_operator" [(match_dup 0)])) - (use (match_operand:V4SF 2 "" "")) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(parallel [(set (match_dup 0) (match_dup 1)) - (clobber (reg:CC FLAGS_REG))])] -{ - rtx tmp; - operands[0] = gen_lowpart (SImode, operands[0]); - if (GET_CODE (operands[1]) == ABS) - { - tmp = gen_int_mode (0x7fffffff, SImode); - tmp = gen_rtx_AND (SImode, operands[0], tmp); - } - else - { - tmp = gen_int_mode (0x80000000, SImode); - tmp = gen_rtx_XOR (SImode, operands[0], tmp); - } - operands[1] = tmp; -}) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operator:DF 1 "absneg_operator" [(match_dup 0)])) - (use (match_operand 2 "" "")) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(parallel [(set (match_dup 0) (match_dup 1)) - (clobber (reg:CC FLAGS_REG))])] -{ - rtx tmp; - if (TARGET_64BIT) - { - tmp = gen_lowpart (DImode, operands[0]); - tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63)); - operands[0] = tmp; - - if (GET_CODE (operands[1]) == ABS) - tmp = const0_rtx; - else - tmp = gen_rtx_NOT (DImode, tmp); - } - else - { - operands[0] = gen_highpart (SImode, operands[0]); - if (GET_CODE (operands[1]) == ABS) - { - tmp = gen_int_mode (0x7fffffff, SImode); - tmp = gen_rtx_AND (SImode, operands[0], tmp); - } - else - { - tmp = gen_int_mode (0x80000000, SImode); - tmp = gen_rtx_XOR (SImode, operands[0], tmp); - } - } - operands[1] = tmp; -}) - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (match_operator:XF 1 "absneg_operator" [(match_dup 0)])) - (use (match_operand 2 "" "")) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(parallel [(set (match_dup 0) (match_dup 1)) - (clobber (reg:CC FLAGS_REG))])] -{ - rtx tmp; - operands[0] = gen_rtx_REG (SImode, - true_regnum (operands[0]) - + (TARGET_64BIT ? 1 : 2)); - if (GET_CODE (operands[1]) == ABS) - { - tmp = GEN_INT (0x7fff); - tmp = gen_rtx_AND (SImode, operands[0], tmp); - } - else - { - tmp = GEN_INT (0x8000); - tmp = gen_rtx_XOR (SImode, operands[0], tmp); - } - operands[1] = tmp; -}) - -;; Conditionalize these after reload. If they match before reload, we -;; lose the clobber and ability to use integer instructions. - -(define_insn "*2_1" - [(set (match_operand:X87MODEF 0 "register_operand" "=f") - (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))] - "TARGET_80387 - && (reload_completed - || !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))" - "f" - [(set_attr "type" "fsgn") - (set_attr "mode" "")]) - -(define_insn "*extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (absneg:DF (float_extend:DF - (match_operand:SF 1 "register_operand" "0"))))] - "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)" - "f" - [(set_attr "type" "fsgn") - (set_attr "mode" "DF")]) - -(define_insn "*extendsfxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (absneg:XF (float_extend:XF - (match_operand:SF 1 "register_operand" "0"))))] - "TARGET_80387" - "f" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF")]) - -(define_insn "*extenddfxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (absneg:XF (float_extend:XF - (match_operand:DF 1 "register_operand" "0"))))] - "TARGET_80387" - "f" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF")]) - -;; Copysign instructions - -(define_mode_iterator CSGNMODE [SF DF TF]) -(define_mode_attr CSGNVMODE [(SF "V4SF") (DF "V2DF") (TF "TF")]) - -(define_expand "copysign3" - [(match_operand:CSGNMODE 0 "register_operand" "") - (match_operand:CSGNMODE 1 "nonmemory_operand" "") - (match_operand:CSGNMODE 2 "register_operand" "")] - "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) - || (TARGET_SSE2 && (mode == TFmode))" -{ - ix86_expand_copysign (operands); - DONE; -}) - -(define_insn_and_split "copysign3_const" - [(set (match_operand:CSGNMODE 0 "register_operand" "=x") - (unspec:CSGNMODE - [(match_operand: 1 "vector_move_operand" "xmC") - (match_operand:CSGNMODE 2 "register_operand" "0") - (match_operand: 3 "nonimmediate_operand" "xm")] - UNSPEC_COPYSIGN))] - "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) - || (TARGET_SSE2 && (mode == TFmode))" - "#" - "&& reload_completed" - [(const_int 0)] -{ - ix86_split_copysign_const (operands); - DONE; -}) - -(define_insn "copysign3_var" - [(set (match_operand:CSGNMODE 0 "register_operand" "=x,x,x,x,x") - (unspec:CSGNMODE - [(match_operand:CSGNMODE 2 "register_operand" "x,0,0,x,x") - (match_operand:CSGNMODE 3 "register_operand" "1,1,x,1,x") - (match_operand: 4 "nonimmediate_operand" "X,xm,xm,0,0") - (match_operand: 5 "nonimmediate_operand" "0,xm,1,xm,1")] - UNSPEC_COPYSIGN)) - (clobber (match_scratch: 1 "=x,x,x,x,x"))] - "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) - || (TARGET_SSE2 && (mode == TFmode))" - "#") - -(define_split - [(set (match_operand:CSGNMODE 0 "register_operand" "") - (unspec:CSGNMODE - [(match_operand:CSGNMODE 2 "register_operand" "") - (match_operand:CSGNMODE 3 "register_operand" "") - (match_operand: 4 "" "") - (match_operand: 5 "" "")] - UNSPEC_COPYSIGN)) - (clobber (match_scratch: 1 ""))] - "((SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) - || (TARGET_SSE2 && (mode == TFmode))) - && reload_completed" - [(const_int 0)] -{ - ix86_split_copysign_var (operands); - DONE; -}) - -;; One complement instructions - -(define_expand "one_cmpldi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (not:DI (match_operand:DI 1 "nonimmediate_operand" "")))] - "TARGET_64BIT" - "ix86_expand_unary_operator (NOT, DImode, operands); DONE;") - -(define_insn "*one_cmpldi2_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))] - "TARGET_64BIT && ix86_unary_operator_ok (NOT, DImode, operands)" - "not{q}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "DI")]) - -(define_insn "*one_cmpldi2_2_rex64" - [(set (reg FLAGS_REG) - (compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (not:DI (match_dup 1)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && ix86_unary_operator_ok (NOT, DImode, operands)" - "#" - [(set_attr "type" "alu1") - (set_attr "mode" "DI")]) - -(define_split - [(set (match_operand 0 "flags_reg_operand" "") - (match_operator 2 "compare_operator" - [(not:DI (match_operand:DI 3 "nonimmediate_operand" "")) - (const_int 0)])) - (set (match_operand:DI 1 "nonimmediate_operand" "") - (not:DI (match_dup 3)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" - [(parallel [(set (match_dup 0) - (match_op_dup 2 - [(xor:DI (match_dup 3) (const_int -1)) - (const_int 0)])) - (set (match_dup 1) - (xor:DI (match_dup 3) (const_int -1)))])] - "") - -(define_expand "one_cmplsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (not:SI (match_operand:SI 1 "nonimmediate_operand" "")))] - "" - "ix86_expand_unary_operator (NOT, SImode, operands); DONE;") - -(define_insn "*one_cmplsi2_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))] - "ix86_unary_operator_ok (NOT, SImode, operands)" - "not{l}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "SI")]) - -;; ??? Currently never generated - xor is used instead. -(define_insn "*one_cmplsi2_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (not:SI (match_operand:SI 1 "register_operand" "0"))))] - "TARGET_64BIT && ix86_unary_operator_ok (NOT, SImode, operands)" - "not{l}\t%k0" - [(set_attr "type" "negnot") - (set_attr "mode" "SI")]) - -(define_insn "*one_cmplsi2_2" - [(set (reg FLAGS_REG) - (compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (not:SI (match_dup 1)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_unary_operator_ok (NOT, SImode, operands)" - "#" - [(set_attr "type" "alu1") - (set_attr "mode" "SI")]) - -(define_split - [(set (match_operand 0 "flags_reg_operand" "") - (match_operator 2 "compare_operator" - [(not:SI (match_operand:SI 3 "nonimmediate_operand" "")) - (const_int 0)])) - (set (match_operand:SI 1 "nonimmediate_operand" "") - (not:SI (match_dup 3)))] - "ix86_match_ccmode (insn, CCNOmode)" - [(parallel [(set (match_dup 0) - (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1)) - (const_int 0)])) - (set (match_dup 1) - (xor:SI (match_dup 3) (const_int -1)))])] - "") - -;; ??? Currently never generated - xor is used instead. -(define_insn "*one_cmplsi2_2_zext" - [(set (reg FLAGS_REG) - (compare (not:SI (match_operand:SI 1 "register_operand" "0")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (not:SI (match_dup 1))))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && ix86_unary_operator_ok (NOT, SImode, operands)" - "#" - [(set_attr "type" "alu1") - (set_attr "mode" "SI")]) - -(define_split - [(set (match_operand 0 "flags_reg_operand" "") - (match_operator 2 "compare_operator" - [(not:SI (match_operand:SI 3 "register_operand" "")) - (const_int 0)])) - (set (match_operand:DI 1 "register_operand" "") - (zero_extend:DI (not:SI (match_dup 3))))] - "ix86_match_ccmode (insn, CCNOmode)" - [(parallel [(set (match_dup 0) - (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1)) - (const_int 0)])) - (set (match_dup 1) - (zero_extend:DI (xor:SI (match_dup 3) (const_int -1))))])] - "") - -(define_expand "one_cmplhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (not:HI (match_operand:HI 1 "nonimmediate_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_unary_operator (NOT, HImode, operands); DONE;") - -(define_insn "*one_cmplhi2_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))] - "ix86_unary_operator_ok (NOT, HImode, operands)" - "not{w}\t%0" - [(set_attr "type" "negnot") - (set_attr "mode" "HI")]) - -(define_insn "*one_cmplhi2_2" - [(set (reg FLAGS_REG) - (compare (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (not:HI (match_dup 1)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_unary_operator_ok (NEG, HImode, operands)" - "#" - [(set_attr "type" "alu1") - (set_attr "mode" "HI")]) - -(define_split - [(set (match_operand 0 "flags_reg_operand" "") - (match_operator 2 "compare_operator" - [(not:HI (match_operand:HI 3 "nonimmediate_operand" "")) - (const_int 0)])) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (not:HI (match_dup 3)))] - "ix86_match_ccmode (insn, CCNOmode)" - [(parallel [(set (match_dup 0) - (match_op_dup 2 [(xor:HI (match_dup 3) (const_int -1)) - (const_int 0)])) - (set (match_dup 1) - (xor:HI (match_dup 3) (const_int -1)))])] - "") - -;; %%% Potential partial reg stall on alternative 1. What to do? -(define_expand "one_cmplqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (not:QI (match_operand:QI 1 "nonimmediate_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_unary_operator (NOT, QImode, operands); DONE;") - -(define_insn "*one_cmplqi2_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") - (not:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))] - "ix86_unary_operator_ok (NOT, QImode, operands)" - "@ - not{b}\t%0 - not{l}\t%k0" - [(set_attr "type" "negnot") - (set_attr "mode" "QI,SI")]) - -(define_insn "*one_cmplqi2_2" - [(set (reg FLAGS_REG) - (compare (not:QI (match_operand:QI 1 "nonimmediate_operand" "0")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (not:QI (match_dup 1)))] - "ix86_match_ccmode (insn, CCNOmode) - && ix86_unary_operator_ok (NOT, QImode, operands)" - "#" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) - -(define_split - [(set (match_operand 0 "flags_reg_operand" "") - (match_operator 2 "compare_operator" - [(not:QI (match_operand:QI 3 "nonimmediate_operand" "")) - (const_int 0)])) - (set (match_operand:QI 1 "nonimmediate_operand" "") - (not:QI (match_dup 3)))] - "ix86_match_ccmode (insn, CCNOmode)" - [(parallel [(set (match_dup 0) - (match_op_dup 2 [(xor:QI (match_dup 3) (const_int -1)) - (const_int 0)])) - (set (match_dup 1) - (xor:QI (match_dup 3) (const_int -1)))])] - "") - -;; Arithmetic shift instructions - -;; DImode shifts are implemented using the i386 "shift double" opcode, -;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count -;; is variable, then the count is in %cl and the "imm" operand is dropped -;; from the assembler input. -;; -;; This instruction shifts the target reg/mem as usual, but instead of -;; shifting in zeros, bits are shifted in from reg operand. If the insn -;; is a left shift double, bits are taken from the high order bits of -;; reg, else if the insn is a shift right double, bits are taken from the -;; low order bits of reg. So if %eax is "1234" and %edx is "5678", -;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345". -;; -;; Since sh[lr]d does not change the `reg' operand, that is done -;; separately, making all shifts emit pairs of shift double and normal -;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to -;; support a 63 bit shift, each shift where the count is in a reg expands -;; to a pair of shifts, a branch, a shift by 32 and a label. -;; -;; If the shift count is a constant, we need never emit more than one -;; shift pair, instead using moves and sign extension for counts greater -;; than 31. - -(define_expand "ashlti3" - [(set (match_operand:TI 0 "register_operand" "") - (ashift:TI (match_operand:TI 1 "reg_or_pm1_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (ASHIFT, TImode, operands); DONE;") - -;; This pattern must be defined before *ashlti3_1 to prevent -;; combine pass from converting sse2_ashlti3 to *ashlti3_1. - -(define_insn "*avx_ashlti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (ashift:TI (match_operand:TI 1 "register_operand" "x") - (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))] - "TARGET_AVX" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return "vpslldq\t{%2, %1, %0|%0, %1, %2}"; -} - [(set_attr "type" "sseishft") - (set_attr "prefix" "vex") - (set_attr "length_immediate" "1") - (set_attr "mode" "TI")]) - -(define_insn "sse2_ashlti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (ashift:TI (match_operand:TI 1 "register_operand" "0") - (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))] - "TARGET_SSE2" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return "pslldq\t{%2, %0|%0, %2}"; -} - [(set_attr "type" "sseishft") - (set_attr "prefix_data16" "1") - (set_attr "length_immediate" "1") - (set_attr "mode" "TI")]) - -(define_insn "*ashlti3_1" - [(set (match_operand:TI 0 "register_operand" "=&r,r") - (ashift:TI (match_operand:TI 1 "reg_or_pm1_operand" "n,0") - (match_operand:QI 2 "nonmemory_operand" "Oc,Oc"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "#" - [(set_attr "type" "multi")]) - -(define_peephole2 - [(match_scratch:DI 3 "r") - (parallel [(set (match_operand:TI 0 "register_operand" "") - (ashift:TI (match_operand:TI 1 "nonmemory_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))]) - (match_dup 3)] - "TARGET_64BIT" - [(const_int 0)] - "ix86_split_ashl (operands, operands[3], TImode); DONE;") - -(define_split - [(set (match_operand:TI 0 "register_operand" "") - (ashift:TI (match_operand:TI 1 "nonmemory_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? epilogue_completed : reload_completed)" - [(const_int 0)] - "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;") - -(define_insn "x86_64_shld" - [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") - (ior:DI (ashift:DI (match_dup 0) - (match_operand:QI 2 "nonmemory_operand" "Jc")) - (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") - (minus:QI (const_int 64) (match_dup 2))))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "shld{q}\t{%s2%1, %0|%0, %1, %2}" - [(set_attr "type" "ishift") - (set_attr "prefix_0f" "1") - (set_attr "mode" "DI") - (set_attr "athlon_decode" "vector") - (set_attr "amdfam10_decode" "vector")]) - -(define_expand "x86_64_shift_adj_1" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "") - (const_int 64)) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0)) - (match_operand:DI 1 "register_operand" "") - (match_dup 0))) - (set (match_dup 1) - (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0)) - (match_operand:DI 3 "register_operand" "r") - (match_dup 1)))] - "TARGET_64BIT" - "") - -(define_expand "x86_64_shift_adj_2" - [(use (match_operand:DI 0 "register_operand" "")) - (use (match_operand:DI 1 "register_operand" "")) - (use (match_operand:QI 2 "register_operand" ""))] - "TARGET_64BIT" -{ - rtx label = gen_label_rtx (); - rtx tmp; - - emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (64))); - - tmp = gen_rtx_REG (CCZmode, FLAGS_REG); - tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); - JUMP_LABEL (tmp) = label; - - emit_move_insn (operands[0], operands[1]); - ix86_expand_clear (operands[1]); - - emit_label (label); - LABEL_NUSES (label) = 1; - - DONE; -}) - -(define_expand "ashldi3" - [(set (match_operand:DI 0 "shiftdi_operand" "") - (ashift:DI (match_operand:DI 1 "ashldi_input_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;") - -(define_insn "*ashldi3_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l") - (match_operand:QI 2 "nonmemory_operand" "cJ,M"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - gcc_assert (rtx_equal_p (operands[0], operands[1])); - return "add{q}\t%0, %0"; - - case TYPE_LEA: - gcc_assert (CONST_INT_P (operands[2])); - gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3); - operands[1] = gen_rtx_MULT (DImode, operands[1], - GEN_INT (1 << INTVAL (operands[2]))); - return "lea{q}\t{%a1, %0|%0, %a1}"; - - default: - if (REG_P (operands[2])) - return "sal{q}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{q}\t%0"; - else - return "sal{q}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "1") - (const_string "lea") - (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "DI")]) - -;; Convert lea to the lea pattern to avoid flags dependency. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "index_register_operand" "") - (match_operand:QI 2 "immediate_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" - [(set (match_dup 0) - (mult:DI (match_dup 1) - (match_dup 2)))] - "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);") - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashldi3_cmp_rex64" - [(set (reg FLAGS_REG) - (compare - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_63_operand" "J")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (ashift:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, DImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{q}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{q}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{q}\t%0"; - else - return "sal{q}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "DI")]) - -(define_insn "*ashldi3_cconly_rex64" - [(set (reg FLAGS_REG) - (compare - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_63_operand" "J")) - (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, DImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{q}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{q}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{q}\t%0"; - else - return "sal{q}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "DI")]) - -(define_insn "*ashldi3_1" - [(set (match_operand:DI 0 "register_operand" "=&r,r") - (ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0") - (match_operand:QI 2 "nonmemory_operand" "Jc,Jc"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT" - "#" - [(set_attr "type" "multi")]) - -;; By default we don't ask for a scratch register, because when DImode -;; values are manipulated, registers are already at a premium. But if -;; we have one handy, we won't turn it away. -(define_peephole2 - [(match_scratch:SI 3 "r") - (parallel [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "nonmemory_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))]) - (match_dup 3)] - "!TARGET_64BIT && TARGET_CMOVE" - [(const_int 0)] - "ix86_split_ashl (operands, operands[3], DImode); DONE;") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "nonmemory_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? epilogue_completed : reload_completed)" - [(const_int 0)] - "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;") - -(define_insn "x86_shld" - [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") - (ior:SI (ashift:SI (match_dup 0) - (match_operand:QI 2 "nonmemory_operand" "Ic")) - (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (minus:QI (const_int 32) (match_dup 2))))) - (clobber (reg:CC FLAGS_REG))] - "" - "shld{l}\t{%s2%1, %0|%0, %1, %2}" - [(set_attr "type" "ishift") - (set_attr "prefix_0f" "1") - (set_attr "mode" "SI") - (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "amdfam10_decode" "vector")]) - -(define_expand "x86_shift_adj_1" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "") - (const_int 32)) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0)) - (match_operand:SI 1 "register_operand" "") - (match_dup 0))) - (set (match_dup 1) - (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0)) - (match_operand:SI 3 "register_operand" "r") - (match_dup 1)))] - "TARGET_CMOVE" - "") - -(define_expand "x86_shift_adj_2" - [(use (match_operand:SI 0 "register_operand" "")) - (use (match_operand:SI 1 "register_operand" "")) - (use (match_operand:QI 2 "register_operand" ""))] - "" -{ - rtx label = gen_label_rtx (); - rtx tmp; - - emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32))); - - tmp = gen_rtx_REG (CCZmode, FLAGS_REG); - tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); - JUMP_LABEL (tmp) = label; - - emit_move_insn (operands[0], operands[1]); - ix86_expand_clear (operands[1]); - - emit_label (label); - LABEL_NUSES (label) = 1; - - DONE; -}) - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;") - -(define_insn "*ashlsi3_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l") - (match_operand:QI 2 "nonmemory_operand" "cI,M"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - gcc_assert (rtx_equal_p (operands[0], operands[1])); - return "add{l}\t%0, %0"; - - case TYPE_LEA: - return "#"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%0"; - else - return "sal{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "1") - (const_string "lea") - (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -;; Convert lea to the lea pattern to avoid flags dependency. -(define_split - [(set (match_operand 0 "register_operand" "") - (ashift (match_operand 1 "index_register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4" - [(const_int 0)] -{ - rtx pat; - enum machine_mode mode = GET_MODE (operands[0]); - - if (GET_MODE_SIZE (mode) < 4) - operands[0] = gen_lowpart (SImode, operands[0]); - if (mode != Pmode) - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); - - pat = gen_rtx_MULT (Pmode, operands[1], operands[2]); - if (Pmode != SImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); - DONE; -}) - -;; Rare case of shifting RSP is handled by generating move and shift -(define_split - [(set (match_operand 0 "register_operand" "") - (ashift (match_operand 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" - [(const_int 0)] -{ - rtx pat, clob; - emit_move_insn (operands[0], operands[1]); - pat = gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_ASHIFT (GET_MODE (operands[0]), - operands[0], operands[2])); - clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); - emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob))); - DONE; -}) - -(define_insn "*ashlsi3_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l") - (match_operand:QI 2 "nonmemory_operand" "cI,M")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{l}\t%k0, %k0"; - - case TYPE_LEA: - return "#"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%k0"; - else - return "sal{l}\t{%2, %k0|%k0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "1") - (const_string "lea") - (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -;; Convert lea to the lea pattern to avoid flags dependency. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (ashift (match_operand 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" "")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" - [(set (match_dup 0) (zero_extend:DI - (subreg:SI (mult:SI (match_dup 1) - (match_dup 2)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); -}) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashlsi3_cmp" - [(set (reg FLAGS_REG) - (compare - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashift:SI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{l}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%0"; - else - return "sal{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -(define_insn "*ashlsi3_cconly" - [(set (reg FLAGS_REG) - (compare - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{l}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%0"; - else - return "sal{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -(define_insn "*ashlsi3_cmp_zext" - [(set (reg FLAGS_REG) - (compare - (ashift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{l}\t%k0, %k0"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%k0"; - else - return "sal{l}\t{%2, %k0|%k0, %2}"; - } -} - [(set (attr "type") - (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -(define_expand "ashlhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;") - -(define_insn "*ashlhi3_1_lea" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l") - (match_operand:QI 2 "nonmemory_operand" "cI,M"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_LEA: - return "#"; - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{w}\t%0"; - else - return "sal{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "1") - (const_string "lea") - (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "HI,SI")]) - -(define_insn "*ashlhi3_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "cI"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{w}\t%0"; - else - return "sal{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "HI")]) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashlhi3_cmp" - [(set (reg FLAGS_REG) - (compare - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashift:HI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{w}\t%0"; - else - return "sal{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "HI")]) - -(define_insn "*ashlhi3_cconly" - [(set (reg FLAGS_REG) - (compare - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{w}\t%0"; - else - return "sal{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "HI")]) - -(define_expand "ashlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;") - -;; %%% Potential partial reg stall on alternative 2. What to do? - -(define_insn "*ashlqi3_1_lea" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l") - (match_operand:QI 2 "nonmemory_operand" "cI,cI,M"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_LEA: - return "#"; - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1])) - return "add{l}\t%k0, %k0"; - else - return "add{b}\t%0, %0"; - - default: - if (REG_P (operands[2])) - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else - return "sal{b}\t{%b2, %0|%0, %b2}"; - } - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t%0"; - else - return "sal{b}\t%0"; - } - else - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t{%2, %k0|%k0, %2}"; - else - return "sal{b}\t{%2, %0|%0, %2}"; - } - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "2") - (const_string "lea") - (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "QI,SI,SI")]) - -(define_insn "*ashlqi3_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "cI,cI"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1])) - return "add{l}\t%k0, %k0"; - else - return "add{b}\t%0, %0"; - - default: - if (REG_P (operands[2])) - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else - return "sal{b}\t{%b2, %0|%0, %b2}"; - } - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t%0"; - else - return "sal{b}\t%0"; - } - else - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t{%2, %k0|%k0, %2}"; - else - return "sal{b}\t{%2, %0|%0, %2}"; - } - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "QI,SI")]) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashlqi3_cmp" - [(set (reg FLAGS_REG) - (compare - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (ashift:QI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{b}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{b}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{b}\t%0"; - else - return "sal{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "QI")]) - -(define_insn "*ashlqi3_cconly" - [(set (reg FLAGS_REG) - (compare - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" + "reload_completed" + [(parallel [(set (match_dup 0) (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] { - switch (get_attr_type (insn)) + rtx tmp; + operands[0] = gen_rtx_REG (SImode, + true_regnum (operands[0]) + + (TARGET_64BIT ? 1 : 2)); + if (GET_CODE (operands[1]) == ABS) { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{b}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{b}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{b}\t%0"; - else - return "sal{b}\t{%2, %0|%0, %2}"; + tmp = GEN_INT (0x7fff); + tmp = gen_rtx_AND (SImode, operands[0], tmp); } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "QI")]) + else + { + tmp = GEN_INT (0x8000); + tmp = gen_rtx_XOR (SImode, operands[0], tmp); + } + operands[1] = tmp; +}) -;; See comment above `ashldi3' about how this works. +;; Conditionalize these after reload. If they match before reload, we +;; lose the clobber and ability to use integer instructions. -(define_expand "ashrti3" - [(set (match_operand:TI 0 "register_operand" "") - (ashiftrt:TI (match_operand:TI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (ASHIFTRT, TImode, operands); DONE;") +(define_insn "*2_1" + [(set (match_operand:X87MODEF 0 "register_operand" "=f") + (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))] + "TARGET_80387 + && (reload_completed + || !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))" + "f" + [(set_attr "type" "fsgn") + (set_attr "mode" "")]) -(define_insn "*ashrti3_1" - [(set (match_operand:TI 0 "register_operand" "=r") - (ashiftrt:TI (match_operand:TI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "Oc"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "#" - [(set_attr "type" "multi")]) +(define_insn "*extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (absneg:DF (float_extend:DF + (match_operand:SF 1 "register_operand" "0"))))] + "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)" + "f" + [(set_attr "type" "fsgn") + (set_attr "mode" "DF")]) -(define_peephole2 - [(match_scratch:DI 3 "r") - (parallel [(set (match_operand:TI 0 "register_operand" "") - (ashiftrt:TI (match_operand:TI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))]) - (match_dup 3)] - "TARGET_64BIT" - [(const_int 0)] - "ix86_split_ashr (operands, operands[3], TImode); DONE;") +(define_insn "*extendsfxf2" + [(set (match_operand:XF 0 "register_operand" "=f") + (absneg:XF (float_extend:XF + (match_operand:SF 1 "register_operand" "0"))))] + "TARGET_80387" + "f" + [(set_attr "type" "fsgn") + (set_attr "mode" "XF")]) -(define_split - [(set (match_operand:TI 0 "register_operand" "") - (ashiftrt:TI (match_operand:TI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? epilogue_completed : reload_completed)" - [(const_int 0)] - "ix86_split_ashr (operands, NULL_RTX, TImode); DONE;") +(define_insn "*extenddfxf2" + [(set (match_operand:XF 0 "register_operand" "=f") + (absneg:XF (float_extend:XF + (match_operand:DF 1 "register_operand" "0"))))] + "TARGET_80387" + "f" + [(set_attr "type" "fsgn") + (set_attr "mode" "XF")]) -(define_insn "x86_64_shrd" - [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") - (ior:DI (ashiftrt:DI (match_dup 0) - (match_operand:QI 2 "nonmemory_operand" "Jc")) - (ashift:DI (match_operand:DI 1 "register_operand" "r") - (minus:QI (const_int 64) (match_dup 2))))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "shrd{q}\t{%s2%1, %0|%0, %1, %2}" - [(set_attr "type" "ishift") - (set_attr "prefix_0f" "1") - (set_attr "mode" "DI") - (set_attr "athlon_decode" "vector") - (set_attr "amdfam10_decode" "vector")]) +;; Copysign instructions -(define_expand "ashrdi3" - [(set (match_operand:DI 0 "shiftdi_operand" "") - (ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (ASHIFTRT, DImode, operands); DONE;") +(define_mode_iterator CSGNMODE [SF DF TF]) +(define_mode_attr CSGNVMODE [(SF "V4SF") (DF "V2DF") (TF "TF")]) -(define_expand "x86_64_shift_adj_3" - [(use (match_operand:DI 0 "register_operand" "")) - (use (match_operand:DI 1 "register_operand" "")) - (use (match_operand:QI 2 "register_operand" ""))] - "" +(define_expand "copysign3" + [(match_operand:CSGNMODE 0 "register_operand" "") + (match_operand:CSGNMODE 1 "nonmemory_operand" "") + (match_operand:CSGNMODE 2 "register_operand" "")] + "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || (TARGET_SSE2 && (mode == TFmode))" { - rtx label = gen_label_rtx (); - rtx tmp; - - emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (64))); - - tmp = gen_rtx_REG (CCZmode, FLAGS_REG); - tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); - JUMP_LABEL (tmp) = label; + ix86_expand_copysign (operands); + DONE; +}) - emit_move_insn (operands[0], operands[1]); - emit_insn (gen_ashrdi3_63_rex64 (operands[1], operands[1], GEN_INT (63))); +(define_insn_and_split "copysign3_const" + [(set (match_operand:CSGNMODE 0 "register_operand" "=x") + (unspec:CSGNMODE + [(match_operand: 1 "vector_move_operand" "xmC") + (match_operand:CSGNMODE 2 "register_operand" "0") + (match_operand: 3 "nonimmediate_operand" "xm")] + UNSPEC_COPYSIGN))] + "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || (TARGET_SSE2 && (mode == TFmode))" + "#" + "&& reload_completed" + [(const_int 0)] +{ + ix86_split_copysign_const (operands); + DONE; +}) - emit_label (label); - LABEL_NUSES (label) = 1; +(define_insn "copysign3_var" + [(set (match_operand:CSGNMODE 0 "register_operand" "=x,x,x,x,x") + (unspec:CSGNMODE + [(match_operand:CSGNMODE 2 "register_operand" "x,0,0,x,x") + (match_operand:CSGNMODE 3 "register_operand" "1,1,x,1,x") + (match_operand: 4 "nonimmediate_operand" "X,xm,xm,0,0") + (match_operand: 5 "nonimmediate_operand" "0,xm,1,xm,1")] + UNSPEC_COPYSIGN)) + (clobber (match_scratch: 1 "=x,x,x,x,x"))] + "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || (TARGET_SSE2 && (mode == TFmode))" + "#") +(define_split + [(set (match_operand:CSGNMODE 0 "register_operand" "") + (unspec:CSGNMODE + [(match_operand:CSGNMODE 2 "register_operand" "") + (match_operand:CSGNMODE 3 "register_operand" "") + (match_operand: 4 "" "") + (match_operand: 5 "" "")] + UNSPEC_COPYSIGN)) + (clobber (match_scratch: 1 ""))] + "((SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || (TARGET_SSE2 && (mode == TFmode))) + && reload_completed" + [(const_int 0)] +{ + ix86_split_copysign_var (operands); DONE; }) + +;; One complement instructions -(define_insn "ashrdi3_63_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm") - (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0") - (match_operand:DI 2 "const_int_operand" "i,i"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && INTVAL (operands[2]) == 63 - && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" - "@ - {cqto|cqo} - sar{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "imovx,ishift") - (set_attr "prefix_0f" "0,*") - (set_attr "length_immediate" "0,*") - (set_attr "modrm" "0,1") - (set_attr "mode" "DI")]) +(define_expand "one_cmpl2" + [(set (match_operand:SWIM 0 "nonimmediate_operand" "") + (not:SWIM (match_operand:SWIM 1 "nonimmediate_operand" "")))] + "" + "ix86_expand_unary_operator (NOT, mode, operands); DONE;") -(define_insn "*ashrdi3_1_one_bit_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" - "sar{q}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) +(define_insn "*one_cmpl2_1" + [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm") + (not:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "0")))] + "ix86_unary_operator_ok (NOT, mode, operands)" + "not{}\t%0" + [(set_attr "type" "negnot") + (set_attr "mode" "")]) -(define_insn "*ashrdi3_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") - (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "J,c"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" +;; %%% Potential partial reg stall on alternative 1. What to do? +(define_insn "*one_cmplqi2_1" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") + (not:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))] + "ix86_unary_operator_ok (NOT, QImode, operands)" "@ - sar{q}\t{%2, %0|%0, %2} - sar{q}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "DI")]) + not{b}\t%0 + not{l}\t%k0" + [(set_attr "type" "negnot") + (set_attr "mode" "QI,SI")]) -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashrdi3_one_bit_cmp_rex64" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (ashiftrt:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" - "sar{q}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) +;; ??? Currently never generated - xor is used instead. +(define_insn "*one_cmplsi2_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (not:SI (match_operand:SI 1 "register_operand" "0"))))] + "TARGET_64BIT && ix86_unary_operator_ok (NOT, SImode, operands)" + "not{l}\t%k0" + [(set_attr "type" "negnot") + (set_attr "mode" "SI")]) -(define_insn "*ashrdi3_one_bit_cconly_rex64" +(define_insn "*one_cmpl2_2" [(set (reg FLAGS_REG) - (compare - (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" - "sar{q}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) + (compare (not:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=m") + (not:SWI (match_dup 1)))] + "ix86_match_ccmode (insn, CCNOmode) + && ix86_unary_operator_ok (NOT, mode, operands)" + "#" + [(set_attr "type" "alu1") + (set_attr "mode" "")]) + +(define_split + [(set (match_operand 0 "flags_reg_operand" "") + (match_operator 2 "compare_operator" + [(not:SWI (match_operand:SWI 3 "nonimmediate_operand" "")) + (const_int 0)])) + (set (match_operand:SWI 1 "nonimmediate_operand" "") + (not:SWI (match_dup 3)))] + "ix86_match_ccmode (insn, CCNOmode)" + [(parallel [(set (match_dup 0) + (match_op_dup 2 [(xor:SWI (match_dup 3) (const_int -1)) + (const_int 0)])) + (set (match_dup 1) + (xor:SWI (match_dup 3) (const_int -1)))])] + "") -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashrdi3_cmp_rex64" +;; ??? Currently never generated - xor is used instead. +(define_insn "*one_cmplsi2_2_zext" [(set (reg FLAGS_REG) - (compare - (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_63_operand" "J")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (ashiftrt:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" - "sar{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "DI")]) + (compare (not:SI (match_operand:SI 1 "register_operand" "0")) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (not:SI (match_dup 1))))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) + && ix86_unary_operator_ok (NOT, SImode, operands)" + "#" + [(set_attr "type" "alu1") + (set_attr "mode" "SI")]) -(define_insn "*ashrdi3_cconly_rex64" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_63_operand" "J")) - (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" - "sar{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "DI")]) +(define_split + [(set (match_operand 0 "flags_reg_operand" "") + (match_operator 2 "compare_operator" + [(not:SI (match_operand:SI 3 "register_operand" "")) + (const_int 0)])) + (set (match_operand:DI 1 "register_operand" "") + (zero_extend:DI (not:SI (match_dup 3))))] + "ix86_match_ccmode (insn, CCNOmode)" + [(parallel [(set (match_dup 0) + (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1)) + (const_int 0)])) + (set (match_dup 1) + (zero_extend:DI (xor:SI (match_dup 3) (const_int -1))))])] + "") + +;; Shift instructions -(define_insn "*ashrdi3_1" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "Jc"))) +;; DImode shifts are implemented using the i386 "shift double" opcode, +;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count +;; is variable, then the count is in %cl and the "imm" operand is dropped +;; from the assembler input. +;; +;; This instruction shifts the target reg/mem as usual, but instead of +;; shifting in zeros, bits are shifted in from reg operand. If the insn +;; is a left shift double, bits are taken from the high order bits of +;; reg, else if the insn is a shift right double, bits are taken from the +;; low order bits of reg. So if %eax is "1234" and %edx is "5678", +;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345". +;; +;; Since sh[lr]d does not change the `reg' operand, that is done +;; separately, making all shifts emit pairs of shift double and normal +;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to +;; support a 63 bit shift, each shift where the count is in a reg expands +;; to a pair of shifts, a branch, a shift by 32 and a label. +;; +;; If the shift count is a constant, we need never emit more than one +;; shift pair, instead using moves and sign extension for counts greater +;; than 31. + +(define_expand "ashl3" + [(set (match_operand:SDWIM 0 "" "") + (ashift:SDWIM (match_operand:SDWIM 1 "" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + "ix86_expand_binary_operator (ASHIFT, mode, operands); DONE;") + +(define_insn "*ashl3_doubleword" + [(set (match_operand:DWI 0 "register_operand" "=&r,r") + (ashift:DWI (match_operand:DWI 1 "reg_or_pm1_operand" "n,0") + (match_operand:QI 2 "nonmemory_operand" "c,c"))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT" + "" "#" [(set_attr "type" "multi")]) -;; By default we don't ask for a scratch register, because when DImode +(define_split + [(set (match_operand:DWI 0 "register_operand" "") + (ashift:DWI (match_operand:DWI 1 "nonmemory_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "(optimize && flag_peephole2) ? epilogue_completed : reload_completed" + [(const_int 0)] + "ix86_split_ashl (operands, NULL_RTX, mode); DONE;") + +;; By default we don't ask for a scratch register, because when DWImode ;; values are manipulated, registers are already at a premium. But if ;; we have one handy, we won't turn it away. + (define_peephole2 - [(match_scratch:SI 3 "r") - (parallel [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) + [(match_scratch:DWIH 3 "r") + (parallel [(set (match_operand: 0 "register_operand" "") + (ashift: + (match_operand: 1 "nonmemory_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) (clobber (reg:CC FLAGS_REG))]) (match_dup 3)] - "!TARGET_64BIT && TARGET_CMOVE" + "TARGET_CMOVE" [(const_int 0)] - "ix86_split_ashr (operands, operands[3], DImode); DONE;") + "ix86_split_ashl (operands, operands[3], mode); DONE;") -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) +(define_insn "x86_64_shld" + [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") + (ior:DI (ashift:DI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand" "Jc")) + (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") + (minus:QI (const_int 64) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? epilogue_completed : reload_completed)" - [(const_int 0)] - "ix86_split_ashr (operands, NULL_RTX, DImode); DONE;") + "TARGET_64BIT" + "shld{q}\t{%s2%1, %0|%0, %1, %2}" + [(set_attr "type" "ishift") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI") + (set_attr "athlon_decode" "vector") + (set_attr "amdfam10_decode" "vector")]) -(define_insn "x86_shrd" +(define_insn "x86_shld" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") - (ior:SI (ashiftrt:SI (match_dup 0) + (ior:SI (ashift:SI (match_dup 0) (match_operand:QI 2 "nonmemory_operand" "Ic")) - (ashift:SI (match_operand:SI 1 "register_operand" "r") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") (minus:QI (const_int 32) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))] "" - "shrd{l}\t{%s2%1, %0|%0, %1, %2}" + "shld{l}\t{%s2%1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") + (set_attr "mode" "SI") (set_attr "pent_pair" "np") - (set_attr "mode" "SI")]) + (set_attr "athlon_decode" "vector") + (set_attr "amdfam10_decode" "vector")]) -(define_expand "x86_shift_adj_3" - [(use (match_operand:SI 0 "register_operand" "")) - (use (match_operand:SI 1 "register_operand" "")) +(define_expand "x86_shift_adj_1" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "") + (match_dup 4)) + (const_int 0))) + (set (match_operand:SWI48 0 "register_operand" "") + (if_then_else:SWI48 (ne (reg:CCZ FLAGS_REG) (const_int 0)) + (match_operand:SWI48 1 "register_operand" "") + (match_dup 0))) + (set (match_dup 1) + (if_then_else:SWI48 (ne (reg:CCZ FLAGS_REG) (const_int 0)) + (match_operand:SWI48 3 "register_operand" "r") + (match_dup 1)))] + "TARGET_CMOVE" + "operands[4] = GEN_INT (GET_MODE_BITSIZE (mode));") + +(define_expand "x86_shift_adj_2" + [(use (match_operand:SWI48 0 "register_operand" "")) + (use (match_operand:SWI48 1 "register_operand" "")) (use (match_operand:QI 2 "register_operand" ""))] "" { rtx label = gen_label_rtx (); rtx tmp; - emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32))); - - tmp = gen_rtx_REG (CCZmode, FLAGS_REG); - tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); - JUMP_LABEL (tmp) = label; - - emit_move_insn (operands[0], operands[1]); - emit_insn (gen_ashrsi3_31 (operands[1], operands[1], GEN_INT (31))); - - emit_label (label); - LABEL_NUSES (label) = 1; - - DONE; -}) - -(define_expand "ashrsi3_31" - [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm") - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0") - (match_operand:SI 2 "const_int_operand" "i,i"))) - (clobber (reg:CC FLAGS_REG))])] - "") - -(define_insn "*ashrsi3_31" - [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm") - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0") - (match_operand:SI 2 "const_int_operand" "i,i"))) - (clobber (reg:CC FLAGS_REG))] - "INTVAL (operands[2]) == 31 - && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "@ - {cltd|cdq} - sar{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "imovx,ishift") - (set_attr "prefix_0f" "0,*") - (set_attr "length_immediate" "0,*") - (set_attr "modrm" "0,1") - (set_attr "mode" "SI")]) - -(define_insn "*ashrsi3_31_zext" - [(set (match_operand:DI 0 "register_operand" "=*d,r") - (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0") - (match_operand:SI 2 "const_int_operand" "i,i")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun)) - && INTVAL (operands[2]) == 31 - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "@ - {cltd|cdq} - sar{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "imovx,ishift") - (set_attr "prefix_0f" "0,*") - (set_attr "length_immediate" "0,*") - (set_attr "modrm" "0,1") - (set_attr "mode" "SI")]) - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (ASHIFTRT, SImode, operands); DONE;") - -(define_insn "*ashrsi3_1_one_bit" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "sar{l}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*ashrsi3_1_one_bit_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const1_operand" "")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "sar{l}\t%k0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*ashrsi3_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "@ - sar{l}\t{%2, %0|%0, %2} - sar{l}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) - -(define_insn "*ashrsi3_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "@ - sar{l}\t{%2, %k0|%k0, %2} - sar{l}\t{%b2, %k0|%k0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashrsi3_one_bit_cmp" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashiftrt:SI (match_dup 1) (match_dup 2)))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "sar{l}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*ashrsi3_one_bit_cconly" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "sar{l}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*ashrsi3_one_bit_cmp_zext" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "sar{l}\t%k0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashrsi3_cmp" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashiftrt:SI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "sar{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) - -(define_insn "*ashrsi3_cconly" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "sar{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) - -(define_insn "*ashrsi3_cmp_zext" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" - "sar{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) - -(define_expand "ashrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (ASHIFTRT, HImode, operands); DONE;") + emit_insn (gen_testqi_ccz_1 (operands[2], + GEN_INT (GET_MODE_BITSIZE (mode)))); -(define_insn "*ashrhi3_1_one_bit" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" - "sar{w}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "HI")]) + tmp = gen_rtx_REG (CCZmode, FLAGS_REG); + tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, + gen_rtx_LABEL_REF (VOIDmode, label), + pc_rtx); + tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); + JUMP_LABEL (tmp) = label; -(define_insn "*ashrhi3_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") - (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" - "@ - sar{w}\t{%2, %0|%0, %2} - sar{w}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "HI")]) + emit_move_insn (operands[0], operands[1]); + ix86_expand_clear (operands[1]); -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashrhi3_one_bit_cmp" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashiftrt:HI (match_dup 1) (match_dup 2)))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" - "sar{w}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "HI")]) + emit_label (label); + LABEL_NUSES (label) = 1; -(define_insn "*ashrhi3_one_bit_cconly" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" - "sar{w}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "HI")]) + DONE; +}) -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashrhi3_cmp" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashiftrt:HI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" - "sar{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "HI")]) +(define_insn "*ashl3_1" + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r") + (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,l") + (match_operand:QI 2 "nonmemory_operand" "c,M"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (ASHIFT, mode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return "#"; -(define_insn "*ashrhi3_cconly" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" - "sar{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "HI")]) + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + gcc_assert (rtx_equal_p (operands[0], operands[1])); + return "add{}\t%0, %0"; -(define_expand "ashrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (ASHIFTRT, QImode, operands); DONE;") + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{}\t%0"; + else + return "sal{}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(eq_attr "alternative" "1") + (const_string "lea") + (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "")]) -(define_insn "*ashrqi3_1_one_bit" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) +(define_insn "*ashlsi3_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (zero_extend:DI + (ashift:SI (match_operand:SI 1 "register_operand" "0,l") + (match_operand:QI 2 "nonmemory_operand" "cI,M")))) (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" - "sar{b}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return "#"; -(define_insn "*ashrqi3_1_one_bit_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (ashiftrt:QI (match_dup 0) - (match_operand:QI 1 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" - "sar{b}\t%0" - [(set_attr "type" "ishift1") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{l}\t%k0, %k0"; -(define_insn "*ashrqi3_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" - "@ - sar{b}\t{%2, %0|%0, %2} - sar{b}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "QI")]) + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{l}\t%k0"; + else + return "sal{l}\t{%2, %k0|%k0, %2}"; + } +} + [(set (attr "type") + (cond [(eq_attr "alternative" "1") + (const_string "lea") + (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "SI")]) -(define_insn "*ashrqi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm")) - (ashiftrt:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "I,c"))) +(define_insn "*ashlhi3_1" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "@ - sar{b}\t{%1, %0|%0, %1} - sar{b}\t{%b1, %0|%0, %b1}" - [(set_attr "type" "ishift1") - (set_attr "mode" "QI")]) + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, HImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{w}\t%0, %0"; -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashrqi3_one_bit_cmp" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "I")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (ashiftrt:QI (match_dup 1) (match_dup 2)))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" - "sar{b}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{w}\t%0"; + else + return "sal{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "HI")]) -(define_insn "*ashrqi3_one_bit_cconly" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" - "sar{b}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) +(define_insn "*ashlhi3_1_lea" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l") + (match_operand:QI 2 "nonmemory_operand" "cI,M"))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, HImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return "#"; -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashrqi3_cmp" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (ashiftrt:QI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" - "sar{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "QI")]) + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{w}\t%0, %0"; -(define_insn "*ashrqi3_cconly" - [(set (reg FLAGS_REG) - (compare - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" - "sar{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "QI")]) + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{w}\t%0"; + else + return "sal{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(eq_attr "alternative" "1") + (const_string "lea") + (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "HI,SI")]) - -;; Logical shift instructions +(define_insn "*ashlqi3_1" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "cI,cI"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, QImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1])) + return "add{l}\t%k0, %k0"; + else + return "add{b}\t%0, %0"; -;; See comment above `ashldi3' about how this works. + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + { + if (get_attr_mode (insn) == MODE_SI) + return "sal{l}\t%k0"; + else + return "sal{b}\t%0"; + } + else + { + if (get_attr_mode (insn) == MODE_SI) + return "sal{l}\t{%2, %k0|%k0, %2}"; + else + return "sal{b}\t{%2, %0|%0, %2}"; + } + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "QI,SI")]) -(define_expand "lshrti3" - [(set (match_operand:TI 0 "register_operand" "") - (lshiftrt:TI (match_operand:TI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (LSHIFTRT, TImode, operands); DONE;") +;; %%% Potential partial reg stall on alternative 2. What to do? +(define_insn "*ashlqi3_1_lea" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r") + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l") + (match_operand:QI 2 "nonmemory_operand" "cI,cI,M"))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, QImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return "#"; -;; This pattern must be defined before *lshrti3_1 to prevent -;; combine pass from converting sse2_lshrti3 to *lshrti3_1. + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1])) + return "add{l}\t%k0, %k0"; + else + return "add{b}\t%0, %0"; -(define_insn "*avx_lshrti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (lshiftrt:TI (match_operand:TI 1 "register_operand" "x") - (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))] - "TARGET_AVX" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return "vpsrldq\t{%2, %1, %0|%0, %1, %2}"; + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + { + if (get_attr_mode (insn) == MODE_SI) + return "sal{l}\t%k0"; + else + return "sal{b}\t%0"; + } + else + { + if (get_attr_mode (insn) == MODE_SI) + return "sal{l}\t{%2, %k0|%k0, %2}"; + else + return "sal{b}\t{%2, %0|%0, %2}"; + } + } } - [(set_attr "type" "sseishft") - (set_attr "prefix" "vex") - (set_attr "length_immediate" "1") - (set_attr "mode" "TI")]) + [(set (attr "type") + (cond [(eq_attr "alternative" "2") + (const_string "lea") + (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "QI,SI,SI")]) -(define_insn "sse2_lshrti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (lshiftrt:TI (match_operand:TI 1 "register_operand" "0") - (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))] - "TARGET_SSE2" +(define_insn "*ashlqi3_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) + (ashift:QI (match_dup 0) + (match_operand:QI 1 "nonmemory_operand" "cI"))) + (clobber (reg:CC FLAGS_REG))] + "(optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[1] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" { - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return "psrldq\t{%2, %0|%0, %2}"; + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[1] == const1_rtx); + return "add{b}\t%0, %0"; + + default: + if (operands[1] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{b}\t%0"; + else + return "sal{b}\t{%1, %0|%0, %1}"; + } } - [(set_attr "type" "sseishft") - (set_attr "prefix_data16" "1") - (set_attr "length_immediate" "1") - (set_attr "mode" "TI")]) + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 1 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift1"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift1") + (and (match_operand 1 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "QI")]) -(define_insn "*lshrti3_1" - [(set (match_operand:TI 0 "register_operand" "=r") - (lshiftrt:TI (match_operand:TI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "Oc"))) +;; Convert lea to the lea pattern to avoid flags dependency. +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (ashift:DI (match_operand:DI 1 "index_register_operand" "") + (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "#" - [(set_attr "type" "multi")]) - -(define_peephole2 - [(match_scratch:DI 3 "r") - (parallel [(set (match_operand:TI 0 "register_operand" "") - (lshiftrt:TI (match_operand:TI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))]) - (match_dup 3)] - "TARGET_64BIT" - [(const_int 0)] - "ix86_split_lshr (operands, operands[3], TImode); DONE;") + "TARGET_64BIT && reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1])" + [(set (match_dup 0) + (mult:DI (match_dup 1) + (match_dup 2)))] + "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);") +;; Convert lea to the lea pattern to avoid flags dependency. (define_split - [(set (match_operand:TI 0 "register_operand" "") - (lshiftrt:TI (match_operand:TI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) + [(set (match_operand 0 "register_operand" "") + (ashift (match_operand 1 "index_register_operand" "") + (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? epilogue_completed : reload_completed)" + "reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1]) + && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4" [(const_int 0)] - "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;") +{ + rtx pat; + enum machine_mode mode = GET_MODE (operands[0]); -(define_expand "lshrdi3" - [(set (match_operand:DI 0 "shiftdi_operand" "") - (lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (LSHIFTRT, DImode, operands); DONE;") + if (GET_MODE_SIZE (mode) < 4) + operands[0] = gen_lowpart (SImode, operands[0]); + if (mode != Pmode) + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); + + pat = gen_rtx_MULT (Pmode, operands[1], operands[2]); + if (Pmode != SImode) + pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); + DONE; +}) -(define_insn "*lshrdi3_1_one_bit_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) +;; Rare case of shifting RSP is handled by generating move and shift +(define_split + [(set (match_operand 0 "register_operand" "") + (ashift (match_operand 1 "register_operand" "") + (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{q}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) + "reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1])" + [(const_int 0)] +{ + rtx pat, clob; + emit_move_insn (operands[0], operands[1]); + pat = gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_ASHIFT (GET_MODE (operands[0]), + operands[0], operands[2])); + clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob))); + DONE; +}) -(define_insn "*lshrdi3_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "J,c"))) +;; Convert lea to the lea pattern to avoid flags dependency. +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (zero_extend:DI + (ashift:SI (match_operand:SI 1 "register_operand" "") + (match_operand:QI 2 "const_int_operand" "")))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "@ - shr{q}\t{%2, %0|%0, %2} - shr{q}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "DI")]) + "TARGET_64BIT && reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1])" + [(set (match_dup 0) + (zero_extend:DI (subreg:SI (mult:SI (match_dup 1) (match_dup 2)) 0)))] +{ + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); +}) ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. -(define_insn "*lshrdi3_cmp_one_bit_rex64" +(define_insn "*ashl3_cmp" [(set (reg FLAGS_REG) (compare - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) + (ashift:SWI (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "" "")) (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (lshiftrt:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) + (set (match_operand:SWI 0 "nonimmediate_operand" "=m") + (ashift:SWI (match_dup 1) (match_dup 2)))] + "(optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{q}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) + && ix86_binary_operator_ok (ASHIFT, mode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{}\t%0, %0"; + + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{}\t%0"; + else + return "sal{}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "")]) -(define_insn "*lshrdi3_cconly_one_bit_rex64" +(define_insn "*ashlsi3_cmp_zext" [(set (reg FLAGS_REG) (compare - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) + (ashift:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))] "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) + && (optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD))) && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{q}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) + && ix86_binary_operator_ok (ASHIFT, SImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{l}\t%k0, %k0"; -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*lshrdi3_cmp_rex64" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_63_operand" "J")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (lshiftrt:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "DI")]) + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{l}\t%k0"; + else + return "sal{l}\t{%2, %k0|%k0, %2}"; + } +} + [(set (attr "type") + (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "SI")]) -(define_insn "*lshrdi3_cconly_rex64" +(define_insn "*ashl3_cconly" [(set (reg FLAGS_REG) (compare - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_63_operand" "J")) + (ashift:SWI (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "" "")) (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) + (clobber (match_scratch:SWI 0 "="))] + "(optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD))) && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "DI")]) + && ix86_binary_operator_ok (ASHIFT, mode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{}\t%0, %0"; -(define_insn "*lshrdi3_1" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "Jc"))) + default: + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{}\t%0"; + else + return "sal{}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set (attr "length_immediate") + (if_then_else + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "")]) + +;; See comment above `ashl3' about how this works. + +(define_expand "3" + [(set (match_operand:SDWIM 0 "" "") + (any_shiftrt:SDWIM (match_operand:SDWIM 1 "" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + "ix86_expand_binary_operator (, mode, operands); DONE;") + +(define_insn_and_split "*3_doubleword" + [(set (match_operand:DWI 0 "register_operand" "=r") + (any_shiftrt:DWI (match_operand:DWI 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "c"))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT" + "" "#" + "(optimize && flag_peephole2) ? epilogue_completed : reload_completed" + [(const_int 0)] + "ix86_split_ (operands, NULL_RTX, mode); DONE;" [(set_attr "type" "multi")]) -;; By default we don't ask for a scratch register, because when DImode +;; By default we don't ask for a scratch register, because when DWImode ;; values are manipulated, registers are already at a premium. But if ;; we have one handy, we won't turn it away. + (define_peephole2 - [(match_scratch:SI 3 "r") - (parallel [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) + [(match_scratch:DWIH 3 "r") + (parallel [(set (match_operand: 0 "register_operand" "") + (any_shiftrt: + (match_operand: 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) (clobber (reg:CC FLAGS_REG))]) (match_dup 3)] - "!TARGET_64BIT && TARGET_CMOVE" - [(const_int 0)] - "ix86_split_lshr (operands, operands[3], DImode); DONE;") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? epilogue_completed : reload_completed)" + "TARGET_CMOVE" [(const_int 0)] - "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;") - -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (LSHIFTRT, SImode, operands); DONE;") + "ix86_split_ (operands, operands[3], mode); DONE;") -(define_insn "*lshrsi3_1_one_bit" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) +(define_insn "x86_64_shrd" + [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") + (ior:DI (ashiftrt:DI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand" "Jc")) + (ashift:DI (match_operand:DI 1 "register_operand" "r") + (minus:QI (const_int 64) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{l}\t%0" + "TARGET_64BIT" + "shrd{q}\t{%s2%1, %0|%0, %1, %2}" [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI") + (set_attr "athlon_decode" "vector") + (set_attr "amdfam10_decode" "vector")]) -(define_insn "*lshrsi3_1_one_bit_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0")) - (match_operand:QI 2 "const1_operand" ""))) +(define_insn "x86_shrd" + [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") + (ior:SI (ashiftrt:SI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand" "Ic")) + (ashift:SI (match_operand:SI 1 "register_operand" "r") + (minus:QI (const_int 32) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{l}\t%k0" + "" + "shrd{l}\t{%s2%1, %0|%0, %1, %2}" [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) + (set_attr "prefix_0f" "1") + (set_attr "mode" "SI") + (set_attr "pent_pair" "np") + (set_attr "athlon_decode" "vector") + (set_attr "amdfam10_decode" "vector")]) -(define_insn "*lshrsi3_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) +(define_insn "ashrdi3_cvt" + [(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm") + (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0") + (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "TARGET_64BIT && INTVAL (operands[2]) == 63 + && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun)) + && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" "@ - shr{l}\t{%2, %0|%0, %2} - shr{l}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) + {cqto|cqo} + sar{q}\t{%2, %0|%0, %2}" + [(set_attr "type" "imovx,ishift") + (set_attr "prefix_0f" "0,*") + (set_attr "length_immediate" "0,*") + (set_attr "modrm" "0,1") + (set_attr "mode" "DI")]) -(define_insn "*lshrsi3_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c")))) +(define_insn "ashrsi3_cvt" + [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm") + (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0") + (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "INTVAL (operands[2]) == 31 + && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun)) + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "@ - shr{l}\t{%2, %k0|%k0, %2} - shr{l}\t{%b2, %k0|%k0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*lshrsi3_one_bit_cmp" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (lshiftrt:SI (match_dup 1) (match_dup 2)))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{l}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*lshrsi3_one_bit_cconly" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{l}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*lshrsi3_cmp_one_bit_zext" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{l}\t%k0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*lshrsi3_cmp" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (lshiftrt:SI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) - -(define_insn "*lshrsi3_cconly" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "SI")]) - -(define_insn "*lshrsi3_cmp_zext" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "ishift") + {cltd|cdq} + sar{l}\t{%2, %0|%0, %2}" + [(set_attr "type" "imovx,ishift") + (set_attr "prefix_0f" "0,*") + (set_attr "length_immediate" "0,*") + (set_attr "modrm" "0,1") (set_attr "mode" "SI")]) -(define_expand "lshrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (LSHIFTRT, HImode, operands); DONE;") - -(define_insn "*lshrhi3_1_one_bit" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{w}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "HI")]) - -(define_insn "*lshrhi3_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) +(define_insn "*ashrsi3_cvt_zext" + [(set (match_operand:DI 0 "register_operand" "=*d,r") + (zero_extend:DI + (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0") + (match_operand:QI 2 "const_int_operand" "")))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "TARGET_64BIT && INTVAL (operands[2]) == 31 + && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun)) + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "@ - shr{w}\t{%2, %0|%0, %2} - shr{w}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") - (set_attr "mode" "HI")]) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*lshrhi3_one_bit_cmp" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (lshiftrt:HI (match_dup 1) (match_dup 2)))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{w}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "HI")]) + {cltd|cdq} + sar{l}\t{%2, %k0|%k0, %2}" + [(set_attr "type" "imovx,ishift") + (set_attr "prefix_0f" "0,*") + (set_attr "length_immediate" "0,*") + (set_attr "modrm" "0,1") + (set_attr "mode" "SI")]) -(define_insn "*lshrhi3_one_bit_cconly" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{w}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "HI")]) +(define_expand "x86_shift_adj_3" + [(use (match_operand:SWI48 0 "register_operand" "")) + (use (match_operand:SWI48 1 "register_operand" "")) + (use (match_operand:QI 2 "register_operand" ""))] + "" +{ + rtx label = gen_label_rtx (); + rtx tmp; -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*lshrhi3_cmp" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (lshiftrt:HI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "HI")]) + emit_insn (gen_testqi_ccz_1 (operands[2], + GEN_INT (GET_MODE_BITSIZE (mode)))); -(define_insn "*lshrhi3_cconly" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" - "shr{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "HI")]) + tmp = gen_rtx_REG (CCZmode, FLAGS_REG); + tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, + gen_rtx_LABEL_REF (VOIDmode, label), + pc_rtx); + tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); + JUMP_LABEL (tmp) = label; -(define_expand "lshrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (LSHIFTRT, QImode, operands); DONE;") + emit_move_insn (operands[0], operands[1]); + emit_insn (gen_ashr3_cvt (operands[1], operands[1], + GEN_INT (GET_MODE_BITSIZE (mode)-1))); + emit_label (label); + LABEL_NUSES (label) = 1; -(define_insn "*lshrqi3_1_one_bit" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" - "shr{b}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + DONE; +}) -(define_insn "*lshrqi3_1_one_bit_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (lshiftrt:QI (match_dup 0) - (match_operand:QI 1 "const1_operand" ""))) +(define_insn "*3_1" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=m") + (any_shiftrt:SWI (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "c"))) (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))" - "shr{b}\t%0" - [(set_attr "type" "ishift1") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + "ix86_binary_operator_ok (, mode, operands)" +{ + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{}\t%0"; + else + return "{}\t{%2, %0|%0, %2}"; +} + [(set_attr "type" "ishift") + (set (attr "length_immediate") + (if_then_else + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "")]) -(define_insn "*lshrqi3_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") - (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) +(define_insn "*si3_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (any_shiftrt:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI")))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" - "@ - shr{b}\t{%2, %0|%0, %2} - shr{b}\t{%b2, %0|%0, %b2}" + "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" +{ + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{l}\t%k0"; + else + return "{l}\t{%2, %k0|%k0, %2}"; +} [(set_attr "type" "ishift") - (set_attr "mode" "QI")]) + (set (attr "length_immediate") + (if_then_else + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "SI")]) -(define_insn "*lshrqi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm")) - (lshiftrt:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "I,c"))) +(define_insn "*qi3_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) + (any_shiftrt:QI (match_dup 0) + (match_operand:QI 1 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "@ - shr{b}\t{%1, %0|%0, %1} - shr{b}\t{%b1, %0|%0, %b1}" + "(optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_REG_STALL + || (operands[1] == const1_rtx + && TARGET_SHIFT1))" +{ + if (operands[1] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{b}\t%0"; + else + return "{b}\t{%1, %0|%0, %1}"; +} [(set_attr "type" "ishift1") + (set (attr "length_immediate") + (if_then_else + (and (match_operand 1 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) (set_attr "mode" "QI")]) ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. -(define_insn "*lshrqi2_one_bit_cmp" - [(set (reg FLAGS_REG) - (compare - (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (lshiftrt:QI (match_dup 1) (match_dup 2)))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" - "shr{b}\t%0" - [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) - -(define_insn "*lshrqi2_one_bit_cconly" +(define_insn "*3_cmp" [(set (reg FLAGS_REG) (compare - (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" "")) + (any_shiftrt:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "" "")) (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) + (set (match_operand:SWI 0 "nonimmediate_operand" "=m") + (any_shiftrt:SWI (match_dup 1) (match_dup 2)))] + "(optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && TARGET_SHIFT1)) && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" - "shr{b}\t%0" + && ix86_binary_operator_ok (, mode, operands)" +{ + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{}\t%0"; + else + return "{}\t{%2, %0|%0, %2}"; +} [(set_attr "type" "ishift") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) + (set (attr "length_immediate") + (if_then_else + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "")]) -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*lshrqi2_cmp" +(define_insn "*si3_cmp_zext" [(set (reg FLAGS_REG) (compare - (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) + (any_shiftrt:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (lshiftrt:QI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (any_shiftrt:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT + && (optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && TARGET_SHIFT1)) && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" - "shr{b}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (, SImode, operands)" +{ + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{l}\t%k0"; + else + return "{l}\t{%2, %k0|%k0, %2}"; +} [(set_attr "type" "ishift") - (set_attr "mode" "QI")]) + (set (attr "length_immediate") + (if_then_else + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "SI")]) -(define_insn "*lshrqi2_cconly" +(define_insn "*3_cconly" [(set (reg FLAGS_REG) (compare - (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) + (any_shiftrt:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "" "")) (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] - "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL) + (clobber (match_scratch:SWI 0 "="))] + "(optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && TARGET_SHIFT1)) && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" - "shr{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "ishift") - (set_attr "mode" "QI")]) - -;; Rotate instructions - -(define_expand "rotldi3" - [(set (match_operand:DI 0 "shiftdi_operand" "") - (rotate:DI (match_operand:DI 1 "shiftdi_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" + && ix86_binary_operator_ok (, mode, operands)" { - if (TARGET_64BIT) - { - ix86_expand_binary_operator (ROTATE, DImode, operands); - DONE; - } - if (!const_1_to_31_operand (operands[2], VOIDmode)) - FAIL; - emit_insn (gen_ix86_rotldi3 (operands[0], operands[1], operands[2])); - DONE; -}) - -;; Implement rotation using two double-precision shift instructions -;; and a scratch register. -(define_insn_and_split "ix86_rotldi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (rotate:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I"))) - (clobber (reg:CC FLAGS_REG)) - (clobber (match_scratch:SI 3 "=&r"))] - "!TARGET_64BIT" - "" - "&& reload_completed" - [(set (match_dup 3) (match_dup 4)) - (parallel - [(set (match_dup 4) - (ior:SI (ashift:SI (match_dup 4) (match_dup 2)) - (lshiftrt:SI (match_dup 5) - (minus:QI (const_int 32) (match_dup 2))))) - (clobber (reg:CC FLAGS_REG))]) - (parallel - [(set (match_dup 5) - (ior:SI (ashift:SI (match_dup 5) (match_dup 2)) - (lshiftrt:SI (match_dup 3) - (minus:QI (const_int 32) (match_dup 2))))) - (clobber (reg:CC FLAGS_REG))])] - "split_di (&operands[0], 1, &operands[4], &operands[5]);") - -(define_insn "*rotlsi3_1_one_bit_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATE, DImode, operands)" - "rol{q}\t%0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) - -(define_insn "*rotldi3_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") - (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "e,c"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)" - "@ - rol{q}\t{%2, %0|%0, %2} - rol{q}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "DI")]) - -(define_expand "rotlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (ROTATE, SImode, operands); DONE;") - -(define_insn "*rotlsi3_1_one_bit" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATE, SImode, operands)" - "rol{l}\t%0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*rotlsi3_1_one_bit_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (rotate:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const1_operand" "")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATE, SImode, operands)" - "rol{l}\t%k0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*rotlsi3_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") - (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ROTATE, SImode, operands)" - "@ - rol{l}\t{%2, %0|%0, %2} - rol{l}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "SI")]) - -(define_insn "*rotlsi3_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI - (rotate:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)" - "@ - rol{l}\t{%2, %k0|%k0, %2} - rol{l}\t{%b2, %k0|%k0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "SI")]) - -(define_expand "rotlhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (ROTATE, HImode, operands); DONE;") - -(define_insn "*rotlhi3_1_one_bit" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATE, HImode, operands)" - "rol{w}\t%0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "HI")]) - -(define_insn "*rotlhi3_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") - (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ROTATE, HImode, operands)" - "@ - rol{w}\t{%2, %0|%0, %2} - rol{w}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "HI")]) - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (rotate:HI (match_dup 0) (const_int 8))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(parallel [(set (strict_low_part (match_dup 0)) - (bswap:HI (match_dup 0))) - (clobber (reg:CC FLAGS_REG))])] - "") - -(define_expand "rotlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;") - -(define_insn "*rotlqi3_1_one_bit_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (rotate:QI (match_dup 0) - (match_operand:QI 1 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))" - "rol{b}\t%0" - [(set_attr "type" "rotate1") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) - -(define_insn "*rotlqi3_1_one_bit" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATE, QImode, operands)" - "rol{b}\t%0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) - -(define_insn "*rotlqi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm")) - (rotate:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "@ - rol{b}\t{%1, %0|%0, %1} - rol{b}\t{%b1, %0|%0, %b1}" - [(set_attr "type" "rotate1") - (set_attr "mode" "QI")]) + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{}\t%0"; + else + return "{}\t{%2, %0|%0, %2}"; +} + [(set_attr "type" "ishift") + (set (attr "length_immediate") + (if_then_else + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "")]) + +;; Rotate instructions -(define_insn "*rotlqi3_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") - (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ROTATE, QImode, operands)" - "@ - rol{b}\t{%2, %0|%0, %2} - rol{b}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "QI")]) +(define_expand "ti3" + [(set (match_operand:TI 0 "register_operand" "") + (any_rotate:TI (match_operand:TI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "TARGET_64BIT" +{ + if (const_1_to_63_operand (operands[2], VOIDmode)) + emit_insn (gen_ix86_ti3_doubleword + (operands[0], operands[1], operands[2])); + else + FAIL; -(define_expand "rotrdi3" + DONE; +}) + +(define_expand "di3" [(set (match_operand:DI 0 "shiftdi_operand" "") - (rotate:DI (match_operand:DI 1 "shiftdi_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] + (any_rotate:DI (match_operand:DI 1 "shiftdi_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] "" { if (TARGET_64BIT) - { - ix86_expand_binary_operator (ROTATERT, DImode, operands); - DONE; - } - if (!const_1_to_31_operand (operands[2], VOIDmode)) + ix86_expand_binary_operator (, DImode, operands); + else if (const_1_to_31_operand (operands[2], VOIDmode)) + emit_insn (gen_ix86_di3_doubleword + (operands[0], operands[1], operands[2])); + else FAIL; - emit_insn (gen_ix86_rotrdi3 (operands[0], operands[1], operands[2])); + DONE; }) -;; Implement rotation using two double-precision shift instructions -;; and a scratch register. -(define_insn_and_split "ix86_rotrdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (rotatert:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I"))) +(define_expand "3" + [(set (match_operand:SWIM124 0 "nonimmediate_operand" "") + (any_rotate:SWIM124 (match_operand:SWIM124 1 "nonimmediate_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + "ix86_expand_binary_operator (, mode, operands); DONE;") + +;; Implement rotation using two double-precision +;; shift instructions and a scratch register. + +(define_insn_and_split "ix86_rotl3_doubleword" + [(set (match_operand: 0 "register_operand" "=r") + (rotate: (match_operand: 1 "register_operand" "0") + (match_operand:QI 2 "" ""))) (clobber (reg:CC FLAGS_REG)) - (clobber (match_scratch:SI 3 "=&r"))] - "!TARGET_64BIT" + (clobber (match_scratch:DWIH 3 "=&r"))] "" - "&& reload_completed" + "#" + "reload_completed" [(set (match_dup 3) (match_dup 4)) (parallel [(set (match_dup 4) - (ior:SI (ashiftrt:SI (match_dup 4) (match_dup 2)) - (ashift:SI (match_dup 5) - (minus:QI (const_int 32) (match_dup 2))))) + (ior:DWIH (ashift:DWIH (match_dup 4) (match_dup 2)) + (lshiftrt:DWIH (match_dup 5) + (minus:QI (match_dup 6) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 5) - (ior:SI (ashiftrt:SI (match_dup 5) (match_dup 2)) - (ashift:SI (match_dup 3) - (minus:QI (const_int 32) (match_dup 2))))) + (ior:DWIH (ashift:DWIH (match_dup 5) (match_dup 2)) + (lshiftrt:DWIH (match_dup 3) + (minus:QI (match_dup 6) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))])] - "split_di (&operands[0], 1, &operands[4], &operands[5]);") +{ + operands[6] = GEN_INT (GET_MODE_BITSIZE (mode)); -(define_insn "*rotrdi3_1_one_bit_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATERT, DImode, operands)" - "ror{q}\t%0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) + split_ (&operands[0], 1, &operands[4], &operands[5]); +}) -(define_insn "*rotrdi3_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") - (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "J,c"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)" - "@ - ror{q}\t{%2, %0|%0, %2} - ror{q}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "DI")]) +(define_insn_and_split "ix86_rotr3_doubleword" + [(set (match_operand: 0 "register_operand" "=r") + (rotatert: (match_operand: 1 "register_operand" "0") + (match_operand:QI 2 "" ""))) + (clobber (reg:CC FLAGS_REG)) + (clobber (match_scratch:DWIH 3 "=&r"))] + "" + "#" + "reload_completed" + [(set (match_dup 3) (match_dup 4)) + (parallel + [(set (match_dup 4) + (ior:DWIH (ashiftrt:DWIH (match_dup 4) (match_dup 2)) + (ashift:DWIH (match_dup 5) + (minus:QI (match_dup 6) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 5) + (ior:DWIH (ashiftrt:DWIH (match_dup 5) (match_dup 2)) + (ashift:DWIH (match_dup 3) + (minus:QI (match_dup 6) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[6] = GEN_INT (GET_MODE_BITSIZE (mode)); -(define_expand "rotrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (ROTATERT, SImode, operands); DONE;") + split_ (&operands[0], 1, &operands[4], &operands[5]); +}) -(define_insn "*rotrsi3_1_one_bit" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) +(define_insn "*3_1" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=m") + (any_rotate:SWI (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "c"))) (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATERT, SImode, operands)" - "ror{l}\t%0" + "ix86_binary_operator_ok (, mode, operands)" +{ + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{}\t%0"; + else + return "{}\t{%2, %0|%0, %2}"; +} [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) + (set (attr "length_immediate") + (if_then_else + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "")]) -(define_insn "*rotrsi3_1_one_bit_zext" +(define_insn "*si3_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (rotatert:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const1_operand" "")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATERT, SImode, operands)" - "ror{l}\t%k0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*rotrsi3_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") - (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ROTATERT, SImode, operands)" - "@ - ror{l}\t{%2, %0|%0, %2} - ror{l}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "SI")]) - -(define_insn "*rotrsi3_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI - (rotatert:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c")))) + (any_rotate:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI")))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)" - "@ - ror{l}\t{%2, %k0|%k0, %2} - ror{l}\t{%b2, %k0|%k0, %b2}" + "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" +{ + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{l}\t%k0"; + else + return "{l}\t{%2, %k0|%k0, %2}"; +} [(set_attr "type" "rotate") + (set (attr "length_immediate") + (if_then_else + (and (match_operand 2 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) (set_attr "mode" "SI")]) -(define_expand "rotrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (ROTATERT, HImode, operands); DONE;") - -(define_insn "*rotrhi3_one_bit" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATERT, HImode, operands)" - "ror{w}\t%0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "HI")]) - -(define_insn "*rotrhi3_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") - (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) +(define_insn "*qi3_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) + (any_rotate:QI (match_dup 0) + (match_operand:QI 1 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ROTATERT, HImode, operands)" - "@ - ror{w}\t{%2, %0|%0, %2} - ror{w}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "HI")]) + "(optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_REG_STALL + || (operands[1] == const1_rtx + && TARGET_SHIFT1))" +{ + if (operands[1] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "{b}\t%0"; + else + return "{b}\t{%1, %0|%0, %1}"; +} + [(set_attr "type" "rotate1") + (set (attr "length_immediate") + (if_then_else + (and (match_operand 1 "const1_operand" "") + (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") + (const_int 0))) + (const_string "0") + (const_string "*"))) + (set_attr "mode" "QI")]) (define_split [(set (match_operand:HI 0 "register_operand" "") - (rotatert:HI (match_dup 0) (const_int 8))) + (any_rotate:HI (match_dup 0) (const_int 8))) (clobber (reg:CC FLAGS_REG))] - "reload_completed" + "reload_completed + && (TARGET_USE_XCHGB || optimize_function_for_size_p (cfun))" [(parallel [(set (strict_low_part (match_dup 0)) (bswap:HI (match_dup 0))) (clobber (reg:CC FLAGS_REG))])] "") - -(define_expand "rotrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (ROTATERT, QImode, operands); DONE;") - -(define_insn "*rotrqi3_1_one_bit" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ROTATERT, QImode, operands)" - "ror{b}\t%0" - [(set_attr "type" "rotate") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) - -(define_insn "*rotrqi3_1_one_bit_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (rotatert:QI (match_dup 0) - (match_operand:QI 1 "const1_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))" - "ror{b}\t%0" - [(set_attr "type" "rotate1") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) - -(define_insn "*rotrqi3_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") - (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ROTATERT, QImode, operands)" - "@ - ror{b}\t{%2, %0|%0, %2} - ror{b}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "rotate") - (set_attr "mode" "QI")]) - -(define_insn "*rotrqi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm")) - (rotatert:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "I,c"))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "@ - ror{b}\t{%1, %0|%0, %1} - ror{b}\t{%b1, %0|%0, %b1}" - [(set_attr "type" "rotate1") - (set_attr "mode" "QI")]) ;; Bit set / bit test instructions @@ -13744,33 +11008,19 @@ 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_function_for_size_p (cfun))" - "bt{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "prefix_0f" "1") - (set_attr "mode" "DI")]) - -(define_insn "*btsi" +(define_insn "*bt" [(set (reg:CCC FLAGS_REG) (compare:CCC - (zero_extract:SI - (match_operand:SI 0 "register_operand" "r") + (zero_extract:SWI48 + (match_operand:SWI48 0 "register_operand" "r") (const_int 1) - (match_operand:SI 1 "nonmemory_operand" "rN")) + (match_operand:SWI48 1 "nonmemory_operand" "rN")) (const_int 0)))] "TARGET_USE_BT || optimize_function_for_size_p (cfun)" - "bt{l}\t{%1, %0|%0, %1}" + "bt{}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "prefix_0f" "1") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) ;; Store-flag instructions. @@ -14027,16 +11277,16 @@ 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 +;; zero_extend in SImode is correct also for DImode, 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" +(define_insn_and_split "*jcc_bt" [(set (pc) (if_then_else (match_operator 0 "bt_comparison_operator" - [(zero_extract:DI - (match_operand:DI 1 "register_operand" "r") + [(zero_extract:SWI48 + (match_operand:SWI48 1 "register_operand" "r") (const_int 1) (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))) @@ -14044,12 +11294,12 @@ (label_ref (match_operand 3 "" "")) (pc))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && (TARGET_USE_BT || optimize_function_for_size_p (cfun))" + "TARGET_USE_BT || optimize_function_for_size_p (cfun)" "#" "&& 1" [(set (reg:CCC FLAGS_REG) (compare:CCC - (zero_extract:DI + (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2)) @@ -14059,17 +11309,18 @@ (label_ref (match_dup 3)) (pc)))] { - operands[2] = simplify_gen_subreg (DImode, operands[2], QImode, 0); + operands[2] = simplify_gen_subreg (mode, 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" +;; Avoid useless masking of bit offset operand. "and" in SImode is correct +;; also for DImode, this is what combine produces. +(define_insn_and_split "*jcc_bt_mask" [(set (pc) (if_then_else (match_operator 0 "bt_comparison_operator" - [(zero_extract:DI - (match_operand:DI 1 "register_operand" "r") + [(zero_extract:SWI48 + (match_operand:SWI48 1 "register_operand" "r") (const_int 1) (and:SI (match_operand:SI 2 "register_operand" "r") @@ -14077,13 +11328,14 @@ (label_ref (match_operand 4 "" "")) (pc))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && (TARGET_USE_BT || optimize_function_for_size_p (cfun)) - && (INTVAL (operands[3]) & 0x3f) == 0x3f" + "(TARGET_USE_BT || optimize_function_for_size_p (cfun)) + && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (mode)-1)) + == GET_MODE_BITSIZE (mode)-1" "#" "&& 1" [(set (reg:CCC FLAGS_REG) (compare:CCC - (zero_extract:DI + (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2)) @@ -14093,73 +11345,11 @@ (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))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_USE_BT || optimize_function_for_size_p (cfun)" - "#" - "&& 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); + operands[2] = simplify_gen_subreg (mode, operands[2], SImode, 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))) - (clobber (reg:CC FLAGS_REG))] - "(TARGET_USE_BT || optimize_function_for_size_p (cfun)) - && (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" @@ -14385,6 +11575,7 @@ [(const_int 0)] { operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]); + ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])), operands[3], operands[7], operands[4], operands[5], operands[6], NULL_RTX); @@ -14408,6 +11599,7 @@ { operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]); operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]); + ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])), operands[3], operands[7], operands[4], operands[5], operands[6], operands[2]); @@ -14538,6 +11730,10 @@ ;; checked for calls. This is a bug in the generic code, but it isn't that ;; easy to fix. Ignore it for now and be prepared to fix things up. +;; P6 processors will jump to the address after the decrement when %esp +;; is used as a call operand, so they will execute return address as a code. +;; See Pentium Pro errata 70, Pentium 2 errata A33 and Pentium 3 errata E17. + ;; Call subroutine returning no value. (define_expand "call_pop" @@ -14548,15 +11744,17 @@ (match_operand:SI 3 "" "")))])] "!TARGET_64BIT" { - ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3], 0); + ix86_expand_call (NULL, operands[0], operands[1], + operands[2], operands[3], 0); DONE; }) (define_insn "*call_pop_0" [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" "")) (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "")))] + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 2 "immediate_operand" "")))] "!TARGET_64BIT" { if (SIBLING_CALL_P (insn)) @@ -14567,11 +11765,12 @@ [(set_attr "type" "call")]) (define_insn "*call_pop_1" - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm")) + [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "i")))] - "!SIBLING_CALL_P (insn) && !TARGET_64BIT" + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 2 "immediate_operand" "i")))] + "!TARGET_64BIT && !SIBLING_CALL_P (insn)" { if (constant_call_address_operand (operands[0], Pmode)) return "call\t%P0"; @@ -14582,9 +11781,10 @@ (define_insn "*sibcall_pop_1" [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "i,i")))] - "SIBLING_CALL_P (insn) && !TARGET_64BIT" + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 2 "immediate_operand" "i,i")))] + "!TARGET_64BIT && SIBLING_CALL_P (insn)" "@ jmp\t%P0 jmp\t%A0" @@ -14623,9 +11823,9 @@ [(set_attr "type" "call")]) (define_insn "*call_1" - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm")) + [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm")) (match_operand 1 "" ""))] - "!SIBLING_CALL_P (insn) && !TARGET_64BIT" + "!TARGET_64BIT && !SIBLING_CALL_P (insn)" { if (constant_call_address_operand (operands[0], Pmode)) return "call\t%P0"; @@ -14636,7 +11836,7 @@ (define_insn "*sibcall_1" [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U")) (match_operand 1 "" ""))] - "SIBLING_CALL_P (insn) && !TARGET_64BIT" + "!TARGET_64BIT && SIBLING_CALL_P (insn)" "@ jmp\t%P0 jmp\t%A0" @@ -14645,7 +11845,7 @@ (define_insn "*call_1_rex64" [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) (match_operand 1 "" ""))] - "!SIBLING_CALL_P (insn) && TARGET_64BIT + "TARGET_64BIT && !SIBLING_CALL_P (insn) && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" { if (constant_call_address_operand (operands[0], Pmode)) @@ -14670,7 +11870,7 @@ (clobber (reg:TI XMM15_REG)) (clobber (reg:DI SI_REG)) (clobber (reg:DI DI_REG))] - "!SIBLING_CALL_P (insn) && TARGET_64BIT" + "TARGET_64BIT && !SIBLING_CALL_P (insn)" { if (constant_call_address_operand (operands[0], Pmode)) return "call\t%P0"; @@ -14681,14 +11881,14 @@ (define_insn "*call_1_rex64_large" [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm")) (match_operand 1 "" ""))] - "!SIBLING_CALL_P (insn) && TARGET_64BIT" + "TARGET_64BIT && !SIBLING_CALL_P (insn)" "call\t%A0" [(set_attr "type" "call")]) (define_insn "*sibcall_1_rex64" [(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U")) (match_operand 1 "" ""))] - "SIBLING_CALL_P (insn) && TARGET_64BIT" + "TARGET_64BIT && SIBLING_CALL_P (insn)" "@ jmp\t%P0 jmp\t%A0" @@ -14714,10 +11914,11 @@ (call (match_operand:QI 1 "" "") (match_operand:SI 2 "" ""))) (use (match_operand:SI 3 "" ""))] - ;; Operand 2 not used on the i386. + ;; Operand 3 is not used on the i386. "" { - ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 0); + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], NULL, 0); DONE; }) @@ -14726,10 +11927,11 @@ (call (match_operand:QI 1 "" "") (match_operand:SI 2 "" ""))) (use (match_operand:SI 3 "" ""))] - ;; Operand 2 not used on the i386. + ;; Operand 3 is not used on the i386. "" { - ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 1); + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], NULL, 1); DONE; }) @@ -15017,38 +12219,33 @@ "leave" [(set_attr "type" "leave")]) -(define_expand "ffssi2" - [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (ffs:SI (match_operand:SI 1 "nonimmediate_operand" ""))) - (clobber (match_scratch:SI 2 "")) - (clobber (reg:CC FLAGS_REG))])] - "" -{ - if (TARGET_CMOVE) - { - emit_insn (gen_ffs_cmove (operands[0], operands[1])); - DONE; - } -}) +;; Bit manipulation instructions. -(define_expand "ffs_cmove" +(define_expand "ffs2" [(set (match_dup 2) (const_int -1)) (parallel [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "") - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "") - (ctz:SI (match_dup 1)))]) - (set (match_dup 0) (if_then_else:SI + (compare:CCZ + (match_operand:SWI48 1 "nonimmediate_operand" "") + (const_int 0))) + (set (match_operand:SWI48 0 "register_operand" "") + (ctz:SWI48 (match_dup 1)))]) + (set (match_dup 0) (if_then_else:SWI48 (eq (reg:CCZ FLAGS_REG) (const_int 0)) (match_dup 2) (match_dup 0))) - (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))) + (parallel [(set (match_dup 0) (plus:SWI48 (match_dup 0) (const_int 1))) (clobber (reg:CC FLAGS_REG))])] - "TARGET_CMOVE" - "operands[2] = gen_reg_rtx (SImode);") + "" +{ + if (mode == SImode && !TARGET_CMOVE) + { + emit_insn (gen_ffssi2_no_cmove (operands[0], operands [1])); + DONE; + } + operands[2] = gen_reg_rtx (mode); +}) -(define_insn_and_split "*ffs_no_cmove" +(define_insn_and_split "ffssi2_no_cmove" [(set (match_operand:SI 0 "register_operand" "=r") (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) (clobber (match_scratch:SI 2 "=&q")) @@ -15072,93 +12269,68 @@ ix86_expand_clear (operands[2]); }) -(define_insn "*ffssi_1" +(define_insn "*ffs_1" [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm") + (compare:CCZ (match_operand:SWI48 1 "nonimmediate_operand" "rm") (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (ctz:SI (match_dup 1)))] + (set (match_operand:SWI48 0 "register_operand" "=r") + (ctz:SWI48 (match_dup 1)))] "" - "bsf{l}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "prefix_0f" "1") - (set_attr "mode" "SI")]) - -(define_expand "ffsdi2" - [(set (match_dup 2) (const_int -1)) - (parallel [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "") - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "") - (ctz:DI (match_dup 1)))]) - (set (match_dup 0) (if_then_else:DI - (eq (reg:CCZ FLAGS_REG) (const_int 0)) - (match_dup 2) - (match_dup 0))) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_64BIT" - "operands[2] = gen_reg_rtx (DImode);") - -(define_insn "*ffsdi_1" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "rm") - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (ctz:DI (match_dup 1)))] - "TARGET_64BIT" - "bsf{q}\t{%1, %0|%0, %1}" + "bsf{}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "prefix_0f" "1") - (set_attr "mode" "DI")]) + (set_attr "mode" "")]) -(define_insn "ctzsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (ctz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) +(define_insn "ctz2" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (ctz:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "rm"))) (clobber (reg:CC FLAGS_REG))] "" - "bsf{l}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "prefix_0f" "1") - (set_attr "mode" "SI")]) - -(define_insn "ctzdi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (ctz:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "bsf{q}\t{%1, %0|%0, %1}" + "bsf{}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "prefix_0f" "1") - (set_attr "mode" "DI")]) + (set_attr "mode" "")]) -(define_expand "clzsi2" +(define_expand "clz2" [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (const_int 31) - (clz:SI (match_operand:SI 1 "nonimmediate_operand" "")))) + [(set (match_operand:SWI248 0 "register_operand" "") + (minus:SWI248 + (match_dup 2) + (clz:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "")))) (clobber (reg:CC FLAGS_REG))]) (parallel - [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 31))) + [(set (match_dup 0) (xor:SWI248 (match_dup 0) (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] "" { if (TARGET_ABM) { - emit_insn (gen_clzsi2_abm (operands[0], operands[1])); + emit_insn (gen_clz2_abm (operands[0], operands[1])); DONE; } + operands[2] = GEN_INT (GET_MODE_BITSIZE (mode)-1); }) -(define_insn "clzsi2_abm" - [(set (match_operand:SI 0 "register_operand" "=r") - (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) +(define_insn "clz2_abm" + [(set (match_operand:SWI248 0 "register_operand" "=r") + (clz:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "rm"))) (clobber (reg:CC FLAGS_REG))] "TARGET_ABM" - "lzcnt{l}\t{%1, %0|%0, %1}" + "lzcnt{}\t{%1, %0|%0, %1}" [(set_attr "prefix_rep" "1") (set_attr "type" "bitmanip") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) + +(define_insn "bsr_rex64" + [(set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (const_int 63) + (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "bsr{q}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI")]) (define_insn "bsr" [(set (match_operand:SI 0 "register_operand" "=r") @@ -15171,6 +12343,17 @@ (set_attr "prefix_0f" "1") (set_attr "mode" "SI")]) +(define_insn "*bsrhi" + [(set (match_operand:HI 0 "register_operand" "=r") + (minus:HI (const_int 15) + (clz:HI (match_operand:HI 1 "nonimmediate_operand" "rm")))) + (clobber (reg:CC FLAGS_REG))] + "" + "bsr{w}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "HI")]) + (define_insn "popcount2" [(set (match_operand:SWI248 0 "register_operand" "=r") (popcount:SWI248 @@ -15220,19 +12403,19 @@ #if TARGET_MACHO return "popcnt\t{%1, %0|%0, %1}"; #else - return "popcnt{}\t{%1, %0|%0, %1}"; + return "popcnt{l}\t{%1, %0|%0, %1}"; #endif } [(set_attr "prefix_rep" "1") (set_attr "type" "bitmanip") (set_attr "mode" "SI")]) -(define_expand "bswapsi2" - [(set (match_operand:SI 0 "register_operand" "") - (bswap:SI (match_operand:SI 1 "register_operand" "")))] +(define_expand "bswap2" + [(set (match_operand:SWI48 0 "register_operand" "") + (bswap:SWI48 (match_operand:SWI48 1 "register_operand" "")))] "" { - if (!(TARGET_BSWAP || TARGET_MOVBE)) + if (mode == SImode && !(TARGET_BSWAP || TARGET_MOVBE)) { rtx x = operands[0]; @@ -15244,28 +12427,29 @@ } }) -(define_insn "*bswapsi_movbe" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m") - (bswap:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,r")))] - "TARGET_MOVBE && !(MEM_P (operands[0]) && MEM_P (operands[1]))" +(define_insn "*bswap2_movbe" + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,r,m") + (bswap:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,m,r")))] + "TARGET_MOVBE + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "@ bswap\t%0 movbe\t{%1, %0|%0, %1} movbe\t{%1, %0|%0, %1}" - [(set_attr "type" "*,imov,imov") - (set_attr "modrm" "*,1,1") - (set_attr "prefix_0f" "1") + [(set_attr "type" "bitmanip,imov,imov") + (set_attr "modrm" "0,1,1") + (set_attr "prefix_0f" "*,1,1") (set_attr "prefix_extra" "*,1,1") - (set_attr "length" "2,*,*") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) -(define_insn "*bswapsi_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (bswap:SI (match_operand:SI 1 "register_operand" "0")))] +(define_insn "*bswap2_1" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (bswap:SWI48 (match_operand:SWI48 1 "register_operand" "0")))] "TARGET_BSWAP" "bswap\t%0" - [(set_attr "prefix_0f" "1") - (set_attr "length" "2")]) + [(set_attr "type" "bitmanip") + (set_attr "modrm" "0") + (set_attr "mode" "")]) (define_insn "*bswaphi_lowpart_1" [(set (strict_low_part (match_operand:HI 0 "register_operand" "+Q,r")) @@ -15287,114 +12471,6 @@ [(set_attr "length" "4") (set_attr "mode" "HI")]) -(define_expand "bswapdi2" - [(set (match_operand:DI 0 "register_operand" "") - (bswap:DI (match_operand:DI 1 "register_operand" "")))] - "TARGET_64BIT" - "") - -(define_insn "*bswapdi_movbe" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m") - (bswap:DI (match_operand:DI 1 "nonimmediate_operand" "0,m,r")))] - "TARGET_64BIT && TARGET_MOVBE - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "@ - bswap\t%0 - movbe\t{%1, %0|%0, %1} - movbe\t{%1, %0|%0, %1}" - [(set_attr "type" "*,imov,imov") - (set_attr "modrm" "*,1,1") - (set_attr "prefix_0f" "1") - (set_attr "prefix_extra" "*,1,1") - (set_attr "length" "3,*,*") - (set_attr "mode" "DI")]) - -(define_insn "*bswapdi_1" - [(set (match_operand:DI 0 "register_operand" "=r") - (bswap:DI (match_operand:DI 1 "register_operand" "0")))] - "TARGET_64BIT" - "bswap\t%0" - [(set_attr "prefix_0f" "1") - (set_attr "length" "3")]) - -(define_expand "clzdi2" - [(parallel - [(set (match_operand:DI 0 "register_operand" "") - (minus:DI (const_int 63) - (clz:DI (match_operand:DI 1 "nonimmediate_operand" "")))) - (clobber (reg:CC FLAGS_REG))]) - (parallel - [(set (match_dup 0) (xor:DI (match_dup 0) (const_int 63))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_64BIT" -{ - if (TARGET_ABM) - { - emit_insn (gen_clzdi2_abm (operands[0], operands[1])); - DONE; - } -}) - -(define_insn "clzdi2_abm" - [(set (match_operand:DI 0 "register_operand" "=r") - (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && TARGET_ABM" - "lzcnt{q}\t{%1, %0|%0, %1}" - [(set_attr "prefix_rep" "1") - (set_attr "type" "bitmanip") - (set_attr "mode" "DI")]) - -(define_insn "bsr_rex64" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (const_int 63) - (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "bsr{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "prefix_0f" "1") - (set_attr "mode" "DI")]) - -(define_expand "clzhi2" - [(parallel - [(set (match_operand:HI 0 "register_operand" "") - (minus:HI (const_int 15) - (clz:HI (match_operand:HI 1 "nonimmediate_operand" "")))) - (clobber (reg:CC FLAGS_REG))]) - (parallel - [(set (match_dup 0) (xor:HI (match_dup 0) (const_int 15))) - (clobber (reg:CC FLAGS_REG))])] - "" -{ - if (TARGET_ABM) - { - emit_insn (gen_clzhi2_abm (operands[0], operands[1])); - DONE; - } -}) - -(define_insn "clzhi2_abm" - [(set (match_operand:HI 0 "register_operand" "=r") - (clz:HI (match_operand:HI 1 "nonimmediate_operand" "rm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_ABM" - "lzcnt{w}\t{%1, %0|%0, %1}" - [(set_attr "prefix_rep" "1") - (set_attr "type" "bitmanip") - (set_attr "mode" "HI")]) - -(define_insn "*bsrhi" - [(set (match_operand:HI 0 "register_operand" "=r") - (minus:HI (const_int 15) - (clz:HI (match_operand:HI 1 "nonimmediate_operand" "rm")))) - (clobber (reg:CC FLAGS_REG))] - "" - "bsr{w}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "prefix_0f" "1") - (set_attr "mode" "HI")]) - (define_expand "paritydi2" [(set (match_operand:DI 0 "register_operand" "") (parity:DI (match_operand:DI 1 "register_operand" "")))] @@ -15423,6 +12499,25 @@ DONE; }) +(define_expand "paritysi2" + [(set (match_operand:SI 0 "register_operand" "") + (parity:SI (match_operand:SI 1 "register_operand" "")))] + "! TARGET_POPCNT" +{ + rtx scratch = gen_reg_rtx (QImode); + rtx cond; + + emit_insn (gen_paritysi2_cmp (NULL_RTX, NULL_RTX, operands[1])); + + cond = gen_rtx_fmt_ee (ORDERED, QImode, + gen_rtx_REG (CCmode, FLAGS_REG), + const0_rtx); + emit_insn (gen_rtx_SET (VOIDmode, scratch, cond)); + + emit_insn (gen_zero_extendqisi2 (operands[0], scratch)); + DONE; +}) + (define_insn_and_split "paritydi2_cmp" [(set (reg:CC FLAGS_REG) (parity:CC (match_operand:DI 3 "register_operand" "0"))) @@ -15453,25 +12548,6 @@ operands[1] = gen_highpart (SImode, operands[3]); }) -(define_expand "paritysi2" - [(set (match_operand:SI 0 "register_operand" "") - (parity:SI (match_operand:SI 1 "register_operand" "")))] - "! TARGET_POPCNT" -{ - rtx scratch = gen_reg_rtx (QImode); - rtx cond; - - emit_insn (gen_paritysi2_cmp (NULL_RTX, NULL_RTX, operands[1])); - - cond = gen_rtx_fmt_ee (ORDERED, QImode, - gen_rtx_REG (CCmode, FLAGS_REG), - const0_rtx); - emit_insn (gen_rtx_SET (VOIDmode, scratch, cond)); - - emit_insn (gen_zero_extendqisi2 (operands[0], scratch)); - DONE; -}) - (define_insn_and_split "paritysi2_cmp" [(set (reg:CC FLAGS_REG) (parity:CC (match_operand:SI 2 "register_operand" "0"))) @@ -15527,25 +12603,10 @@ (clobber (match_scratch:SI 5 "=c")) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_GNU_TLS" - "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3" + "lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}\;call\t%P3" [(set_attr "type" "multi") (set_attr "length" "12")]) -(define_insn "*tls_global_dynamic_32_sun" - [(set (match_operand:SI 0 "register_operand" "=a") - (unspec:SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "tls_symbolic_operand" "") - (match_operand:SI 3 "call_insn_operand" "")] - UNSPEC_TLS_GD)) - (clobber (match_scratch:SI 4 "=d")) - (clobber (match_scratch:SI 5 "=c")) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && TARGET_SUN_TLS" - "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]} - push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop" - [(set_attr "type" "multi") - (set_attr "length" "14")]) - (define_expand "tls_global_dynamic_32" [(parallel [(set (match_operand:SI 0 "register_operand" "") (unspec:SI @@ -15581,7 +12642,7 @@ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)] "TARGET_64BIT" - { return ASM_BYTE "0x66\n\tlea{q}\t{%a1@TLSGD(%%rip), %%rdi|rdi, %a1@TLSGD[rip]}\n" ASM_SHORT "0x6666\n\trex64\n\tcall\t%P2"; } + { return ASM_BYTE "0x66\n\tlea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}\n" ASM_SHORT "0x6666\n\trex64\n\tcall\t%P2"; } [(set_attr "type" "multi") (set_attr "length" "16")]) @@ -15610,24 +12671,10 @@ (clobber (match_scratch:SI 4 "=c")) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_GNU_TLS" - "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2" + "lea{l}\t{%&@tlsldm(%1), %0|%0, %&@tlsldm[%1]}\;call\t%P2" [(set_attr "type" "multi") (set_attr "length" "11")]) -(define_insn "*tls_local_dynamic_base_32_sun" - [(set (match_operand:SI 0 "register_operand" "=a") - (unspec:SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "call_insn_operand" "")] - UNSPEC_TLS_LD_BASE)) - (clobber (match_scratch:SI 3 "=d")) - (clobber (match_scratch:SI 4 "=c")) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && TARGET_SUN_TLS" - "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]} - push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3" - [(set_attr "type" "multi") - (set_attr "length" "13")]) - (define_expand "tls_local_dynamic_base_32" [(parallel [(set (match_operand:SI 0 "register_operand" "") (unspec:SI [(match_dup 1) (match_dup 2)] @@ -15659,7 +12706,7 @@ (match_operand:DI 2 "" ""))) (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)] "TARGET_64BIT" - "lea{q}\t{%&@TLSLD(%%rip), %%rdi|rdi, %&@TLSLD[rip]}\;call\t%P1" + "lea{q}\t{%&@tlsld(%%rip), %%rdi|rdi, %&@tlsld[rip]}\;call\t%P1" [(set_attr "type" "multi") (set_attr "length" "12")]) @@ -19192,10 +16239,13 @@ } else { + rtx (*cmp_insn)(rtx, rtx); + if (TARGET_64BIT) - emit_insn (gen_cmpdi_1_rex64 (countreg, countreg)); + cmp_insn = gen_cmpdi_1; else - emit_insn (gen_cmpsi_1 (countreg, countreg)); + cmp_insn = gen_cmpsi_1; + emit_insn (cmp_insn (countreg, countreg)); emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align, operands[1], operands[2])); } @@ -19482,9 +16532,23 @@ ;; the register first winds up with `sbbl $0,reg', which is also weird. ;; So just document what we're doing explicitly. -(define_insn "x86_movcc_0_m1" +(define_expand "x86_movcc_0_m1" + [(parallel + [(set (match_operand:SWI48 0 "register_operand" "") + (if_then_else:SWI48 + (match_operator:SWI48 2 "ix86_carry_flag_operator" + [(match_operand 1 "flags_reg_operand" "") + (const_int 0)]) + (const_int -1) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))])] + "" + "") + +(define_insn "*x86_movcc_0_m1" [(set (match_operand:SWI48 0 "register_operand" "=r") - (if_then_else:SWI48 (match_operand 1 "ix86_carry_flag_operator" "") + (if_then_else:SWI48 (match_operator 1 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)]) (const_int -1) (const_int 0))) (clobber (reg:CC FLAGS_REG))] @@ -19502,7 +16566,8 @@ (define_insn "*x86_movcc_0_m1_se" [(set (match_operand:SWI48 0 "register_operand" "=r") - (sign_extract:SWI48 (match_operand 1 "ix86_carry_flag_operator" "") + (sign_extract:SWI48 (match_operator 1 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)]) (const_int 1) (const_int 0))) (clobber (reg:CC FLAGS_REG))] @@ -19518,7 +16583,8 @@ (define_insn "*x86_movcc_0_m1_neg" [(set (match_operand:SWI48 0 "register_operand" "=r") - (neg:SWI48 (match_operand 1 "ix86_carry_flag_operator" "")))] + (neg:SWI48 (match_operator 1 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)])))] "" "sbb{}\t%0, %0" [(set_attr "type" "alu") @@ -19636,8 +16702,10 @@ (if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)]) (match_dup 7) (match_dup 8)))] - "split_di (&operands[2], 2, &operands[5], &operands[7]); - split_di (&operands[0], 1, &operands[2], &operands[3]);") +{ + 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") @@ -19652,6 +16720,20 @@ [(set_attr "type" "fcmov") (set_attr "mode" "XF")]) +;; All moves in XOP pcmov instructions are 128 bits and hence we restrict +;; the scalar versions to have only XMM registers as operands. + +;; XOP conditional move +(define_insn "*xop_pcmov_" + [(set (match_operand:MODEF 0 "register_operand" "=x") + (if_then_else:MODEF + (match_operand:MODEF 1 "register_operand" "x") + (match_operand:MODEF 2 "register_operand" "x") + (match_operand:MODEF 3 "register_operand" "x")))] + "TARGET_XOP" + "vpcmov\t{%1, %3, %2, %0|%0, %2, %3, %1}" + [(set_attr "type" "sse4arg")]) + ;; These versions of the min/max patterns are intentionally ignorant of ;; their behavior wrt -0.0 and NaN (via the commutative operand mark). ;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator @@ -19663,7 +16745,7 @@ (match_operand:MODEF 1 "nonimmediate_operand" "%x") (match_operand:MODEF 2 "nonimmediate_operand" "xm")))] "AVX_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "vs\t{%2, %1, %0|%0, %1, %2}" + "vs\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "sseadd") (set_attr "prefix" "vex") (set_attr "mode" "")]) @@ -19674,7 +16756,7 @@ (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}" + "s\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") (set_attr "mode" "")]) @@ -19961,6 +17043,18 @@ DONE; }) +;; Use IOR for stack probes, this is shorter. +(define_expand "probe_stack" + [(match_operand 0 "memory_operand" "")] + "" +{ + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_iordi3 (operands[0], operands[0], const0_rtx)); + else + emit_insn (gen_iorsi3 (operands[0], operands[0], const0_rtx)); + DONE; +}) + (define_expand "builtin_setjmp_receiver" [(label_ref (match_operand 0 "" ""))] "!TARGET_64BIT && flag_pic" @@ -20464,7 +17558,9 @@ [(match_dup 0) (match_operand:SI 1 "nonmemory_operand" "")])) (clobber (reg:CC FLAGS_REG))])] - "optimize_insn_for_speed_p () && ! TARGET_READ_MODIFY_WRITE" + "optimize_insn_for_speed_p () && ! TARGET_READ_MODIFY_WRITE + /* Do not split stack checking probes. */ + && GET_CODE (operands[3]) != IOR && operands[1] != const0_rtx" [(set (match_dup 2) (match_dup 0)) (parallel [(set (match_dup 2) (match_op_dup 3 [(match_dup 2) (match_dup 1)])) @@ -20479,7 +17575,9 @@ [(match_operand:SI 1 "nonmemory_operand" "") (match_dup 0)])) (clobber (reg:CC FLAGS_REG))])] - "optimize_insn_for_speed_p () && ! TARGET_READ_MODIFY_WRITE" + "optimize_insn_for_speed_p () && ! TARGET_READ_MODIFY_WRITE + /* Do not split stack checking probes. */ + && GET_CODE (operands[3]) != IOR && operands[1] != const0_rtx" [(set (match_dup 2) (match_dup 0)) (parallel [(set (match_dup 2) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) @@ -21073,8 +18171,9 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "")))] + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "")))] "!TARGET_64BIT" { if (SIBLING_CALL_P (insn)) @@ -21086,11 +18185,12 @@ (define_insn "*call_value_pop_1" [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm")) + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i")))] - "!SIBLING_CALL_P (insn) && !TARGET_64BIT" + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i")))] + "!TARGET_64BIT && !SIBLING_CALL_P (insn)" { if (constant_call_address_operand (operands[1], Pmode)) return "call\t%P1"; @@ -21102,9 +18202,10 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i,i")))] - "SIBLING_CALL_P (insn) && !TARGET_64BIT" + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i,i")))] + "!TARGET_64BIT && SIBLING_CALL_P (insn)" "@ jmp\t%P1 jmp\t%A1" @@ -21153,7 +18254,7 @@ (clobber (reg:TI XMM15_REG)) (clobber (reg:DI SI_REG)) (clobber (reg:DI DI_REG))] - "!SIBLING_CALL_P (insn) && TARGET_64BIT" + "TARGET_64BIT && !SIBLING_CALL_P (insn)" { if (SIBLING_CALL_P (insn)) return "jmp\t%P1"; @@ -21164,9 +18265,9 @@ (define_insn "*call_value_1" [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm")) + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) (match_operand:SI 2 "" "")))] - "!SIBLING_CALL_P (insn) && !TARGET_64BIT" + "!TARGET_64BIT && !SIBLING_CALL_P (insn)" { if (constant_call_address_operand (operands[1], Pmode)) return "call\t%P1"; @@ -21178,7 +18279,7 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U")) (match_operand:SI 2 "" "")))] - "SIBLING_CALL_P (insn) && !TARGET_64BIT" + "!TARGET_64BIT && SIBLING_CALL_P (insn)" "@ jmp\t%P1 jmp\t%A1" @@ -21188,7 +18289,7 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) (match_operand:DI 2 "" "")))] - "!SIBLING_CALL_P (insn) && TARGET_64BIT + "TARGET_64BIT && !SIBLING_CALL_P (insn) && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC" { if (constant_call_address_operand (operands[1], Pmode)) @@ -21202,19 +18303,19 @@ (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) (match_operand:DI 2 "" ""))) (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI 27)) - (clobber (reg:TI 28)) - (clobber (reg:TI 45)) - (clobber (reg:TI 46)) - (clobber (reg:TI 47)) - (clobber (reg:TI 48)) - (clobber (reg:TI 49)) - (clobber (reg:TI 50)) - (clobber (reg:TI 51)) - (clobber (reg:TI 52)) + (clobber (reg:TI XMM6_REG)) + (clobber (reg:TI XMM7_REG)) + (clobber (reg:TI XMM8_REG)) + (clobber (reg:TI XMM9_REG)) + (clobber (reg:TI XMM10_REG)) + (clobber (reg:TI XMM11_REG)) + (clobber (reg:TI XMM12_REG)) + (clobber (reg:TI XMM13_REG)) + (clobber (reg:TI XMM14_REG)) + (clobber (reg:TI XMM15_REG)) (clobber (reg:DI SI_REG)) (clobber (reg:DI DI_REG))] - "!SIBLING_CALL_P (insn) && TARGET_64BIT" + "TARGET_64BIT && !SIBLING_CALL_P (insn)" { if (constant_call_address_operand (operands[1], Pmode)) return "call\t%P1"; @@ -21226,7 +18327,7 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm")) (match_operand:DI 2 "" "")))] - "!SIBLING_CALL_P (insn) && TARGET_64BIT" + "TARGET_64BIT && !SIBLING_CALL_P (insn)" "call\t%A1" [(set_attr "type" "callv")]) @@ -21234,7 +18335,7 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U")) (match_operand:DI 2 "" "")))] - "SIBLING_CALL_P (insn) && TARGET_64BIT" + "TARGET_64BIT && SIBLING_CALL_P (insn)" "@ jmp\t%P1 jmp\t%A1" @@ -21253,34 +18354,135 @@ (define_expand "sse_prologue_save" [(parallel [(set (match_operand:BLK 0 "" "") - (unspec:BLK [(reg:DI 21) - (reg:DI 22) - (reg:DI 23) - (reg:DI 24) - (reg:DI 25) - (reg:DI 26) - (reg:DI 27) - (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE)) - (use (match_operand:DI 1 "register_operand" "")) + (unspec:BLK [(reg:DI XMM0_REG) + (reg:DI XMM1_REG) + (reg:DI XMM2_REG) + (reg:DI XMM3_REG) + (reg:DI XMM4_REG) + (reg:DI XMM5_REG) + (reg:DI XMM6_REG) + (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE)) + (clobber (reg:CC FLAGS_REG)) + (clobber (match_operand:DI 1 "register_operand" "")) (use (match_operand:DI 2 "immediate_operand" "")) - (use (label_ref:DI (match_operand 3 "" "")))])] + (use (label_ref:DI (match_operand 3 "" ""))) + (clobber (match_operand:DI 4 "register_operand" "")) + (use (match_dup 1))])] "TARGET_64BIT" "") -(define_insn "*sse_prologue_save_insn" +;; Pre-reload version of prologue save. Until after prologue generation we don't know +;; what the size of save instruction will be. +;; Operand 0+operand 6 is the memory save area +;; Operand 1 is number of registers to save (will get overwritten to operand 5) +;; Operand 2 is number of non-vaargs SSE arguments +;; Operand 3 is label starting the save block +;; Operand 4 is used for temporary computation of jump address +(define_insn "*sse_prologue_save_insn1" + [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R") + (match_operand:DI 6 "const_int_operand" "n"))) + (unspec:BLK [(reg:DI XMM0_REG) + (reg:DI XMM1_REG) + (reg:DI XMM2_REG) + (reg:DI XMM3_REG) + (reg:DI XMM4_REG) + (reg:DI XMM5_REG) + (reg:DI XMM6_REG) + (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE)) + (clobber (reg:CC FLAGS_REG)) + (clobber (match_operand:DI 1 "register_operand" "=r")) + (use (match_operand:DI 2 "const_int_operand" "i")) + (use (label_ref:DI (match_operand 3 "" "X"))) + (clobber (match_operand:DI 4 "register_operand" "=&r")) + (use (match_operand:DI 5 "register_operand" "1"))] + "TARGET_64BIT + && INTVAL (operands[6]) + X86_64_SSE_REGPARM_MAX * 16 - 16 < 128 + && INTVAL (operands[6]) + INTVAL (operands[2]) * 16 >= -128" + "#" + [(set_attr "type" "other") + (set_attr "memory" "store") + (set_attr "mode" "DI")]) + +;; We know size of save instruction; expand the computation of jump address +;; in the jumptable. +(define_split + [(parallel [(set (match_operand:BLK 0 "" "") + (unspec:BLK [(reg:DI XMM0_REG) + (reg:DI XMM1_REG) + (reg:DI XMM2_REG) + (reg:DI XMM3_REG) + (reg:DI XMM4_REG) + (reg:DI XMM5_REG) + (reg:DI XMM6_REG) + (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE)) + (clobber (reg:CC FLAGS_REG)) + (clobber (match_operand:DI 1 "register_operand" "")) + (use (match_operand:DI 2 "const_int_operand" "")) + (use (match_operand 3 "" "")) + (clobber (match_operand:DI 4 "register_operand" "")) + (use (match_operand:DI 5 "register_operand" ""))])] + "reload_completed" + [(parallel [(set (match_dup 0) + (unspec:BLK [(reg:DI XMM0_REG) + (reg:DI XMM1_REG) + (reg:DI XMM2_REG) + (reg:DI XMM3_REG) + (reg:DI XMM4_REG) + (reg:DI XMM5_REG) + (reg:DI XMM6_REG) + (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE_LOW)) + (use (match_dup 1)) + (use (match_dup 2)) + (use (match_dup 3)) + (use (match_dup 5))])] +{ + /* Movaps is 4 bytes, AVX and movsd is 5 bytes. */ + int size = 4 + (TARGET_AVX || crtl->stack_alignment_needed < 128); + + /* Compute address to jump to: + label - eax*size + nnamed_sse_arguments*size. */ + if (size == 5) + emit_insn (gen_rtx_SET (VOIDmode, operands[4], + gen_rtx_PLUS + (Pmode, + gen_rtx_MULT (Pmode, operands[1], + GEN_INT (4)), + operands[1]))); + else if (size == 4) + emit_insn (gen_rtx_SET (VOIDmode, operands[4], + gen_rtx_MULT (Pmode, operands[1], + GEN_INT (4)))); + else + gcc_unreachable (); + if (INTVAL (operands[2])) + emit_move_insn + (operands[1], + gen_rtx_CONST (DImode, + gen_rtx_PLUS (DImode, + operands[3], + GEN_INT (INTVAL (operands[2]) + * size)))); + else + emit_move_insn (operands[1], operands[3]); + emit_insn (gen_subdi3 (operands[1], operands[1], operands[4])); + operands[5] = GEN_INT (size); +}) + +(define_insn "sse_prologue_save_insn" [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R") (match_operand:DI 4 "const_int_operand" "n"))) - (unspec:BLK [(reg:DI 21) - (reg:DI 22) - (reg:DI 23) - (reg:DI 24) - (reg:DI 25) - (reg:DI 26) - (reg:DI 27) - (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE)) + (unspec:BLK [(reg:DI XMM0_REG) + (reg:DI XMM1_REG) + (reg:DI XMM2_REG) + (reg:DI XMM3_REG) + (reg:DI XMM4_REG) + (reg:DI XMM5_REG) + (reg:DI XMM6_REG) + (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE_LOW)) (use (match_operand:DI 1 "register_operand" "r")) (use (match_operand:DI 2 "const_int_operand" "i")) - (use (label_ref:DI (match_operand 3 "" "X")))] + (use (label_ref:DI (match_operand 3 "" "X"))) + (use (match_operand:DI 5 "const_int_operand" "i"))] "TARGET_64BIT && INTVAL (operands[4]) + X86_64_SSE_REGPARM_MAX * 16 - 16 < 128 && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128" @@ -21300,7 +18502,10 @@ PUT_MODE (operands[4], TImode); if (GET_CODE (XEXP (operands[0], 0)) != PLUS) output_asm_insn ("rex", operands); - output_asm_insn ("%vmovaps\t{%5, %4|%4, %5}", operands); + if (crtl->stack_alignment_needed < 128) + output_asm_insn ("%vmovsd\t{%5, %4|%4, %5}", operands); + else + output_asm_insn ("%vmovaps\t{%5, %4|%4, %5}", operands); } (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (operands[3])); @@ -21309,11 +18514,11 @@ [(set_attr "type" "other") (set_attr "length_immediate" "0") (set_attr "length_address" "0") + ;; 2 bytes for jump and opernds[4] bytes for each save. (set (attr "length") - (if_then_else - (eq (symbol_ref "TARGET_AVX") (const_int 0)) - (const_string "34") - (const_string "42"))) + (plus (const_int 2) + (mult (symbol_ref ("INTVAL (operands[5])")) + (symbol_ref ("X86_64_SSE_REGPARM_MAX - INTVAL (operands[2])"))))) (set_attr "memory" "store") (set_attr "modrm" "0") (set_attr "prefix" "maybe_vex") @@ -21553,18 +18758,14 @@ } [(set_attr "type" "multi")]) -(define_mode_iterator CRC32MODE [QI HI SI]) -(define_mode_attr crc32modesuffix [(QI "b") (HI "w") (SI "l")]) -(define_mode_attr crc32modeconstraint [(QI "qm") (HI "rm") (SI "rm")]) - (define_insn "sse4_2_crc32" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "0") - (match_operand:CRC32MODE 2 "nonimmediate_operand" "")] + (match_operand:SWI124 2 "nonimmediate_operand" "m")] UNSPEC_CRC32))] "TARGET_SSE4_2 || TARGET_CRC32" - "crc32\t{%2, %0|%0, %2}" + "crc32{}\t{%2, %0|%0, %2}" [(set_attr "type" "sselog1") (set_attr "prefix_rep" "1") (set_attr "prefix_extra" "1") @@ -21585,7 +18786,7 @@ (match_operand:DI 2 "nonimmediate_operand" "rm")] UNSPEC_CRC32))] "TARGET_64BIT && (TARGET_SSE4_2 || TARGET_CRC32)" - "crc32q\t{%2, %0|%0, %2}" + "crc32{q}\t{%2, %0|%0, %2}" [(set_attr "type" "sselog1") (set_attr "prefix_rep" "1") (set_attr "prefix_extra" "1") @@ -21754,6 +18955,93 @@ [(set_attr "type" "other") (set_attr "length" "3")]) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; LWP instructions +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define_expand "lwp_llwpcb" + [(unspec_volatile [(match_operand 0 "register_operand" "r")] + UNSPECV_LLWP_INTRINSIC)] + "TARGET_LWP" + "") + +(define_insn "*lwp_llwpcb1" + [(unspec_volatile [(match_operand:P 0 "register_operand" "r")] + UNSPECV_LLWP_INTRINSIC)] + "TARGET_LWP" + "llwpcb\t%0" + [(set_attr "type" "lwp") + (set_attr "mode" "") + (set_attr "length" "5")]) + +(define_expand "lwp_slwpcb" + [(set (match_operand 0 "register_operand" "=r") + (unspec_volatile [(const_int 0)] UNSPECV_SLWP_INTRINSIC))] + "TARGET_LWP" + { + if (TARGET_64BIT) + emit_insn (gen_lwp_slwpcbdi (operands[0])); + else + emit_insn (gen_lwp_slwpcbsi (operands[0])); + DONE; + }) + +(define_insn "lwp_slwpcb" + [(set (match_operand:P 0 "register_operand" "=r") + (unspec_volatile:P [(const_int 0)] UNSPECV_SLWP_INTRINSIC))] + "TARGET_LWP" + "slwpcb\t%0" + [(set_attr "type" "lwp") + (set_attr "mode" "") + (set_attr "length" "5")]) + +(define_expand "lwp_lwpval3" + [(unspec_volatile [(match_operand:SWI48 1 "register_operand" "r") + (match_operand:SI 2 "nonimmediate_operand" "rm") + (match_operand:SI 3 "const_int_operand" "i")] + UNSPECV_LWPVAL_INTRINSIC)] + "TARGET_LWP" + "/* Avoid unused variable warning. */ + (void) operand0;") + +(define_insn "*lwp_lwpval3_1" + [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r") + (match_operand:SI 1 "nonimmediate_operand" "rm") + (match_operand:SI 2 "const_int_operand" "i")] + UNSPECV_LWPVAL_INTRINSIC)] + "TARGET_LWP" + "lwpval\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "lwp") + (set_attr "mode" "") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 9"))]) + +(define_expand "lwp_lwpins3" + [(set (reg:CCC FLAGS_REG) + (unspec_volatile:CCC [(match_operand:SWI48 1 "register_operand" "r") + (match_operand:SI 2 "nonimmediate_operand" "rm") + (match_operand:SI 3 "const_int_operand" "i")] + UNSPECV_LWPINS_INTRINSIC)) + (set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (eq:QI (reg:CCC FLAGS_REG) (const_int 0)))] + "TARGET_LWP" + "") + +(define_insn "*lwp_lwpins3_1" + [(set (reg:CCC FLAGS_REG) + (unspec_volatile:CCC [(match_operand:SWI48 0 "register_operand" "r") + (match_operand:SI 1 "nonimmediate_operand" "rm") + (match_operand:SI 2 "const_int_operand" "i")] + UNSPECV_LWPINS_INTRINSIC))] + "TARGET_LWP" + "lwpins\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "lwp") + (set_attr "mode" "") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 9"))]) + (include "mmx.md") (include "sse.md") (include "sync.md")