Mercurial > hg > CbC > CbC_gcc
diff gcc/config/i386/i386.md @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | 3bfb6c00c1e0 |
children | 326d9e06c2e3 b7f97abdc517 |
line wrap: on
line diff
--- a/gcc/config/i386/i386.md Sun Feb 07 18:28:00 2010 +0900 +++ b/gcc/config/i386/i386.md Fri Feb 12 23:39:51 2010 +0900 @@ -27,22 +27,39 @@ ;; See file "rtl.def" for documentation on define_insn, match_*, et. al. ;; ;; The special asm out single letter directives following a '%' are: -;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of -;; operands[1]. -;; 'L' Print the opcode suffix for a 32-bit integer opcode. -;; 'W' Print the opcode suffix for a 16-bit integer opcode. -;; 'B' Print the opcode suffix for an 8-bit integer opcode. -;; 'Q' Print the opcode suffix for a 64-bit float opcode. -;; 'S' Print the opcode suffix for a 32-bit float opcode. -;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode. -;; 'J' Print the appropriate jump operand. -;; -;; 'b' Print the QImode name of the register for the indicated operand. -;; %b0 would print %al if operands[0] is reg 0. -;; 'w' Likewise, print the HImode name of the register. -;; 'k' Likewise, print the SImode name of the register. -;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh. -;; 'y' Print "st(0)" instead of "st" as a register. +;; 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 +;; R -- print the prefix for register names. +;; z -- print the opcode suffix for the size of the current operand. +;; Z -- likewise, with special suffixes for x87 instructions. +;; * -- print a star (in certain assembler syntax) +;; A -- print an absolute memory reference. +;; w -- print the operand as if it's a "word" (HImode) even if it isn't. +;; s -- print a shift double count, followed by the assemblers argument +;; delimiter. +;; b -- print the QImode name of the register for the indicated operand. +;; %b0 would print %al if operands[0] is reg 0. +;; w -- likewise, print the HImode name of the register. +;; k -- likewise, print the SImode name of the register. +;; q -- likewise, print the DImode name of the register. +;; x -- likewise, print the V4SFmode name of the register. +;; t -- likewise, print the V8SFmode name of the register. +;; h -- print the QImode name for a "high" register, either ah, bh, ch or dh. +;; y -- print "st(0)" instead of "st" as a register. +;; d -- print duplicated register operand for AVX instruction. +;; D -- print condition for SSE cmp instruction. +;; P -- if PIC, print an @PLT suffix. +;; 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). ;; UNSPEC usage: @@ -84,7 +101,6 @@ (UNSPEC_ADD_CARRY 34) (UNSPEC_FLDCW 35) (UNSPEC_REP 36) - (UNSPEC_EH_RETURN 37) (UNSPEC_LD_MPIC 38) ; load_macho_picbase (UNSPEC_TRUNC_NOOP 39) @@ -180,14 +196,14 @@ (UNSPEC_PCMPESTR 144) (UNSPEC_PCMPISTR 145) - ;; For SSE5 - (UNSPEC_SSE5_INTRINSIC 150) - (UNSPEC_SSE5_UNSIGNED_CMP 151) - (UNSPEC_SSE5_TRUEFALSE 152) - (UNSPEC_SSE5_PERMUTE 153) + ; For FMA4 support + (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) - (UNSPEC_CVTPH2PS 155) - (UNSPEC_CVTPS2PH 156) ; For AES support (UNSPEC_AESENC 159) @@ -228,6 +244,14 @@ (UNSPECV_CLD 15) (UNSPECV_VZEROALL 16) (UNSPECV_VZEROUPPER 17) + (UNSPECV_RDTSC 18) + (UNSPECV_RDTSCP 19) + (UNSPECV_RDPMC 20) + (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 @@ -240,7 +264,7 @@ (COM_TRUE_P 5) ]) -;; Constants used in the SSE5 pperm instruction +;; Constants used in the XOP pperm instruction (define_constants [(PPERM_SRC 0x00) /* copy source */ (PPERM_INVERT 0x20) /* invert source */ @@ -295,6 +319,7 @@ (R9_REG 38) (R10_REG 39) (R11_REG 40) + (R12_REG 41) (R13_REG 42) (XMM8_REG 45) (XMM9_REG 46) @@ -316,7 +341,7 @@ ;; Processor type. -(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2, +(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,atom, generic64,amdfam10" (const (symbol_ref "ix86_schedule"))) @@ -332,7 +357,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")) @@ -398,16 +423,23 @@ ;; Set when length prefix is used. (define_attr "prefix_data16" "" - (if_then_else (ior (eq_attr "mode" "HI") - (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF"))) - (const_int 1) - (const_int 0))) + (cond [(eq_attr "type" "ssemuladd,sse4arg,sseiadd1,ssecvt1") + (const_int 0) + (eq_attr "mode" "HI") + (const_int 1) + (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF,TI")) + (const_int 1) + ] + (const_int 0))) ;; Set when string REP prefix is used. (define_attr "prefix_rep" "" - (if_then_else (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF")) - (const_int 1) - (const_int 0))) + (cond [(eq_attr "type" "ssemuladd,sse4arg,sseiadd1,ssecvt1") + (const_int 0) + (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF")) + (const_int 1) + ] + (const_int 0))) ;; Set when 0f opcode prefix is used. (define_attr "prefix_0f" "" @@ -419,8 +451,11 @@ ;; Set when REX opcode prefix is used. (define_attr "prefix_rex" "" - (cond [(and (eq_attr "mode" "DI") - (eq_attr "type" "!push,pop,call,callv,leave,ibr")) + (cond [(ne (symbol_ref "!TARGET_64BIT") (const_int 0)) + (const_int 0) + (and (eq_attr "mode" "DI") + (and (eq_attr "type" "!push,pop,call,callv,leave,ibr") + (eq_attr "unit" "!mmx"))) (const_int 1) (and (eq_attr "mode" "QI") (ne (symbol_ref "x86_extended_QIreg_mentioned_p (insn)") @@ -429,11 +464,23 @@ (ne (symbol_ref "x86_extended_reg_mentioned_p (insn)") (const_int 0)) (const_int 1) + (and (eq_attr "type" "imovx") + (match_operand:QI 1 "ext_QIreg_operand" "")) + (const_int 1) ] (const_int 0))) -;; There are also additional prefixes in SSSE3. -(define_attr "prefix_extra" "" (const_int 0)) +;; There are also additional prefixes in 3DNOW, SSSE3. +;; ssemuladd,sse4arg default to 0f24/0f25 and DREX byte, +;; sseiadd1,ssecvt1 to 0f7a with no DREX byte. +;; 3DNOW has 0f0f prefix, SSSE3 and SSE4_{1,2} 0f38/0f3a. +(define_attr "prefix_extra" "" + (cond [(eq_attr "type" "ssemuladd,sse4arg") + (const_int 2) + (eq_attr "type" "sseiadd1,ssecvt1") + (const_int 1) + ] + (const_int 0))) ;; Prefix used: original, VEX or maybe VEX. (define_attr "prefix" "orig,vex,maybe_vex" @@ -441,15 +488,16 @@ (const_string "vex") (const_string "orig"))) -;; There is a 8bit immediate for VEX. -(define_attr "prefix_vex_imm8" "" (const_int 0)) - ;; VEX W bit is used. (define_attr "prefix_vex_w" "" (const_int 0)) ;; The length of VEX prefix +;; Only instructions with 0f prefix can have 2 byte VEX prefix, +;; 0f38/0f3a prefixes can't. In i386.md 0f3[8a] is +;; still prefix_0f 1, with prefix_extra 1. (define_attr "length_vex" "" - (if_then_else (eq_attr "prefix_0f" "1") + (if_then_else (and (eq_attr "prefix_0f" "1") + (eq_attr "prefix_extra" "0")) (if_then_else (eq_attr "prefix_vex_w" "1") (symbol_ref "ix86_attr_length_vex_default (insn, 1, 1)") (symbol_ref "ix86_attr_length_vex_default (insn, 1, 0)")) @@ -464,8 +512,9 @@ (eq_attr "unit" "i387") (const_int 0) (and (eq_attr "type" "incdec") - (ior (match_operand:SI 1 "register_operand" "") - (match_operand:HI 1 "register_operand" ""))) + (and (eq (symbol_ref "TARGET_64BIT") (const_int 0)) + (ior (match_operand:SI 1 "register_operand" "") + (match_operand:HI 1 "register_operand" "")))) (const_int 0) (and (eq_attr "type" "push") (not (match_operand 1 "memory_operand" ""))) @@ -474,12 +523,13 @@ (not (match_operand 0 "memory_operand" ""))) (const_int 0) (and (eq_attr "type" "imov") - (ior (and (match_operand 0 "register_operand" "") - (match_operand 1 "immediate_operand" "")) - (ior (and (match_operand 0 "ax_reg_operand" "") - (match_operand 1 "memory_displacement_only_operand" "")) - (and (match_operand 0 "memory_displacement_only_operand" "") - (match_operand 1 "ax_reg_operand" ""))))) + (and (not (eq_attr "mode" "DI")) + (ior (and (match_operand 0 "register_operand" "") + (match_operand 1 "immediate_operand" "")) + (ior (and (match_operand 0 "ax_reg_operand" "") + (match_operand 1 "memory_displacement_only_operand" "")) + (and (match_operand 0 "memory_displacement_only_operand" "") + (match_operand 1 "ax_reg_operand" "")))))) (const_int 0) (and (eq_attr "type" "call") (match_operand 0 "constant_call_address_operand" "")) @@ -487,6 +537,9 @@ (and (eq_attr "type" "callv") (match_operand 1 "constant_call_address_operand" "")) (const_int 0) + (and (eq_attr "type" "alu,alu1,icmp,test") + (match_operand 0 "ax_reg_operand" "")) + (symbol_ref "(get_attr_length_immediate (insn) <= (get_attr_mode (insn) != MODE_QI))") ] (const_int 1))) @@ -507,7 +560,7 @@ (and (eq_attr "prefix" "maybe_vex") (ne (symbol_ref "TARGET_AVX") (const_int 0)))) (plus (attr "length_vex") - (plus (attr "prefix_vex_imm8") + (plus (attr "length_immediate") (plus (attr "modrm") (attr "length_address"))))] (plus (plus (attr "modrm") @@ -525,7 +578,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") @@ -612,17 +665,23 @@ (define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any" (const_string "any")) +;; Define attribute to classify add/sub insns that consumes carry flag (CF) +(define_attr "use_carry" "0,1" (const_string "0")) + +;; Define attribute to indicate unaligned ssemov insns +(define_attr "movu" "0,1" (const_string "0")) + ;; Describe a user's asm statement. (define_asm_attributes [(set_attr "length" "128") (set_attr "type" "multi")]) ;; All integer comparison codes. -(define_code_iterator int_cond [ne eq ge gt le lt geu gtu leu ltu ]) +(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]) @@ -637,6 +696,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 "%") @@ -656,11 +717,12 @@ (umax "maxu") (umin "minu")]) (define_code_attr maxminfprefix [(smax "max") (smin "min")]) -;; Mapping of parallel logic operators -(define_code_iterator plogic [and ior xor]) +;; 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 plogicprefix [(and "and") (ior "or") (xor "xor")]) +(define_code_attr logicprefix [(and "and") (ior "or") (xor "xor")]) ;; Mapping of abs neg operators (define_code_iterator absneg [abs neg]) @@ -668,12 +730,55 @@ ;; Base name for x87 insn mnemonic. (define_code_attr absnegprefix [(abs "abs") (neg "chs")]) +;; Used in signed and unsigned widening multiplications. +(define_code_iterator any_extend [sign_extend zero_extend]) + +;; 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 "")]) + ;; 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")]) +;; Single word integer modes without QImode and HImode. +(define_mode_iterator SWI48 [SI (DI "TARGET_64BIT")]) + +;; All math-dependant single and double word integer modes. +(define_mode_iterator SDWIM [(QI "TARGET_QIMODE_MATH") + (HI "TARGET_HIMODE_MATH") + SI DI (TI "TARGET_64BIT")]) + +;; Math-dependant single word integer modes. +(define_mode_iterator SWIM [(QI "TARGET_QIMODE_MATH") + (HI "TARGET_HIMODE_MATH") + SI (DI "TARGET_64BIT")]) + +;; 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_attr DWI [(SI "DI") (DI "TI")]) +(define_mode_attr dwi [(SI "di") (DI "ti")]) + ;; Instruction suffix for integer modes. (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")]) @@ -683,12 +788,26 @@ ;; Immediate operand constraint for integer modes. (define_mode_attr i [(QI "n") (HI "n") (SI "i") (DI "e")]) +;; General operand constraint for word modes. +(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")]) + ;; General operand predicate for integer modes. (define_mode_attr general_operand [(QI "general_operand") (HI "general_operand") (SI "general_operand") - (DI "x86_64_general_operand")]) + (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")]) ;; SSE and x87 SFmode and DFmode floating point modes (define_mode_iterator MODEF [SF DF]) @@ -718,7 +837,6 @@ ;; This mode iterator allows :P to be used for patterns that operate on ;; pointer-sized quantities. Exactly one of the two alternatives will match. (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) - ;; Scheduling descriptions @@ -727,6 +845,7 @@ (include "k6.md") (include "athlon.md") (include "geode.md") +(include "atom.md") ;; Operand and operator predicates and constraints @@ -735,218 +854,82 @@ (include "constraints.md") -;; Compare instructions. - -;; All compare insns have expanders that save the operands away without -;; actually generating RTL. The bCOND or sCOND (emitted immediately -;; after the cmp) will actually emit the cmpM. - -(define_expand "cmpti" +;; Compare and branch/compare and store instructions. + +(define_expand "cbranch<mode>4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:TI 0 "nonimmediate_operand" "") - (match_operand:TI 1 "x86_64_general_operand" "")))] - "TARGET_64BIT" -{ - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (TImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpdi" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "x86_64_general_operand" "")))] - "" -{ - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (DImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpsi" + (compare:CC (match_operand:SDWIM 1 "nonimmediate_operand" "") + (match_operand:SDWIM 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 (<MODE>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 "cstore<mode>4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:SI 0 "cmpsi_operand" "") - (match_operand:SI 1 "general_operand" "")))] - "" -{ - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (SImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmphi" + (compare:CC (match_operand:SWIM 2 "nonimmediate_operand" "") + (match_operand:SWIM 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 (<MODE>mode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + +(define_expand "cmp<mode>_1" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" "")))] - "" -{ - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (HImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpqi" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")))] - "TARGET_QIMODE_MATH" -{ - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (QImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - 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}" + (compare:CC (match_operand:SWI48 0 "nonimmediate_operand" "") + (match_operand:SWI48 1 "<general_operand>" "")))] + "" + "") + +(define_insn "*cmp<mode>_ccno_1" + [(set (reg FLAGS_REG) + (compare (match_operand:SWI 0 "nonimmediate_operand" "<r>,?m<r>") + (match_operand:SWI 1 "const0_operand" "")))] + "ix86_match_ccmode (insn, CCNOmode)" + "@ + test{<imodesuffix>}\t%0, %0 + cmp{<imodesuffix>}\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" - [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" "")))] - "" - "") - -(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 "mode" "<MODE>")]) + +(define_insn "*cmp<mode>_1" + [(set (reg FLAGS_REG) + (compare (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>") + (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")))] + "ix86_match_ccmode (insn, CCmode)" + "cmp{<imodesuffix>}\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)))] + (set_attr "mode" "<MODE>")]) + +(define_insn "*cmp<mode>_minus_1" + [(set (reg FLAGS_REG) + (compare + (minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>") + (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")) + (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}" + "cmp{<imodesuffix>}\t{%1, %0|%0, %1}" [(set_attr "type" "icmp") - (set_attr "mode" "HI")]) - -(define_insn "*cmpqi_ccno_1" - [(set (reg FLAGS_REG) - (compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq") - (match_operand:QI 1 "const0_operand" "")))] - "ix86_match_ccmode (insn, CCNOmode)" - "@ - test{b}\t%0, %0 - cmp{b}\t{$0, %0|%0, 0}" - [(set_attr "type" "test,icmp") - (set_attr "length_immediate" "0,1") - (set_attr "mode" "QI")]) - -(define_insn "*cmpqi_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}" - [(set_attr "type" "icmp") - (set_attr "mode" "QI")]) - -(define_insn "*cmpqi_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)))] - "ix86_match_ccmode (insn, CCGOCmode)" - "cmp{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "QI")]) + (set_attr "mode" "<MODE>")]) (define_insn "*cmpqi_ext_1" [(set (reg FLAGS_REG) @@ -999,11 +982,11 @@ (match_operand 0 "ext_register_operand" "") (const_int 8) (const_int 8)) 0) - (match_operand:QI 1 "general_operand" "")))] - "" - "") - -(define_insn "cmpqi_ext_3_insn" + (match_operand:QI 1 "immediate_operand" "")))] + "" + "") + +(define_insn "*cmpqi_ext_3_insn" [(set (reg FLAGS_REG) (compare (subreg:QI @@ -1015,9 +998,10 @@ "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)" "cmp{b}\t{%1, %h0|%h0, %1}" [(set_attr "type" "icmp") - (set_attr "mode" "QI")]) - -(define_insn "cmpqi_ext_3_insn_rex64" + (set_attr "modrm" "1") + (set_attr "mode" "QI")]) + +(define_insn "*cmpqi_ext_3_insn_rex64" [(set (reg FLAGS_REG) (compare (subreg:QI @@ -1029,6 +1013,7 @@ "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)" "cmp{b}\t{%1, %h0|%h0, %1}" [(set_attr "type" "icmp") + (set_attr "modrm" "1") (set_attr "mode" "QI")]) (define_insn "*cmpqi_ext_4" @@ -1054,27 +1039,102 @@ ;; which would allow mix and match FP modes on the compares. Which is what ;; the old patterns did, but with many more of them. -(define_expand "cmpxf" +(define_expand "cbranchxf4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:XF 0 "nonmemory_operand" "") - (match_operand:XF 1 "nonmemory_operand" "")))] + (compare:CC (match_operand:XF 1 "nonmemory_operand" "") + (match_operand:XF 2 "nonmemory_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "ix86_fp_comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_80387" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstorexf4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:XF 2 "nonmemory_operand" "") + (match_operand:XF 3 "nonmemory_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "ix86_fp_comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "TARGET_80387" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmp<mode>" + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + +(define_expand "cbranch<mode>4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand" "") + (match_operand:MODEF 2 "cmp_fp_expander_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "ix86_fp_comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstore<mode>4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:MODEF 0 "cmp_fp_expander_operand" "") - (match_operand:MODEF 1 "cmp_fp_expander_operand" "")))] + (compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand" "") + (match_operand:MODEF 3 "cmp_fp_expander_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "ix86_fp_comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - DONE; -}) + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + +(define_expand "cbranchcc4" + [(set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(match_operand 1 "flags_reg_operand" "") + (match_operand 2 "const0_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstorecc4" + [(set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(match_operand 2 "flags_reg_operand" "") + (match_operand 3 "const0_operand" "")]))] + "" +{ + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + ;; FP compares, step 1: ;; Set the FP condition codes. @@ -1301,7 +1361,7 @@ (unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))] "TARGET_80387" "fnstsw\t%0" - [(set_attr "length" "2") + [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2")) (set_attr "mode" "SI") (set_attr "unit" "i387")]) @@ -1317,7 +1377,7 @@ #ifdef HAVE_AS_IX86_SAHF return "sahf"; #else - return ".byte\t0x9e"; + return ASM_BYTE "0x9e"; #endif } [(set_attr "length" "1") @@ -1341,6 +1401,17 @@ (if_then_else (match_operand:SF 1 "" "") (const_string "SF") (const_string "DF"))) + (set (attr "prefix_rep") + (if_then_else (eq_attr "type" "ssecomi") + (const_string "0") + (const_string "*"))) + (set (attr "prefix_data16") + (cond [(eq_attr "type" "fcmp") + (const_string "*") + (eq_attr "mode" "DF") + (const_string "1") + ] + (const_string "0"))) (set_attr "athlon_decode" "vector") (set_attr "amdfam10_decode" "direct")]) @@ -1358,6 +1429,11 @@ (if_then_else (match_operand:SF 1 "" "") (const_string "SF") (const_string "DF"))) + (set_attr "prefix_rep" "0") + (set (attr "prefix_data16") + (if_then_else (eq_attr "mode" "DF") + (const_string "1") + (const_string "0"))) (set_attr "athlon_decode" "vector") (set_attr "amdfam10_decode" "direct")]) @@ -1395,6 +1471,17 @@ (if_then_else (match_operand:SF 1 "" "") (const_string "SF") (const_string "DF"))) + (set (attr "prefix_rep") + (if_then_else (eq_attr "type" "ssecomi") + (const_string "0") + (const_string "*"))) + (set (attr "prefix_data16") + (cond [(eq_attr "type" "fcmp") + (const_string "*") + (eq_attr "mode" "DF") + (const_string "1") + ] + (const_string "0"))) (set_attr "athlon_decode" "vector") (set_attr "amdfam10_decode" "direct")]) @@ -1412,6 +1499,11 @@ (if_then_else (match_operand:SF 1 "" "") (const_string "SF") (const_string "DF"))) + (set_attr "prefix_rep" "0") + (set (attr "prefix_data16") + (if_then_else (eq_attr "mode" "DF") + (const_string "1") + (const_string "0"))) (set_attr "athlon_decode" "vector") (set_attr "amdfam10_decode" "direct")]) @@ -1587,6 +1679,10 @@ (if_then_else (eq_attr "alternative" "0,1,2,3,4,5") (const_string "orig") (const_string "maybe_vex"))) + (set (attr "prefix_data16") + (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI")) + (const_string "1") + (const_string "*"))) (set (attr "mode") (cond [(eq_attr "alternative" "2,3") (const_string "DI") @@ -2078,7 +2174,7 @@ "TARGET_64BIT" "movz{bl|x}\t{%h1, %k0|%k0, %h1}" [(set_attr "type" "imovx") - (set_attr "mode" "DI")]) + (set_attr "mode" "SI")]) (define_insn "*movsi_extzv_1" [(set (match_operand:SI 0 "register_operand" "=R") @@ -2426,8 +2522,18 @@ (const_string "lea") ] (const_string "imov"))) - (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*") - (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*") + (set (attr "modrm") + (if_then_else + (and (eq_attr "alternative" "2") (eq_attr "type" "imov")) + (const_string "0") + (const_string "*"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "alternative" "2") (eq_attr "type" "imov")) + (const_string "8") + (const_string "*"))) + (set_attr "prefix_rex" "*,*,*,*,*,*,*,1,*,1,*,*,*,*,*,*,*,*,*") + (set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,1,*,*,*") (set (attr "prefix") (if_then_else (eq_attr "alternative" "11,12,13,14,15,16") (const_string "maybe_vex") @@ -2730,7 +2836,6 @@ [(set (match_dup 0) (match_dup 2))]) - ;; %%% Kill this when call knows how to work this out. (define_split [(set (match_operand:SF 0 "push_operand" "") @@ -3012,6 +3117,10 @@ (if_then_else (eq_attr "alternative" "0,1,2,3,4") (const_string "orig") (const_string "maybe_vex"))) + (set (attr "prefix_data16") + (if_then_else (eq_attr "mode" "V1DF") + (const_string "1") + (const_string "*"))) (set (attr "mode") (cond [(eq_attr "alternative" "0,1,2") (const_string "DF") @@ -3146,6 +3255,10 @@ (if_then_else (eq_attr "alternative" "0,1,2,3,4") (const_string "orig") (const_string "maybe_vex"))) + (set (attr "prefix_data16") + (if_then_else (eq_attr "mode" "V1DF") + (const_string "1") + (const_string "*"))) (set (attr "mode") (cond [(eq_attr "alternative" "0,1,2") (const_string "DF") @@ -3266,6 +3379,10 @@ } } [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov") + (set (attr "prefix_data16") + (if_then_else (eq_attr "mode" "V1DF") + (const_string "1") + (const_string "*"))) (set (attr "mode") (cond [(eq_attr "alternative" "0,1,2") (const_string "DF") @@ -3764,9 +3881,11 @@ && (TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)) && !reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (match_dup 0) (const_int 0)) - (set (strict_low_part (match_dup 2)) (match_dup 1))] - "operands[2] = gen_lowpart (QImode, operands[0]);") + [(set (strict_low_part (match_dup 2)) (match_dup 1))] +{ + operands[2] = gen_lowpart (QImode, operands[0]); + ix86_expand_clear (operands[0]); +}) ;; Rest is handled by single and. (define_split @@ -3796,7 +3915,7 @@ [(set_attr "type" "alu1") (set_attr "mode" "SI")]) -(define_insn "*zero_extendqisi2_movzbw_and" +(define_insn "*zero_extendqisi2_movzbl_and" [(set (match_operand:SI 0 "register_operand" "=r,r") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm,0"))) (clobber (reg:CC FLAGS_REG))] @@ -3805,7 +3924,7 @@ [(set_attr "type" "imovx,alu1") (set_attr "mode" "SI")]) -(define_insn "*zero_extendqisi2_movzbw" +(define_insn "*zero_extendqisi2_movzbl" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))] "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun)) @@ -3836,9 +3955,11 @@ && (ANY_QI_REG_P (operands[1]) || MEM_P (operands[1])) && (TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)) && !reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (match_dup 0) (const_int 0)) - (set (strict_low_part (match_dup 2)) (match_dup 1))] - "operands[2] = gen_lowpart (QImode, operands[0]);") + [(set (strict_low_part (match_dup 2)) (match_dup 1))] +{ + operands[2] = gen_lowpart (QImode, operands[0]); + ix86_expand_clear (operands[0]); +}) ;; Rest is handled by single and. (define_split @@ -3896,6 +4017,7 @@ %vmovd\t{%1, %0|%0, %1}" [(set_attr "type" "imovx,imov,mmxmov,mmxmov,ssemov,ssemov") (set_attr "prefix" "orig,*,orig,orig,maybe_vex,maybe_vex") + (set_attr "prefix_0f" "0,*,*,*,*,*") (set_attr "mode" "SI,DI,DI,DI,TI,TI")]) (define_split @@ -3930,7 +4052,7 @@ "TARGET_64BIT" "movz{wl|x}\t{%1, %k0|%k0, %1}" [(set_attr "type" "imovx") - (set_attr "mode" "DI")]) + (set_attr "mode" "SI")]) (define_insn "zero_extendqidi2" [(set (match_operand:DI 0 "register_operand" "=r") @@ -3938,7 +4060,7 @@ "TARGET_64BIT" "movz{bl|x}\t{%1, %k0|%k0, %1}" [(set_attr "type" "imovx") - (set_attr "mode" "DI")]) + (set_attr "mode" "SI")]) ;; Sign extension instructions @@ -3970,7 +4092,7 @@ "TARGET_64BIT" "@ {cltq|cdqe} - movs{lq|x}\t{%1,%0|%0, %1}" + movs{lq|x}\t{%1, %0|%0, %1}" [(set_attr "type" "imovx") (set_attr "mode" "DI") (set_attr "prefix_0f" "0") @@ -3980,7 +4102,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))] "TARGET_64BIT" - "movs{wq|x}\t{%1,%0|%0, %1}" + "movs{wq|x}\t{%1, %0|%0, %1}" [(set_attr "type" "imovx") (set_attr "mode" "DI")]) @@ -3988,7 +4110,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "qm")))] "TARGET_64BIT" - "movs{bq|x}\t{%1,%0|%0, %1}" + "movs{bq|x}\t{%1, %0|%0, %1}" [(set_attr "type" "imovx") (set_attr "mode" "DI")]) @@ -4076,7 +4198,7 @@ case 0: return "{cwtl|cwde}"; default: - return "movs{wl|x}\t{%1,%0|%0, %1}"; + return "movs{wl|x}\t{%1, %0|%0, %1}"; } } [(set_attr "type" "imovx") @@ -4103,7 +4225,7 @@ case 0: return "{cwtl|cwde}"; default: - return "movs{wl|x}\t{%1,%k0|%k0, %1}"; + return "movs{wl|x}\t{%1, %k0|%k0, %1}"; } } [(set_attr "type" "imovx") @@ -4129,7 +4251,7 @@ case 0: return "{cbtw|cbw}"; default: - return "movs{bw|x}\t{%1,%0|%0, %1}"; + return "movs{bw|x}\t{%1, %0|%0, %1}"; } } [(set_attr "type" "imovx") @@ -4149,7 +4271,7 @@ [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))] "" - "movs{bl|x}\t{%1,%0|%0, %1}" + "movs{bl|x}\t{%1, %0|%0, %1}" [(set_attr "type" "imovx") (set_attr "mode" "SI")]) @@ -4158,7 +4280,7 @@ (zero_extend:DI (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))))] "TARGET_64BIT" - "movs{bl|x}\t{%1,%k0|%k0, %1}" + "movs{bl|x}\t{%1, %k0|%k0, %1}" [(set_attr "type" "imovx") (set_attr "mode" "SI")]) @@ -4261,7 +4383,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], @@ -4357,7 +4480,9 @@ ; else { - int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + enum ix86_stack_slot slot = (virtuals_instantiated + ? SLOT_TEMP + : SLOT_VIRTUAL); rtx temp = assign_386_stack_local (SFmode, slot); emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp)); DONE; @@ -4542,7 +4667,9 @@ } else { - int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + enum ix86_stack_slot slot = (virtuals_instantiated + ? SLOT_TEMP + : SLOT_VIRTUAL); operands[2] = assign_386_stack_local (<MODE>mode, slot); } }) @@ -4766,6 +4893,7 @@ "%vcvtts<ssemodefsuffix>2si{q}\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") (set_attr "prefix" "maybe_vex") + (set_attr "prefix_rex" "1") (set_attr "mode" "<MODE>") (set_attr "athlon_decode" "double,vector") (set_attr "amdfam10_decode" "double,double")]) @@ -4820,7 +4948,7 @@ && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && (TARGET_64BIT || <MODE>mode != DImode)) && TARGET_SSE_MATH) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -4900,7 +5028,7 @@ && !TARGET_FISTTP && !(SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && (TARGET_64BIT || <MODE>mode != DImode)) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -5040,7 +5168,7 @@ (unspec:HI [(reg:HI FPCR_REG)] UNSPEC_FSTCW))] "TARGET_80387" "fnstcw\t%0" - [(set_attr "length" "2") + [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2")) (set_attr "mode" "HI") (set_attr "unit" "i387")]) @@ -5049,7 +5177,7 @@ (unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))] "TARGET_80387" "fldcw\t%0" - [(set_attr "length" "2") + [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2")) (set_attr "mode" "HI") (set_attr "unit" "i387") (set_attr "athlon_decode" "vector") @@ -5075,7 +5203,7 @@ "TARGET_80387 && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(parallel [(set (match_dup 0) @@ -5102,7 +5230,7 @@ "TARGET_80387 && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)" - "fild%z1\t%1" + "fild%Z1\t%1" [(set_attr "type" "fmov") (set_attr "mode" "<MODE>") (set_attr "fp_int_src" "true")]) @@ -5137,13 +5265,34 @@ "TARGET_80387 || ((<SSEMODEI24:MODE>mode != DImode || TARGET_64BIT) && SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH)" - "") +{ + if (!((<SSEMODEI24:MODE>mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH) + && !X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode)) + { + rtx reg = gen_reg_rtx (XFmode); + rtx insn; + + emit_insn (gen_float<SSEMODEI24:mode>xf2 (reg, operands[1])); + + if (<X87MODEF:MODE>mode == SFmode) + insn = gen_truncxfsf2 (operands[0], reg); + else if (<X87MODEF:MODE>mode == DFmode) + insn = gen_truncxfdf2 (operands[0], reg); + else + gcc_unreachable (); + + emit_insn (insn); + DONE; + } +}) ;; Pre-reload splitter to add memory clobber to the pattern. (define_insn_and_split "*float<SSEMODEI24:mode><X87MODEF:mode>2_1" [(set (match_operand:X87MODEF 0 "register_operand" "") (float:X87MODEF (match_operand:SSEMODEI24 1 "register_operand" "")))] "((TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode) && (!((<SSEMODEI24:MODE>mode != DImode || TARGET_64BIT) && SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)) @@ -5155,7 +5304,7 @@ && flag_trapping_math) || !(TARGET_INTER_UNIT_CONVERSIONS || optimize_function_for_size_p (cfun))))) - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(parallel [(set (match_dup 0) (float:X87MODEF (match_dup 1))) @@ -5197,7 +5346,7 @@ "TARGET_SSE2 && TARGET_MIX_SSE_I387 && TARGET_USE_VECTOR_CONVERTS && optimize_function_for_speed_p (cfun)" "@ - fild%z1\t%1 + fild%Z1\t%1 #" [(set_attr "type" "fmov,sseicvt") (set_attr "mode" "<MODE>,<ssevecmode>") @@ -5258,12 +5407,18 @@ && SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_MIX_SSE_I387 && (TARGET_INTER_UNIT_CONVERSIONS || optimize_function_for_size_p (cfun))" "@ - fild%z1\t%1 + fild%Z1\t%1 %vcvtsi2s<MODEF:ssemodefsuffix><SSEMODEI24:rex64suffix>\t{%1, %d0|%d0, %1} %vcvtsi2s<MODEF:ssemodefsuffix><SSEMODEI24:rex64suffix>\t{%1, %d0|%d0, %1}" [(set_attr "type" "fmov,sseicvt,sseicvt") (set_attr "prefix" "orig,maybe_vex,maybe_vex") (set_attr "mode" "<MODEF:MODE>") + (set (attr "prefix_rex") + (if_then_else + (and (eq_attr "prefix" "maybe_vex") + (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0))) + (const_string "1") + (const_string "*"))) (set_attr "unit" "i387,*,*") (set_attr "athlon_decode" "*,double,direct") (set_attr "amdfam10_decode" "*,vector,double") @@ -5277,11 +5432,17 @@ && SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_MIX_SSE_I387 && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_function_for_size_p (cfun))" "@ - fild%z1\t%1 + fild%Z1\t%1 %vcvtsi2s<MODEF:ssemodefsuffix><SSEMODEI24:rex64suffix>\t{%1, %d0|%d0, %1}" [(set_attr "type" "fmov,sseicvt") (set_attr "prefix" "orig,maybe_vex") (set_attr "mode" "<MODEF:MODE>") + (set (attr "prefix_rex") + (if_then_else + (and (eq_attr "prefix" "maybe_vex") + (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0))) + (const_string "1") + (const_string "*"))) (set_attr "athlon_decode" "*,direct") (set_attr "amdfam10_decode" "*,double") (set_attr "fp_int_src" "true")]) @@ -5458,6 +5619,12 @@ [(set_attr "type" "sseicvt") (set_attr "prefix" "maybe_vex") (set_attr "mode" "<MODEF:MODE>") + (set (attr "prefix_rex") + (if_then_else + (and (eq_attr "prefix" "maybe_vex") + (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0))) + (const_string "1") + (const_string "*"))) (set_attr "athlon_decode" "double,direct") (set_attr "amdfam10_decode" "vector,double") (set_attr "fp_int_src" "true")]) @@ -5487,6 +5654,12 @@ [(set_attr "type" "sseicvt") (set_attr "prefix" "maybe_vex") (set_attr "mode" "<MODEF:MODE>") + (set (attr "prefix_rex") + (if_then_else + (and (eq_attr "prefix" "maybe_vex") + (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0))) + (const_string "1") + (const_string "*"))) (set_attr "athlon_decode" "direct") (set_attr "amdfam10_decode" "double") (set_attr "fp_int_src" "true")]) @@ -5524,9 +5697,10 @@ (float:X87MODEF (match_operand:SSEMODEI24 1 "nonimmediate_operand" "m,?r"))) (clobber (match_operand:SSEMODEI24 2 "memory_operand" "=X,m"))] - "TARGET_80387" - "@ - fild%z1\t%1 + "TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode)" + "@ + fild%Z1\t%1 #" [(set_attr "type" "fmov,multi") (set_attr "mode" "<X87MODEF:MODE>") @@ -5537,8 +5711,9 @@ [(set (match_operand:X87MODEF 0 "register_operand" "=f") (float:X87MODEF (match_operand:SSEMODEI24 1 "memory_operand" "m")))] - "TARGET_80387" - "fild%z1\t%1" + "TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode)" + "fild%Z1\t%1" [(set_attr "type" "fmov") (set_attr "mode" "<X87MODEF:MODE>") (set_attr "fp_int_src" "true")]) @@ -5548,6 +5723,7 @@ (float:X87MODEF (match_operand:SSEMODEI24 1 "register_operand" ""))) (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] "TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode) && reload_completed && FP_REG_P (operands[0])" [(set (match_dup 2) (match_dup 1)) @@ -5559,6 +5735,7 @@ (float:X87MODEF (match_operand:SSEMODEI24 1 "memory_operand" ""))) (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] "TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode) && reload_completed && FP_REG_P (operands[0])" [(set (match_dup 0) (float:X87MODEF (match_dup 1)))] @@ -5574,7 +5751,8 @@ (clobber (match_scratch:V4SI 3 "=X,x")) (clobber (match_scratch:V4SI 4 "=X,x")) (clobber (match_operand:DI 2 "memory_operand" "=X,m"))] - "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES && !TARGET_64BIT && optimize_function_for_speed_p (cfun)" "#" [(set_attr "type" "multi") @@ -5588,7 +5766,8 @@ (clobber (match_scratch:V4SI 3 "")) (clobber (match_scratch:V4SI 4 "")) (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES && !TARGET_64BIT && optimize_function_for_speed_p (cfun) && reload_completed && FP_REG_P (operands[0])" @@ -5601,7 +5780,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])); }) @@ -5612,7 +5792,8 @@ (clobber (match_scratch:V4SI 3 "")) (clobber (match_scratch:V4SI 4 "")) (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES && !TARGET_64BIT && optimize_function_for_speed_p (cfun) && reload_completed && FP_REG_P (operands[0])" @@ -5632,7 +5813,8 @@ (clobber (match_operand:DI 2 "memory_operand" "=m,m")) (clobber (match_scratch:SI 3 "=X,x"))] "!TARGET_64BIT - && TARGET_80387 && TARGET_SSE" + && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE" "#" [(set_attr "type" "multi") (set_attr "mode" "<MODE>")]) @@ -5644,7 +5826,8 @@ (clobber (match_operand:DI 2 "memory_operand" "")) (clobber (match_scratch:SI 3 ""))] "!TARGET_64BIT - && TARGET_80387 && TARGET_SSE + && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE && reload_completed" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) @@ -5658,7 +5841,8 @@ (clobber (match_operand:DI 2 "memory_operand" "")) (clobber (match_scratch:SI 3 ""))] "!TARGET_64BIT - && TARGET_80387 && TARGET_SSE + && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE && reload_completed" [(set (match_dup 2) (match_dup 3)) (set (match_dup 0) @@ -5676,7 +5860,8 @@ (clobber (match_dup 2)) (clobber (match_scratch:SI 3 ""))])] "!TARGET_64BIT - && ((TARGET_80387 && TARGET_SSE) + && ((TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE) || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))" { if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) @@ -5686,7 +5871,9 @@ } else { - int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + enum ix86_stack_slot slot = (virtuals_instantiated + ? SLOT_TEMP + : SLOT_VIRTUAL); operands[2] = assign_386_stack_local (DImode, slot); } }) @@ -5712,215 +5899,55 @@ ;; Add instructions -;; %%% splits for addditi3 - -(define_expand "addti3" - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (plus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;") - -(define_insn "*addti3_1" - [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o") - (plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0") - (match_operand:TI 2 "x86_64_general_operand" "roe,re"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)" - "#") - -(define_split - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (plus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)] - UNSPEC_ADD_CARRY)) - (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]) +(define_expand "add<mode>3" + [(set (match_operand:SDWIM 0 "nonimmediate_operand" "") + (plus:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand" "") + (match_operand:SDWIM 2 "<general_operand>" "")))] + "" + "ix86_expand_binary_operator (PLUS, <MODE>mode, operands); DONE;") + +(define_insn_and_split "*add<dwi>3_doubleword" + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o") + (plus:<DWI> + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0") + (match_operand:<DWI> 2 "<general_operand>" "ro<di>,r<di>"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)" + "#" + "reload_completed" + [(parallel [(set (reg:CC FLAGS_REG) + (unspec:CC [(match_dup 1) (match_dup 2)] + UNSPEC_ADD_CARRY)) + (set (match_dup 0) + (plus:DWIH (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) - (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 4)) - (match_dup 5))) - (clobber (reg:CC FLAGS_REG))])] - "split_ti (&operands[0], 3, &operands[0], &operands[3]);") - -;; %%% splits for addsidi3 -; [(set (match_operand:DI 0 "nonimmediate_operand" "") -; (plus:DI (match_operand:DI 1 "general_operand" "") -; (zero_extend:DI (match_operand:SI 2 "general_operand" ""))))] - -(define_expand "adddi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "x86_64_general_operand" "")))] - "" - "ix86_expand_binary_operator (PLUS, DImode, operands); DONE;") - -(define_insn "*adddi3_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "general_operand" "roiF,riF"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - "#") - -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "general_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)] - UNSPEC_ADD_CARRY)) - (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) - (parallel [(set (match_dup 3) - (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 4)) - (match_dup 5))) - (clobber (reg:CC FLAGS_REG))])] - "split_di (&operands[0], 3, &operands[0], &operands[3]);") - -(define_insn "adddi3_carry_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") - (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 (PLUS, DImode, operands)" - "adc{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "mode" "DI")]) - -(define_insn "*adddi3_cc_rex64" + (plus:DWIH + (match_dup 4) + (plus:DWIH + (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 5)))) + (clobber (reg:CC FLAGS_REG))])] + "split_<dwi> (&operands[0], 3, &operands[0], &operands[3]);") + +(define_insn "*add<mode>3_cc" [(set (reg:CC FLAGS_REG) - (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm")] - UNSPEC_ADD_CARRY)) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (plus:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - "add{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*<plusminus_insn><mode>3_cc_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (plusminus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0") - (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m")) - (match_dup 1))) - (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") - (plusminus:SWI (match_dup 1) (match_dup 2)))] - "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)" - "<plusminus_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "<MODE>")]) - -(define_insn "*add<mode>3_cconly_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (plus:SWI (match_operand:SWI 1 "nonimmediate_operand" "%0") - (match_operand:SWI 2 "<general_operand>" "<r><i>m")) - (match_dup 1))) - (clobber (match_scratch:SWI 0 "=<r>"))] + (unspec:CC + [(match_operand:SWI48 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI48 2 "<general_operand>" "r<i>,rm")] + UNSPEC_ADD_CARRY)) + (set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r") + (plus:SWI48 (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" "add{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "<MODE>")]) -(define_insn "*sub<mode>3_cconly_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>") - (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")) - (match_dup 0)))] - "" - "cmp{<imodesuffix>}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "<MODE>")]) - -(define_insn "*<plusminus_insn>si3_zext_cc_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (plusminus:SI (match_operand:SI 1 "nonimmediate_operand" "<comm>0") - (match_operand:SI 2 "general_operand" "g")) - (match_dup 1))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)" - "<plusminus_mnemonic>{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) - -(define_insn "addqi3_carry" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") - (match_operand:QI 1 "nonimmediate_operand" "%0,0")) - (match_operand:QI 2 "general_operand" "qn,qm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, QImode, operands)" - "adc{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "mode" "QI")]) - -(define_insn "addhi3_carry" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") - (match_operand:HI 1 "nonimmediate_operand" "%0,0")) - (match_operand:HI 2 "general_operand" "rn,rm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, HImode, operands)" - "adc{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "mode" "HI")]) - -(define_insn "addsi3_carry" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") - (match_operand:SI 1 "nonimmediate_operand" "%0,0")) - (match_operand:SI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" - "adc{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - -(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 "pent_pair" "pu") - (set_attr "mode" "SI")]) - -(define_insn "*addsi3_cc" - [(set (reg:CC FLAGS_REG) - (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "ri,rm")] - UNSPEC_ADD_CARRY)) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" - "add{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) - (define_insn "addqi3_cc" [(set (reg:CC FLAGS_REG) - (unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qm")] - UNSPEC_ADD_CARRY)) + (unspec:CC + [(match_operand:QI 1 "nonimmediate_operand" "%0,0") + (match_operand:QI 2 "general_operand" "qn,qm")] + UNSPEC_ADD_CARRY)) (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") (plus:QI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, QImode, operands)" @@ -5928,22 +5955,15 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) -(define_expand "addsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "ix86_expand_binary_operator (PLUS, SImode, operands); DONE;") - (define_insn "*lea_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "no_seg_address_operand" "p"))] - "!TARGET_64BIT" - "lea{l}\t{%a1, %0|%0, %a1}" + [(set (match_operand:DWIH 0 "register_operand" "=r") + (match_operand:DWIH 1 "no_seg_address_operand" "p"))] + "" + "lea{<imodesuffix>}\t{%a1, %0|%0, %a1}" [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn "*lea_1_rex64" + (set_attr "mode" "<MODE>")]) + +(define_insn "*lea_2" [(set (match_operand:SI 0 "register_operand" "=r") (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))] "TARGET_64BIT" @@ -5951,25 +5971,1200 @@ [(set_attr "type" "lea") (set_attr "mode" "SI")]) -(define_insn "*lea_1_zext" +(define_insn "*lea_2_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))] + (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))] "TARGET_64BIT" "lea{l}\t{%a1, %k0|%k0, %a1}" [(set_attr "type" "lea") (set_attr "mode" "SI")]) -(define_insn "*lea_2_rex64" - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:DI 1 "no_seg_address_operand" "p"))] - "TARGET_64BIT" - "lea{q}\t{%a1, %0|%0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "DI")]) - -;; The lea patterns for non-Pmodes needs to be matched by several -;; insns converted to real lea by splitters. +(define_insn "*add<mode>_1" + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r") + (plus:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r") + (match_operand:SWI48 2 "<general_operand>" "<g>,r<i>,0,l<i>"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); + return "lea{<imodesuffix>}\t{%a2, %0|%0, %a2}"; + + case TYPE_INCDEC: + gcc_assert (rtx_equal_p (operands[0], operands[1])); + if (operands[2] == const1_rtx) + return "inc{<imodesuffix>}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{<imodesuffix>}\t%0"; + } + + default: + /* Use add as much as possible to replace lea for AGU optimization. */ + if (which_alternative == 2 && TARGET_OPT_AGU) + return "add{<imodesuffix>}\t{%1, %0|%0, %1}"; + + 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>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{<imodesuffix>}\t{%2, %0|%0, %2}"; + } + return "add{<imodesuffix>}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (eq_attr "alternative" "2") + (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) + (const_string "lea") + (eq_attr "alternative" "3") + (const_string "lea") + ; Current assemblers are broken and do not allow @GOTOFF in + ; ought but a memory context. + (match_operand:SWI48 2 "pic_symbolic_operand" "") + (const_string "lea") + (match_operand:SWI48 2 "incdec_operand" "") + (const_string "incdec") + ] + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "<MODE>")]) + +;; It may seem that nonimmediate operand is proper one for operand 1. +;; The addsi_1 pattern allows nonimmediate operand at that place and +;; we take care in ix86_binary_operator_ok to not allow two memory +;; operands so proper swapping will be done in reload. This allow +;; patterns constructed from addsi_1 to match. + +(define_insn "*addsi_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (zero_extend:DI + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r") + (match_operand:SI 2 "general_operand" "g,li")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + operands[2] = XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0); + return "lea{l}\t{%a2, %k0|%k0, %a2}"; + + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{l}\t%k0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%k0"; + } + + 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}"; + } + return "add{l}\t{%2, %k0|%k0, %2}"; + } +} + [(set (attr "type") + (cond [(eq_attr "alternative" "1") + (const_string "lea") + ; Current assemblers are broken and do not allow @GOTOFF in + ; ought but a memory context. + (match_operand:SI 2 "pic_symbolic_operand" "") + (const_string "lea") + (match_operand:SI 2 "incdec_operand" "") + (const_string "incdec") + ] + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "SI")]) + +(define_insn "*addhi_1" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") + (match_operand:HI 2 "general_operand" "rn,rm"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, HImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{w}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } + + 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}"; + } + return "add{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "HI")]) + +;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah +;; type optimizations enabled by define-splits. This is not important +;; for PII, and in fact harmful because of partial register stalls. + +(define_insn "*addhi_1_lea" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r") + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r") + (match_operand:HI 2 "general_operand" "rn,rm,ln"))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, HImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return "#"; + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{w}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } + + 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}"; + } + return "add{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (eq_attr "alternative" "2") + (const_string "lea") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu")))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "HI,HI,SI")]) + +(define_insn "*addqi_1" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:QI 2 "general_operand" "qn,qmn,rn"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, QImode, operands)" +{ + int widen = (which_alternative == 2); + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; + } + + 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))) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + if (widen) + return "sub{l}\t{%2, %k0|%k0, %2}"; + else + return "sub{b}\t{%2, %0|%0, %2}"; + } + if (widen) + return "add{l}\t{%k2, %k0|%k0, %k2}"; + else + return "add{b}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "QI,QI,SI")]) + +;; %%% Potential partial reg stall on alternative 2. What to do? +(define_insn "*addqi_1_lea" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r") + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r") + (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln"))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, QImode, operands)" +{ + int widen = (which_alternative == 2); + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return "#"; + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; + } + + 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))) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + if (widen) + return "sub{l}\t{%2, %k0|%k0, %2}"; + else + return "sub{b}\t{%2, %0|%0, %2}"; + } + if (widen) + return "add{l}\t{%k2, %k0|%k0, %k2}"; + else + return "add{b}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (eq_attr "alternative" "3") + (const_string "lea") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu")))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "QI,QI,SI,SI")]) + +(define_insn "*addqi_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) + (plus:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "qn,qnm"))) + (clobber (reg:CC FLAGS_REG))] + "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[1] == const1_rtx) + return "inc{b}\t%0"; + else + { + gcc_assert (operands[1] == constm1_rtx); + return "dec{b}\t%0"; + } + + 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}"; + } + return "add{b}\t{%1, %0|%0, %1}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:QI 1 "incdec_operand" "") + (const_string "incdec") + (const_string "alu1"))) + (set (attr "memory") + (if_then_else (match_operand 1 "memory_operand" "") + (const_string "load") + (const_string "none"))) + (set_attr "mode" "QI")]) + +(define_insn "*add<mode>_2" + [(set (reg FLAGS_REG) + (compare + (plus:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI48 2 "<general_operand>" "<g>,r<i>")) + (const_int 0))) + (set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm") + (plus:SWI48 (match_dup 1) (match_dup 2)))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (PLUS, <MODE>mode, operands) + /* Current assemblers are broken and do not allow @GOTOFF in + ought but a memory context. */ + && ! pic_symbolic_operand (operands[2], VOIDmode)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + gcc_assert (rtx_equal_p (operands[0], operands[1])); + if (operands[2] == const1_rtx) + return "inc{<imodesuffix>}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{<imodesuffix>}\t%0"; + } + + default: + 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>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{<imodesuffix>}\t{%2, %0|%0, %2}"; + } + return "add{<imodesuffix>}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:SWI48 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "<MODE>")]) + +;; See comment for addsi_1_zext why we do use nonimmediate_operand +(define_insn "*addsi_2_zext" + [(set (reg FLAGS_REG) + (compare + (plus: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 (plus:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (PLUS, SImode, operands) + /* Current assemblers are broken and do not allow @GOTOFF in + ought but a memory context. */ + && ! pic_symbolic_operand (operands[2], VOIDmode)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{l}\t%k0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%k0"; + } + + 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}"; + } + return "add{l}\t{%2, %k0|%k0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:SI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "SI")]) + +(define_insn "*addhi_2" + [(set (reg FLAGS_REG) + (compare + (plus: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") + (plus:HI (match_dup 1) (match_dup 2)))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (PLUS, HImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{w}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } + + 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}"; + } + return "add{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "HI")]) + +(define_insn "*addqi_2" + [(set (reg FLAGS_REG) + (compare + (plus: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") + (plus:QI (match_dup 1) (match_dup 2)))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (PLUS, QImode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{b}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%0"; + } + + 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}"; + } + return "add{b}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set_attr "mode" "QI")]) + +(define_insn "*add<mode>_3" + [(set (reg FLAGS_REG) + (compare + (neg:SWI48 (match_operand:SWI48 2 "<general_operand>" "<g>")) + (match_operand:SWI48 1 "nonimmediate_operand" "%0"))) + (clobber (match_scratch:SWI48 0 "=r"))] + "ix86_match_ccmode (insn, CCZmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2])) + /* Current assemblers are broken and do not allow @GOTOFF in + ought but a memory context. */ + && ! pic_symbolic_operand (operands[2], VOIDmode)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + gcc_assert (rtx_equal_p (operands[0], operands[1])); + if (operands[2] == const1_rtx) + return "inc{<imodesuffix>}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{<imodesuffix>}\t%0"; + } + + default: + 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>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{<imodesuffix>}\t{%2, %0|%0, %2}"; + } + return "add{<imodesuffix>}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:SWI48 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "<MODE>")]) + +;; See comment for addsi_1_zext why we do use nonimmediate_operand +(define_insn "*addsi_3_zext" + [(set (reg FLAGS_REG) + (compare + (neg:SI (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 1 "nonimmediate_operand" "%0"))) + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode) + && ix86_binary_operator_ok (PLUS, SImode, operands) + /* Current assemblers are broken and do not allow @GOTOFF in + ought but a memory context. */ + && ! pic_symbolic_operand (operands[2], VOIDmode)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{l}\t%k0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%k0"; + } + + 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}"; + } + return "add{l}\t{%2, %k0|%k0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:SI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "SI")]) + +(define_insn "*addhi_3" + [(set (reg FLAGS_REG) + (compare + (neg:HI (match_operand:HI 2 "general_operand" "rmn")) + (match_operand:HI 1 "nonimmediate_operand" "%0"))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCZmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2]))" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{w}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } + + 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}"; + } + return "add{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "HI")]) + +(define_insn "*addqi_3" + [(set (reg FLAGS_REG) + (compare + (neg:QI (match_operand:QI 2 "general_operand" "qmn")) + (match_operand:QI 1 "nonimmediate_operand" "%0"))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCZmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2]))" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{b}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%0"; + } + + 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}"; + } + return "add{b}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set_attr "mode" "QI")]) + +; For comparisons against 1, -1 and 128, we may generate better code +; 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. + +(define_insn "*adddi_4" + [(set (reg FLAGS_REG) + (compare + (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:DI 2 "x86_64_immediate_operand" "e"))) + (clobber (match_scratch:DI 0 "=rm"))] + "TARGET_64BIT + && ix86_match_ccmode (insn, CCGCmode)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == constm1_rtx) + return "inc{q}\t%0"; + else + { + gcc_assert (operands[2] == const1_rtx); + return "dec{q}\t%0"; + } + + 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}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:DI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "DI")]) + +; For comparisons against 1, -1 and 128, we may generate better code +; 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. + +(define_insn "*addsi_4" + [(set (reg FLAGS_REG) + (compare + (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" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == constm1_rtx) + return "inc{l}\t%0"; + else + { + gcc_assert (operands[2] == const1_rtx); + return "dec{l}\t%0"; + } + + 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}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:SI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "SI")]) + +; See comments above addsi_4 for details. + +(define_insn "*addhi_4" + [(set (reg FLAGS_REG) + (compare + (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" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == constm1_rtx) + return "inc{w}\t%0"; + else + { + gcc_assert (operands[2] == const1_rtx); + return "dec{w}\t%0"; + } + + 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}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "HI")]) + +; See comments above addsi_4 for details. + +(define_insn "*addqi_4" + [(set (reg FLAGS_REG) + (compare + (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" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)) + return "inc{b}\t%0"; + else + { + gcc_assert (operands[2] == const1_rtx); + return "dec{b}\t%0"; + } + + 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}"; + } + return "sub{b}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set_attr "mode" "QI")]) + +(define_insn "*add<mode>_5" + [(set (reg FLAGS_REG) + (compare + (plus:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "%0") + (match_operand:SWI48 2 "<general_operand>" "<g>")) + (const_int 0))) + (clobber (match_scratch:SWI48 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2])) + /* Current assemblers are broken and do not allow @GOTOFF in + ought but a memory context. */ + && ! pic_symbolic_operand (operands[2], VOIDmode)" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + gcc_assert (rtx_equal_p (operands[0], operands[1])); + if (operands[2] == const1_rtx) + return "inc{<imodesuffix>}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{<imodesuffix>}\t%0"; + } + + 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>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{<imodesuffix>}\t{%2, %0|%0, %2}"; + } + return "add{<imodesuffix>}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:SWI48 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "<MODE>")]) + +(define_insn "*addhi_5" + [(set (reg FLAGS_REG) + (compare + (plus: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, CCGOCmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2]))" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{w}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } + + 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}"; + } + return "add{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "HI")]) + +(define_insn "*addqi_5" + [(set (reg FLAGS_REG) + (compare + (plus: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, CCGOCmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2]))" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{b}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%0"; + } + + 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}"; + } + return "add{b}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set_attr "mode" "QI")]) + +(define_insn "*addqi_ext_1_rex64" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (plus:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (match_operand:QI 2 "nonmemory_operand" "Qn"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{b}\t%h0"; + else + { + gcc_assert (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%h0"; + } + + default: + return "add{b}\t{%2, %h0|%h0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set_attr "modrm" "1") + (set_attr "mode" "QI")]) + +(define_insn "addqi_ext_1" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (plus:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (match_operand:QI 2 "general_operand" "Qmn"))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT" +{ + switch (get_attr_type (insn)) + { + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return "inc{b}\t%h0"; + else + { + gcc_assert (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%h0"; + } + + default: + return "add{b}\t{%2, %h0|%h0, %2}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set_attr "modrm" "1") + (set_attr "mode" "QI")]) + +(define_insn "*addqi_ext_2" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (plus: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)))) + (clobber (reg:CC FLAGS_REG))] + "" + "add{b}\t{%h2, %h0|%h0, %h2}" + [(set_attr "type" "alu") + (set_attr "mode" "QI")]) + +;; The lea patterns for non-Pmodes needs to be matched by +;; several insns converted to real lea by splitters. (define_insn_and_split "*lea_general_1" [(set (match_operand 0 "register_operand" "=r") @@ -6005,8 +7200,9 @@ (define_insn_and_split "*lea_general_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "register_operand" "r")) + (plus:SI (plus:SI + (match_operand:SI 1 "index_register_operand" "l") + (match_operand:SI 2 "register_operand" "r")) (match_operand:SI 3 "immediate_operand" "i"))))] "TARGET_64BIT" "#" @@ -6055,8 +7251,9 @@ (define_insn_and_split "*lea_general_2_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "const248_operand" "n")) + (plus:SI (mult:SI + (match_operand:SI 1 "index_register_operand" "l") + (match_operand:SI 2 "const248_operand" "n")) (match_operand:SI 3 "nonmemory_operand" "ri"))))] "TARGET_64BIT" "#" @@ -6108,10 +7305,11 @@ (define_insn_and_split "*lea_general_3_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (plus:SI (mult:SI - (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "const248_operand" "n")) - (match_operand:SI 3 "register_operand" "r")) + (plus:SI (plus:SI + (mult:SI + (match_operand:SI 1 "index_register_operand" "l") + (match_operand:SI 2 "const248_operand" "n")) + (match_operand:SI 3 "register_operand" "r")) (match_operand:SI 4 "immediate_operand" "i"))))] "TARGET_64BIT" "#" @@ -6129,330 +7327,26 @@ [(set_attr "type" "lea") (set_attr "mode" "SI")]) -(define_insn "*adddi_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:DI 2 "x86_64_general_operand" "rme,re,le"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_LEA: - operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); - return "lea{q}\t{%a2, %0|%0, %a2}"; - - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{q}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{q}\t%0"; - } - - 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. */ - && ((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{q}\t{%2, %0|%0, %2}"; - } - return "add{q}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "2") - (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. - (match_operand:DI 2 "pic_symbolic_operand" "") - (const_string "lea") - (match_operand:DI 2 "incdec_operand" "") - (const_string "incdec") - ] - (const_string "alu"))) - (set_attr "mode" "DI")]) - ;; Convert lea to the lea pattern to avoid flags dependency. (define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "x86_64_nonmemory_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" + "TARGET_64BIT && reload_completed + && ix86_lea_for_add_ok (PLUS, insn, operands)" [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))] "") -(define_insn "*adddi_2_rex64" - [(set (reg FLAGS_REG) - (compare - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "rme,re")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm") - (plus:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, DImode, operands) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{q}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{q}\t%0"; - } - - default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* ???? 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. */ - && ((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{q}\t{%2, %0|%0, %2}"; - } - return "add{q}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:DI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "DI")]) - -(define_insn "*adddi_3_rex64" - [(set (reg FLAGS_REG) - (compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme")) - (match_operand:DI 1 "x86_64_general_operand" "%0"))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCZmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2])) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{q}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{q}\t%0"; - } - - default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* ???? 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. */ - && ((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{q}\t{%2, %0|%0, %2}"; - } - return "add{q}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:DI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "DI")]) - -; For comparisons against 1, -1 and 128, we may generate better code -; 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. -(define_insn "*adddi_4_rex64" - [(set (reg FLAGS_REG) - (compare (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:DI 2 "x86_64_immediate_operand" "e"))) - (clobber (match_scratch:DI 0 "=rm"))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCGCmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == constm1_rtx) - return "inc{q}\t%0"; - else - { - gcc_assert (operands[2] == const1_rtx); - return "dec{q}\t%0"; - } - - 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}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:DI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "DI")]) - -(define_insn "*adddi_5_rex64" - [(set (reg FLAGS_REG) - (compare - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0") - (match_operand:DI 2 "x86_64_general_operand" "rme")) - (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCGOCmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2])) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{q}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{q}\t%0"; - } - - 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. */ - && ((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{q}\t{%2, %0|%0, %2}"; - } - return "add{q}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:DI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "DI")]) - - -(define_insn "*addsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:SI 2 "general_operand" "g,ri,li"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_LEA: - operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); - return "lea{l}\t{%a2, %0|%0, %a2}"; - - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{l}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%0"; - } - - 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]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %0|%0, %2}"; - } - return "add{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "2") - (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. - (match_operand:SI 2 "pic_symbolic_operand" "") - (const_string "lea") - (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - ] - (const_string "alu"))) - (set_attr "mode" "SI")]) - ;; Convert lea to the lea pattern to avoid flags dependency. (define_split [(set (match_operand 0 "register_operand" "") (plus (match_operand 1 "register_operand" "") (match_operand 2 "nonmemory_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" + "reload_completed && ix86_lea_for_add_ok (PLUS, insn, operands)" [(const_int 0)] { rtx pat; @@ -6471,61 +7365,6 @@ DONE; }) -;; It may seem that nonimmediate operand is proper one for operand 1. -;; The addsi_1 pattern allows nonimmediate operand at that place and -;; we take care in ix86_binary_operator_ok to not allow two memory -;; operands so proper swapping will be done in reload. This allow -;; patterns constructed from addsi_1 to match. -(define_insn "addsi_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r") - (match_operand:SI 2 "general_operand" "g,li")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_LEA: - operands[2] = XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0); - return "lea{l}\t{%a2, %k0|%k0, %a2}"; - - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{l}\t%k0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%k0"; - } - - 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}"; - } - return "add{l}\t{%2, %k0|%k0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "1") - (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. - (match_operand:SI 2 "pic_symbolic_operand" "") - (const_string "lea") - (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - ] - (const_string "alu"))) - (set_attr "mode" "SI")]) - ;; Convert lea to the lea pattern to avoid flags dependency. (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -6541,1122 +7380,48 @@ operands[1] = gen_lowpart (Pmode, operands[1]); operands[2] = gen_lowpart (Pmode, operands[2]); }) - -(define_insn "*addsi_2" - [(set (reg FLAGS_REG) - (compare - (plus: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") - (plus:SI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, SImode, operands) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{l}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%0"; - } - - 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]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %0|%0, %2}"; - } - return "add{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "SI")]) - -;; See comment for addsi_1_zext why we do use nonimmediate_operand -(define_insn "*addsi_2_zext" - [(set (reg FLAGS_REG) - (compare - (plus: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 (plus:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, SImode, operands) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{l}\t%k0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%k0"; - } - - 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}"; - } - return "add{l}\t{%2, %k0|%k0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "SI")]) - -(define_insn "*addsi_3" - [(set (reg FLAGS_REG) - (compare (neg:SI (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 1 "nonimmediate_operand" "%0"))) - (clobber (match_scratch:SI 0 "=r"))] - "ix86_match_ccmode (insn, CCZmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2])) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{l}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%0"; - } - - 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]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %0|%0, %2}"; - } - return "add{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "SI")]) - -;; See comment for addsi_1_zext why we do use nonimmediate_operand -(define_insn "*addsi_3_zext" - [(set (reg FLAGS_REG) - (compare (neg:SI (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 1 "nonimmediate_operand" "%0"))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode) - && ix86_binary_operator_ok (PLUS, SImode, operands) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{l}\t%k0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%k0"; - } - - 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}"; - } - return "add{l}\t{%2, %k0|%k0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "SI")]) - -; For comparisons against 1, -1 and 128, we may generate better code -; 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. -(define_insn "*addsi_4" - [(set (reg FLAGS_REG) - (compare (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" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == constm1_rtx) - return "inc{l}\t%0"; - else - { - gcc_assert (operands[2] == const1_rtx); - return "dec{l}\t%0"; - } - - 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}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "SI")]) - -(define_insn "*addsi_5" - [(set (reg FLAGS_REG) - (compare - (plus: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, CCGOCmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2])) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{l}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%0"; - } - - 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]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %0|%0, %2}"; - } - return "add{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "SI")]) - -(define_expand "addhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;") - -;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah -;; type optimizations enabled by define-splits. This is not important -;; for PII, and in fact harmful because of partial register stalls. - -(define_insn "*addhi_1_lea" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:HI 2 "general_operand" "rn,rm,ln"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (PLUS, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_LEA: - return "#"; - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{w}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; - } - - 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{w}\t{%2, %0|%0, %2}"; - } - return "add{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (eq_attr "alternative" "2") - (const_string "lea") - (if_then_else (match_operand:HI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu")))) - (set_attr "mode" "HI,HI,SI")]) - -(define_insn "*addhi_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "rn,rm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (PLUS, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{w}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; - } - - 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{w}\t{%2, %0|%0, %2}"; - } - return "add{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "HI")]) - -(define_insn "*addhi_2" - [(set (reg FLAGS_REG) - (compare - (plus: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") - (plus:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{w}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; - } - - 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{w}\t{%2, %0|%0, %2}"; - } - return "add{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "HI")]) - -(define_insn "*addhi_3" - [(set (reg FLAGS_REG) - (compare (neg:HI (match_operand:HI 2 "general_operand" "rmn")) - (match_operand:HI 1 "nonimmediate_operand" "%0"))) - (clobber (match_scratch:HI 0 "=r"))] - "ix86_match_ccmode (insn, CCZmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{w}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; - } - - 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{w}\t{%2, %0|%0, %2}"; - } - return "add{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "HI")]) - -; See comments above addsi_4 for details. -(define_insn "*addhi_4" - [(set (reg FLAGS_REG) - (compare (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" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == constm1_rtx) - return "inc{w}\t%0"; - else - { - gcc_assert (operands[2] == const1_rtx); - return "dec{w}\t%0"; - } - - 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{w}\t{%2, %0|%0, %2}"; - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "add{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "SI")]) - - -(define_insn "*addhi_5" - [(set (reg FLAGS_REG) - (compare - (plus: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, CCGOCmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{w}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; - } - - 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{w}\t{%2, %0|%0, %2}"; - } - return "add{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "HI")]) - -(define_expand "addqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;") - -;; %%% Potential partial reg stall on alternative 2. What to do? -(define_insn "*addqi_1_lea" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r") - (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (PLUS, QImode, operands)" -{ - int widen = (which_alternative == 2); - switch (get_attr_type (insn)) - { - case TYPE_LEA: - return "#"; - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; - } - - 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])); - if (widen) - return "sub{l}\t{%2, %k0|%k0, %2}"; - else - return "sub{b}\t{%2, %0|%0, %2}"; - } - if (widen) - return "add{l}\t{%k2, %k0|%k0, %k2}"; - else - return "add{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (eq_attr "alternative" "3") - (const_string "lea") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu")))) - (set_attr "mode" "QI,QI,SI,SI")]) - -(define_insn "*addqi_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "qn,qmn,rn"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (PLUS, QImode, operands)" -{ - int widen = (which_alternative == 2); - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; - } - - 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])); - if (widen) - return "sub{l}\t{%2, %k0|%k0, %2}"; - else - return "sub{b}\t{%2, %0|%0, %2}"; - } - if (widen) - return "add{l}\t{%k2, %k0|%k0, %k2}"; - else - return "add{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI,QI,SI")]) - -(define_insn "*addqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (plus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,qnm"))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[1] == const1_rtx) - return "inc{b}\t%0"; - else - { - gcc_assert (operands[1] == constm1_rtx); - return "dec{b}\t%0"; - } - - default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. */ - 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}"; - } - return "add{b}\t{%1, %0|%0, %1}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 1 "incdec_operand" "") - (const_string "incdec") - (const_string "alu1"))) - (set (attr "memory") - (if_then_else (match_operand 1 "memory_operand" "") - (const_string "load") - (const_string "none"))) - (set_attr "mode" "QI")]) - -(define_insn "*addqi_2" - [(set (reg FLAGS_REG) - (compare - (plus: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") - (plus:QI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, QImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)); - return "dec{b}\t%0"; - } - - 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}"; - } - return "add{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI")]) - -(define_insn "*addqi_3" - [(set (reg FLAGS_REG) - (compare (neg:QI (match_operand:QI 2 "general_operand" "qmn")) - (match_operand:QI 1 "nonimmediate_operand" "%0"))) - (clobber (match_scratch:QI 0 "=q"))] - "ix86_match_ccmode (insn, CCZmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)); - return "dec{b}\t%0"; - } - - 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}"; - } - return "add{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI")]) - -; See comments above addsi_4 for details. -(define_insn "*addqi_4" - [(set (reg FLAGS_REG) - (compare (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" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)) - return "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == const1_rtx); - return "dec{b}\t%0"; - } - - 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}"; - } - return "sub{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI")]) - - -(define_insn "*addqi_5" - [(set (reg FLAGS_REG) - (compare - (plus: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, CCGOCmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)); - return "dec{b}\t%0"; - } - - 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}"; - } - return "add{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI")]) - - -(define_insn "addqi_ext_1" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (plus:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "0") - (const_int 8) - (const_int 8)) - (match_operand:QI 2 "general_operand" "Qmn"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{b}\t%h0"; - else - { - gcc_assert (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)); - return "dec{b}\t%h0"; - } - - default: - return "add{b}\t{%2, %h0|%h0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI")]) - -(define_insn "*addqi_ext_1_rex64" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (plus:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "0") - (const_int 8) - (const_int 8)) - (match_operand:QI 2 "nonmemory_operand" "Qn"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{b}\t%h0"; - else - { - gcc_assert (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)); - return "dec{b}\t%h0"; - } - - default: - return "add{b}\t{%2, %h0|%h0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI")]) - -(define_insn "*addqi_ext_2" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (plus: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)))) - (clobber (reg:CC FLAGS_REG))] - "" - "add{b}\t{%h2, %h0|%h0, %h2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI")]) - -;; The patterns that match these are at the end of this file. - -(define_expand "addxf3" - [(set (match_operand:XF 0 "register_operand" "") - (plus:XF (match_operand:XF 1 "register_operand" "") - (match_operand:XF 2 "register_operand" "")))] - "TARGET_80387" - "") - -(define_expand "add<mode>3" - [(set (match_operand:MODEF 0 "register_operand" "") - (plus:MODEF (match_operand:MODEF 1 "register_operand" "") - (match_operand:MODEF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" - "") ;; Subtract instructions -;; %%% splits for subditi3 - -(define_expand "subti3" - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (minus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;") - -(define_insn "*subti3_1" - [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o") - (minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0") - (match_operand:TI 2 "x86_64_general_operand" "roe,re"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)" - "#") - -(define_split - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (minus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))]) +(define_expand "sub<mode>3" + [(set (match_operand:SDWIM 0 "nonimmediate_operand" "") + (minus:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand" "") + (match_operand:SDWIM 2 "<general_operand>" "")))] + "" + "ix86_expand_binary_operator (MINUS, <MODE>mode, operands); DONE;") + +(define_insn_and_split "*sub<dwi>3_doubleword" + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o") + (minus:<DWI> + (match_operand:<DWI> 1 "nonimmediate_operand" "0,0") + (match_operand:<DWI> 2 "<general_operand>" "ro<di>,r<di>"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)" + "#" + "reload_completed" + [(parallel [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (minus:DWIH (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) - (minus:DI (match_dup 4) - (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 5)))) - (clobber (reg:CC FLAGS_REG))])] - "split_ti (&operands[0], 3, &operands[0], &operands[3]);") - -;; %%% splits for subsidi3 - -(define_expand "subdi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "x86_64_general_operand" "")))] - "" - "ix86_expand_binary_operator (MINUS, DImode, operands); DONE;") - -(define_insn "*subdi3_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:DI 2 "general_operand" "roiF,riF"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" - "#") - -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "general_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) - (parallel [(set (match_dup 3) - (minus:SI (match_dup 4) - (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 5)))) - (clobber (reg:CC FLAGS_REG))])] - "split_di (&operands[0], 3, &operands[0], &operands[3]);") - -(define_insn "subdi3_carry_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") - (match_operand:DI 2 "x86_64_general_operand" "re,rm")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" - "sbb{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "mode" "DI")]) - -(define_insn "*subdi_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (minus: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 (MINUS, DImode, operands)" - "sub{q}\t{%2, %0|%0, %2}" + (minus:DWIH + (match_dup 4) + (plus:DWIH + (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 5)))) + (clobber (reg:CC FLAGS_REG))])] + "split_<dwi> (&operands[0], 3, &operands[0], &operands[3]);") + +(define_insn "*sub<mode>_1" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)" + "sub{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*subdi_2_rex64" - [(set (reg FLAGS_REG) - (compare - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (minus:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (MINUS, DImode, operands)" - "sub{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*subdi_3_rex63" - [(set (reg FLAGS_REG) - (compare (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (minus:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "subqi3_carry" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") - (match_operand:QI 2 "general_operand" "qn,qm")))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, QImode, operands)" - "sbb{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "mode" "QI")]) - -(define_insn "subhi3_carry" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") - (match_operand:HI 2 "general_operand" "rn,rm")))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, HImode, operands)" - "sbb{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "mode" "HI")]) - -(define_insn "subsi3_carry" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") - (match_operand:SI 2 "general_operand" "ri,rm")))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, SImode, operands)" - "sbb{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (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_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_expand "subsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "ix86_expand_binary_operator (MINUS, SImode, operands); DONE;") - -(define_insn "*subsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) (define_insn "*subsi_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -7669,19 +7434,31 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*subsi_2" - [(set (reg FLAGS_REG) - (compare - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_dup 1) (match_dup 2)))] +(define_insn "*subqi_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) + (minus:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "qn,qm"))) + (clobber (reg:CC FLAGS_REG))] + "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "sub{b}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + +(define_insn "*sub<mode>_2" + [(set (reg FLAGS_REG) + (compare + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") + (minus:SWI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{l}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (MINUS, <MODE>mode, operands)" + "sub{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) (define_insn "*subsi_2_zext" [(set (reg FLAGS_REG) @@ -7699,17 +7476,17 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*subsi_3" - [(set (reg FLAGS_REG) - (compare (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm"))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_dup 1) (match_dup 2)))] +(define_insn "*sub<mode>_3" + [(set (reg FLAGS_REG) + (compare (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") + (minus:SWI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{l}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (MINUS, <MODE>mode, operands)" + "sub{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) (define_insn "*subsi_3_zext" [(set (reg FLAGS_REG) @@ -7723,150 +7500,181 @@ && ix86_binary_operator_ok (MINUS, SImode, operands)" "sub{l}\t{%2, %1|%1, %2}" [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_expand "subhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (MINUS, HImode, operands); DONE;") - -(define_insn "*subhi_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:HI 2 "general_operand" "rn,rm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, HImode, operands)" - "sub{w}\t{%2, %0|%0, %2}" + (set_attr "mode" "SI")]) + +;; Add with carry and subtract with borrow + +(define_expand "<plusminus_insn><mode>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 "<general_operand>" "")))) + (clobber (reg:CC FLAGS_REG))])] + "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)" + "") + +(define_insn "*<plusminus_insn><mode>3_carry" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") + (plusminus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0") + (plus:SWI + (match_operator 3 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m")))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" + "<plusminus_carry_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_insn "*subhi_2" - [(set (reg FLAGS_REG) - (compare - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:HI 2 "general_operand" "rn,rm")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (MINUS, HImode, operands)" - "sub{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_insn "*subhi_3" - [(set (reg FLAGS_REG) - (compare (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:HI 2 "general_operand" "rn,rm"))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (MINUS, HImode, operands)" - "sub{w}\t{%2, %0|%0, %2}" + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<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 "mode" "HI")]) - -(define_expand "subqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (MINUS, QImode, operands); DONE;") - -(define_insn "*subqi_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "general_operand" "qn,qm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, QImode, operands)" - "sub{b}\t{%2, %0|%0, %2}" + (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 "*add<mode>3_cconly_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0") + (match_operand:SWI 2 "<general_operand>" "<r><i>m")) + (match_dup 1))) + (clobber (match_scratch:SWI 0 "=<r>"))] + "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" + "add{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) - -(define_insn "*subqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (minus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,qm"))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "sub{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) - -(define_insn "*subqi_2" - [(set (reg FLAGS_REG) - (compare - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "general_operand" "qn,qm")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (MINUS, QImode, operands)" - "sub{b}\t{%2, %0|%0, %2}" + (set_attr "mode" "<MODE>")]) + +(define_insn "*sub<mode>3_cconly_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (minus:SWI + (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>") + (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")) + (match_dup 0)))] + "" + "cmp{<imodesuffix>}\t{%1, %0|%0, %1}" + [(set_attr "type" "icmp") + (set_attr "mode" "<MODE>")]) + +(define_insn "*<plusminus_insn><mode>3_cc_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plusminus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0") + (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m")) + (match_dup 1))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") + (plusminus:SWI (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)" + "<plusminus_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) - -(define_insn "*subqi_3" - [(set (reg FLAGS_REG) - (compare (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "general_operand" "qn,qm"))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (MINUS, QImode, operands)" - "sub{b}\t{%2, %0|%0, %2}" + (set_attr "mode" "<MODE>")]) + +(define_insn "*<plusminus_insn>si3_zext_cc_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plusminus:SI + (match_operand:SI 1 "nonimmediate_operand" "<comm>0") + (match_operand:SI 2 "general_operand" "g")) + (match_dup 1))) + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)" + "<plusminus_mnemonic>{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) + (set_attr "mode" "SI")]) ;; The patterns that match these are at the end of this file. -(define_expand "subxf3" +(define_expand "<plusminus_insn>xf3" [(set (match_operand:XF 0 "register_operand" "") - (minus:XF (match_operand:XF 1 "register_operand" "") - (match_operand:XF 2 "register_operand" "")))] + (plusminus:XF + (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") -(define_expand "sub<mode>3" +(define_expand "<plusminus_insn><mode>3" [(set (match_operand:MODEF 0 "register_operand" "") - (minus:MODEF (match_operand:MODEF 1 "register_operand" "") - (match_operand:MODEF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" + (plusminus:MODEF + (match_operand:MODEF 1 "register_operand" "") + (match_operand:MODEF 2 "nonimmediate_operand" "")))] + "(TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode)) + || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" "") ;; Multiply instructions -(define_expand "muldi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (mult:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_64BIT" +(define_expand "mul<mode>3" + [(parallel [(set (match_operand:SWIM248 0 "register_operand" "") + (mult:SWIM248 + (match_operand:SWIM248 1 "register_operand" "") + (match_operand:SWIM248 2 "<general_operand>" ""))) + (clobber (reg:CC FLAGS_REG))])] + "" + "") + +(define_expand "mulqi3" + [(parallel [(set (match_operand:QI 0 "register_operand" "") + (mult:QI + (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "nonimmediate_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_QIMODE_MATH" "") ;; On AMDFAM10 -;; IMUL reg64, reg64, imm8 Direct -;; IMUL reg64, mem64, imm8 VectorPath -;; IMUL reg64, reg64, imm32 Direct -;; IMUL reg64, mem64, imm32 VectorPath -;; IMUL reg64, reg64 Direct -;; IMUL reg64, mem64 Direct - -(define_insn "*muldi3_1_rex64" - [(set (match_operand:DI 0 "register_operand" "=r,r,r") - (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,rm,0") - (match_operand:DI 2 "x86_64_general_operand" "K,e,mr"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "@ - imul{q}\t{%2, %1, %0|%0, %1, %2} - imul{q}\t{%2, %1, %0|%0, %1, %2} - imul{q}\t{%2, %0|%0, %2}" +;; IMUL reg32/64, reg32/64, imm8 Direct +;; IMUL reg32/64, mem32/64, imm8 VectorPath +;; IMUL reg32/64, reg32/64, imm32 Direct +;; IMUL reg32/64, mem32/64, imm32 VectorPath +;; IMUL reg32/64, reg32/64 Direct +;; IMUL reg32/64, mem32/64 Direct + +(define_insn "*mul<mode>3_1" + [(set (match_operand:SWI48 0 "register_operand" "=r,r,r") + (mult:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "%rm,rm,0") + (match_operand:SWI48 2 "<general_operand>" "K,<i>,mr"))) + (clobber (reg:CC FLAGS_REG))] + "!(MEM_P (operands[1]) && MEM_P (operands[2]))" + "@ + imul{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + imul{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + imul{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "imul") (set_attr "prefix_0f" "0,0,1") (set (attr "athlon_decode") @@ -7883,51 +7691,7 @@ (match_operand 1 "memory_operand" "")) (const_string "vector")] (const_string "direct"))) - (set_attr "mode" "DI")]) - -(define_expand "mulsi3" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "general_operand" ""))) - (clobber (reg:CC FLAGS_REG))])] - "" - "") - -;; On AMDFAM10 -;; IMUL reg32, reg32, imm8 Direct -;; IMUL reg32, mem32, imm8 VectorPath -;; IMUL reg32, reg32, imm32 Direct -;; IMUL reg32, mem32, imm32 VectorPath -;; IMUL reg32, reg32 Direct -;; IMUL reg32, mem32 Direct - -(define_insn "*mulsi3_1" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0") - (match_operand:SI 2 "general_operand" "K,i,mr"))) - (clobber (reg:CC FLAGS_REG))] - "!(MEM_P (operands[1]) && MEM_P (operands[2]))" - "@ - imul{l}\t{%2, %1, %0|%0, %1, %2} - imul{l}\t{%2, %1, %0|%0, %1, %2} - imul{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "imul") - (set_attr "prefix_0f" "0,0,1") - (set (attr "athlon_decode") - (cond [(eq_attr "cpu" "athlon") - (const_string "vector") - (eq_attr "alternative" "1") - (const_string "vector") - (and (eq_attr "alternative" "2") - (match_operand 1 "memory_operand" "")) - (const_string "vector")] - (const_string "direct"))) - (set (attr "amdfam10_decode") - (cond [(and (eq_attr "alternative" "0,1") - (match_operand 1 "memory_operand" "")) - (const_string "vector")] - (const_string "direct"))) - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) (define_insn "*mulsi3_1_zext" [(set (match_operand:DI 0 "register_operand" "=r,r,r") @@ -7959,14 +7723,6 @@ (const_string "direct"))) (set_attr "mode" "SI")]) -(define_expand "mulhi3" - [(parallel [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_HIMODE_MATH" - "") - ;; On AMDFAM10 ;; IMUL reg16, reg16, imm8 VectorPath ;; IMUL reg16, mem16, imm8 VectorPath @@ -7974,12 +7730,14 @@ ;; IMUL reg16, mem16, imm16 VectorPath ;; IMUL reg16, reg16 Direct ;; IMUL reg16, mem16 Direct + (define_insn "*mulhi3_1" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:HI 2 "general_operand" "K,n,mr"))) (clobber (reg:CC FLAGS_REG))] - "!(MEM_P (operands[1]) && MEM_P (operands[2]))" + "TARGET_HIMODE_MATH + && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "@ imul{w}\t{%2, %1, %0|%0, %1, %2} imul{w}\t{%2, %1, %0|%0, %1, %2} @@ -7998,14 +7756,6 @@ (const_string "direct"))) (set_attr "mode" "HI")]) -(define_expand "mulqi3" - [(parallel [(set (match_operand:QI 0 "register_operand" "") - (mult:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "register_operand" ""))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_QIMODE_MATH" - "") - ;;On AMDFAM10 ;; MUL reg8 Direct ;; MUL mem8 Direct @@ -8027,158 +7777,38 @@ (set_attr "amdfam10_decode" "direct") (set_attr "mode" "QI")]) -(define_expand "umulqihi3" +(define_expand "<u>mul<mode><dwi>3" + [(parallel [(set (match_operand:<DWI> 0 "register_operand" "") + (mult:<DWI> + (any_extend:<DWI> + (match_operand:DWIH 1 "nonimmediate_operand" "")) + (any_extend:<DWI> + (match_operand:DWIH 2 "register_operand" "")))) + (clobber (reg:CC FLAGS_REG))])] + "" + "") + +(define_expand "<u>mulqihi3" [(parallel [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "")) - (zero_extend:HI - (match_operand:QI 2 "register_operand" "")))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_QIMODE_MATH" - "") - -(define_insn "*umulqihi3_1" - [(set (match_operand:HI 0 "register_operand" "=a") - (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) - (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_QIMODE_MATH - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "mul{b}\t%2" - [(set_attr "type" "imul") - (set_attr "length_immediate" "0") - (set (attr "athlon_decode") - (if_then_else (eq_attr "cpu" "athlon") - (const_string "vector") - (const_string "direct"))) - (set_attr "amdfam10_decode" "direct") - (set_attr "mode" "QI")]) - -(define_expand "mulqihi3" - [(parallel [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")) - (sign_extend:HI (match_operand:QI 2 "register_operand" "")))) + (mult:HI + (any_extend:HI + (match_operand:QI 1 "nonimmediate_operand" "")) + (any_extend:HI + (match_operand:QI 2 "register_operand" "")))) (clobber (reg:CC FLAGS_REG))])] "TARGET_QIMODE_MATH" "") -(define_insn "*mulqihi3_insn" - [(set (match_operand:HI 0 "register_operand" "=a") - (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) - (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_QIMODE_MATH - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "imul{b}\t%2" - [(set_attr "type" "imul") - (set_attr "length_immediate" "0") - (set (attr "athlon_decode") - (if_then_else (eq_attr "cpu" "athlon") - (const_string "vector") - (const_string "direct"))) - (set_attr "amdfam10_decode" "direct") - (set_attr "mode" "QI")]) - -(define_expand "umulditi3" - [(parallel [(set (match_operand:TI 0 "register_operand" "") - (mult:TI (zero_extend:TI - (match_operand:DI 1 "nonimmediate_operand" "")) - (zero_extend:TI - (match_operand:DI 2 "register_operand" "")))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_64BIT" - "") - -(define_insn "*umulditi3_insn" - [(set (match_operand:TI 0 "register_operand" "=A") - (mult:TI (zero_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0")) - (zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "mul{q}\t%2" - [(set_attr "type" "imul") - (set_attr "length_immediate" "0") - (set (attr "athlon_decode") - (if_then_else (eq_attr "cpu" "athlon") - (const_string "vector") - (const_string "double"))) - (set_attr "amdfam10_decode" "double") - (set_attr "mode" "DI")]) - -;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers -(define_expand "umulsidi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (mult:DI (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "")) - (zero_extend:DI - (match_operand:SI 2 "register_operand" "")))) - (clobber (reg:CC FLAGS_REG))])] - "!TARGET_64BIT" - "") - -(define_insn "*umulsidi3_insn" - [(set (match_operand:DI 0 "register_operand" "=A") - (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0")) - (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "mul{l}\t%2" - [(set_attr "type" "imul") - (set_attr "length_immediate" "0") - (set (attr "athlon_decode") - (if_then_else (eq_attr "cpu" "athlon") - (const_string "vector") - (const_string "double"))) - (set_attr "amdfam10_decode" "double") - (set_attr "mode" "SI")]) - -(define_expand "mulditi3" - [(parallel [(set (match_operand:TI 0 "register_operand" "") - (mult:TI (sign_extend:TI - (match_operand:DI 1 "nonimmediate_operand" "")) - (sign_extend:TI - (match_operand:DI 2 "register_operand" "")))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_64BIT" - "") - -(define_insn "*mulditi3_insn" - [(set (match_operand:TI 0 "register_operand" "=A") - (mult:TI (sign_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0")) - (sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "imul{q}\t%2" - [(set_attr "type" "imul") - (set_attr "length_immediate" "0") - (set (attr "athlon_decode") - (if_then_else (eq_attr "cpu" "athlon") - (const_string "vector") - (const_string "double"))) - (set_attr "amdfam10_decode" "double") - (set_attr "mode" "DI")]) - -(define_expand "mulsidi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (mult:DI (sign_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "")) - (sign_extend:DI - (match_operand:SI 2 "register_operand" "")))) - (clobber (reg:CC FLAGS_REG))])] - "!TARGET_64BIT" - "") - -(define_insn "*mulsidi3_insn" - [(set (match_operand:DI 0 "register_operand" "=A") - (mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0")) - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "imul{l}\t%2" +(define_insn "*<u>mul<mode><dwi>3_1" + [(set (match_operand:<DWI> 0 "register_operand" "=A") + (mult:<DWI> + (any_extend:<DWI> + (match_operand:DWIH 1 "nonimmediate_operand" "%0")) + (any_extend:<DWI> + (match_operand:DWIH 2 "nonimmediate_operand" "rm")))) + (clobber (reg:CC FLAGS_REG))] + "!(MEM_P (operands[1]) && MEM_P (operands[2]))" + "<sgnprefix>mul{<imodesuffix>}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") (set (attr "athlon_decode") @@ -8186,72 +7816,58 @@ (const_string "vector") (const_string "double"))) (set_attr "amdfam10_decode" "double") - (set_attr "mode" "SI")]) - -(define_expand "umuldi3_highpart" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (truncate:DI - (lshiftrt:TI - (mult:TI (zero_extend:TI - (match_operand:DI 1 "nonimmediate_operand" "")) - (zero_extend:TI - (match_operand:DI 2 "register_operand" ""))) - (const_int 64)))) - (clobber (match_scratch:DI 3 "")) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_64BIT" - "") - -(define_insn "*umuldi3_highpart_rex64" + (set_attr "mode" "<MODE>")]) + +(define_insn "*<u>mulqihi3_1" + [(set (match_operand:HI 0 "register_operand" "=a") + (mult:HI + (any_extend:HI + (match_operand:QI 1 "nonimmediate_operand" "%0")) + (any_extend:HI + (match_operand:QI 2 "nonimmediate_operand" "qm")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_QIMODE_MATH + && !(MEM_P (operands[1]) && MEM_P (operands[2]))" + "<sgnprefix>mul{b}\t%2" + [(set_attr "type" "imul") + (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "direct"))) + (set_attr "amdfam10_decode" "direct") + (set_attr "mode" "QI")]) + +(define_expand "<s>mul<mode>3_highpart" + [(parallel [(set (match_operand:SWI48 0 "register_operand" "") + (truncate:SWI48 + (lshiftrt:<DWI> + (mult:<DWI> + (any_extend:<DWI> + (match_operand:SWI48 1 "nonimmediate_operand" "")) + (any_extend:<DWI> + (match_operand:SWI48 2 "register_operand" ""))) + (match_dup 4)))) + (clobber (match_scratch:SWI48 3 "")) + (clobber (reg:CC FLAGS_REG))])] + "" + "operands[4] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));") + +(define_insn "*<s>muldi3_highpart_1" [(set (match_operand:DI 0 "register_operand" "=d") (truncate:DI (lshiftrt:TI - (mult:TI (zero_extend:TI - (match_operand:DI 1 "nonimmediate_operand" "%a")) - (zero_extend:TI - (match_operand:DI 2 "nonimmediate_operand" "rm"))) + (mult:TI + (any_extend:TI + (match_operand:DI 1 "nonimmediate_operand" "%a")) + (any_extend:TI + (match_operand:DI 2 "nonimmediate_operand" "rm"))) (const_int 64)))) (clobber (match_scratch:DI 3 "=1")) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "mul{q}\t%2" - [(set_attr "type" "imul") - (set_attr "length_immediate" "0") - (set (attr "athlon_decode") - (if_then_else (eq_attr "cpu" "athlon") - (const_string "vector") - (const_string "double"))) - (set_attr "amdfam10_decode" "double") - (set_attr "mode" "DI")]) - -(define_expand "umulsi3_highpart" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (truncate:SI - (lshiftrt:DI - (mult:DI (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "")) - (zero_extend:DI - (match_operand:SI 2 "register_operand" ""))) - (const_int 32)))) - (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC FLAGS_REG))])] - "" - "") - -(define_insn "*umulsi3_highpart_insn" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI - (lshiftrt:DI - (mult:DI (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "%a")) - (zero_extend:DI - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (const_int 32)))) - (clobber (match_scratch:SI 3 "=1")) - (clobber (reg:CC FLAGS_REG))] - "!(MEM_P (operands[1]) && MEM_P (operands[2]))" - "mul{l}\t%2" + "<sgnprefix>mul{q}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") (set (attr "athlon_decode") @@ -8259,22 +7875,22 @@ (const_string "vector") (const_string "double"))) (set_attr "amdfam10_decode" "double") - (set_attr "mode" "SI")]) - -(define_insn "*umulsi3_highpart_zext" - [(set (match_operand:DI 0 "register_operand" "=d") - (zero_extend:DI (truncate:SI + (set_attr "mode" "DI")]) + +(define_insn "*<s>mulsi3_highpart_1" + [(set (match_operand:SI 0 "register_operand" "=d") + (truncate:SI (lshiftrt:DI - (mult:DI (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "%a")) - (zero_extend:DI - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (const_int 32))))) + (mult:DI + (any_extend:DI + (match_operand:SI 1 "nonimmediate_operand" "%a")) + (any_extend:DI + (match_operand:SI 2 "nonimmediate_operand" "rm"))) + (const_int 32)))) (clobber (match_scratch:SI 3 "=1")) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "mul{l}\t%2" + "!(MEM_P (operands[1]) && MEM_P (operands[2]))" + "<sgnprefix>mul{l}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") (set (attr "athlon_decode") @@ -8284,92 +7900,22 @@ (set_attr "amdfam10_decode" "double") (set_attr "mode" "SI")]) -(define_expand "smuldi3_highpart" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (truncate:DI - (lshiftrt:TI - (mult:TI (sign_extend:TI - (match_operand:DI 1 "nonimmediate_operand" "")) - (sign_extend:TI - (match_operand:DI 2 "register_operand" ""))) - (const_int 64)))) - (clobber (match_scratch:DI 3 "")) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_64BIT" - "") - -(define_insn "*smuldi3_highpart_rex64" - [(set (match_operand:DI 0 "register_operand" "=d") - (truncate:DI - (lshiftrt:TI - (mult:TI (sign_extend:TI - (match_operand:DI 1 "nonimmediate_operand" "%a")) - (sign_extend:TI - (match_operand:DI 2 "nonimmediate_operand" "rm"))) - (const_int 64)))) - (clobber (match_scratch:DI 3 "=1")) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "imul{q}\t%2" - [(set_attr "type" "imul") - (set (attr "athlon_decode") - (if_then_else (eq_attr "cpu" "athlon") - (const_string "vector") - (const_string "double"))) - (set_attr "amdfam10_decode" "double") - (set_attr "mode" "DI")]) - -(define_expand "smulsi3_highpart" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (truncate:SI - (lshiftrt:DI - (mult:DI (sign_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "")) - (sign_extend:DI - (match_operand:SI 2 "register_operand" ""))) - (const_int 32)))) - (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC FLAGS_REG))])] - "" - "") - -(define_insn "*smulsi3_highpart_insn" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI - (lshiftrt:DI - (mult:DI (sign_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "%a")) - (sign_extend:DI - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (const_int 32)))) - (clobber (match_scratch:SI 3 "=1")) - (clobber (reg:CC FLAGS_REG))] - "!(MEM_P (operands[1]) && MEM_P (operands[2]))" - "imul{l}\t%2" - [(set_attr "type" "imul") - (set (attr "athlon_decode") - (if_then_else (eq_attr "cpu" "athlon") - (const_string "vector") - (const_string "double"))) - (set_attr "amdfam10_decode" "double") - (set_attr "mode" "SI")]) - -(define_insn "*smulsi3_highpart_zext" +(define_insn "*<s>mulsi3_highpart_zext" [(set (match_operand:DI 0 "register_operand" "=d") (zero_extend:DI (truncate:SI (lshiftrt:DI - (mult:DI (sign_extend:DI + (mult:DI (any_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%a")) - (sign_extend:DI + (any_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))) (const_int 32))))) (clobber (match_scratch:SI 3 "=1")) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "imul{l}\t%2" + "<sgnprefix>mul{l}\t%2" [(set_attr "type" "imul") + (set_attr "length_immediate" "0") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") (const_string "vector") @@ -8390,31 +7936,20 @@ [(set (match_operand:MODEF 0 "register_operand" "") (mult:MODEF (match_operand:MODEF 1 "register_operand" "") (match_operand:MODEF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" - "") - -;; SSE5 scalar multiply/add instructions are defined in sse.md. - + "(TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode)) + || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" + "") ;; Divide instructions -(define_insn "divqi3" +(define_insn "<u>divqi3" [(set (match_operand:QI 0 "register_operand" "=a") - (div:QI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonimmediate_operand" "qm"))) + (any_div:QI + (match_operand:HI 1 "register_operand" "0") + (match_operand:QI 2 "nonimmediate_operand" "qm"))) (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" - "idiv{b}\t%2" - [(set_attr "type" "idiv") - (set_attr "mode" "QI")]) - -(define_insn "udivqi3" - [(set (match_operand:QI 0 "register_operand" "=a") - (udiv:QI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonimmediate_operand" "qm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_QIMODE_MATH" - "div{b}\t%2" + "<sgnprefix>div{b}\t%2" [(set_attr "type" "idiv") (set_attr "mode" "QI")]) @@ -8431,14 +7966,16 @@ [(set (match_operand:DF 0 "register_operand" "") (div:DF (match_operand:DF 1 "register_operand" "") (match_operand:DF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" + "(TARGET_80387 && X87_ENABLE_ARITH (DFmode)) + || (TARGET_SSE2 && TARGET_SSE_MATH)" "") (define_expand "divsf3" [(set (match_operand:SF 0 "register_operand" "") (div:SF (match_operand:SF 1 "register_operand" "") (match_operand:SF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || TARGET_SSE_MATH" + "(TARGET_80387 && X87_ENABLE_ARITH (SFmode)) + || TARGET_SSE_MATH" { if (TARGET_SSE_MATH && TARGET_RECIP && optimize_insn_for_speed_p () && flag_finite_math_only && !flag_trapping_math @@ -8450,296 +7987,111 @@ } }) -;; Remainder instructions. - -(define_expand "divmoddi4" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (div:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "nonimmediate_operand" ""))) - (set (match_operand:DI 3 "register_operand" "") - (mod:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_64BIT" - "") - -;; Allow to come the parameter in eax or edx to avoid extra moves. -;; Penalize eax case slightly because it results in worse scheduling -;; of code. -(define_insn "*divmoddi4_nocltd_rex64" - [(set (match_operand:DI 0 "register_operand" "=&a,?a") - (div:DI (match_operand:DI 2 "register_operand" "1,0") - (match_operand:DI 3 "nonimmediate_operand" "rm,rm"))) - (set (match_operand:DI 1 "register_operand" "=&d,&d") - (mod:DI (match_dup 2) (match_dup 3))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && optimize_function_for_speed_p (cfun) && !TARGET_USE_CLTD" - "#" - [(set_attr "type" "multi")]) - -(define_insn "*divmoddi4_cltd_rex64" - [(set (match_operand:DI 0 "register_operand" "=a") - (div:DI (match_operand:DI 2 "register_operand" "a") - (match_operand:DI 3 "nonimmediate_operand" "rm"))) - (set (match_operand:DI 1 "register_operand" "=&d") - (mod:DI (match_dup 2) (match_dup 3))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD)" - "#" - [(set_attr "type" "multi")]) - -(define_insn "*divmoddi_noext_rex64" - [(set (match_operand:DI 0 "register_operand" "=a") - (div:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:DI 3 "register_operand" "=d") - (mod:DI (match_dup 1) (match_dup 2))) - (use (match_operand:DI 4 "register_operand" "3")) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "idiv{q}\t%2" - [(set_attr "type" "idiv") - (set_attr "mode" "DI")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (div:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "nonimmediate_operand" ""))) - (set (match_operand:DI 3 "register_operand" "") - (mod:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed" - [(parallel [(set (match_dup 3) - (ashiftrt:DI (match_dup 4) (const_int 63))) - (clobber (reg:CC FLAGS_REG))]) - (parallel [(set (match_dup 0) - (div:DI (reg:DI 0) (match_dup 2))) - (set (match_dup 3) - (mod:DI (reg:DI 0) (match_dup 2))) - (use (match_dup 3)) - (clobber (reg:CC FLAGS_REG))])] -{ - /* Avoid use of cltd in favor of a mov+shift. */ - if (!TARGET_USE_CLTD && optimize_function_for_speed_p (cfun)) - { - if (true_regnum (operands[1])) - emit_move_insn (operands[0], operands[1]); - else - emit_move_insn (operands[3], operands[1]); - operands[4] = operands[3]; - } - else - { - gcc_assert (!true_regnum (operands[1])); - operands[4] = operands[1]; - } -}) - - -(define_expand "divmodsi4" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (div:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonimmediate_operand" ""))) - (set (match_operand:SI 3 "register_operand" "") - (mod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))])] - "" - "") - -;; Allow to come the parameter in eax or edx to avoid extra moves. -;; Penalize eax case slightly because it results in worse scheduling -;; of code. -(define_insn "*divmodsi4_nocltd" - [(set (match_operand:SI 0 "register_operand" "=&a,?a") - (div:SI (match_operand:SI 2 "register_operand" "1,0") - (match_operand:SI 3 "nonimmediate_operand" "rm,rm"))) - (set (match_operand:SI 1 "register_operand" "=&d,&d") - (mod:SI (match_dup 2) (match_dup 3))) - (clobber (reg:CC FLAGS_REG))] - "optimize_function_for_speed_p (cfun) && !TARGET_USE_CLTD" - "#" - [(set_attr "type" "multi")]) - -(define_insn "*divmodsi4_cltd" - [(set (match_operand:SI 0 "register_operand" "=a") - (div:SI (match_operand:SI 2 "register_operand" "a") - (match_operand:SI 3 "nonimmediate_operand" "rm"))) - (set (match_operand:SI 1 "register_operand" "=&d") - (mod:SI (match_dup 2) (match_dup 3))) - (clobber (reg:CC FLAGS_REG))] - "optimize_function_for_size_p (cfun) || TARGET_USE_CLTD" - "#" - [(set_attr "type" "multi")]) - -(define_insn "*divmodsi_noext" - [(set (match_operand:SI 0 "register_operand" "=a") - (div:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:SI 3 "register_operand" "=d") - (mod:SI (match_dup 1) (match_dup 2))) - (use (match_operand:SI 4 "register_operand" "3")) - (clobber (reg:CC FLAGS_REG))] - "" - "idiv{l}\t%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (div:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonimmediate_operand" ""))) - (set (match_operand:SI 3 "register_operand" "") - (mod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(parallel [(set (match_dup 3) - (ashiftrt:SI (match_dup 4) (const_int 31))) +;; Divmod instructions. + +(define_expand "divmod<mode>4" + [(parallel [(set (match_operand:SWIM248 0 "register_operand" "") + (div:SWIM248 + (match_operand:SWIM248 1 "register_operand" "") + (match_operand:SWIM248 2 "nonimmediate_operand" ""))) + (set (match_operand:SWIM248 3 "register_operand" "") + (mod:SWIM248 (match_dup 1) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] + "" + "") + +(define_insn_and_split "*divmod<mode>4" + [(set (match_operand:SWIM248 0 "register_operand" "=a") + (div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") + (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) + (set (match_operand:SWIM248 1 "register_operand" "=&d") + (mod:SWIM248 (match_dup 2) (match_dup 3))) + (clobber (reg:CC FLAGS_REG))] + "" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 1) + (ashiftrt:SWIM248 (match_dup 4) (match_dup 5))) (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 0) - (div:SI (reg:SI 0) (match_dup 2))) - (set (match_dup 3) - (mod:SI (reg:SI 0) (match_dup 2))) - (use (match_dup 3)) - (clobber (reg:CC FLAGS_REG))])] -{ - /* Avoid use of cltd in favor of a mov+shift. */ - if (!TARGET_USE_CLTD && optimize_function_for_speed_p (cfun)) - { - if (true_regnum (operands[1])) - emit_move_insn (operands[0], operands[1]); - else - emit_move_insn (operands[3], operands[1]); - operands[4] = operands[3]; - } - else - { - gcc_assert (!true_regnum (operands[1])); + (div:SWIM248 (match_dup 2) (match_dup 3))) + (set (match_dup 1) + (mod:SWIM248 (match_dup 2) (match_dup 3))) + (use (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1); + + if (<MODE>mode != HImode + && (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD)) + operands[4] = operands[2]; + else + { + /* Avoid use of cltd in favor of a mov+shift. */ + emit_move_insn (operands[1], operands[2]); operands[4] = operands[1]; } -}) -;; %%% Split me. -(define_insn "divmodhi4" - [(set (match_operand:HI 0 "register_operand" "=a") - (div:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:HI 3 "register_operand" "=&d") - (mod:HI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_HIMODE_MATH" - "cwtd\;idiv{w}\t%2" +} [(set_attr "type" "multi") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "udivmoddi4" - [(set (match_operand:DI 0 "register_operand" "=a") - (udiv:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:DI 3 "register_operand" "=&d") - (umod:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "xor{q}\t%3, %3\;div{q}\t%2" - [(set_attr "type" "multi") - (set_attr "length_immediate" "0") - (set_attr "mode" "DI")]) - -(define_insn "*udivmoddi4_noext" - [(set (match_operand:DI 0 "register_operand" "=a") - (udiv:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:DI 3 "register_operand" "=d") - (umod:DI (match_dup 1) (match_dup 2))) - (use (match_dup 3)) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "div{q}\t%2" + (set_attr "mode" "<MODE>")]) + +(define_insn "*divmod<mode>4_noext" + [(set (match_operand:SWIM248 0 "register_operand" "=a") + (div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") + (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) + (set (match_operand:SWIM248 1 "register_operand" "=d") + (mod:SWIM248 (match_dup 2) (match_dup 3))) + (use (match_operand:SWIM248 4 "register_operand" "1")) + (clobber (reg:CC FLAGS_REG))] + "" + "idiv{<imodesuffix>}\t%3" [(set_attr "type" "idiv") - (set_attr "mode" "DI")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (udiv:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "nonimmediate_operand" ""))) - (set (match_operand:DI 3 "register_operand" "") - (umod:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed" - [(set (match_dup 3) (const_int 0)) + (set_attr "mode" "<MODE>")]) + +(define_expand "udivmod<mode>4" + [(parallel [(set (match_operand:SWIM248 0 "register_operand" "") + (udiv:SWIM248 + (match_operand:SWIM248 1 "register_operand" "") + (match_operand:SWIM248 2 "nonimmediate_operand" ""))) + (set (match_operand:SWIM248 3 "register_operand" "") + (umod:SWIM248 (match_dup 1) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] + "" + "") + +(define_insn_and_split "*udivmod<mode>4" + [(set (match_operand:SWIM248 0 "register_operand" "=a") + (udiv:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") + (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) + (set (match_operand:SWIM248 1 "register_operand" "=&d") + (umod:SWIM248 (match_dup 2) (match_dup 3))) + (clobber (reg:CC FLAGS_REG))] + "" + "#" + "&& reload_completed" + [(set (match_dup 1) (const_int 0)) (parallel [(set (match_dup 0) - (udiv:DI (match_dup 1) (match_dup 2))) - (set (match_dup 3) - (umod:DI (match_dup 1) (match_dup 2))) - (use (match_dup 3)) - (clobber (reg:CC FLAGS_REG))])] - "") - -(define_insn "udivmodsi4" - [(set (match_operand:SI 0 "register_operand" "=a") - (udiv:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:SI 3 "register_operand" "=&d") - (umod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))] - "" - "xor{l}\t%3, %3\;div{l}\t%2" + (udiv:SWIM248 (match_dup 2) (match_dup 3))) + (set (match_dup 1) + (umod:SWIM248 (match_dup 2) (match_dup 3))) + (use (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] + "" [(set_attr "type" "multi") - (set_attr "length_immediate" "0") - (set_attr "mode" "SI")]) - -(define_insn "*udivmodsi4_noext" - [(set (match_operand:SI 0 "register_operand" "=a") - (udiv:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:SI 3 "register_operand" "=d") - (umod:SI (match_dup 1) (match_dup 2))) - (use (match_dup 3)) - (clobber (reg:CC FLAGS_REG))] - "" - "div{l}\t%2" + (set_attr "mode" "<MODE>")]) + +(define_insn "*udivmod<mode>4_noext" + [(set (match_operand:SWIM248 0 "register_operand" "=a") + (udiv:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") + (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) + (set (match_operand:SWIM248 1 "register_operand" "=d") + (umod:SWIM248 (match_dup 2) (match_dup 3))) + (use (match_operand:SWIM248 4 "register_operand" "1")) + (clobber (reg:CC FLAGS_REG))] + "" + "div{<imodesuffix>}\t%3" [(set_attr "type" "idiv") - (set_attr "mode" "SI")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (udiv:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonimmediate_operand" ""))) - (set (match_operand:SI 3 "register_operand" "") - (umod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(set (match_dup 3) (const_int 0)) - (parallel [(set (match_dup 0) - (udiv:SI (match_dup 1) (match_dup 2))) - (set (match_dup 3) - (umod:SI (match_dup 1) (match_dup 2))) - (use (match_dup 3)) - (clobber (reg:CC FLAGS_REG))])] - "") - -(define_expand "udivmodhi4" - [(set (match_dup 4) (const_int 0)) - (parallel [(set (match_operand:HI 0 "register_operand" "") - (udiv:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonimmediate_operand" ""))) - (set (match_operand:HI 3 "register_operand" "") - (umod:HI (match_dup 1) (match_dup 2))) - (use (match_dup 4)) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_HIMODE_MATH" - "operands[4] = gen_reg_rtx (HImode);") - -(define_insn "*udivmodhi_noext" - [(set (match_operand:HI 0 "register_operand" "=a") - (udiv:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:HI 3 "register_operand" "=d") - (umod:HI (match_dup 1) (match_dup 2))) - (use (match_operand:HI 4 "register_operand" "3")) - (clobber (reg:CC FLAGS_REG))] - "" - "div{w}\t%2" - [(set_attr "type" "idiv") - (set_attr "mode" "HI")]) + (set_attr "mode" "<MODE>")]) ;; We cannot use div/idiv for double division, because it causes ;; "division by zero" on the overflow and that's not what we expect @@ -8765,12 +8117,30 @@ ;; 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")) +(define_expand "testsi_ccno_1" + [(set (reg:CCNO FLAGS_REG) + (compare:CCNO + (and:SI (match_operand:SI 0 "nonimmediate_operand" "") + (match_operand:SI 1 "nonmemory_operand" "")) (const_int 0)))] + "" + "") + +(define_expand "testqi_ccz_1" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "") + (match_operand:QI 1 "nonmemory_operand" "")) + (const_int 0)))] + "" + "") + +(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]))" "@ @@ -8781,52 +8151,7 @@ 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 - (and:SI (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")) - (const_int 0)))] - "" - "") - -(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" "") - (match_operand:QI 1 "nonmemory_operand" "")) - (const_int 0)))] - "" - "") + (set_attr "mode" "SI,SI,DI,DI,DI")]) (define_insn "*testqi_1_maybe_si" [(set (reg FLAGS_REG) @@ -8853,19 +8178,19 @@ (set_attr "mode" "QI,QI,QI,SI") (set_attr "pent_pair" "uv,np,uv,np")]) -(define_insn "*testqi_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}" +(define_insn "*test<mode>_1" + [(set (reg FLAGS_REG) + (compare + (and:SWI124 + (match_operand:SWI124 0 "nonimmediate_operand" "%!*a,<r>,<r>m") + (match_operand:SWI124 1 "general_operand" "<i>,<i>,<r><i>")) + (const_int 0)))] + "ix86_match_ccmode (insn, CCNOmode) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "test{<imodesuffix>}\t{%1, %0|%0, %1}" [(set_attr "type" "test") (set_attr "modrm" "0,1,1") - (set_attr "mode" "QI") + (set_attr "mode" "<MODE>") (set_attr "pent_pair" "uv,np,uv")]) (define_expand "testqi_ext_ccno_0" @@ -8896,25 +8221,9 @@ [(set_attr "type" "test") (set_attr "mode" "QI") (set_attr "length_immediate" "1") + (set_attr "modrm" "1") (set_attr "pent_pair" "np")]) -(define_insn "*testqi_ext_1" - [(set (reg FLAGS_REG) - (compare - (and:SI - (zero_extract:SI - (match_operand 0 "ext_register_operand" "Q") - (const_int 8) - (const_int 8)) - (zero_extend:SI - (match_operand:QI 1 "general_operand" "Qm"))) - (const_int 0)))] - "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "test{b}\t{%1, %h0|%h0, %1}" - [(set_attr "type" "test") - (set_attr "mode" "QI")]) - (define_insn "*testqi_ext_1_rex64" [(set (reg FLAGS_REG) (compare @@ -8931,6 +8240,22 @@ [(set_attr "type" "test") (set_attr "mode" "QI")]) +(define_insn "*testqi_ext_1" + [(set (reg FLAGS_REG) + (compare + (and:SI + (zero_extract:SI + (match_operand 0 "ext_register_operand" "Q") + (const_int 8) + (const_int 8)) + (zero_extend:SI + (match_operand:QI 1 "general_operand" "Qm"))) + (const_int 0)))] + "!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_2" [(set (reg FLAGS_REG) (compare @@ -8949,24 +8274,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 @@ -8988,6 +8295,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" @@ -9087,22 +8412,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_insn "*anddi_1_rex64" +(define_expand "and<mode>3" + [(set (match_operand:SWIM 0 "nonimmediate_operand" "") + (and:SWIM (match_operand:SWIM 1 "nonimmediate_operand" "") + (match_operand:SWIM 2 "<general_szext_operand>" "")))] + "" + "ix86_expand_binary_operator (AND, <MODE>mode, operands); DONE;") + +(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)" { @@ -9123,9 +8448,9 @@ operands[1] = gen_lowpart (mode, operands[1]); if (mode == QImode) - return "movz{bq|x}\t{%1,%0|%0, %1}"; + return "movz{bl|x}\t{%1, %k0|%k0, %1}"; else - return "movz{wq|x}\t{%1,%0|%0, %1}"; + return "movz{wl|x}\t{%1, %k0|%k0, %1}"; } default: @@ -9138,30 +8463,14 @@ } [(set_attr "type" "alu,alu,alu,imovx") (set_attr "length_immediate" "*,*,*,0") - (set_attr "mode" "SI,DI,DI,DI")]) - -(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;") + (set (attr "prefix_rex") + (if_then_else + (and (eq_attr "type" "imovx") + (and (ne (symbol_ref "INTVAL (operands[2]) == 0xff") (const_int 0)) + (match_operand 1 "ext_QIreg_nomode_operand" ""))) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "SI,DI,DI,SI")]) (define_insn "*andsi_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r") @@ -9187,9 +8496,9 @@ operands[1] = gen_lowpart (mode, operands[1]); if (mode == QImode) - return "movz{bl|x}\t{%1,%0|%0, %1}"; + return "movz{bl|x}\t{%1, %0|%0, %1}"; else - return "movz{wl|x}\t{%1,%0|%0, %1}"; + return "movz{wl|x}\t{%1, %0|%0, %1}"; } default: @@ -9198,46 +8507,16 @@ } } [(set_attr "type" "alu,alu,imovx") + (set (attr "prefix_rex") + (if_then_else + (and (eq_attr "type" "imovx") + (and (ne (symbol_ref "INTVAL (operands[2]) == 0xff") (const_int 0)) + (match_operand 1 "ext_QIreg_nomode_operand" ""))) + (const_string "1") + (const_string "*"))) (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") @@ -9250,40 +8529,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") @@ -9306,28 +8551,14 @@ } [(set_attr "type" "alu,alu,imovx") (set_attr "length_immediate" "*,*,0") + (set (attr "prefix_rex") + (if_then_else + (and (eq_attr "type" "imovx") + (match_operand 1 "ext_QIreg_nomode_operand" "")) + (const_string "1") + (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") @@ -9347,17 +8578,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)))] @@ -9377,19 +8666,34 @@ [(set_attr "type" "alu") (set_attr "mode" "QI,QI,SI")]) -(define_insn "*andqi_2" - [(set (reg FLAGS_REG) - (compare (and:QI - (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qmn,qn")) +(define_insn "*and<mode>_2" + [(set (reg FLAGS_REG) + (compare (and:SWI124 + (match_operand:SWI124 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI124 2 "general_operand" "<g>,<r><i>")) (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" "=<r>,<r>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>mode, operands)" + "and{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) + (set_attr "mode" "<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) @@ -9399,7 +8703,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}" @@ -9409,7 +8713,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) @@ -9425,11 +8728,11 @@ "and{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "1") + (set_attr "modrm" "1") (set_attr "mode" "QI")]) ;; 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 @@ -9453,6 +8756,25 @@ "and{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 "*andqi_ext_1_rex64" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (and: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" + "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" @@ -9473,24 +8795,6 @@ (set_attr "length_immediate" "0") (set_attr "mode" "QI")]) -(define_insn "*andqi_ext_1_rex64" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (and: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" - "and{b}\t{%2, %h0|%h0, %2}" - [(set_attr "type" "alu") - (set_attr "length_immediate" "0") - (set_attr "mode" "QI")]) - (define_insn "*andqi_ext_2" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) @@ -9556,303 +8860,170 @@ 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_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"))) - (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}" +(define_expand "<code><mode>3" + [(set (match_operand:SWIM 0 "nonimmediate_operand" "") + (any_or:SWIM (match_operand:SWIM 1 "nonimmediate_operand" "") + (match_operand:SWIM 2 "<general_operand>" "")))] + "" + "ix86_expand_binary_operator (<CODE>, <MODE>mode, operands); DONE;") + +(define_insn "*<code><mode>_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 "<general_operand>" "<g>,r<i>"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)" + "<logicprefix>{<imodesuffix>}\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}" + (set_attr "mode" "<MODE>")]) + +;; %%% Potential partial reg stall on alternative 2. What to do? +(define_insn "*<code>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 (<CODE>, QImode, operands)" + "@ + <logicprefix>{b}\t{%2, %0|%0, %2} + <logicprefix>{b}\t{%2, %0|%0, %2} + <logicprefix>{l}\t{%k2, %k0|%k0, %k2}" [(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;") - -(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"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (IOR, SImode, operands)" - "or{l}\t{%2, %0|%0, %2}" - [(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 "*<code>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")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)" - "or{l}\t{%2, %k0|%k0, %2}" + (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 (<CODE>, SImode, operands)" + "<logicprefix>{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*iorsi_1_zext_imm" +(define_insn "*<code>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"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "or{l}\t{%2, %k0|%k0, %2}" + (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 && ix86_binary_operator_ok (<CODE>, SImode, operands)" + "<logicprefix>{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*iorsi_2" - [(set (reg FLAGS_REG) - (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "g,ri")) +(define_insn "*<code>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]))" + "<logicprefix>{b}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + +(define_insn "*<code><mode>_2" + [(set (reg FLAGS_REG) + (compare (any_or:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI 2 "<general_operand>" "<g>,<r><i>")) (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" "=<r>,<r>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 (<CODE>, <MODE>mode, operands)" + "<logicprefix>{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "<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" - [(set (reg FLAGS_REG) - (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) +(define_insn "*<code>si_2_zext" + [(set (reg FLAGS_REG) + (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 (<CODE>, SImode, operands)" + "<logicprefix>{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*iorsi_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")) +(define_insn "*<code>si_2_zext_imm" + [(set (reg FLAGS_REG) + (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}" - [(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}" + && ix86_binary_operator_ok (<CODE>, SImode, operands)" + "<logicprefix>{l}\t{%2, %k0|%k0, %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" - [(set (reg FLAGS_REG) - (compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") - (match_operand:QI 1 "general_operand" "qmn,qn")) + (set_attr "mode" "SI")]) + +(define_insn "*<code>qi_2_slp" + [(set (reg FLAGS_REG) + (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}" + "<logicprefix>{b}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) -(define_insn "*iorqi_3" - [(set (reg FLAGS_REG) - (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0") - (match_operand:QI 2 "general_operand" "qmn")) +(define_insn "*<code><mode>_3" + [(set (reg FLAGS_REG) + (compare (any_or:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0") + (match_operand:SWI 2 "<general_operand>" "<g>")) (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] + (clobber (match_scratch:SWI 0 "=<r>"))] "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "or{b}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)" + "<logicprefix>{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) - -(define_insn "*iorqi_ext_0" + (set_attr "mode" "<MODE>")]) + +(define_insn "*<code>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)" + "<logicprefix>{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "1") - (set_attr "mode" "QI")]) - -(define_insn "*iorqi_ext_1" + (set_attr "modrm" "1") + (set_attr "mode" "QI")]) + +(define_insn "*<code>qi_ext_1_rex64" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) - (ior: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")))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT - && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "or{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" - [(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) @@ -9862,16 +9033,35 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "or{b}\t{%2, %h0|%h0, %2}" + "<logicprefix>{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 "*<code>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:QI 2 "general_operand" "Qm")))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT + && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" + "<logicprefix>{b}\t{%2, %h0|%h0, %2}" + [(set_attr "type" "alu") + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) + +(define_insn "*<code>qi_ext_2" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (any_or:SI (zero_extract:SI (match_operand 1 "ext_register_operand" "0") (const_int 8) (const_int 8)) @@ -9879,16 +9069,16 @@ (const_int 8) (const_int 8)))) (clobber (reg:CC FLAGS_REG))] - "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))" - "or{b}\t{%h2, %h0|%h0, %h2}" + "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" + "<logicprefix>{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]) @@ -9896,9 +9086,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]); @@ -9908,8 +9098,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]) @@ -9918,342 +9108,59 @@ && (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_insn "*xordi_2_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}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*xordi_3_rex64" - [(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}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_expand "xorsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (xor:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "ix86_expand_binary_operator (XOR, SImode, 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"))) - (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")]) - -;; 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")))) - (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")]) - -(define_insn "*xorsi_1_zext_imm" - [(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"))) - (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")]) - -(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")]) - -;; 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 "*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))) - (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") - (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")]) - -(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"))) - (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")]) - -(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 "*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_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;") - -;; %%% 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"))) - (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")]) - -(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")]) - -(define_insn "*xorqi_ext_0" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + +(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 "*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_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))" - "xor{b}\t{%2, %h0|%h0, %2}" - [(set_attr "type" "alu") - (set_attr "length_immediate" "1") - (set_attr "mode" "QI")]) - -(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")))) - (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")]) - -(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))" + (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 "length_immediate" "0") - (set_attr "mode" "QI")]) - -(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)))) - (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")]) - -(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_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 "modrm" "1") (set_attr "mode" "QI")]) (define_insn "*xorqi_cc_ext_1" @@ -10270,212 +9177,64 @@ (const_int 8) (const_int 8)) (xor:SI - (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8)) + (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" "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 "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]);") + (set_attr "modrm" "1") + (set_attr "mode" "QI")]) ;; 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" +(define_expand "neg<mode>2" + [(set (match_operand:SDWIM 0 "nonimmediate_operand" "") + (neg:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand" "")))] + "" + "ix86_expand_unary_operator (NEG, <MODE>mode, operands); DONE;") + +(define_insn_and_split "*neg<dwi>2_doubleword" + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro") + (neg:<DWI> (match_operand:<DWI> 1 "nonimmediate_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (NEG, <DWI>mode, operands)" + "#" + "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)))]) + (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:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 3)) - (const_int 0))) + (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: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)" - "#") - -(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))) + (neg:DWIH (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" + "split_<dwi> (&operands[0], 2, &operands[0], &operands[2]);") + +(define_insn "*neg<mode>2_1" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (NEG, <MODE>mode, operands)" + "neg{<imodesuffix>}\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")]) + (set_attr "mode" "<MODE>")]) ;; 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))) + (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" @@ -10486,25 +9245,27 @@ ;; it really performs (compare 0 x), which leaves us with the zero ;; flag being the only useful item. -(define_insn "*negsi2_cmpz" +(define_insn "*neg<mode>2_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" + (compare:CCZ + (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (neg:SWI (match_dup 1)))] + "ix86_unary_operator_ok (NEG, <MODE>mode, operands)" + "neg{<imodesuffix>}\t%0" [(set_attr "type" "negnot") - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) (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))) + (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))) @@ -10514,58 +9275,6 @@ [(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 "<code><mode>2" @@ -10848,96 +9557,66 @@ ;; 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" +(define_expand "one_cmpl<mode>2" + [(set (match_operand:SWIM 0 "nonimmediate_operand" "") + (not:SWIM (match_operand:SWIM 1 "nonimmediate_operand" "")))] + "" + "ix86_expand_unary_operator (NOT, <MODE>mode, operands); DONE;") + +(define_insn "*one_cmpl<mode>2_1" + [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm") + (not:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "0")))] + "ix86_unary_operator_ok (NOT, <MODE>mode, operands)" + "not{<imodesuffix>}\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")) + (set_attr "mode" "<MODE>")]) + +;; %%% 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)" + "@ + not{b}\t%0 + not{l}\t%k0" + [(set_attr "type" "negnot") + (set_attr "mode" "QI,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_cmpl<mode>2_2" + [(set (reg FLAGS_REG) + (compare (not:SWI (match_operand:SWI 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 (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (not:SWI (match_dup 1)))] + "ix86_match_ccmode (insn, CCNOmode) + && ix86_unary_operator_ok (NOT, <MODE>mode, operands)" "#" [(set_attr "type" "alu1") - (set_attr "mode" "DI")]) + (set_attr "mode" "<MODE>")]) (define_split [(set (match_operand 0 "flags_reg_operand" "") (match_operator 2 "compare_operator" - [(not:DI (match_operand:DI 3 "nonimmediate_operand" "")) + [(not:SWI (match_operand:SWI 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)))] + (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:SI (match_dup 3) (const_int -1)) + (match_op_dup 2 [(xor:SWI (match_dup 3) (const_int -1)) (const_int 0)])) (set (match_dup 1) - (xor:SI (match_dup 3) (const_int -1)))])] + (xor:SWI (match_dup 3) (const_int -1)))])] "") ;; ??? Currently never generated - xor is used instead. @@ -10967,91 +9646,6 @@ (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 @@ -11084,35 +9678,6 @@ "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 "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 "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") @@ -11250,6 +9815,15 @@ (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. @@ -11309,6 +9883,15 @@ (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" @@ -11351,6 +9934,15 @@ (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" @@ -11490,6 +10082,15 @@ (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. @@ -11574,6 +10175,15 @@ (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. @@ -11635,6 +10245,15 @@ (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" @@ -11676,6 +10295,15 @@ (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" @@ -11718,6 +10346,15 @@ (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" @@ -11763,6 +10400,15 @@ (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" @@ -11797,6 +10443,15 @@ (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 @@ -11842,6 +10497,15 @@ (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" @@ -11883,6 +10547,15 @@ (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" @@ -11948,6 +10621,15 @@ (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" @@ -12000,6 +10682,15 @@ (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 @@ -12045,6 +10736,15 @@ (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" @@ -12086,6 +10786,15 @@ (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")]) ;; See comment above `ashldi3' about how this works. @@ -12204,10 +10913,8 @@ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" "sar{q}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:DI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "DI")]) (define_insn "*ashrdi3_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") @@ -12238,10 +10945,8 @@ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" "sar{q}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:DI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "DI")]) (define_insn "*ashrdi3_one_bit_cconly_rex64" [(set (reg FLAGS_REG) @@ -12256,7 +10961,8 @@ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" "sar{q}\t%0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (set_attr "mode" "DI")]) ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant @@ -12424,10 +11130,8 @@ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "sar{l}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*ashrsi3_1_one_bit_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -12439,7 +11143,8 @@ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "sar{l}\t%k0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*ashrsi3_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") @@ -12481,10 +11186,8 @@ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "sar{l}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*ashrsi3_one_bit_cconly" [(set (reg FLAGS_REG) @@ -12498,7 +11201,8 @@ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "sar{l}\t%0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*ashrsi3_one_bit_cmp_zext" [(set (reg FLAGS_REG) @@ -12514,7 +11218,8 @@ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "sar{l}\t%k0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (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 @@ -12580,10 +11285,8 @@ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" "sar{w}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "HI")]) (define_insn "*ashrhi3_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") @@ -12613,10 +11316,8 @@ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" "sar{w}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "HI")]) (define_insn "*ashrhi3_one_bit_cconly" [(set (reg FLAGS_REG) @@ -12630,7 +11331,8 @@ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" "sar{w}\t%0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (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 @@ -12680,10 +11382,8 @@ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" "sar{b}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) (define_insn "*ashrqi3_1_one_bit_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) @@ -12695,10 +11395,8 @@ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" "sar{b}\t%0" [(set_attr "type" "ishift1") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) (define_insn "*ashrqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") @@ -12741,10 +11439,8 @@ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" "sar{b}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) (define_insn "*ashrqi3_one_bit_cconly" [(set (reg FLAGS_REG) @@ -12758,7 +11454,8 @@ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" "sar{b}\t%0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (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 @@ -12804,35 +11501,6 @@ "TARGET_64BIT" "ix86_expand_binary_operator (LSHIFTRT, TImode, operands); DONE;") -;; This pattern must be defined before *lshrti3_1 to prevent -;; combine pass from converting sse2_lshrti3 to *lshrti3_1. - -(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}"; -} - [(set_attr "type" "sseishft") - (set_attr "prefix" "vex") - (set_attr "mode" "TI")]) - -(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" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return "psrldq\t{%2, %0|%0, %2}"; -} - [(set_attr "type" "sseishft") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - (define_insn "*lshrti3_1" [(set (match_operand:TI 0 "register_operand" "=r") (lshiftrt:TI (match_operand:TI 1 "register_operand" "0") @@ -12880,10 +11548,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{q}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:DI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "DI")]) (define_insn "*lshrdi3_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") @@ -12914,10 +11580,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{q}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:DI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "DI")]) (define_insn "*lshrdi3_cconly_one_bit_rex64" [(set (reg FLAGS_REG) @@ -12932,7 +11596,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{q}\t%0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (set_attr "mode" "DI")]) ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant @@ -13017,10 +11682,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{l}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*lshrsi3_1_one_bit_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -13032,7 +11695,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{l}\t%k0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*lshrsi3_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") @@ -13075,10 +11739,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{l}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*lshrsi3_one_bit_cconly" [(set (reg FLAGS_REG) @@ -13092,7 +11754,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{l}\t%0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*lshrsi3_cmp_one_bit_zext" [(set (reg FLAGS_REG) @@ -13108,7 +11771,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{l}\t%k0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (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 @@ -13174,10 +11838,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{w}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "HI")]) (define_insn "*lshrhi3_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") @@ -13207,10 +11869,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{w}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "HI")]) (define_insn "*lshrhi3_one_bit_cconly" [(set (reg FLAGS_REG) @@ -13224,7 +11884,8 @@ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{w}\t%0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (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 @@ -13274,10 +11935,8 @@ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" "shr{b}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) (define_insn "*lshrqi3_1_one_bit_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) @@ -13288,10 +11947,8 @@ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))" "shr{b}\t%0" [(set_attr "type" "ishift1") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) (define_insn "*lshrqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") @@ -13334,10 +11991,8 @@ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" "shr{b}\t%0" [(set_attr "type" "ishift") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) (define_insn "*lshrqi2_one_bit_cconly" [(set (reg FLAGS_REG) @@ -13351,7 +12006,8 @@ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" "shr{b}\t%0" [(set_attr "type" "ishift") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (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 @@ -13440,10 +12096,8 @@ && ix86_binary_operator_ok (ROTATE, DImode, operands)" "rol{q}\t%0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand:DI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "DI")]) (define_insn "*rotldi3_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") @@ -13473,10 +12127,8 @@ && ix86_binary_operator_ok (ROTATE, SImode, operands)" "rol{l}\t%0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*rotlsi3_1_one_bit_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -13489,7 +12141,8 @@ && ix86_binary_operator_ok (ROTATE, SImode, operands)" "rol{l}\t%k0" [(set_attr "type" "rotate") - (set_attr "length" "2")]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*rotlsi3_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") @@ -13532,10 +12185,8 @@ && ix86_binary_operator_ok (ROTATE, HImode, operands)" "rol{w}\t%0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "HI")]) (define_insn "*rotlhi3_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") @@ -13575,10 +12226,8 @@ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))" "rol{b}\t%0" [(set_attr "type" "rotate1") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) (define_insn "*rotlqi3_1_one_bit" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") @@ -13589,10 +12238,8 @@ && ix86_binary_operator_ok (ROTATE, QImode, operands)" "rol{b}\t%0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (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")) @@ -13672,10 +12319,8 @@ && ix86_binary_operator_ok (ROTATERT, DImode, operands)" "ror{q}\t%0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand:DI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "DI")]) (define_insn "*rotrdi3_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") @@ -13705,10 +12350,8 @@ && ix86_binary_operator_ok (ROTATERT, SImode, operands)" "ror{l}\t%0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*rotrsi3_1_one_bit_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -13721,10 +12364,8 @@ && ix86_binary_operator_ok (ROTATERT, SImode, operands)" "ror{l}\t%k0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand:SI 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "SI")]) (define_insn "*rotrsi3_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") @@ -13767,10 +12408,8 @@ && ix86_binary_operator_ok (ROTATERT, HImode, operands)" "ror{w}\t%0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "HI")]) (define_insn "*rotrhi3_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") @@ -13810,10 +12449,8 @@ && ix86_binary_operator_ok (ROTATERT, QImode, operands)" "ror{b}\t%0" [(set_attr "type" "rotate") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (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")) @@ -13824,10 +12461,8 @@ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))" "ror{b}\t%0" [(set_attr "type" "rotate1") - (set (attr "length") - (if_then_else (match_operand 0 "register_operand" "") - (const_string "2") - (const_string "*")))]) + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) (define_insn "*rotrqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") @@ -13935,7 +12570,9 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" "bts{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1")]) + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI")]) (define_insn "*btrq" [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") @@ -13945,7 +12582,9 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" "btr{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1")]) + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI")]) (define_insn "*btcq" [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") @@ -13955,7 +12594,9 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" "btc{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1")]) + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI")]) ;; Allow Nocona to avoid these instructions if a register is available. @@ -14066,7 +12707,9 @@ (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 "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI")]) (define_insn "*btsi" [(set (reg:CCC FLAGS_REG) @@ -14078,30 +12721,62 @@ (const_int 0)))] "TARGET_USE_BT || optimize_function_for_size_p (cfun)" "bt{l}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1")]) + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "SI")]) ;; Store-flag instructions. ;; For all sCOND expanders, also expand the compare or test insn that ;; generates cc0. Generate an equality comparison if `seq' or `sne'. -;; %%% Do the expansion to SImode. If PII, do things the xor+setcc way -;; to avoid partial register stalls. Otherwise do things the setcc+movzx -;; way, which can later delete the movzx if only QImode is needed. - -(define_expand "s<code>" - [(set (match_operand:QI 0 "register_operand" "") - (int_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (<CODE>, operands[0])) DONE; else FAIL;") - -(define_expand "s<code>" - [(set (match_operand:QI 0 "register_operand" "") - (fp_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (<CODE>, operands[0])) DONE; else FAIL;") - -(define_insn "*setcc_1" +(define_insn_and_split "*setcc_di_1" + [(set (match_operand:DI 0 "register_operand" "=q") + (match_operator:DI 1 "ix86_comparison_operator" + [(reg FLAGS_REG) (const_int 0)]))] + "TARGET_64BIT && !TARGET_PARTIAL_REG_STALL" + "#" + "&& reload_completed" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (zero_extend:DI (match_dup 2)))] +{ + PUT_MODE (operands[1], QImode); + operands[2] = gen_lowpart (QImode, operands[0]); +}) + +(define_insn_and_split "*setcc_si_1_and" + [(set (match_operand:SI 0 "register_operand" "=q") + (match_operator:SI 1 "ix86_comparison_operator" + [(reg FLAGS_REG) (const_int 0)])) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_PARTIAL_REG_STALL + && TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)" + "#" + "&& reload_completed" + [(set (match_dup 2) (match_dup 1)) + (parallel [(set (match_dup 0) (zero_extend:SI (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + PUT_MODE (operands[1], QImode); + operands[2] = gen_lowpart (QImode, operands[0]); +}) + +(define_insn_and_split "*setcc_si_1_movzbl" + [(set (match_operand:SI 0 "register_operand" "=q") + (match_operator:SI 1 "ix86_comparison_operator" + [(reg FLAGS_REG) (const_int 0)]))] + "!TARGET_PARTIAL_REG_STALL + && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun))" + "#" + "&& reload_completed" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (zero_extend:SI (match_dup 2)))] +{ + PUT_MODE (operands[1], QImode); + operands[2] = gen_lowpart (QImode, operands[0]); +}) + +(define_insn "*setcc_qi" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (match_operator:QI 1 "ix86_comparison_operator" [(reg FLAGS_REG) (const_int 0)]))] @@ -14110,7 +12785,7 @@ [(set_attr "type" "setcc") (set_attr "mode" "QI")]) -(define_insn "*setcc_2" +(define_insn "*setcc_qi_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (match_operator:QI 1 "ix86_comparison_operator" [(reg FLAGS_REG) (const_int 0)]))] @@ -14203,6 +12878,7 @@ "vcmp%D1s<ssemodefsuffix>\t{%3, %2, %0|%0, %2, %3}" [(set_attr "type" "ssecmp") (set_attr "prefix" "vex") + (set_attr "length_immediate" "1") (set_attr "mode" "<MODE>")]) (define_insn "*sse_setcc<mode>" @@ -14210,46 +12886,15 @@ (match_operator:MODEF 1 "sse_comparison_operator" [(match_operand:MODEF 2 "register_operand" "0") (match_operand:MODEF 3 "nonimmediate_operand" "xm")]))] - "SSE_FLOAT_MODE_P (<MODE>mode) && !TARGET_SSE5" + "SSE_FLOAT_MODE_P (<MODE>mode)" "cmp%D1s<ssemodefsuffix>\t{%3, %0|%0, %3}" [(set_attr "type" "ssecmp") - (set_attr "mode" "<MODE>")]) - -(define_insn "*sse5_setcc<mode>" - [(set (match_operand:MODEF 0 "register_operand" "=x") - (match_operator:MODEF 1 "sse5_comparison_float_operator" - [(match_operand:MODEF 2 "register_operand" "x") - (match_operand:MODEF 3 "nonimmediate_operand" "xm")]))] - "TARGET_SSE5" - "com%Y1s<ssemodefsuffix>\t{%3, %2, %0|%0, %2, %3}" - [(set_attr "type" "sse4arg") - (set_attr "mode" "<MODE>")]) - + (set_attr "length_immediate" "1") + (set_attr "mode" "<MODE>")]) ;; Basic conditional jump instructions. ;; We ignore the overflow flag for signed branch instructions. -;; For all bCOND expanders, also expand the compare or test insn that -;; generates reg FLAGS_REG. Generate an equality comparison if `beq' or `bne'. - -(define_expand "b<code>" - [(set (pc) - (if_then_else (int_cond:CC (reg:CC FLAGS_REG) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - "ix86_expand_branch (<CODE>, operands[0]); DONE;") - -(define_expand "b<code>" - [(set (pc) - (if_then_else (fp_cond:CC (reg:CC FLAGS_REG) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (<CODE>, operands[0]); DONE;") - (define_insn "*jcc_1" [(set (pc) (if_then_else (match_operator 1 "ix86_comparison_operator" @@ -14534,103 +13179,12 @@ (pc)))] "PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));") -;; Define combination compare-and-branch fp compare instructions to use -;; during early optimization. Splitting the operation apart early makes -;; for bad code when we want to reverse the operation. - -(define_insn "*fp_jcc_1_mixed" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f,x") - (match_operand 2 "nonimmediate_operand" "f,xm")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "TARGET_MIX_SSE_I387 - && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_1_sse" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "x") - (match_operand 2 "nonimmediate_operand" "xm")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "TARGET_SSE_MATH - && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_1_387" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "X87_FLOAT_MODE_P (GET_MODE (operands[1])) - && TARGET_CMOVE - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_2_mixed" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f,x") - (match_operand 2 "nonimmediate_operand" "f,xm")]) - (pc) - (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "TARGET_MIX_SSE_I387 - && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_2_sse" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "x") - (match_operand 2 "nonimmediate_operand" "xm")]) - (pc) - (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "TARGET_SSE_MATH - && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") - -(define_insn "*fp_jcc_2_387" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f")]) - (pc) - (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP FPSR_REG)) - (clobber (reg:CCFP FLAGS_REG))] - "X87_FLOAT_MODE_P (GET_MODE (operands[1])) - && TARGET_CMOVE - && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" - "#") +;; Define combination compare-and-branch fp compare instructions to help +;; combine. (define_insn "*fp_jcc_3_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "nonimmediate_operand" "fm")]) (label_ref (match_operand 3 "" "")) @@ -14641,15 +13195,14 @@ "TARGET_80387 && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && !ix86_use_fcomi_compare (GET_CODE (operands[0])) && SELECT_CC_MODE (GET_CODE (operands[0]), operands[1], operands[2]) == CCFPmode - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") (define_insn "*fp_jcc_4_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "nonimmediate_operand" "fm")]) (pc) @@ -14660,15 +13213,14 @@ "TARGET_80387 && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && !ix86_use_fcomi_compare (GET_CODE (operands[0])) && SELECT_CC_MODE (GET_CODE (operands[0]), operands[1], operands[2]) == CCFPmode - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") (define_insn "*fp_jcc_5_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "register_operand" "f")]) (label_ref (match_operand 3 "" "")) @@ -14678,12 +13230,12 @@ (clobber (match_scratch:HI 4 "=a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") (define_insn "*fp_jcc_6_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "register_operand" "f")]) (pc) @@ -14693,12 +13245,12 @@ (clobber (match_scratch:HI 4 "=a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") (define_insn "*fp_jcc_7_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "const0_operand" "")]) (label_ref (match_operand 3 "" "")) @@ -14708,10 +13260,9 @@ (clobber (match_scratch:HI 4 "=a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) - && !ix86_use_fcomi_compare (GET_CODE (operands[0])) && SELECT_CC_MODE (GET_CODE (operands[0]), operands[1], operands[2]) == CCFPmode - && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + && !TARGET_CMOVE" "#") ;; The order of operands in *fp_jcc_8_387 is forced by combine in @@ -14721,7 +13272,7 @@ (define_insn "*fp_jcc_8<mode>_387" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operator 1 "float_operator" [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")]) (match_operand 3 "register_operand" "f,f")]) @@ -14733,14 +13284,13 @@ "X87_FLOAT_MODE_P (GET_MODE (operands[3])) && (TARGET_USE_<MODE>MODE_FIOP || optimize_function_for_size_p (cfun)) && GET_MODE (operands[1]) == GET_MODE (operands[3]) - && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0]))) && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode - && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))" + && !TARGET_CMOVE" "#") (define_split [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "") (match_operand 2 "nonimmediate_operand" "")]) (match_operand 3 "" "") @@ -14757,7 +13307,7 @@ (define_split [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operand 1 "register_operand" "") (match_operand 2 "general_operand" "")]) (match_operand 3 "" "") @@ -14775,7 +13325,7 @@ (define_split [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operator 1 "float_operator" [(match_operand:X87MODEI12 2 "memory_operand" "")]) (match_operand 3 "register_operand" "")]) @@ -14797,7 +13347,7 @@ ;; %%% Kill this when reload knows how to do it. (define_split [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ix86_fp_comparison_operator" [(match_operator 1 "float_operator" [(match_operand:X87MODEI12 2 "register_operand" "")]) (match_operand 3 "register_operand" "")]) @@ -14944,7 +13494,7 @@ ;; 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" @@ -14955,15 +13505,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)) @@ -14976,8 +13528,9 @@ (define_insn "*call_pop_1" [(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")))] + (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)) @@ -14989,8 +13542,9 @@ (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")))] + (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 @@ -15121,10 +13675,11 @@ (call (match_operand:QI 1 "" "") (match_operand:SI 2 "" ""))) (use (match_operand:SI 3 "" ""))] - ;; Operand 2 not used on the i386. - "" -{ - ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 0); + ;; Operand 3 is not used on the i386. + "" +{ + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], NULL, 0); DONE; }) @@ -15133,10 +13688,11 @@ (call (match_operand:QI 1 "" "") (match_operand:SI 2 "" ""))) (use (match_operand:SI 3 "" ""))] - ;; Operand 2 not used on the i386. - "" -{ - ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 1); + ;; Operand 3 is not used on the i386. + "" +{ + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], NULL, 1); DONE; }) @@ -15163,9 +13719,9 @@ ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL), operands[0], const0_rtx, GEN_INT ((TARGET_64BIT - ? (DEFAULT_ABI == SYSV_ABI + ? (ix86_abi == SYSV_ABI ? X86_64_SSE_REGPARM_MAX - : X64_SSE_REGPARM_MAX) + : X86_64_MS_SSE_REGPARM_MAX) : X86_32_SSE_REGPARM_MAX) - 1), NULL, 0); @@ -15243,6 +13799,7 @@ "reload_completed" "ret" [(set_attr "length" "1") + (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) @@ -15254,7 +13811,8 @@ (unspec [(const_int 0)] UNSPEC_REP)] "reload_completed" "rep\;ret" - [(set_attr "length" "1") + [(set_attr "length" "2") + (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "0") (set_attr "prefix_rep" "1") (set_attr "modrm" "0")]) @@ -15265,6 +13823,7 @@ "reload_completed" "ret\t%0" [(set_attr "length" "3") + (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "2") (set_attr "modrm" "0")]) @@ -15284,16 +13843,26 @@ (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) -;; Align to 16-byte boundary, max skip in op0. Used to avoid +(define_insn "vswapmov" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "register_operand" "r")) + (unspec_volatile [(const_int 0)] UNSPECV_VSWAPMOV)] + "" + "movl.s\t{%1, %0|%0, %1}" + [(set_attr "length" "2") + (set_attr "length_immediate" "0") + (set_attr "modrm" "0")]) + +;; Pad to 16-byte boundary, max skip in op0. Used to avoid ;; branch prediction penalty for the third jump in a 16-byte ;; block on K8. -(define_insn "align" +(define_insn "pad" [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_ALIGN)] "" { -#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN - ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0])); +#ifdef ASM_OUTPUT_MAX_SKIP_PAD + ASM_OUTPUT_MAX_SKIP_PAD (asm_out_file, 4, (int)INTVAL (operands[0])); #else /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that. The align insn is used to avoid 3 jump instructions in the row to improve @@ -15334,7 +13903,8 @@ "TARGET_64BIT" "lea{q}\t{_GLOBAL_OFFSET_TABLE_(%%rip), %0|%0, _GLOBAL_OFFSET_TABLE_[rip]}" [(set_attr "type" "lea") - (set_attr "length" "6")]) + (set_attr "length_address" "4") + (set_attr "mode" "DI")]) (define_insn "set_rip_rex64" [(set (match_operand:DI 0 "register_operand" "=r") @@ -15342,7 +13912,8 @@ "TARGET_64BIT" "lea{q}\t{%l1(%%rip), %0|%0, %l1[rip]}" [(set_attr "type" "lea") - (set_attr "length" "6")]) + (set_attr "length_address" "4") + (set_attr "mode" "DI")]) (define_insn "set_got_offset_rex64" [(set (match_operand:DI 0 "register_operand" "=r") @@ -15352,7 +13923,9 @@ "TARGET_64BIT" "movabs{q}\t{$_GLOBAL_OFFSET_TABLE_-%l1, %0|%0, OFFSET FLAT:_GLOBAL_OFFSET_TABLE_-%l1}" [(set_attr "type" "imov") - (set_attr "length" "11")]) + (set_attr "length_immediate" "0") + (set_attr "length_address" "8") + (set_attr "mode" "DI")]) (define_expand "epilogue" [(const_int 0)] @@ -15378,21 +13951,16 @@ tmp = gen_rtx_MEM (Pmode, tmp); emit_move_insn (tmp, ra); - if (Pmode == SImode) - emit_jump_insn (gen_eh_return_si (sa)); - else - emit_jump_insn (gen_eh_return_di (sa)); + emit_jump_insn (gen_eh_return_internal ()); emit_barrier (); DONE; }) -(define_insn_and_split "eh_return_<mode>" - [(set (pc) - (unspec [(match_operand:P 0 "register_operand" "c")] - UNSPEC_EH_RETURN))] - "" - "#" - "reload_completed" +(define_insn_and_split "eh_return_internal" + [(eh_return)] + "" + "#" + "epilogue_completed" [(const_int 0)] "ix86_expand_epilogue (2); DONE;") @@ -15475,7 +14043,9 @@ (ctz:SI (match_dup 1)))] "" "bsf{l}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "1")]) + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "SI")]) (define_expand "ffsdi2" [(set (match_dup 2) (const_int -1)) @@ -15501,7 +14071,9 @@ (ctz:DI (match_dup 1)))] "TARGET_64BIT" "bsf{q}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "1")]) + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI")]) (define_insn "ctzsi2" [(set (match_operand:SI 0 "register_operand" "=r") @@ -15509,7 +14081,9 @@ (clobber (reg:CC FLAGS_REG))] "" "bsf{l}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "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") @@ -15517,7 +14091,9 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "bsf{q}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "1")]) + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI")]) (define_expand "clzsi2" [(parallel @@ -15547,14 +14123,15 @@ (set_attr "type" "bitmanip") (set_attr "mode" "SI")]) -(define_insn "*bsr" +(define_insn "bsr" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (const_int 31) (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))) (clobber (reg:CC FLAGS_REG))] "" "bsr{l}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "1") + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") (set_attr "mode" "SI")]) (define_insn "popcount<mode>2" @@ -15618,7 +14195,7 @@ (bswap:SI (match_operand:SI 1 "register_operand" "")))] "" { - if (!TARGET_BSWAP) + if (!(TARGET_BSWAP || TARGET_MOVBE)) { rtx x = operands[0]; @@ -15630,6 +14207,21 @@ } }) +(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]))" + "@ + 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" "2,*,*") + (set_attr "mode" "SI")]) + (define_insn "*bswapsi_1" [(set (match_operand:SI 0 "register_operand" "=r") (bswap:SI (match_operand:SI 1 "register_operand" "0")))] @@ -15658,7 +14250,29 @@ [(set_attr "length" "4") (set_attr "mode" "HI")]) -(define_insn "bswapdi2" +(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" @@ -15694,14 +14308,15 @@ (set_attr "type" "bitmanip") (set_attr "mode" "DI")]) -(define_insn "*bsr_rex64" +(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 "prefix_0f" "1") + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") (set_attr "mode" "DI")]) (define_expand "clzhi2" @@ -15739,7 +14354,8 @@ (clobber (reg:CC FLAGS_REG))] "" "bsr{w}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "1") + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") (set_attr "mode" "HI")]) (define_expand "paritydi2" @@ -15928,7 +14544,7 @@ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)] "TARGET_64BIT" - { return ".byte\t0x66\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")]) @@ -16116,7 +14732,7 @@ (clobber (reg:CC FLAGS_REG))])] "!TARGET_64BIT && TARGET_GNU2_TLS" { - operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); + operands[3] = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : operands[0]; ix86_tls_descriptor_calls_expanded_in_cfun = true; }) @@ -16165,7 +14781,7 @@ "" [(set (match_dup 0) (match_dup 5))] { - operands[5] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); + operands[5] = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : operands[0]; emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2])); }) @@ -16180,7 +14796,7 @@ (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT && TARGET_GNU2_TLS" { - operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); + operands[2] = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : operands[0]; ix86_tls_descriptor_calls_expanded_in_cfun = true; }) @@ -16224,7 +14840,7 @@ "" [(set (match_dup 0) (match_dup 4))] { - operands[4] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); + operands[4] = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : operands[0]; emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1])); }) @@ -16316,7 +14932,7 @@ (match_operator:MODEF 3 "binary_fp_operator" [(match_operand:MODEF 1 "nonimmediate_operand" "%0") (match_operand:MODEF 2 "nonimmediate_operand" "fm")]))] - "TARGET_80387 + "TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode) && COMMUTATIVE_ARITH_P (operands[3]) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "* return output_387_binary_op (insn, operands);" @@ -16386,6 +15002,7 @@ "TARGET_SSE_MATH" "%vrcpss\t{%1, %d0|%d0, %1}" [(set_attr "type" "sse") + (set_attr "atom_sse_attr" "rcp") (set_attr "prefix" "maybe_vex") (set_attr "mode" "SF")]) @@ -16430,7 +15047,8 @@ (match_operator:MODEF 3 "binary_fp_operator" [(match_operand:MODEF 1 "nonimmediate_operand" "0,fm") (match_operand:MODEF 2 "nonimmediate_operand" "fm,0")]))] - "TARGET_80387 && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) + "TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode) + && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) && !COMMUTATIVE_ARITH_P (operands[3]) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "* return output_387_binary_op (insn, operands);" @@ -16450,7 +15068,8 @@ [(float:MODEF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) (match_operand:MODEF 2 "register_operand" "0,0")]))] - "TARGET_80387 && !(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH) + "TARGET_80387 && X87_ENABLE_FLOAT (<MODEF:MODE>mode, <X87MODEI12:MODE>mode) + && !(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH) && (TARGET_USE_<X87MODEI12:MODE>MODE_FIOP || optimize_function_for_size_p (cfun))" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") @@ -16469,7 +15088,8 @@ [(match_operand:MODEF 1 "register_operand" "0,0") (float:MODEF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && !(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH) + "TARGET_80387 && X87_ENABLE_FLOAT (<MODEF:MODE>mode, <X87MODEI12:MODE>mode) + && !(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH) && (TARGET_USE_<X87MODEI12:MODE>MODE_FIOP || optimize_function_for_size_p (cfun))" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") @@ -16488,7 +15108,8 @@ [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) (match_operand:DF 2 "register_operand" "0,f")]))] - "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH) + "TARGET_80387 && X87_ENABLE_ARITH (DFmode) + && !(TARGET_SSE2 && TARGET_SSE_MATH) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "* return output_387_binary_op (insn, operands);" [(set (attr "type") @@ -16506,7 +15127,8 @@ [(match_operand:DF 1 "register_operand" "0,f") (float_extend:DF (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] - "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)" + "TARGET_80387 && X87_ENABLE_ARITH (DFmode) + && !(TARGET_SSE2 && TARGET_SSE_MATH)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:DF 3 "mult_operator" "") @@ -16524,7 +15146,8 @@ (match_operand:SF 1 "register_operand" "0,f")) (float_extend:DF (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] - "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)" + "TARGET_80387 && X87_ENABLE_ARITH (DFmode) + && !(TARGET_SSE2 && TARGET_SSE_MATH)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:DF 3 "mult_operator" "") @@ -16660,7 +15283,8 @@ [(float (match_operand:X87MODEI12 1 "register_operand" "")) (match_operand 2 "register_operand" "")]))] "reload_completed - && X87_FLOAT_MODE_P (GET_MODE (operands[0]))" + && X87_FLOAT_MODE_P (GET_MODE (operands[0])) + && X87_ENABLE_FLOAT (GET_MODE (operands[0]), GET_MODE (operands[1]))" [(const_int 0)] { operands[4] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]); @@ -16680,7 +15304,8 @@ [(match_operand 1 "register_operand" "") (float (match_operand:X87MODEI12 2 "register_operand" ""))]))] "reload_completed - && X87_FLOAT_MODE_P (GET_MODE (operands[0]))" + && X87_FLOAT_MODE_P (GET_MODE (operands[0])) + && X87_ENABLE_FLOAT (GET_MODE (operands[0]), GET_MODE (operands[2]))" [(const_int 0)] { operands[4] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]); @@ -16737,6 +15362,7 @@ "TARGET_SSE_MATH" "%vrsqrtss\t{%1, %d0|%d0, %1}" [(set_attr "type" "sse") + (set_attr "atom_sse_attr" "rcp") (set_attr "prefix" "maybe_vex") (set_attr "mode" "SF")]) @@ -16757,6 +15383,7 @@ "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH" "%vsqrts<ssemodefsuffix>\t{%1, %d0|%d0, %1}" [(set_attr "type" "sse") + (set_attr "atom_sse_attr" "sqrt") (set_attr "prefix" "maybe_vex") (set_attr "mode" "<MODE>") (set_attr "athlon_decode" "*") @@ -16766,7 +15393,7 @@ [(set (match_operand:MODEF 0 "register_operand" "") (sqrt:MODEF (match_operand:MODEF 1 "nonimmediate_operand" "")))] - "TARGET_USE_FANCY_MATH_387 + "(TARGET_USE_FANCY_MATH_387 && X87_ENABLE_ARITH (<MODE>mode)) || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" { if (<MODE>mode == SFmode @@ -17871,7 +16498,7 @@ (define_expand "scalb<mode>3" [(use (match_operand:MODEF 0 "register_operand" "")) (use (match_operand:MODEF 1 "general_operand" "")) - (use (match_operand:MODEF 2 "register_operand" ""))] + (use (match_operand:MODEF 2 "general_operand" ""))] "TARGET_USE_FANCY_MATH_387 && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) @@ -17892,6 +16519,34 @@ emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0)); DONE; }) + +(define_expand "significandxf2" + [(parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_operand:XF 1 "register_operand" "")] + UNSPEC_XTRACT_FRACT)) + (set (match_dup 2) + (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); +}) + +(define_expand "significand<mode>2" + [(use (match_operand:MODEF 0 "register_operand" "")) + (use (match_operand:MODEF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_fxtract_extend<mode>xf3_i387 (op0, op1, operands[1])); + emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0)); + DONE; +}) (define_insn "sse4_1_round<mode>2" @@ -17970,7 +16625,7 @@ (unspec:DI [(match_operand:XF 1 "register_operand" "")] UNSPEC_FIST))] "TARGET_USE_FANCY_MATH_387 - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -18037,7 +16692,7 @@ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")] UNSPEC_FIST))] "TARGET_USE_FANCY_MATH_387 - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -18124,7 +16779,7 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -18215,7 +16870,7 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -18366,25 +17021,13 @@ && flag_unsafe_math_optimizations" "") -(define_expand "lfloor<mode>di2" - [(match_operand:DI 0 "nonimmediate_operand" "") +(define_expand "lfloor<MODEF:mode><SWI48:mode>2" + [(match_operand:SWI48 0 "nonimmediate_operand" "") (match_operand:MODEF 1 "register_operand" "")] - "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH && TARGET_64BIT + "SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH && !flag_trapping_math" { - if (optimize_insn_for_size_p ()) - FAIL; - ix86_expand_lfloorceil (operand0, operand1, true); - DONE; -}) - -(define_expand "lfloor<mode>si2" - [(match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:MODEF 1 "register_operand" "")] - "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH - && !flag_trapping_math" -{ - if (optimize_insn_for_size_p () && TARGET_64BIT) + if (TARGET_64BIT && optimize_insn_for_size_p ()) FAIL; ix86_expand_lfloorceil (operand0, operand1, true); DONE; @@ -18398,7 +17041,7 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -18489,7 +17132,7 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -18640,20 +17283,10 @@ && flag_unsafe_math_optimizations" "") -(define_expand "lceil<mode>di2" - [(match_operand:DI 0 "nonimmediate_operand" "") +(define_expand "lceil<MODEF:mode><SWI48:mode>2" + [(match_operand:SWI48 0 "nonimmediate_operand" "") (match_operand:MODEF 1 "register_operand" "")] - "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH && TARGET_64BIT - && !flag_trapping_math" -{ - ix86_expand_lfloorceil (operand0, operand1, false); - DONE; -}) - -(define_expand "lceil<mode>si2" - [(match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:MODEF 1 "register_operand" "")] - "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH + "SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH && !flag_trapping_math" { ix86_expand_lfloorceil (operand0, operand1, false); @@ -18668,7 +17301,7 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -18760,7 +17393,7 @@ (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] @@ -18828,6 +17461,7 @@ "TARGET_USE_FANCY_MATH_387" "fxam\n\tfnstsw\t%0" [(set_attr "type" "multi") + (set_attr "length" "4") (set_attr "unit" "i387") (set_attr "mode" "<MODE>")]) @@ -18837,7 +17471,7 @@ [(match_operand:MODEF 1 "memory_operand" "")] UNSPEC_FXAM_MEM))] "TARGET_USE_FANCY_MATH_387 - && !(reload_completed || reload_in_progress)" + && can_create_pseudo_p ()" "#" "&& 1" [(set (match_dup 2)(match_dup 1)) @@ -18898,7 +17532,9 @@ emit_insn (gen_fxam<mode>2_i387_with_temp (scratch, operands[1])); else { - int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + enum ix86_stack_slot slot = (virtuals_instantiated + ? SLOT_TEMP + : SLOT_VIRTUAL); rtx temp = assign_386_stack_local (<MODE>mode, slot); emit_move_insn (temp, operands[1]); @@ -19117,6 +17753,7 @@ "movsb" [(set_attr "type" "str") (set_attr "memory" "both") + (set_attr "prefix_rex" "0") (set_attr "mode" "QI")]) (define_expand "rep_mov" @@ -19373,6 +18010,7 @@ "stosb" [(set_attr "type" "str") (set_attr "memory" "store") + (set_attr "prefix_rex" "0") (set_attr "mode" "QI")]) (define_expand "rep_stos" @@ -19466,6 +18104,7 @@ [(set_attr "type" "str") (set_attr "prefix_rep" "1") (set_attr "memory" "store") + (set_attr "prefix_rex" "0") (set_attr "mode" "QI")]) (define_expand "cmpstrnsi" @@ -19516,10 +18155,13 @@ } else { + rtx (*cmp_insn)(rtx, rtx); + if (TARGET_64BIT) - emit_insn (gen_cmpdi_1_rex64 (countreg, countreg)); - else - emit_insn (gen_cmpsi_1 (countreg, countreg)); + cmp_insn = gen_cmpdi_1; + else + cmp_insn = gen_cmpsi_1; + emit_insn (cmp_insn (countreg, countreg)); emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align, operands[1], operands[2])); } @@ -19592,6 +18234,7 @@ "repz cmpsb" [(set_attr "type" "str") (set_attr "mode" "QI") + (set_attr "prefix_rex" "0") (set_attr "prefix_rep" "1")]) ;; The same, but the count is not known to not be zero. @@ -19645,6 +18288,7 @@ "repz cmpsb" [(set_attr "type" "str") (set_attr "mode" "QI") + (set_attr "prefix_rex" "0") (set_attr "prefix_rep" "1")]) (define_expand "strlensi" @@ -19706,6 +18350,7 @@ "repnz scasb" [(set_attr "type" "str") (set_attr "mode" "QI") + (set_attr "prefix_rex" "0") (set_attr "prefix_rep" "1")]) ;; Peephole optimizations to clean up after cmpstrn*. This should be @@ -19791,65 +18436,11 @@ ;; Conditional move instructions. -(define_expand "movdicc" - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (match_operand 1 "comparison_operator" "") - (match_operand:DI 2 "general_operand" "") - (match_operand:DI 3 "general_operand" "")))] - "TARGET_64BIT" - "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") - -(define_insn "x86_movdicc_0_m1_rex64" - [(set (match_operand:DI 0 "register_operand" "=r") - (if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "") - (const_int -1) - (const_int 0))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "sbb{q}\t%0, %0" - ; Since we don't have the proper number of operands for an alu insn, - ; fill in all the blanks. - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") - (set_attr "mode" "DI") - (set_attr "length_immediate" "0")]) - -(define_insn "*x86_movdicc_0_m1_se" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extract:DI (match_operand 1 "ix86_carry_flag_operator" "") - (const_int 1) - (const_int 0))) - (clobber (reg:CC FLAGS_REG))] - "" - "sbb{q}\t%0, %0" - [(set_attr "type" "alu") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") - (set_attr "mode" "DI") - (set_attr "length_immediate" "0")]) - -(define_insn "*movdicc_c_rex64" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (if_then_else:DI (match_operator 1 "ix86_comparison_operator" - [(reg FLAGS_REG) (const_int 0)]) - (match_operand:DI 2 "nonimmediate_operand" "rm,0") - (match_operand:DI 3 "nonimmediate_operand" "0,rm")))] - "TARGET_64BIT && TARGET_CMOVE - && !(MEM_P (operands[2]) && MEM_P (operands[3]))" - "@ - cmov%O2%C1\t{%2, %0|%0, %2} - cmov%O2%c1\t{%3, %0|%0, %3}" - [(set_attr "type" "icmov") - (set_attr "mode" "DI")]) - -(define_expand "movsicc" - [(set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "general_operand" "") - (match_operand:SI 3 "general_operand" "")))] +(define_expand "mov<mode>cc" + [(set (match_operand:SWIM 0 "register_operand" "") + (if_then_else:SWIM (match_operand 1 "comparison_operator" "") + (match_operand:SWIM 2 "general_operand" "") + (match_operand:SWIM 3 "general_operand" "")))] "" "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") @@ -19857,87 +18448,87 @@ ;; the register first winds up with `sbbl $0,reg', which is also weird. ;; So just document what we're doing explicitly. -(define_insn "x86_movsicc_0_m1" - [(set (match_operand:SI 0 "register_operand" "=r") - (if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "") +(define_expand "x86_mov<mode>cc_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_mov<mode>cc_0_m1" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (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))] "" - "sbb{l}\t%0, %0" + "sbb{<imodesuffix>}\t%0, %0" ; Since we don't have the proper number of operands for an alu insn, ; fill in all the blanks. [(set_attr "type" "alu") + (set_attr "use_carry" "1") (set_attr "pent_pair" "pu") (set_attr "memory" "none") (set_attr "imm_disp" "false") - (set_attr "mode" "SI") + (set_attr "mode" "<MODE>") (set_attr "length_immediate" "0")]) -(define_insn "*x86_movsicc_0_m1_se" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extract:SI (match_operand 1 "ix86_carry_flag_operator" "") - (const_int 1) - (const_int 0))) - (clobber (reg:CC FLAGS_REG))] - "" - "sbb{l}\t%0, %0" +(define_insn "*x86_mov<mode>cc_0_m1_se" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (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))] + "" + "sbb{<imodesuffix>}\t%0, %0" [(set_attr "type" "alu") + (set_attr "use_carry" "1") (set_attr "pent_pair" "pu") (set_attr "memory" "none") (set_attr "imm_disp" "false") - (set_attr "mode" "SI") + (set_attr "mode" "<MODE>") (set_attr "length_immediate" "0")]) -(define_insn "*movsicc_noc" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (if_then_else:SI (match_operator 1 "ix86_comparison_operator" - [(reg FLAGS_REG) (const_int 0)]) - (match_operand:SI 2 "nonimmediate_operand" "rm,0") - (match_operand:SI 3 "nonimmediate_operand" "0,rm")))] - "TARGET_CMOVE - && !(MEM_P (operands[2]) && MEM_P (operands[3]))" +(define_insn "*x86_mov<mode>cc_0_m1_neg" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (neg:SWI48 (match_operator 1 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)])))] + "" + "sbb{<imodesuffix>}\t%0, %0" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "memory" "none") + (set_attr "imm_disp" "false") + (set_attr "mode" "<MODE>") + (set_attr "length_immediate" "0")]) + +(define_insn "*mov<mode>cc_noc" + [(set (match_operand:SWI248 0 "register_operand" "=r,r") + (if_then_else:SWI248 (match_operator 1 "ix86_comparison_operator" + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:SWI248 2 "nonimmediate_operand" "rm,0") + (match_operand:SWI248 3 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && !(MEM_P (operands[2]) && MEM_P (operands[3]))" "@ cmov%O2%C1\t{%2, %0|%0, %2} cmov%O2%c1\t{%3, %0|%0, %3}" [(set_attr "type" "icmov") - (set_attr "mode" "SI")]) - -(define_expand "movhicc" - [(set (match_operand:HI 0 "register_operand" "") - (if_then_else:HI (match_operand 1 "comparison_operator" "") - (match_operand:HI 2 "general_operand" "") - (match_operand:HI 3 "general_operand" "")))] - "TARGET_HIMODE_MATH" - "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") - -(define_insn "*movhicc_noc" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (if_then_else:HI (match_operator 1 "ix86_comparison_operator" - [(reg FLAGS_REG) (const_int 0)]) - (match_operand:HI 2 "nonimmediate_operand" "rm,0") - (match_operand:HI 3 "nonimmediate_operand" "0,rm")))] - "TARGET_CMOVE - && !(MEM_P (operands[2]) && MEM_P (operands[3]))" - "@ - cmov%O2%C1\t{%2, %0|%0, %2} - cmov%O2%c1\t{%3, %0|%0, %3}" - [(set_attr "type" "icmov") - (set_attr "mode" "HI")]) - -(define_expand "movqicc" - [(set (match_operand:QI 0 "register_operand" "") - (if_then_else:QI (match_operand 1 "comparison_operator" "") - (match_operand:QI 2 "general_operand" "") - (match_operand:QI 3 "general_operand" "")))] - "TARGET_QIMODE_MATH" - "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") + (set_attr "mode" "<MODE>")]) (define_insn_and_split "*movqicc_noc" [(set (match_operand:QI 0 "register_operand" "=r,r") (if_then_else:QI (match_operator 1 "ix86_comparison_operator" - [(match_operand 4 "flags_reg_operand" "") - (const_int 0)]) + [(match_operand 4 "flags_reg_operand" "") + (const_int 0)]) (match_operand:QI 2 "register_operand" "r,0") (match_operand:QI 3 "register_operand" "0,r")))] "TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL" @@ -19956,7 +18547,7 @@ (define_expand "mov<mode>cc" [(set (match_operand:X87MODEF 0 "register_operand" "") (if_then_else:X87MODEF - (match_operand 1 "comparison_operator" "") + (match_operand 1 "ix86_fp_comparison_operator" "") (match_operand:X87MODEF 2 "register_operand" "") (match_operand:X87MODEF 3 "register_operand" "")))] "(TARGET_80387 && TARGET_CMOVE) @@ -20043,18 +18634,18 @@ [(set_attr "type" "fcmov") (set_attr "mode" "XF")]) -;; All moves in SSE5 pcmov instructions are 128 bits and hence we restrict +;; All moves in XOP pcmov instructions are 128 bits and hence we restrict ;; the scalar versions to have only XMM registers as operands. -;; SSE5 conditional move -(define_insn "*sse5_pcmov_<mode>" - [(set (match_operand:MODEF 0 "register_operand" "=x,x") +;; XOP conditional move +(define_insn "*xop_pcmov_<mode>" + [(set (match_operand:MODEF 0 "register_operand" "=x") (if_then_else:MODEF - (match_operand:MODEF 1 "register_operand" "x,0") - (match_operand:MODEF 2 "register_operand" "0,x") - (match_operand:MODEF 3 "register_operand" "x,x")))] - "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1, false)" - "pcmov\t{%1, %3, %2, %0|%0, %2, %3, %1}" + (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 @@ -20215,12 +18806,21 @@ } } [(set (attr "type") - (cond [(eq_attr "alternative" "0") + (cond [(and (eq_attr "alternative" "0") + (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) (const_string "alu") (match_operand:SI 2 "const0_operand" "") (const_string "imov") ] (const_string "lea"))) + (set (attr "length_immediate") + (cond [(eq_attr "type" "imov") + (const_string "0") + (and (eq_attr "type" "alu") + (match_operand 2 "const128_operand" "")) + (const_string "1") + ] + (const_string "*"))) (set_attr "mode" "SI")]) (define_insn "pro_epilogue_adjust_stack_rex64" @@ -20258,12 +18858,21 @@ } } [(set (attr "type") - (cond [(eq_attr "alternative" "0") + (cond [(and (eq_attr "alternative" "0") + (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) (const_string "alu") (match_operand:DI 2 "const0_operand" "") (const_string "imov") ] (const_string "lea"))) + (set (attr "length_immediate") + (cond [(eq_attr "type" "imov") + (const_string "0") + (and (eq_attr "type" "alu") + (match_operand 2 "const128_operand" "")) + (const_string "1") + ] + (const_string "*"))) (set_attr "mode" "DI")]) (define_insn "pro_epilogue_adjust_stack_rex64_2" @@ -20348,6 +18957,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" @@ -20851,7 +19472,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)])) @@ -20866,7 +19489,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)])) @@ -21113,7 +19738,7 @@ (match_operator 1 "compare_operator" [(match_operand 2 "register_operand" "") (match_operand 3 "const_int_operand" "")]))] - "(((!TARGET_FUSE_CMP_AND_BRANCH || optimize_size) + "(((!TARGET_FUSE_CMP_AND_BRANCH || optimize_insn_for_size_p ()) && incdec_operand (operands[3], GET_MODE (operands[3]))) || (!TARGET_FUSE_CMP_AND_BRANCH && INTVAL (operands[3]) == 128)) @@ -21460,8 +20085,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)) @@ -21475,8 +20101,9 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm")) (match_operand:SI 2 "" ""))) - (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i")))] + (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)) @@ -21489,8 +20116,9 @@ [(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")))] + (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 @@ -21589,19 +20217,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"; @@ -21640,14 +20268,14 @@ (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)) + (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)) (use (match_operand:DI 1 "register_operand" "")) (use (match_operand:DI 2 "immediate_operand" "")) (use (label_ref:DI (match_operand 3 "" "")))])] @@ -21657,14 +20285,14 @@ (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)) (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")))] @@ -21746,6 +20374,8 @@ return patterns[locality]; } [(set_attr "type" "sse") + (set_attr "atom_sse_attr" "prefetch") + (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])")) (set_attr "memory" "none")]) (define_insn "*prefetch_sse_rex" @@ -21764,6 +20394,8 @@ return patterns[locality]; } [(set_attr "type" "sse") + (set_attr "atom_sse_attr" "prefetch") + (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])")) (set_attr "memory" "none")]) (define_insn "*prefetch_3dnow" @@ -21778,6 +20410,7 @@ return "prefetchw\t%a0"; } [(set_attr "type" "mmx") + (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])")) (set_attr "memory" "none")]) (define_insn "*prefetch_3dnow_rex" @@ -21792,6 +20425,7 @@ return "prefetchw\t%a0"; } [(set_attr "type" "mmx") + (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])")) (set_attr "memory" "none")]) (define_expand "stack_protect_set" @@ -21866,9 +20500,6 @@ "" { rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - ix86_compare_emitted = flags; #ifdef TARGET_THREAD_SSP_OFFSET if (TARGET_64BIT) @@ -21883,7 +20514,9 @@ else emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1])); #endif - emit_jump_insn (gen_beq (operands[2])); + + emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx), + flags, const0_rtx, operands[2])); DONE; }) @@ -21935,21 +20568,25 @@ } [(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<mode>" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "0") - (match_operand:CRC32MODE 2 "nonimmediate_operand" "<crc32modeconstraint>")] + (match_operand:SWI124 2 "nonimmediate_operand" "<r>m")] UNSPEC_CRC32))] - "TARGET_SSE4_2" - "crc32<crc32modesuffix>\t{%2, %0|%0, %2}" + "TARGET_SSE4_2 || TARGET_CRC32" + "crc32{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "sselog1") (set_attr "prefix_rep" "1") (set_attr "prefix_extra" "1") + (set (attr "prefix_data16") + (if_then_else (match_operand:HI 2 "" "") + (const_string "1") + (const_string "*"))) + (set (attr "prefix_rex") + (if_then_else (match_operand:QI 2 "ext_QIreg_operand" "") + (const_string "1") + (const_string "*"))) (set_attr "mode" "SI")]) (define_insn "sse4_2_crc32di" @@ -21958,13 +20595,263 @@ [(match_operand:DI 1 "register_operand" "0") (match_operand:DI 2 "nonimmediate_operand" "rm")] UNSPEC_CRC32))] - "TARGET_SSE4_2 && TARGET_64BIT" + "TARGET_64BIT && (TARGET_SSE4_2 || TARGET_CRC32)" "crc32{q}\t{%2, %0|%0, %2}" [(set_attr "type" "sselog1") (set_attr "prefix_rep" "1") (set_attr "prefix_extra" "1") (set_attr "mode" "DI")]) +(define_expand "rdpmc" + [(match_operand:DI 0 "register_operand" "") + (match_operand:SI 1 "register_operand" "")] + "" +{ + rtx reg = gen_reg_rtx (DImode); + rtx si; + + /* Force operand 1 into ECX. */ + rtx ecx = gen_rtx_REG (SImode, CX_REG); + emit_insn (gen_rtx_SET (VOIDmode, ecx, operands[1])); + si = gen_rtx_UNSPEC_VOLATILE (DImode, gen_rtvec (1, ecx), + UNSPECV_RDPMC); + + if (TARGET_64BIT) + { + rtvec vec = rtvec_alloc (2); + rtx load = gen_rtx_PARALLEL (VOIDmode, vec); + rtx upper = gen_reg_rtx (DImode); + rtx di = gen_rtx_UNSPEC_VOLATILE (DImode, + gen_rtvec (1, const0_rtx), + UNSPECV_RDPMC); + RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, si); + RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, di); + emit_insn (load); + upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), + NULL, 1, OPTAB_DIRECT); + reg = expand_simple_binop (DImode, IOR, reg, upper, reg, 1, + OPTAB_DIRECT); + } + else + emit_insn (gen_rtx_SET (VOIDmode, reg, si)); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], reg)); + DONE; +}) + +(define_insn "*rdpmc" + [(set (match_operand:DI 0 "register_operand" "=A") + (unspec_volatile:DI [(match_operand:SI 1 "register_operand" "c")] + UNSPECV_RDPMC))] + "!TARGET_64BIT" + "rdpmc" + [(set_attr "type" "other") + (set_attr "length" "2")]) + +(define_insn "*rdpmc_rex64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec_volatile:DI [(match_operand:SI 2 "register_operand" "c")] + UNSPECV_RDPMC)) + (set (match_operand:DI 1 "register_operand" "=d") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDPMC))] + "TARGET_64BIT" + "rdpmc" + [(set_attr "type" "other") + (set_attr "length" "2")]) + +(define_expand "rdtsc" + [(set (match_operand:DI 0 "register_operand" "") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC))] + "" +{ + if (TARGET_64BIT) + { + rtvec vec = rtvec_alloc (2); + rtx load = gen_rtx_PARALLEL (VOIDmode, vec); + rtx upper = gen_reg_rtx (DImode); + rtx lower = gen_reg_rtx (DImode); + rtx src = gen_rtx_UNSPEC_VOLATILE (DImode, + gen_rtvec (1, const0_rtx), + UNSPECV_RDTSC); + RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, lower, src); + RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, src); + emit_insn (load); + upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), + NULL, 1, OPTAB_DIRECT); + lower = expand_simple_binop (DImode, IOR, lower, upper, lower, 1, + OPTAB_DIRECT); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], lower)); + DONE; + } +}) + +(define_insn "*rdtsc" + [(set (match_operand:DI 0 "register_operand" "=A") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC))] + "!TARGET_64BIT" + "rdtsc" + [(set_attr "type" "other") + (set_attr "length" "2")]) + +(define_insn "*rdtsc_rex64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC)) + (set (match_operand:DI 1 "register_operand" "=d") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC))] + "TARGET_64BIT" + "rdtsc" + [(set_attr "type" "other") + (set_attr "length" "2")]) + +(define_expand "rdtscp" + [(match_operand:DI 0 "register_operand" "") + (match_operand:SI 1 "memory_operand" "")] + "" +{ + rtx di = gen_rtx_UNSPEC_VOLATILE (DImode, + gen_rtvec (1, const0_rtx), + UNSPECV_RDTSCP); + rtx si = gen_rtx_UNSPEC_VOLATILE (SImode, + gen_rtvec (1, const0_rtx), + UNSPECV_RDTSCP); + rtx reg = gen_reg_rtx (DImode); + rtx tmp = gen_reg_rtx (SImode); + + if (TARGET_64BIT) + { + rtvec vec = rtvec_alloc (3); + rtx load = gen_rtx_PARALLEL (VOIDmode, vec); + rtx upper = gen_reg_rtx (DImode); + RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, di); + RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, di); + RTVEC_ELT (vec, 2) = gen_rtx_SET (VOIDmode, tmp, si); + emit_insn (load); + upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), + NULL, 1, OPTAB_DIRECT); + reg = expand_simple_binop (DImode, IOR, reg, upper, reg, 1, + OPTAB_DIRECT); + } + else + { + rtvec vec = rtvec_alloc (2); + rtx load = gen_rtx_PARALLEL (VOIDmode, vec); + RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, di); + RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, tmp, si); + emit_insn (load); + } + emit_insn (gen_rtx_SET (VOIDmode, operands[0], reg)); + emit_insn (gen_rtx_SET (VOIDmode, operands[1], tmp)); + DONE; +}) + +(define_insn "*rdtscp" + [(set (match_operand:DI 0 "register_operand" "=A") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) + (set (match_operand:SI 1 "register_operand" "=c") + (unspec_volatile:SI [(const_int 0)] UNSPECV_RDTSCP))] + "!TARGET_64BIT" + "rdtscp" + [(set_attr "type" "other") + (set_attr "length" "3")]) + +(define_insn "*rdtscp_rex64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) + (set (match_operand:DI 1 "register_operand" "=d") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) + (set (match_operand:SI 2 "register_operand" "=c") + (unspec_volatile:SI [(const_int 0)] UNSPECV_RDTSCP))] + "TARGET_64BIT" + "rdtscp" + [(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_llwpcb<mode>1" + [(unspec_volatile [(match_operand:P 0 "register_operand" "r")] + UNSPECV_LLWP_INTRINSIC)] + "TARGET_LWP" + "llwpcb\t%0" + [(set_attr "type" "lwp") + (set_attr "mode" "<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<mode>" + [(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" "<MODE>") + (set_attr "length" "5")]) + +(define_expand "lwp_lwpval<mode>3" + [(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_lwpval<mode>3_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" "<MODE>") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 9"))]) + +(define_expand "lwp_lwpins<mode>3" + [(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_lwpins<mode>3_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" "<MODE>") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 9"))]) + (include "mmx.md") (include "sse.md") (include "sync.md")