;; GCC machine description for IA-32 and x86-64.
;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;; x86_64 support added by Jan Hubicka
;; 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
;; 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 SSE5 com* instruction.
+;; 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_ADD_CARRY 34)
(UNSPEC_FLDCW 35)
(UNSPEC_REP 36)
- (UNSPEC_EH_RETURN 37)
(UNSPEC_LD_MPIC 38) ; load_macho_picbase
(UNSPEC_TRUNC_NOOP 39)
(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)
; For AVX support
(UNSPEC_PCMP 166)
(UNSPEC_VPERMIL 167)
- (UNSPEC_VPERMIL2F128 168)
- (UNSPEC_MASKLOAD 169)
- (UNSPEC_MASKSTORE 170)
- (UNSPEC_CAST 171)
- (UNSPEC_VTESTP 172)
+ (UNSPEC_VPERMIL2 168)
+ (UNSPEC_VPERMIL2F128 169)
+ (UNSPEC_MASKLOAD 170)
+ (UNSPEC_MASKSTORE 171)
+ (UNSPEC_CAST 172)
+ (UNSPEC_VTESTP 173)
])
(define_constants
(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
(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 */
(R9_REG 38)
(R10_REG 39)
(R11_REG 40)
+ (R12_REG 41)
(R13_REG 42)
(XMM8_REG 45)
(XMM9_REG 46)
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"))
;; 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" ""
;; 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)")
(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"
(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)"))
(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" "")))
(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" ""))
(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)))
(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")
;; 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")
(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])
(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 "%")
(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])
;; 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")])
+
+;; Double word integer modes.
+(define_mode_iterator DWI [(DI "!TARGET_64BIT")
+ (TI "TARGET_64BIT")])
+
+;; Double word integer modes as mode attribute.
+(define_mode_attr DWI [(SI "DI") (DI "TI")])
+(define_mode_attr dwi [(SI "di") (DI "ti")])
+
+;; Half mode for double word integer modes.
+(define_mode_iterator DWIH [(SI "!TARGET_64BIT")
+ (DI "TARGET_64BIT")])
+
;; Instruction suffix for integer modes.
(define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
;; 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")])
+
+;; Immediate operand constraint for shifts.
+(define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")])
+
;; General operand predicate for integer modes.
(define_mode_attr general_operand
[(QI "general_operand")
(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")])
+
+;; Operand predicate for shifts.
+(define_mode_attr shift_operand
+ [(QI "nonimmediate_operand")
+ (HI "nonimmediate_operand")
+ (SI "nonimmediate_operand")
+ (DI "shiftdi_operand")
+ (TI "register_operand")])
+
+;; Operand predicate for shift argument.
+(define_mode_attr shift_immediate_operand
+ [(QI "const_1_to_31_operand")
+ (HI "const_1_to_31_operand")
+ (SI "const_1_to_31_operand")
+ (DI "const_1_to_63_operand")])
+
+;; Input operand predicate for arithmetic left shifts.
+(define_mode_attr ashl_input_operand
+ [(QI "nonimmediate_operand")
+ (HI "nonimmediate_operand")
+ (SI "nonimmediate_operand")
+ (DI "ashldi_input_operand")
+ (TI "reg_or_pm1_operand")])
;; SSE and x87 SFmode and DFmode floating point modes
(define_mode_iterator MODEF [SF DF])
;; 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")])
-
\f
;; Scheduling descriptions
\f
;; Compare and branch/compare and store instructions.
-(define_expand "cbranchti4"
- [(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:TI 1 "nonimmediate_operand" "")
- (match_operand:TI 2 "x86_64_general_operand" "")))
- (set (pc) (if_then_else
- (match_operator 0 "comparison_operator"
- [(reg:CC FLAGS_REG)
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "TARGET_64BIT"
-{
- if (MEM_P (operands[1]) && MEM_P (operands[2]))
- operands[1] = force_reg (TImode, operands[1]);
- ix86_compare_op0 = operands[1];
- ix86_compare_op1 = operands[2];
- ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
- DONE;
-})
-
-(define_expand "cbranchdi4"
- [(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:DI 1 "nonimmediate_operand" "")
- (match_operand:DI 2 "x86_64_general_operand" "")))
- (set (pc) (if_then_else
- (match_operator 0 "comparison_operator"
- [(reg:CC FLAGS_REG)
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
-{
- if (MEM_P (operands[1]) && MEM_P (operands[2]))
- operands[1] = force_reg (DImode, operands[1]);
- ix86_compare_op0 = operands[1];
- ix86_compare_op1 = operands[2];
- ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
- DONE;
-})
-
-(define_expand "cstoredi4"
- [(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:DI 2 "nonimmediate_operand" "")
- (match_operand:DI 3 "x86_64_general_operand" "")))
- (set (match_operand:QI 0 "register_operand" "")
- (match_operator 1 "comparison_operator"
- [(reg:CC FLAGS_REG)
- (const_int 0)]))]
- "TARGET_64BIT"
-{
- if (MEM_P (operands[2]) && MEM_P (operands[3]))
- operands[2] = force_reg (DImode, operands[2]);
- ix86_compare_op0 = operands[2];
- ix86_compare_op1 = operands[3];
- ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
- DONE;
-})
-
-(define_expand "cbranchsi4"
- [(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:SI 1 "cmpsi_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (set (pc) (if_then_else
- (match_operator 0 "comparison_operator"
- [(reg:CC FLAGS_REG)
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
-{
- if (MEM_P (operands[1]) && MEM_P (operands[2]))
- operands[1] = force_reg (SImode, operands[1]);
- ix86_compare_op0 = operands[1];
- ix86_compare_op1 = operands[2];
- ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
- DONE;
-})
-
-(define_expand "cstoresi4"
- [(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:SI 2 "cmpsi_operand" "")
- (match_operand:SI 3 "general_operand" "")))
- (set (match_operand:QI 0 "register_operand" "")
- (match_operator 1 "comparison_operator"
- [(reg:CC FLAGS_REG)
- (const_int 0)]))]
- ""
-{
- if (MEM_P (operands[2]) && MEM_P (operands[3]))
- operands[2] = force_reg (SImode, operands[2]);
- ix86_compare_op0 = operands[2];
- ix86_compare_op1 = operands[3];
- ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
- DONE;
-})
-
-(define_expand "cbranchhi4"
- [(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:HI 1 "nonimmediate_operand" "")
- (match_operand:HI 2 "general_operand" "")))
- (set (pc) (if_then_else
- (match_operator 0 "comparison_operator"
- [(reg:CC FLAGS_REG)
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
-{
- if (MEM_P (operands[1]) && MEM_P (operands[2]))
- operands[1] = force_reg (HImode, operands[1]);
- ix86_compare_op0 = operands[1];
- ix86_compare_op1 = operands[2];
- ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
- DONE;
-})
-
-(define_expand "cstorehi4"
- [(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:HI 2 "nonimmediate_operand" "")
- (match_operand:HI 3 "general_operand" "")))
- (set (match_operand:QI 0 "register_operand" "")
- (match_operator 1 "comparison_operator"
- [(reg:CC FLAGS_REG)
- (const_int 0)]))]
- ""
-{
- if (MEM_P (operands[2]) && MEM_P (operands[3]))
- operands[2] = force_reg (HImode, operands[2]);
- ix86_compare_op0 = operands[2];
- ix86_compare_op1 = operands[3];
- ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
- DONE;
-})
-
-
-(define_expand "cbranchqi4"
+(define_expand "cbranch<mode>4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:QI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "general_operand" "")))
+ (compare:CC (match_operand:SDWIM 1 "nonimmediate_operand" "")
+ (match_operand:SDWIM 2 "<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)))]
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
{
if (MEM_P (operands[1]) && MEM_P (operands[2]))
- operands[1] = force_reg (QImode, operands[1]);
+ operands[1] = force_reg (<MODE>mode, operands[1]);
ix86_compare_op0 = operands[1];
ix86_compare_op1 = operands[2];
ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
DONE;
})
-
-(define_expand "cstoreqi4"
+(define_expand "cstore<mode>4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:QI 2 "nonimmediate_operand" "")
- (match_operand:QI 3 "general_operand" "")))
+ (compare:CC (match_operand:SWIM 2 "nonimmediate_operand" "")
+ (match_operand:SWIM 3 "<general_operand>" "")))
(set (match_operand:QI 0 "register_operand" "")
- (match_operator 1 "comparison_operator"
- [(reg:CC FLAGS_REG)
- (const_int 0)]))]
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG) (const_int 0)]))]
""
{
if (MEM_P (operands[2]) && MEM_P (operands[3]))
- operands[2] = force_reg (QImode, operands[2]);
+ operands[2] = force_reg (<MODE>mode, operands[2]);
ix86_compare_op0 = operands[2];
ix86_compare_op1 = operands[3];
ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
DONE;
})
-
-(define_insn "cmpdi_ccno_1_rex64"
- [(set (reg FLAGS_REG)
- (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
- (match_operand:DI 1 "const0_operand" "")))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
- "@
- test{q}\t%0, %0
- cmp{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "test,icmp")
- (set_attr "length_immediate" "0,1")
- (set_attr "mode" "DI")])
-
-(define_insn "*cmpdi_minus_1_rex64"
- [(set (reg FLAGS_REG)
- (compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r")
- (match_operand:DI 1 "x86_64_general_operand" "re,mr"))
- (const_int 0)))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)"
- "cmp{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "DI")])
-
-(define_expand "cmpdi_1_rex64"
- [(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "general_operand" "")))]
- "TARGET_64BIT"
- "")
-
-(define_insn "cmpdi_1_insn_rex64"
- [(set (reg FLAGS_REG)
- (compare (match_operand:DI 0 "nonimmediate_operand" "mr,r")
- (match_operand:DI 1 "x86_64_general_operand" "re,mr")))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
- "cmp{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "DI")])
-
-
-(define_insn "*cmpsi_ccno_1"
- [(set (reg FLAGS_REG)
- (compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
- (match_operand:SI 1 "const0_operand" "")))]
- "ix86_match_ccmode (insn, CCNOmode)"
- "@
- test{l}\t%0, %0
- cmp{l}\t{%1, %0|%0, %1}"
- [(set_attr "type" "test,icmp")
- (set_attr "length_immediate" "0,1")
- (set_attr "mode" "SI")])
-
-(define_insn "*cmpsi_minus_1"
- [(set (reg FLAGS_REG)
- (compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r")
- (match_operand:SI 1 "general_operand" "ri,mr"))
- (const_int 0)))]
- "ix86_match_ccmode (insn, CCGOCmode)"
- "cmp{l}\t{%1, %0|%0, %1}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "SI")])
-
-(define_expand "cmpsi_1"
+(define_expand "cmp<mode>_1"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "general_operand" "")))]
+ (compare:CC (match_operand:SWI48 0 "nonimmediate_operand" "")
+ (match_operand:SWI48 1 "<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 "type" "icmp")
- (set_attr "mode" "SI")])
-
-(define_insn "*cmphi_ccno_1"
- [(set (reg FLAGS_REG)
- (compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr")
- (match_operand:HI 1 "const0_operand" "")))]
- "ix86_match_ccmode (insn, CCNOmode)"
- "@
- test{w}\t%0, %0
- cmp{w}\t{%1, %0|%0, %1}"
- [(set_attr "type" "test,icmp")
- (set_attr "length_immediate" "0,1")
- (set_attr "mode" "HI")])
-
-(define_insn "*cmphi_minus_1"
- [(set (reg FLAGS_REG)
- (compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r")
- (match_operand:HI 1 "general_operand" "rn,mr"))
- (const_int 0)))]
- "ix86_match_ccmode (insn, CCGOCmode)"
- "cmp{w}\t{%1, %0|%0, %1}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "HI")])
-
-(define_insn "*cmphi_1"
- [(set (reg FLAGS_REG)
- (compare (match_operand:HI 0 "nonimmediate_operand" "rm,r")
- (match_operand:HI 1 "general_operand" "rn,mr")))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))
- && ix86_match_ccmode (insn, CCmode)"
- "cmp{w}\t{%1, %0|%0, %1}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "HI")])
-
-(define_insn "*cmpqi_ccno_1"
+(define_insn "*cmp<mode>_ccno_1"
[(set (reg FLAGS_REG)
- (compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
- (match_operand:QI 1 "const0_operand" "")))]
+ (compare (match_operand:SWI 0 "nonimmediate_operand" "<r>,?m<r>")
+ (match_operand:SWI 1 "const0_operand" "")))]
"ix86_match_ccmode (insn, CCNOmode)"
"@
- test{b}\t%0, %0
- cmp{b}\t{$0, %0|%0, 0}"
+ 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" "QI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*cmpqi_1"
+(define_insn "*cmp<mode>_1"
[(set (reg FLAGS_REG)
- (compare (match_operand:QI 0 "nonimmediate_operand" "qm,q")
- (match_operand:QI 1 "general_operand" "qn,mq")))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))
- && ix86_match_ccmode (insn, CCmode)"
- "cmp{b}\t{%1, %0|%0, %1}"
+ (compare (match_operand:SWI 0 "nonimmediate_operand" "<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" "QI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*cmpqi_minus_1"
+(define_insn "*cmp<mode>_minus_1"
[(set (reg FLAGS_REG)
- (compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "qm,q")
- (match_operand:QI 1 "general_operand" "qn,mq"))
- (const_int 0)))]
+ (compare
+ (minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
+ (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
+ (const_int 0)))]
"ix86_match_ccmode (insn, CCGOCmode)"
- "cmp{b}\t{%1, %0|%0, %1}"
+ "cmp{<imodesuffix>}\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)
(match_operand 0 "ext_register_operand" "")
(const_int 8)
(const_int 8)) 0)
- (match_operand:QI 1 "general_operand" "")))]
+ (match_operand:QI 1 "immediate_operand" "")))]
""
"")
-(define_insn "cmpqi_ext_3_insn"
+(define_insn "*cmpqi_ext_3_insn"
[(set (reg FLAGS_REG)
(compare
(subreg:QI
"!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_3_insn_rex64"
+(define_insn "*cmpqi_ext_3_insn_rex64"
[(set (reg FLAGS_REG)
(compare
(subreg:QI
"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"
(compare:CC (match_operand:XF 1 "nonmemory_operand" "")
(match_operand:XF 2 "nonmemory_operand" "")))
(set (pc) (if_then_else
- (match_operator 0 "comparison_operator"
+ (match_operator 0 "ix86_fp_comparison_operator"
[(reg:CC FLAGS_REG)
(const_int 0)])
(label_ref (match_operand 3 "" ""))
(compare:CC (match_operand:XF 2 "nonmemory_operand" "")
(match_operand:XF 3 "nonmemory_operand" "")))
(set (match_operand:QI 0 "register_operand" "")
- (match_operator 1 "comparison_operator"
+ (match_operator 1 "ix86_fp_comparison_operator"
[(reg:CC FLAGS_REG)
(const_int 0)]))]
"TARGET_80387"
(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 "comparison_operator"
+ (match_operator 0 "ix86_fp_comparison_operator"
[(reg:CC FLAGS_REG)
(const_int 0)])
(label_ref (match_operand 3 "" ""))
(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 "comparison_operator"
+ (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)"
(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")])
#ifdef HAVE_AS_IX86_SAHF
return "sahf";
#else
- return ".byte\t0x9e";
+ return ASM_BYTE "0x9e";
#endif
}
[(set_attr "length" "1")
(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")])
(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")])
(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")])
(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")])
(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")
"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")
(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")
[(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" "")
(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")
(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")
}
}
[(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")
&& (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
[(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))]
[(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))
&& (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
%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
"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")
"TARGET_64BIT"
"movz{bl|x}\t{%1, %k0|%k0, %1}"
[(set_attr "type" "imovx")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "SI")])
\f
;; Sign extension instructions
"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")
[(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")])
[(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")])
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")
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")
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")
[(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")])
(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")])
\f
}
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],
"%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")])
&& !((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)]
&& !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)]
(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")])
(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")
"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)
"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]));
-/* Avoid references to nonexistent function in dead code in XFmode case. */
-#define gen_truncxfxf2 gen_truncxfdf2
- emit_insn (gen_truncxf<X87MODEF:mode>2 (operands[0], reg));
-#undef gen_truncxfxf2
+
+ 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"
&& 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)))
[(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")
[(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")])
[(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")])
[(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")])
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]));
})
\f
;; 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)))])
- (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" "")))]
+(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, 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)"
- "#")
+ "ix86_expand_binary_operator (PLUS, <MODE>mode, operands); DONE;")
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
- (match_operand:DI 2 "general_operand" "")))
+(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))]
- "!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)))])
+ "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:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
- (match_dup 4))
- (match_dup 5)))
+ (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_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 "use_carry" "1")
- (set_attr "pent_pair" "pu")
- (set_attr "mode" "DI")])
+ "split_<dwi> (&operands[0], 3, &operands[0], &operands[3]);")
-(define_insn "*adddi3_cc_rex64"
+(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 "use_carry" "1")
- (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 "use_carry" "1")
- (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 "use_carry" "1")
- (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 "use_carry" "1")
- (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)"
[(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")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*lea_1_rex64"
+(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"
[(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")])
+(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}";
-;; The lea patterns for non-Pmodes needs to be matched by several
-;; insns converted to real lea by splitters.
+ 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";
+ }
-(define_insn_and_split "*lea_general_1"
- [(set (match_operand 0 "register_operand" "=r")
- (plus (plus (match_operand 1 "index_register_operand" "l")
- (match_operand 2 "register_operand" "r"))
- (match_operand 3 "immediate_operand" "i")))]
- "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
- || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
- && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && GET_MODE (operands[0]) == GET_MODE (operands[1])
- && GET_MODE (operands[0]) == GET_MODE (operands[2])
- && (GET_MODE (operands[0]) == GET_MODE (operands[3])
- || GET_MODE (operands[3]) == VOIDmode)"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rtx pat;
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_lowpart (Pmode, operands[2]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
- pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
- operands[3]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
- DONE;
+ 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]));
+ if (x86_maybe_negate_const_int (&operands[2], <MODE>mode))
+ return "sub{<imodesuffix>}\t{%2, %0|%0, %2}";
+
+ return "add{<imodesuffix>}\t{%2, %0|%0, %2}";
+ }
}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
+ [(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>")])
-(define_insn_and_split "*lea_general_1_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
+;; 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 (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"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1)
- (match_dup 2))
- (match_dup 3)) 0)))]
+ (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)"
{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_lowpart (Pmode, operands[2]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
+ 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:
+ if (x86_maybe_negate_const_int (&operands[2], SImode))
+ return "sub{l}\t{%2, %k0|%k0, %2}";
+
+ return "add{l}\t{%2, %k0|%k0, %2}";
+ }
}
- [(set_attr "type" "lea")
+ [(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_and_split "*lea_general_2"
- [(set (match_operand 0 "register_operand" "=r")
- (plus (mult (match_operand 1 "index_register_operand" "l")
- (match_operand 2 "const248_operand" "i"))
- (match_operand 3 "nonmemory_operand" "ri")))]
- "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
- || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
- && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && GET_MODE (operands[0]) == GET_MODE (operands[1])
- && (GET_MODE (operands[0]) == GET_MODE (operands[3])
- || GET_MODE (operands[3]) == VOIDmode)"
- "#"
- "&& reload_completed"
- [(const_int 0)]
+(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)"
{
- rtx pat;
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
- pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
- operands[3]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
- DONE;
-}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
+ 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";
+ }
-(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"))
- (match_operand:SI 3 "nonmemory_operand" "ri"))))]
- "TARGET_64BIT"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1)
- (match_dup 2))
- (match_dup 3)) 0)))]
-{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
-}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
+ default:
+ if (x86_maybe_negate_const_int (&operands[2], HImode))
+ return "sub{w}\t{%2, %0|%0, %2}";
-(define_insn_and_split "*lea_general_3"
- [(set (match_operand 0 "register_operand" "=r")
- (plus (plus (mult (match_operand 1 "index_register_operand" "l")
- (match_operand 2 "const248_operand" "i"))
- (match_operand 3 "register_operand" "r"))
- (match_operand 4 "immediate_operand" "i")))]
- "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
- || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
- && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && GET_MODE (operands[0]) == GET_MODE (operands[1])
- && GET_MODE (operands[0]) == GET_MODE (operands[3])"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rtx pat;
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
- operands[4] = gen_lowpart (Pmode, operands[4]);
- pat = gen_rtx_PLUS (Pmode,
- gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
- operands[2]),
- operands[3]),
- operands[4]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
- DONE;
+ return "add{w}\t{%2, %0|%0, %2}";
+ }
}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
+ [(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_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"))
- (match_operand:SI 4 "immediate_operand" "i"))))]
- "TARGET_64BIT"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1)
- (match_dup 2))
- (match_dup 3))
- (match_dup 4)) 0)))]
-{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
- operands[4] = gen_lowpart (Pmode, operands[4]);
-}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
+;; %%% 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 "*adddi_1_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r,r")
- (match_operand:DI 2 "x86_64_general_operand" "rme,re,0,le")))
+(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_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
+ "!TARGET_PARTIAL_REG_STALL
+ && ix86_binary_operator_ok (PLUS, HImode, 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}";
-
+ return "#";
case TYPE_INCDEC:
- gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
- return "inc{q}\t%0";
+ return "inc{w}\t%0";
else
- {
+ {
gcc_assert (operands[2] == constm1_rtx);
- return "dec{q}\t%0";
+ return "dec{w}\t%0";
}
default:
- /* Use add as much as possible to replace lea for AGU optimization. */
- if (which_alternative == 2 && TARGET_OPT_AGU)
- return "add{q}\t{%1, %0|%0, %1}";
-
- gcc_assert (rtx_equal_p (operands[0], operands[1]));
+ if (x86_maybe_negate_const_int (&operands[2], HImode))
+ return "sub{w}\t{%2, %0|%0, %2}";
- /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
- Exceptions: -128 encodes smaller than 128, so swap sign and op. */
- if (CONST_INT_P (operands[2])
- /* Avoid overflows. */
- && ((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}";
+ return "add{w}\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:DI 2 "pic_symbolic_operand" "")
- (const_string "lea")
- (match_operand:DI 2 "incdec_operand" "")
- (const_string "incdec")
- ]
- (const_string "alu")))
- (set_attr "mode" "DI")])
+ (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")])
-;; 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" "")))
+(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_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)"
+ "TARGET_PARTIAL_REG_STALL
+ && ix86_binary_operator_ok (PLUS, QImode, operands)"
{
+ int widen = (which_alternative == 2);
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";
+ return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
else
- {
+ {
gcc_assert (operands[2] == constm1_rtx);
- return "dec{q}\t%0";
+ return widen ? "dec{l}\t%k0" : "dec{b}\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}";
+ if (x86_maybe_negate_const_int (&operands[2], QImode))
+ {
+ 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:DI 2 "incdec_operand" "")
+ (if_then_else (match_operand:QI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
- (set_attr "mode" "DI")])
+ (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")])
-(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)"
+;; %%% 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:
- gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
- return "inc{q}\t%0";
+ return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
else
- {
+ {
gcc_assert (operands[2] == constm1_rtx);
- return "dec{q}\t%0";
+ return widen ? "dec{l}\t%k0" : "dec{b}\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}";
- }
+ if (x86_maybe_negate_const_int (&operands[2], QImode))
+ {
+ 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:DI 2 "incdec_operand" "")
- (const_string "incdec")
- (const_string "alu")))
- (set_attr "mode" "DI")])
+ (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")])
-; 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)"
+(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[2] == constm1_rtx)
- return "inc{q}\t%0";
+ if (operands[1] == const1_rtx)
+ return "inc{b}\t%0";
else
- {
- gcc_assert (operands[2] == const1_rtx);
- return "dec{q}\t%0";
+ {
+ gcc_assert (operands[1] == constm1_rtx);
+ return "dec{b}\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}";
+ if (x86_maybe_negate_const_int (&operands[1], QImode))
+ return "sub{b}\t{%1, %0|%0, %1}";
+
+ return "add{b}\t{%1, %0|%0, %1}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:DI 2 "incdec_operand" "")
+ (if_then_else (match_operand:QI 1 "incdec_operand" "")
(const_string "incdec")
- (const_string "alu")))
- (set_attr "mode" "DI")])
+ (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 "*adddi_5_rex64"
+(define_insn "*add<mode>_2"
[(set (reg FLAGS_REG)
(compare
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
- (match_operand:DI 2 "x86_64_general_operand" "rme"))
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SWI48 2 "<general_operand>" "<g>,r<i>"))
(const_int 0)))
- (clobber (match_scratch:DI 0 "=r"))]
- "TARGET_64BIT
- && ix86_match_ccmode (insn, CCGOCmode)
- && !(MEM_P (operands[1]) && MEM_P (operands[2]))
+ (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)"
case TYPE_INCDEC:
gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
- return "inc{q}\t%0";
+ return "inc{<imodesuffix>}\t%0";
else
{
- gcc_assert (operands[2] == constm1_rtx);
- return "dec{q}\t%0";
+ 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. */
- && ((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}";
+ /* ???? In DImode, we ought to handle there the 32bit case too
+ - do we need new constraint? */
+ if (x86_maybe_negate_const_int (&operands[2], <MODE>mode))
+ return "sub{<imodesuffix>}\t{%2, %0|%0, %2}";
+
+ return "add{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:DI 2 "incdec_operand" "")
+ (if_then_else (match_operand:SWI48 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
- (set_attr "mode" "DI")])
-
+ (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 "*addsi_1"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r,r")
- (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r,r")
- (match_operand:SI 2 "general_operand" "g,ri,0,li")))
- (clobber (reg:CC FLAGS_REG))]
- "ix86_binary_operator_ok (PLUS, SImode, operands)"
+;; 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_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";
+ return "inc{l}\t%k0";
else
{
- gcc_assert (operands[2] == constm1_rtx);
- return "dec{l}\t%0";
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{l}\t%k0";
}
default:
- /* Use add as much as possible to replace lea for AGU optimization. */
- if (which_alternative == 2 && TARGET_OPT_AGU)
- return "add{l}\t{%1, %0|%0, %1}";
+ if (x86_maybe_negate_const_int (&operands[2], SImode))
+ return "sub{l}\t{%2, %k0|%k0, %2}";
- 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}";
+ return "add{l}\t{%2, %k0|%k0, %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:SI 2 "pic_symbolic_operand" "")
- (const_string "lea")
- (match_operand:SI 2 "incdec_operand" "")
- (const_string "incdec")
- ]
- (const_string "alu")))
+ (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")])
-;; 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 && ix86_lea_for_add_ok (PLUS, insn, operands)"
- [(const_int 0)]
-{
- rtx pat;
- /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
- may confuse gen_lowpart. */
- if (GET_MODE (operands[0]) != Pmode)
- {
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_lowpart (Pmode, operands[2]);
- }
- operands[0] = gen_lowpart (SImode, operands[0]);
- pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
- DONE;
-})
-
-;; 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)"
+(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_LEA:
- operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
- return "lea{l}\t{%a2, %k0|%k0, %a2}";
-
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
- return "inc{l}\t%k0";
+ return "inc{w}\t%0";
else
{
gcc_assert (operands[2] == constm1_rtx);
- return "dec{l}\t%k0";
+ 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{l}\t{%2, %k0|%k0, %2}";
- }
- return "add{l}\t{%2, %k0|%k0, %2}";
+ if (x86_maybe_negate_const_int (&operands[2], HImode))
+ return "sub{w}\t{%2, %0|%0, %2}";
+
+ return "add{w}\t{%2, %0|%0, %2}";
}
}
[(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" "")
- (zero_extend:DI
- (plus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" ""))))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
- [(set (match_dup 0)
- (zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
-{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_lowpart (Pmode, operands[2]);
-})
+ (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 "*addsi_2"
+(define_insn "*addqi_2"
[(set (reg FLAGS_REG)
(compare
- (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "g,ri"))
+ (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "qmn,qn"))
(const_int 0)))
- (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ (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, SImode, operands)
- /* Current assemblers are broken and do not allow @GOTOFF in
- ought but a memory context. */
- && ! pic_symbolic_operand (operands[2], VOIDmode)"
+ && ix86_binary_operator_ok (PLUS, QImode, operands)"
{
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";
+ return "inc{b}\t%0";
else
{
- gcc_assert (operands[2] == constm1_rtx);
- return "dec{l}\t%0";
+ gcc_assert (operands[2] == constm1_rtx
+ || (CONST_INT_P (operands[2])
+ && INTVAL (operands[2]) == 255));
+ return "dec{b}\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}";
+ if (x86_maybe_negate_const_int (&operands[2], QImode))
+ return "sub{b}\t{%2, %0|%0, %2}";
+
+ return "add{b}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (if_then_else (match_operand:QI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
- (set_attr "mode" "SI")])
+ (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? */
+ if (x86_maybe_negate_const_int (&operands[2], <MODE>mode))
+ 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"
+(define_insn "*addsi_3_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)))
+ (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, CCGOCmode)
+ "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. */
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}";
- }
+ if (x86_maybe_negate_const_int (&operands[2], SImode))
+ return "sub{l}\t{%2, %k0|%k0, %2}";
+
return "add{l}\t{%2, %k0|%k0, %2}";
}
}
(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 "*addsi_3"
+(define_insn "*addhi_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"))]
+ (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]))
- /* Current assemblers are broken and do not allow @GOTOFF in
- ought but a memory context. */
- && ! pic_symbolic_operand (operands[2], VOIDmode)"
+ && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
{
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";
+ return "inc{w}\t%0";
else
{
gcc_assert (operands[2] == constm1_rtx);
- return "dec{l}\t%0";
+ 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 (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}";
+ if (x86_maybe_negate_const_int (&operands[2], HImode))
+ return "sub{w}\t{%2, %0|%0, %2}";
+
+ return "add{w}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
- (set_attr "mode" "SI")])
+ (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 comment for addsi_1_zext why we do use nonimmediate_operand
-(define_insn "*addsi_3_zext"
+(define_insn "*addqi_3"
[(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)"
+ (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{l}\t%k0";
+ return "inc{b}\t%0";
else
{
- gcc_assert (operands[2] == constm1_rtx);
- return "dec{l}\t%k0";
+ 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 `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}";
+ if (x86_maybe_negate_const_int (&operands[2], QImode))
+ return "sub{b}\t{%2, %0|%0, %2}";
+
+ return "add{b}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (if_then_else (match_operand:QI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
- (set_attr "mode" "SI")])
+ (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 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"
+
+(define_insn "*adddi_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"
+ (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{l}\t%0";
+ return "inc{q}\t%0";
else
{
gcc_assert (operands[2] == const1_rtx);
- return "dec{l}\t%0";
+ 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)))
- return "sub{l}\t{%2, %0|%0, %2}";
- operands[2] = GEN_INT (-INTVAL (operands[2]));
- return "add{l}\t{%2, %0|%0, %2}";
+ if (x86_maybe_negate_const_int (&operands[2], DImode))
+ return "add{q}\t{%2, %0|%0, %2}";
+
+ return "sub{q}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (if_then_else (match_operand:DI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
- (set_attr "mode" "SI")])
+ (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")])
-(define_insn "*addsi_5"
+; 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.
+; 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
- (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)"
+ (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)"
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- gcc_assert (rtx_equal_p (operands[0], operands[1]));
- if (operands[2] == const1_rtx)
+ if (operands[2] == constm1_rtx)
return "inc{l}\t%0";
else
{
- gcc_assert (operands[2] == constm1_rtx);
+ 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 (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}";
+ if (x86_maybe_negate_const_int (&operands[2], SImode))
+ return "add{l}\t{%2, %0|%0, %2}";
+
+ return "sub{l}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
(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_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.
+; See comments above addsi_4 for details.
-(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)"
+(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)"
{
switch (get_attr_type (insn))
{
- case TYPE_LEA:
- return "#";
case TYPE_INCDEC:
- if (operands[2] == const1_rtx)
- return "inc{w}\t%0";
+ if (operands[2] == constm1_rtx)
+ return "inc{w}\t%0";
else
{
- gcc_assert (operands[2] == constm1_rtx);
- return "dec{w}\t%0";
+ gcc_assert (operands[2] == const1_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}";
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
+ if (x86_maybe_negate_const_int (&operands[2], HImode))
+ return "add{w}\t{%2, %0|%0, %2}";
+
+ return "sub{w}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (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")])
+ (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 "*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)"
+; 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)"
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (operands[2] == const1_rtx)
- return "inc{w}\t%0";
+ if (operands[2] == constm1_rtx
+ || (CONST_INT_P (operands[2])
+ && INTVAL (operands[2]) == 255))
+ return "inc{b}\t%0";
else
- {
- gcc_assert (operands[2] == constm1_rtx);
- return "dec{w}\t%0";
+ {
+ gcc_assert (operands[2] == const1_rtx);
+ return "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]));
- return "sub{w}\t{%2, %0|%0, %2}";
- }
- return "add{w}\t{%2, %0|%0, %2}";
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
+ if (x86_maybe_negate_const_int (&operands[2], QImode))
+ return "add{b}\t{%2, %0|%0, %2}";
+
+ return "sub{b}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
(if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
- (set_attr "mode" "HI")])
+ (set_attr "mode" "QI")])
-(define_insn "*addhi_2"
+(define_insn "*add<mode>_5"
[(set (reg FLAGS_REG)
(compare
- (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rmn,rn"))
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "%0")
+ (match_operand:SWI48 2 "<general_operand>" "<g>"))
(const_int 0)))
- (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
- (plus:HI (match_dup 1) (match_dup 2)))]
+ (clobber (match_scratch:SWI48 0 "=r"))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (PLUS, HImode, operands)"
+ && !(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{w}\t%0";
+ return "inc{<imodesuffix>}\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";
+ 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 ((INTVAL (operands[2]) == -128
- || (INTVAL (operands[2]) > 0
- && INTVAL (operands[2]) != 128)))
- return "sub{w}\t{%2, %0|%0, %2}";
- operands[2] = GEN_INT (-INTVAL (operands[2]));
- return "add{w}\t{%2, %0|%0, %2}";
+ if (x86_maybe_negate_const_int (&operands[2], <MODE>mode))
+ return "sub{<imodesuffix>}\t{%2, %0|%0, %2}";
+
+ return "add{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:HI 2 "incdec_operand" "")
+ (if_then_else (match_operand:SWI48 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
- (set_attr "mode" "SI")])
-
+ (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)
}
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}";
- }
+ if (x86_maybe_negate_const_int (&operands[2], HImode))
+ return "sub{w}\t{%2, %0|%0, %2}";
+
return "add{w}\t{%2, %0|%0, %2}";
}
}
(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_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)"
+(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]))"
{
- 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";
+ return "inc{b}\t%0";
else
- {
- gcc_assert (operands[2] == constm1_rtx);
- return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
+ {
+ 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 `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";
- }
+ if (x86_maybe_negate_const_int (&operands[2], QImode))
+ return "sub{b}\t{%2, %0|%0, %2}";
- 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}";
+ 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")])
+ (set_attr "mode" "QI")])
-(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")))
+(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_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "TARGET_64BIT"
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (operands[1] == const1_rtx)
- return "inc{b}\t%0";
+ if (operands[2] == const1_rtx)
+ return "inc{b}\t%h0";
else
- {
- gcc_assert (operands[1] == constm1_rtx);
- return "dec{b}\t%0";
- }
+ {
+ gcc_assert (operands[2] == constm1_rtx
+ || (CONST_INT_P (operands[2])
+ && INTVAL (operands[2]) == 255));
+ return "dec{b}\t%h0";
+ }
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}";
+ return "add{b}\t{%2, %h0|%h0, %2}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:QI 1 "incdec_operand" "")
+ (if_then_else (match_operand:QI 2 "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")))
+ (const_string "alu")))
+ (set_attr "modrm" "1")
(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)"
+(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%0";
+ 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%0";
+ && INTVAL (operands[2]) == 255));
+ return "dec{b}\t%h0";
}
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}";
+ 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_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 && X87_ENABLE_ARITH (<MODE>mode))
- || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
- "")
-\f
-;; Subtract instructions
+;; The lea patterns for non-Pmodes needs to be matched by
+;; several insns converted to real lea by splitters.
-;; %%% splits for subditi3
+(define_insn_and_split "*lea_general_1"
+ [(set (match_operand 0 "register_operand" "=r")
+ (plus (plus (match_operand 1 "index_register_operand" "l")
+ (match_operand 2 "register_operand" "r"))
+ (match_operand 3 "immediate_operand" "i")))]
+ "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
+ || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
+ && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE (operands[0]) == GET_MODE (operands[2])
+ && (GET_MODE (operands[0]) == GET_MODE (operands[3])
+ || GET_MODE (operands[3]) == VOIDmode)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx pat;
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[2] = gen_lowpart (Pmode, operands[2]);
+ operands[3] = gen_lowpart (Pmode, operands[3]);
+ pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
+ operands[3]);
+ if (Pmode != SImode)
+ pat = gen_rtx_SUBREG (SImode, pat, 0);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+ DONE;
+}
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")])
-(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" "")))]
+(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"))
+ (match_operand:SI 3 "immediate_operand" "i"))))]
"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)))])
- (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)"
- "#")
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1)
+ (match_dup 2))
+ (match_dup 3)) 0)))]
+{
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[2] = gen_lowpart (Pmode, operands[2]);
+ operands[3] = gen_lowpart (Pmode, operands[3]);
+}
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")])
-(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 "use_carry" "1")
- (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}"
- [(set_attr "type" "alu")
- (set_attr "mode" "DI")])
+(define_insn_and_split "*lea_general_2"
+ [(set (match_operand 0 "register_operand" "=r")
+ (plus (mult (match_operand 1 "index_register_operand" "l")
+ (match_operand 2 "const248_operand" "i"))
+ (match_operand 3 "nonmemory_operand" "ri")))]
+ "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
+ || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
+ && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && (GET_MODE (operands[0]) == GET_MODE (operands[3])
+ || GET_MODE (operands[3]) == VOIDmode)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx pat;
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[3] = gen_lowpart (Pmode, operands[3]);
+ pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
+ operands[3]);
+ if (Pmode != SImode)
+ pat = gen_rtx_SUBREG (SImode, pat, 0);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+ DONE;
+}
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")])
-(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_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"))
+ (match_operand:SI 3 "nonmemory_operand" "ri"))))]
+ "TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1)
+ (match_dup 2))
+ (match_dup 3)) 0)))]
+{
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[3] = gen_lowpart (Pmode, operands[3]);
+}
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")])
-(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_and_split "*lea_general_3"
+ [(set (match_operand 0 "register_operand" "=r")
+ (plus (plus (mult (match_operand 1 "index_register_operand" "l")
+ (match_operand 2 "const248_operand" "i"))
+ (match_operand 3 "register_operand" "r"))
+ (match_operand 4 "immediate_operand" "i")))]
+ "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
+ || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
+ && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE (operands[0]) == GET_MODE (operands[3])"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx pat;
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[3] = gen_lowpart (Pmode, operands[3]);
+ operands[4] = gen_lowpart (Pmode, operands[4]);
+ pat = gen_rtx_PLUS (Pmode,
+ gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
+ operands[2]),
+ operands[3]),
+ operands[4]);
+ if (Pmode != SImode)
+ pat = gen_rtx_SUBREG (SImode, pat, 0);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+ DONE;
+}
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")])
-(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 "use_carry" "1")
- (set_attr "pent_pair" "pu")
- (set_attr "mode" "QI")])
+(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"))
+ (match_operand:SI 4 "immediate_operand" "i"))))]
+ "TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1)
+ (match_dup 2))
+ (match_dup 3))
+ (match_dup 4)) 0)))]
+{
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[3] = gen_lowpart (Pmode, operands[3]);
+ operands[4] = gen_lowpart (Pmode, operands[4]);
+}
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")])
-(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"))))
+;; 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))]
- "ix86_binary_operator_ok (MINUS, HImode, operands)"
- "sbb{w}\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "use_carry" "1")
- (set_attr "pent_pair" "pu")
- (set_attr "mode" "HI")])
+ "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 "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"))))
+;; 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))]
- "ix86_binary_operator_ok (MINUS, SImode, operands)"
- "sbb{l}\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "use_carry" "1")
- (set_attr "pent_pair" "pu")
- (set_attr "mode" "SI")])
+ "reload_completed && ix86_lea_for_add_ok (PLUS, insn, operands)"
+ [(const_int 0)]
+{
+ rtx pat;
+ /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
+ may confuse gen_lowpart. */
+ if (GET_MODE (operands[0]) != Pmode)
+ {
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[2] = gen_lowpart (Pmode, operands[2]);
+ }
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
+ if (Pmode != SImode)
+ pat = gen_rtx_SUBREG (SImode, pat, 0);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+ DONE;
+})
-(define_insn "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")))))
+;; Convert lea to the lea pattern to avoid flags dependency.
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" ""))))
(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")])
+ "TARGET_64BIT && reload_completed
+ && true_regnum (operands[0]) != true_regnum (operands[1])"
+ [(set (match_dup 0)
+ (zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
+{
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[2] = gen_lowpart (Pmode, operands[2]);
+})
+\f
+;; Subtract instructions
-(define_expand "subsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
+(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, SImode, operands); DONE;")
+ "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: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 "*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")))
+(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, 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_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
-(define_insn "*subsi_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:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
- (match_operand:SI 2 "general_operand" "ri,rm"))
+ (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:SI 0 "nonimmediate_operand" "=rm,r")
- (minus:SI (match_dup 1) (match_dup 2)))]
+ (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)
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
-(define_insn "*subsi_3"
+(define_insn "*sub<mode>_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)))]
+ (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)
&& ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\t{%2, %1|%1, %2}"
[(set_attr "type" "alu")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "SI")])
+\f
+;; Add with carry and subtract with borrow
-(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_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 "*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")))
+(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 (MINUS, HImode, operands)"
- "sub{w}\t{%2, %0|%0, %2}"
+ "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")])
+ (set_attr "use_carry" "1")
+ (set_attr "pent_pair" "pu")
+ (set_attr "mode" "<MODE>")])
-(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}"
+(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")])
+ (set_attr "use_carry" "1")
+ (set_attr "pent_pair" "pu")
+ (set_attr "mode" "SI")])
-(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}"
+(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 "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;")
+ (set_attr "pent_pair" "pu")
+ (set_attr "mode" "SI")])
+\f
+;; Overflow setting add and subtract instructions
-(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}"
+(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")])
+ (set_attr "mode" "<MODE>")])
-(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>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 "*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}"
+(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")])
+ (set_attr "mode" "<MODE>")])
-(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}"
+(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" "")))]
+ (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)"
"")
\f
;; 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" "")))
+(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))])]
- "TARGET_64BIT"
+ ""
"")
-;; 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}"
- [(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" "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" "")))
+(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 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")))
+;; 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{l}\t{%2, %1, %0|%0, %1, %2}
- imul{l}\t{%2, %1, %0|%0, %1, %2}
- imul{l}\t{%2, %0|%0, %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")
(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")
(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
;; 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}
(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
(set_attr "amdfam10_decode" "direct")
(set_attr "mode" "QI")])
-(define_expand "umulqihi3"
- [(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" ""))))
+(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))])]
- "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"
+(define_expand "<u>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"))))
+(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))]
- "TARGET_64BIT
- && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
- "imul{q}\t%2"
+ "!(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")
(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"
- "")
+ (set_attr "mode" "<MODE>")])
-(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"))))
+(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_64BIT
+ "TARGET_QIMODE_MATH
&& !(MEM_P (operands[1]) && MEM_P (operands[2]))"
- "imul{l}\t%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 "double")))
- (set_attr "amdfam10_decode" "double")
- (set_attr "mode" "SI")])
+ (const_string "direct")))
+ (set_attr "amdfam10_decode" "direct")
+ (set_attr "mode" "QI")])
-(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 ""))
+(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))])]
- "TARGET_64BIT"
- "")
+ ""
+ "operands[4] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));")
-(define_insn "*umuldi3_highpart_rex64"
+(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"
+ "<sgnprefix>mul{q}\t%2"
[(set_attr "type" "imul")
(set_attr "length_immediate" "0")
(set (attr "athlon_decode")
(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"
+(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")))
+ (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))]
"!(MEM_P (operands[1]) && MEM_P (operands[2]))"
- "mul{l}\t%2"
+ "<sgnprefix>mul{l}\t%2"
[(set_attr "type" "imul")
(set_attr "length_immediate" "0")
(set (attr "athlon_decode")
(set_attr "amdfam10_decode" "double")
(set_attr "mode" "SI")])
-(define_insn "*umulsi3_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 (zero_extend:DI
+ (mult:DI (any_extend:DI
(match_operand:SI 1 "nonimmediate_operand" "%a"))
- (zero_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]))"
- "mul{l}\t%2"
+ "<sgnprefix>mul{l}\t%2"
[(set_attr "type" "imul")
(set_attr "length_immediate" "0")
(set (attr "athlon_decode")
(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"
- "")
+;; The patterns that match these are at the end of this file.
-(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 "mulxf3"
+ [(set (match_operand:XF 0 "register_operand" "")
+ (mult:XF (match_operand:XF 1 "register_operand" "")
+ (match_operand:XF 2 "register_operand" "")))]
+ "TARGET_80387"
+ "")
-(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_expand "mul<mode>3"
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (mult: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)"
"")
+\f
+;; Divide instructions
-(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"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (zero_extend:DI (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))]
- "TARGET_64BIT
- && !(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")])
-
-;; The patterns that match these are at the end of this file.
-
-(define_expand "mulxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- (mult:XF (match_operand:XF 1 "register_operand" "")
- (match_operand:XF 2 "register_operand" "")))]
- "TARGET_80387"
- "")
-
-(define_expand "mul<mode>3"
- [(set (match_operand:MODEF 0 "register_operand" "")
- (mult: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)"
- "")
-
-;; SSE5 scalar multiply/add instructions are defined in sse.md.
-
-\f
-;; Divide instructions
-
-(define_insn "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")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_QIMODE_MATH"
- "idiv{b}\t%2"
- [(set_attr "type" "idiv")
- (set_attr "mode" "QI")])
-
-(define_insn "udivqi3"
+(define_insn "<u>divqi3"
[(set (match_operand:QI 0 "register_operand" "=a")
- (udiv: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"
- "div{b}\t%2"
+ "<sgnprefix>div{b}\t%2"
[(set_attr "type" "idiv")
(set_attr "mode" "QI")])
}
})
\f
-;; 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)))
+;; 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))])]
""
"")
-;; 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"))
+(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))]
""
- "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)))
+ "#"
+ "&& 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))
+ (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))])]
{
- /* 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];
- }
+ 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
{
- gcc_assert (!true_regnum (operands[1]));
+ /* 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")])
+ (set_attr "mode" "<MODE>")])
-(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))
+(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))]
- "TARGET_64BIT"
- "div{q}\t%2"
+ ""
+ "idiv{<imodesuffix>}\t%3"
[(set_attr "type" "idiv")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "<MODE>")])
-(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))
- (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))
+(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 "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"
- [(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))
+(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))]
""
- "div{l}\t%2"
- [(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))
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 1) (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))
+ (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))])]
- "TARGET_HIMODE_MATH"
- "operands[4] = gen_reg_rtx (HImode);")
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "mode" "<MODE>")])
-(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"))
+(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{w}\t%2"
+ "div{<imodesuffix>}\t%3"
[(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
;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al.
;; Note that this excludes ah.
-(define_insn "*testdi_1_rex64"
- [(set (reg FLAGS_REG)
- (compare
- (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm")
- (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re"))
- (const_int 0)))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "@
- test{l}\t{%k1, %k0|%k0, %k1}
- test{l}\t{%k1, %k0|%k0, %k1}
- test{q}\t{%1, %0|%0, %1}
- test{q}\t{%1, %0|%0, %1}
- test{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "test")
- (set_attr "modrm" "0,1,0,1,1")
- (set_attr "mode" "SI,SI,DI,DI,DI")
- (set_attr "pent_pair" "uv,np,uv,np,uv")])
-
-(define_insn "testsi_1"
- [(set (reg FLAGS_REG)
- (compare
- (and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm")
- (match_operand:SI 1 "general_operand" "i,i,ri"))
- (const_int 0)))]
- "ix86_match_ccmode (insn, CCNOmode)
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "test{l}\t{%1, %0|%0, %1}"
- [(set_attr "type" "test")
- (set_attr "modrm" "0,1,1")
- (set_attr "mode" "SI")
- (set_attr "pent_pair" "uv,np,uv")])
-
(define_expand "testsi_ccno_1"
[(set (reg:CCNO FLAGS_REG)
(compare:CCNO
""
"")
-(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" "")
""
"")
+(define_insn "*testdi_1"
+ [(set (reg FLAGS_REG)
+ (compare
+ (and:DI
+ (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm")
+ (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re"))
+ (const_int 0)))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ test{l}\t{%k1, %k0|%k0, %k1}
+ test{l}\t{%k1, %k0|%k0, %k1}
+ test{q}\t{%1, %0|%0, %1}
+ test{q}\t{%1, %0|%0, %1}
+ test{q}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "test")
+ (set_attr "modrm" "0,1,0,1,1")
+ (set_attr "mode" "SI,SI,DI,DI,DI")])
+
(define_insn "*testqi_1_maybe_si"
[(set (reg FLAGS_REG)
(compare
(set_attr "mode" "QI,QI,QI,SI")
(set_attr "pent_pair" "uv,np,uv,np")])
-(define_insn "*testqi_1"
+(define_insn "*test<mode>_1"
[(set (reg FLAGS_REG)
- (compare
- (and:QI
- (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm")
- (match_operand:QI 1 "general_operand" "n,n,qn"))
- (const_int 0)))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))
- && ix86_match_ccmode (insn, CCNOmode)"
- "test{b}\t{%1, %0|%0, %1}"
+ (compare
+ (and:SWI124
+ (match_operand:SWI124 0 "nonimmediate_operand" "%!*a,<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"
[(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"
+(define_insn "*testqi_ext_1_rex64"
[(set (reg FLAGS_REG)
(compare
(and:SI
(const_int 8)
(const_int 8))
(zero_extend:SI
- (match_operand:QI 1 "general_operand" "Qm")))
+ (match_operand:QI 1 "register_operand" "Q")))
(const_int 0)))]
- "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
"test{b}\t{%1, %h0|%h0, %1}"
[(set_attr "type" "test")
(set_attr "mode" "QI")])
-(define_insn "*testqi_ext_1_rex64"
+(define_insn "*testqi_ext_1"
[(set (reg FLAGS_REG)
(compare
(and:SI
(const_int 8)
(const_int 8))
(zero_extend:SI
- (match_operand:QI 1 "register_operand" "Q")))
+ (match_operand:QI 1 "general_operand" "Qm")))
(const_int 0)))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+ "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
"test{b}\t{%1, %h0|%h0, %1}"
[(set_attr "type" "test")
(set_attr "mode" "QI")])
[(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"
+(define_insn "*testqi_ext_3_rex64"
[(set (reg FLAGS_REG)
(compare (zero_extract:DI
(match_operand 0 "nonimmediate_operand" "rm")
|| 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"
else if (GET_CODE (val) == SUBREG
&& (submode = GET_MODE (SUBREG_REG (val)),
GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (submode))
- && pos + len <= GET_MODE_BITSIZE (submode))
+ && pos + len <= GET_MODE_BITSIZE (submode)
+ && GET_MODE_CLASS (submode) == MODE_INT)
{
/* Narrow a paradoxical subreg to prevent partial register stalls. */
mode = submode;
"operands[2] = gen_lowpart (QImode, operands[2]);
operands[3] = gen_lowpart (QImode, operands[3]);")
-
;; %%% This used to optimize known byte-wide and operations to memory,
;; and sometimes to QImode registers. If this is considered useful,
;; it should be done with splitters.
-(define_expand "anddi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (and:DI (match_operand:DI 1 "nonimmediate_operand" "")
- (match_operand:DI 2 "x86_64_szext_general_operand" "")))]
- "TARGET_64BIT"
- "ix86_expand_binary_operator (AND, DImode, operands); DONE;")
+(define_expand "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_rex64"
+(define_insn "*anddi_1"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
- (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
- (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
+ (and:DI
+ (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
+ (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
{
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:
}
[(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")
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:
gcc_assert (rtx_equal_p (operands[0], operands[1]));
return "and{l}\t{%2, %0|%0, %2}";
}
-}
- [(set_attr "type" "alu,alu,imovx")
- (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")
- (zero_extend:DI
- (and: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 (AND, SImode, operands)"
- "and{l}\t{%2, %k0|%k0, %2}"
- [(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")
- (match_operand:HI 2 "general_operand" "rn,rm,L")))
- (clobber (reg:CC FLAGS_REG))]
- "ix86_binary_operator_ok (AND, HImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_IMOVX:
- gcc_assert (CONST_INT_P (operands[2]));
- gcc_assert (INTVAL (operands[2]) == 0xff);
- return "movz{bl|x}\t{%b1, %k0|%k0, %b1}";
-
- default:
- gcc_assert (rtx_equal_p (operands[0], operands[1]));
-
- return "and{w}\t{%2, %0|%0, %2}";
- }
-}
- [(set_attr "type" "alu,alu,imovx")
- (set_attr "length_immediate" "*,*,0")
- (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")
- (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:QI 2 "general_operand" "qn,qmn,rn")))
- (clobber (reg:CC FLAGS_REG))]
- "ix86_binary_operator_ok (AND, QImode, operands)"
- "@
- and{b}\t{%2, %0|%0, %2}
- and{b}\t{%2, %0|%0, %2}
- and{l}\t{%k2, %k0|%k0, %k2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "QI,QI,SI")])
-
-(define_insn "*andqi_1_slp"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
- (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))
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "and{b}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")
- (set_attr "mode" "QI")])
-
-(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"))
- (const_int 0)))
- (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,*r")
- (and:QI (match_dup 1) (match_dup 2)))]
- "ix86_binary_operator_ok (AND, QImode, operands)
- && ix86_match_ccmode (insn,
- CONST_INT_P (operands[2])
- && INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)"
-{
- if (which_alternative == 2)
- {
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
- return "and{l}\t{%2, %k0|%k0, %2}";
- }
- return "and{b}\t{%2, %0|%0, %2}";
-}
- [(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"))
- (const_int 0)))
- (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
- (and:QI (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}"
- [(set_attr "type" "alu")
- (set_attr "mode" "QI")])
-
-(define_insn "*andqi_2_slp"
- [(set (reg FLAGS_REG)
- (compare (and:QI
- (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
- (match_operand:QI 1 "nonimmediate_operand" "qmn,qn"))
- (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))
- && ix86_match_ccmode (insn, CCNOmode)
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "and{b}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")
- (set_attr "mode" "QI")])
-
-;; ??? 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)
- (const_int 8))
- (and: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))]
- ""
- "and{b}\t{%2, %h0|%h0, %2}"
- [(set_attr "type" "alu")
- (set_attr "length_immediate" "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
- (and:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0")
- (const_int 8)
- (const_int 8))
- (match_operand 2 "const_int_operand" "n"))
- (const_int 0)))
- (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
- (const_int 8)
- (const_int 8))
- (and:SI
- (zero_extract:SI
- (match_dup 1)
- (const_int 8)
- (const_int 8))
- (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)"
- "and{b}\t{%2, %h0|%h0, %2}"
- [(set_attr "type" "alu")
- (set_attr "length_immediate" "1")
- (set_attr "mode" "QI")])
-
-(define_insn "*andqi_ext_1"
- [(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:QI 2 "general_operand" "Qm"))))
- (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_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)
- (const_int 8))
- (and: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))]
- ""
- "and{b}\t{%h2, %h0|%h0, %h2}"
- [(set_attr "type" "alu")
- (set_attr "length_immediate" "0")
- (set_attr "mode" "QI")])
-
-;; Convert wide AND instructions with immediate operand to shorter QImode
-;; equivalents when possible.
-;; Don't do the splitting with memory operands, since it introduces risk
-;; of memory mismatch stalls. We may want to do the splitting for optimizing
-;; for size, but that can (should?) be handled by generic code instead.
-(define_split
- [(set (match_operand 0 "register_operand" "")
- (and (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))
- (and: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 AND can be encoded with sign extended immediate, this is only
-;; profitable when 7th bit is not set.
-(define_split
- [(set (match_operand 0 "register_operand" "")
- (and (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))
- (and: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]);")
-\f
-;; Logical inclusive 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}"
- [(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 "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 "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")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
-(define_insn "*iorsi_1_zext"
+(define_insn "*andsi_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "g"))))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
- "or{l}\t{%2, %k0|%k0, %2}"
+ "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
+ "and{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
-(define_insn "*iorsi_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")))
+(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")
+ (match_operand:HI 2 "general_operand" "rn,rm,L")))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
- "or{l}\t{%2, %k0|%k0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "SI")])
+ "ix86_binary_operator_ok (AND, HImode, operands)"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_IMOVX:
+ gcc_assert (CONST_INT_P (operands[2]));
+ gcc_assert (INTVAL (operands[2]) == 0xff);
+ return "movz{bl|x}\t{%b1, %k0|%k0, %b1}";
-(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"))
- (const_int 0)))
- (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
- (ior:SI (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}"
- [(set_attr "type" "alu")
- (set_attr "mode" "SI")])
+ default:
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
-;; 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"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (ior: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}"
- [(set_attr "type" "alu")
- (set_attr "mode" "SI")])
+ return "and{w}\t{%2, %0|%0, %2}";
+ }
+}
+ [(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 "*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"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=r")
- (ior: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}"
+;; %%% Potential partial reg stall on alternative 2. What to do?
+(define_insn "*andqi_1"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
+ (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:QI 2 "general_operand" "qn,qmn,rn")))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_binary_operator_ok (AND, QImode, operands)"
+ "@
+ and{b}\t{%2, %0|%0, %2}
+ and{b}\t{%2, %0|%0, %2}
+ and{l}\t{%k2, %k0|%k0, %k2}"
[(set_attr "type" "alu")
- (set_attr "mode" "SI")])
+ (set_attr "mode" "QI,QI,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_insn "*andqi_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
+ (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))
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "and{b}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "alu1")
+ (set_attr "mode" "QI")])
-(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_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_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")))
+(define_split
+ [(set (match_operand 0 "ext_register_operand" "")
+ (and (match_dup 0)
+ (const_int -65281)))
(clobber (reg:CC FLAGS_REG))]
- "ix86_binary_operator_ok (IOR, HImode, operands)"
- "or{w}\t{%2, %0|%0, %2}"
+ "(!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" "HI")])
+ (set_attr "mode" "SI,DI,DI")])
-(define_insn "*iorhi_2"
+(define_insn "*andqi_2_maybe_si"
[(set (reg FLAGS_REG)
- (compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rmn,rn"))
+ (compare (and:QI
+ (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:QI 2 "general_operand" "qmn,qn,n"))
(const_int 0)))
- (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
- (ior:HI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
- && ix86_binary_operator_ok (IOR, HImode, operands)"
- "or{w}\t{%2, %0|%0, %2}"
+ (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,*r")
+ (and:QI (match_dup 1) (match_dup 2)))]
+ "ix86_binary_operator_ok (AND, QImode, operands)
+ && ix86_match_ccmode (insn,
+ CONST_INT_P (operands[2])
+ && INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)"
+{
+ if (which_alternative == 2)
+ {
+ if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
+ return "and{l}\t{%2, %k0|%k0, %2}";
+ }
+ return "and{b}\t{%2, %0|%0, %2}";
+}
[(set_attr "type" "alu")
- (set_attr "mode" "HI")])
+ (set_attr "mode" "QI,QI,SI")])
-(define_insn "*iorhi_3"
+(define_insn "*and<mode>_2"
[(set (reg FLAGS_REG)
- (compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
- (match_operand:HI 2 "general_operand" "rmn"))
+ (compare (and:SWI124
+ (match_operand:SWI124 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SWI124 2 "general_operand" "<g>,<r><i>"))
(const_int 0)))
- (clobber (match_scratch:HI 0 "=r"))]
+ (set (match_operand:SWI124 0 "nonimmediate_operand" "=<r>,<r>m")
+ (and:SWI124 (match_dup 1) (match_dup 2)))]
"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}"
+ && ix86_binary_operator_ok (AND, <MODE>mode, operands)"
+ "and{<imodesuffix>}\t{%2, %0|%0, %2}"
[(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")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*iorqi_2"
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+(define_insn "*andsi_2_zext"
[(set (reg FLAGS_REG)
- (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "qmn,qn"))
+ (compare (and:SI
+ (match_operand:SI 1 "nonimmediate_operand" "%0")
+ (match_operand:SI 2 "general_operand" "g"))
(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 (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" "QI")])
+ (set_attr "mode" "SI")])
-(define_insn "*iorqi_2_slp"
+(define_insn "*andqi_2_slp"
[(set (reg FLAGS_REG)
- (compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
- (match_operand:QI 1 "general_operand" "qmn,qn"))
+ (compare (and:QI
+ (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
+ (match_operand:QI 1 "nonimmediate_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))
+ (and: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}"
+ "and{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"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=q"))]
- "ix86_match_ccmode (insn, CCNOmode)
- && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
- "or{b}\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "QI")])
-
-(define_insn "*iorqi_ext_0"
+;; ??? 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)
(const_int 8))
- (ior:SI
+ (and: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}"
+ ""
+ "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
+ (and:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (match_operand 2 "const_int_operand" "n"))
+ (const_int 0)))
+ (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (and:SI
+ (zero_extract:SI
+ (match_dup 1)
+ (const_int 8)
+ (const_int 8))
+ (match_dup 2)))]
+ "ix86_match_ccmode (insn, CCNOmode)"
+ "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 "*iorqi_ext_1"
+(define_insn "*andqi_ext_1_rex64"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (ior:SI
+ (and:SI
(zero_extract:SI
(match_operand 1 "ext_register_operand" "0")
(const_int 8)
(const_int 8))
(zero_extend:SI
- (match_operand:QI 2 "general_operand" "Qm"))))
+ (match_operand 2 "ext_register_operand" "Q"))))
(clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT
- && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))"
- "or{b}\t{%2, %h0|%h0, %2}"
+ "TARGET_64BIT"
+ "and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
-(define_insn "*iorqi_ext_1_rex64"
+(define_insn "*andqi_ext_1"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (ior:SI
+ (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"))))
+ (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}"
+ "!TARGET_64BIT"
+ "and{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 "*andqi_ext_2"
[(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_extract:SI (match_operand 2 "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_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))"
- "ior{b}\t{%h2, %h0|%h0, %h2}"
+ ""
+ "and{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
+;; Convert wide AND instructions with immediate operand to shorter QImode
+;; equivalents when possible.
+;; Don't do the splitting with memory operands, since it introduces risk
+;; of memory mismatch stalls. We may want to do the splitting for optimizing
+;; for size, but that can (should?) be handled by generic code instead.
(define_split
[(set (match_operand 0 "register_operand" "")
- (ior (match_operand 1 "register_operand" "")
+ (and (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))
+ && !(~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)
+ (and:SI (zero_extract:SI (match_dup 1)
(const_int 8) (const_int 8))
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
operands[1] = gen_lowpart (SImode, operands[1]);
operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
-;; Since OR can be encoded with sign extended immediate, this is only
-;; profitable when 7th bit is set.
+;; Since AND can be encoded with sign extended immediate, this is only
+;; profitable when 7th bit is not set.
(define_split
[(set (match_operand 0 "register_operand" "")
- (ior (match_operand 1 "general_operand" "")
+ (and (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)
+ && !(~INTVAL (operands[2]) & ~255)
+ && !(INTVAL (operands[2]) & 128)
&& GET_MODE (operands[0]) != QImode"
[(parallel [(set (strict_low_part (match_dup 0))
- (ior:QI (match_dup 1)
+ (and: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]);")
\f
-;; Logical XOR 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 "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_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 "*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")))
+(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))]
- "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}"
+ "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+ "<logicprefix>{<imodesuffix>}\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;")
+ (set_attr "mode" "<MODE>")])
-(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")))
+;; %%% 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 (XOR, SImode, operands)"
- "xor{l}\t{%2, %0|%0, %2}"
+ "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" "SI")])
+ (set_attr "mode" "QI,QI,SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
-;; Add speccase for immediates
-(define_insn "*xorsi_1_zext"
+(define_insn "*<code>si_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"))))
+ (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 (XOR, SImode, operands)"
- "xor{l}\t{%2, %k0|%k0, %2}"
+ "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 "*xorsi_1_zext_imm"
+(define_insn "*<code>si_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")))
+ (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 (XOR, SImode, operands)"
- "xor{l}\t{%2, %k0|%k0, %2}"
+ "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 "*xorsi_2"
+(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 (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "g,ri"))
+ (compare (any_or:SWI
+ (match_operand:SWI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SWI 2 "<general_operand>" "<g>,<r><i>"))
(const_int 0)))
- (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
- (xor: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 (XOR, SImode, operands)"
- "xor{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 "*xorsi_2_zext"
+(define_insn "*<code>si_2_zext"
[(set (reg FLAGS_REG)
- (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "g"))
+ (compare (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+ (match_operand:SI 2 "general_operand" "g"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (xor: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 (XOR, SImode, operands)"
- "xor{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 "*xorsi_2_zext_imm"
+(define_insn "*<code>si_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"))
+ (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")
- (xor: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 (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}"
+ && ix86_binary_operator_ok (<CODE>, SImode, operands)"
+ "<logicprefix>{l}\t{%2, %k0|%k0, %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"
+(define_insn "*<code>qi_2_slp"
[(set (reg FLAGS_REG)
- (compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rmn,rn"))
+ (compare (any_or:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
+ (match_operand:QI 1 "general_operand" "qmn,qn"))
(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")])
+ (set (strict_low_part (match_dup 0))
+ (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]))"
+ "<logicprefix>{b}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "alu1")
+ (set_attr "mode" "QI")])
-(define_insn "*xorhi_3"
+(define_insn "*<code><mode>_3"
[(set (reg FLAGS_REG)
- (compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
- (match_operand:HI 2 "general_operand" "rmn"))
+ (compare (any_or:SWI
+ (match_operand:SWI 1 "nonimmediate_operand" "%0")
+ (match_operand:SWI 2 "<general_operand>" "<g>"))
(const_int 0)))
- (clobber (match_scratch:HI 0 "=r"))]
+ (clobber (match_scratch:SWI 0 "=<r>"))]
"ix86_match_ccmode (insn, CCNOmode)
- && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
- "xor{w}\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" "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")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*xorqi_ext_0"
+(define_insn "*<code>qi_ext_0"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (xor: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))"
- "xor{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 "modrm" "1")
(set_attr "mode" "QI")])
-(define_insn "*xorqi_ext_1"
+(define_insn "*<code>qi_ext_1_rex64"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (xor:SI
+ (any_or:SI
(zero_extract:SI
(match_operand 1 "ext_register_operand" "0")
(const_int 8)
(const_int 8))
(zero_extend:SI
- (match_operand:QI 2 "general_operand" "Qm"))))
+ (match_operand 2 "ext_register_operand" "Q"))))
(clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT
+ "TARGET_64BIT
&& (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))"
- "xor{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 "*xorqi_ext_1_rex64"
+(define_insn "*<code>qi_ext_1"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (xor:SI
+ (any_or:SI
(zero_extract:SI
(match_operand 1 "ext_register_operand" "0")
(const_int 8)
(const_int 8))
(zero_extend:SI
- (match_operand 2 "ext_register_operand" "Q"))))
+ (match_operand:QI 2 "general_operand" "Qm"))))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT
+ "!TARGET_64BIT
&& (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))"
- "xor{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 "*xorqi_ext_2"
+(define_insn "*<code>qi_ext_2"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (xor:SI
+ (any_or:SI
(zero_extract:SI (match_operand 1 "ext_register_operand" "0")
(const_int 8)
(const_int 8))
(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}"
+ "!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_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 "mode" "QI")])
-
-(define_insn "*xorqi_cc_ext_1"
- [(set (reg FLAGS_REG)
- (compare
- (xor:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0")
- (const_int 8)
- (const_int 8))
- (match_operand:QI 2 "general_operand" "qmn"))
- (const_int 0)))
- (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q")
- (const_int 8)
- (const_int 8))
- (xor:SI
- (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
- (match_dup 2)))]
- "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
- "xor{b}\t{%2, %h0|%h0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "QI")])
+(define_split
+ [(set (match_operand 0 "register_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])
+ && (!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))
+ (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]);
+ operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
-(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")])
+;; Since OR can be encoded with sign extended immediate, this is only
+;; profitable when 7th bit is set.
+(define_split
+ [(set (match_operand 0 "register_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])
+ && (!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))
+ (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]);")
(define_expand "xorqi_cc_ext_1"
[(parallel [
(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)))])]
""
"")
-(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);")
+(define_insn "*xorqi_cc_ext_1_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (xor:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (match_operand:QI 2 "nonmemory_operand" "Qn"))
+ (const_int 0)))
+ (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (xor:SI
+ (zero_extract:SI
+ (match_dup 1)
+ (const_int 8)
+ (const_int 8))
+ (match_dup 2)))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+ "xor{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
-;; 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]);")
+(define_insn "*xorqi_cc_ext_1"
+ [(set (reg FLAGS_REG)
+ (compare
+ (xor:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (match_operand:QI 2 "general_operand" "qmn"))
+ (const_int 0)))
+ (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q")
+ (const_int 8)
+ (const_int 8))
+ (xor:SI
+ (zero_extract:SI
+ (match_dup 1)
+ (const_int 8)
+ (const_int 8))
+ (match_dup 2)))]
+ "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+ "xor{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
\f
;; Negation instructions
-(define_expand "negti2"
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))]
- "TARGET_64BIT"
- "ix86_expand_unary_operator (NEG, TImode, operands); DONE;")
-
-(define_insn "*negti2_1"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=ro")
- (neg:TI (match_operand:TI 1 "nonimmediate_operand" "0")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT
- && ix86_unary_operator_ok (NEG, TImode, operands)"
- "#")
-
-(define_split
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && reload_completed"
- [(parallel
- [(set (reg:CCZ FLAGS_REG)
- (compare:CCZ (neg:DI (match_dup 1)) (const_int 0)))
- (set (match_dup 0) (neg:DI (match_dup 1)))])
- (parallel
- [(set (match_dup 2)
- (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
- (match_dup 3))
- (const_int 0)))
- (clobber (reg:CC FLAGS_REG))])
- (parallel
- [(set (match_dup 2)
- (neg:DI (match_dup 2)))
- (clobber (reg:CC FLAGS_REG))])]
- "split_ti (&operands[0], 2, &operands[0], &operands[2]);")
-
-(define_expand "negdi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
+(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, 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)"
- "#")
+ "ix86_expand_unary_operator (NEG, <MODE>mode, operands); DONE;")
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (neg:DI (match_operand:DI 1 "general_operand" "")))
+(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))]
- "!TARGET_64BIT && reload_completed"
+ "ix86_unary_operator_ok (NEG, <DWI>mode, operands)"
+ "#"
+ "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)))])
+ (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:SI (plus:SI (ltu:SI (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: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"
- [(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")])
-
+ "split_<dwi> (&operands[0], 2, &operands[0], &operands[2]);")
-(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")))
+(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, SImode, operands)"
- "neg{l}\t%0"
+ "ix86_unary_operator_ok (NEG, <MODE>mode, operands)"
+ "neg{<imodesuffix>}\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"
;; 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)))
[(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"
(unspec:CSGNMODE
[(match_operand:CSGNMODE 2 "register_operand" "x,0,0,x,x")
(match_operand:CSGNMODE 3 "register_operand" "1,1,x,1,x")
- (match_operand:<CSGNVMODE> 4 "nonimmediate_operand" "X,xm,xm,0,0")
- (match_operand:<CSGNVMODE> 5 "nonimmediate_operand" "0,xm,1,xm,1")]
- UNSPEC_COPYSIGN))
- (clobber (match_scratch:<CSGNVMODE> 1 "=x,x,x,x,x"))]
- "(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || (TARGET_SSE2 && (<MODE>mode == TFmode))"
- "#")
-
-(define_split
- [(set (match_operand:CSGNMODE 0 "register_operand" "")
- (unspec:CSGNMODE
- [(match_operand:CSGNMODE 2 "register_operand" "")
- (match_operand:CSGNMODE 3 "register_operand" "")
- (match_operand:<CSGNVMODE> 4 "" "")
- (match_operand:<CSGNVMODE> 5 "" "")]
- UNSPEC_COPYSIGN))
- (clobber (match_scratch:<CSGNVMODE> 1 ""))]
- "((SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || (TARGET_SSE2 && (<MODE>mode == TFmode)))
- && reload_completed"
- [(const_int 0)]
-{
- ix86_split_copysign_var (operands);
- DONE;
-})
-\f
-;; One complement instructions
-
-(define_expand "one_cmpldi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (not:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_64BIT"
- "ix86_expand_unary_operator (NOT, DImode, operands); DONE;")
-
-(define_insn "*one_cmpldi2_1_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- (not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
- "TARGET_64BIT && ix86_unary_operator_ok (NOT, DImode, operands)"
- "not{q}\t%0"
- [(set_attr "type" "negnot")
- (set_attr "mode" "DI")])
-
-(define_insn "*one_cmpldi2_2_rex64"
- [(set (reg FLAGS_REG)
- (compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
- (const_int 0)))
- (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- (not:DI (match_dup 1)))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
- && ix86_unary_operator_ok (NOT, DImode, operands)"
- "#"
- [(set_attr "type" "alu1")
- (set_attr "mode" "DI")])
-
-(define_split
- [(set (match_operand 0 "flags_reg_operand" "")
- (match_operator 2 "compare_operator"
- [(not:DI (match_operand:DI 3 "nonimmediate_operand" ""))
- (const_int 0)]))
- (set (match_operand:DI 1 "nonimmediate_operand" "")
- (not:DI (match_dup 3)))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
- [(parallel [(set (match_dup 0)
- (match_op_dup 2
- [(xor:DI (match_dup 3) (const_int -1))
- (const_int 0)]))
- (set (match_dup 1)
- (xor:DI (match_dup 3) (const_int -1)))])]
- "")
-
-(define_expand "one_cmplsi2"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
- ""
- "ix86_expand_unary_operator (NOT, SImode, operands); DONE;")
-
-(define_insn "*one_cmplsi2_1"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
- "ix86_unary_operator_ok (NOT, SImode, operands)"
- "not{l}\t%0"
- [(set_attr "type" "negnot")
- (set_attr "mode" "SI")])
-
-;; ??? Currently never generated - xor is used instead.
-(define_insn "*one_cmplsi2_1_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (not:SI (match_operand:SI 1 "register_operand" "0"))))]
- "TARGET_64BIT && ix86_unary_operator_ok (NOT, SImode, operands)"
- "not{l}\t%k0"
- [(set_attr "type" "negnot")
- (set_attr "mode" "SI")])
-
-(define_insn "*one_cmplsi2_2"
- [(set (reg FLAGS_REG)
- (compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
- (const_int 0)))
- (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- (not:SI (match_dup 1)))]
- "ix86_match_ccmode (insn, CCNOmode)
- && ix86_unary_operator_ok (NOT, SImode, operands)"
- "#"
- [(set_attr "type" "alu1")
- (set_attr "mode" "SI")])
-
-(define_split
- [(set (match_operand 0 "flags_reg_operand" "")
- (match_operator 2 "compare_operator"
- [(not:SI (match_operand:SI 3 "nonimmediate_operand" ""))
- (const_int 0)]))
- (set (match_operand:SI 1 "nonimmediate_operand" "")
- (not:SI (match_dup 3)))]
- "ix86_match_ccmode (insn, CCNOmode)"
- [(parallel [(set (match_dup 0)
- (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
- (const_int 0)]))
- (set (match_dup 1)
- (xor:SI (match_dup 3) (const_int -1)))])]
- "")
-
-;; ??? Currently never generated - xor is used instead.
-(define_insn "*one_cmplsi2_2_zext"
- [(set (reg FLAGS_REG)
- (compare (not:SI (match_operand:SI 1 "register_operand" "0"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (not:SI (match_dup 1))))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
- && ix86_unary_operator_ok (NOT, SImode, operands)"
- "#"
- [(set_attr "type" "alu1")
- (set_attr "mode" "SI")])
-
-(define_split
- [(set (match_operand 0 "flags_reg_operand" "")
- (match_operator 2 "compare_operator"
- [(not:SI (match_operand:SI 3 "register_operand" ""))
- (const_int 0)]))
- (set (match_operand:DI 1 "register_operand" "")
- (zero_extend:DI (not:SI (match_dup 3))))]
- "ix86_match_ccmode (insn, CCNOmode)"
- [(parallel [(set (match_dup 0)
- (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
- (const_int 0)]))
- (set (match_dup 1)
- (zero_extend:DI (xor:SI (match_dup 3) (const_int -1))))])]
- "")
-
-(define_expand "one_cmplhi2"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
- "TARGET_HIMODE_MATH"
- "ix86_expand_unary_operator (NOT, HImode, operands); DONE;")
+ (match_operand:<CSGNVMODE> 4 "nonimmediate_operand" "X,xm,xm,0,0")
+ (match_operand:<CSGNVMODE> 5 "nonimmediate_operand" "0,xm,1,xm,1")]
+ UNSPEC_COPYSIGN))
+ (clobber (match_scratch:<CSGNVMODE> 1 "=x,x,x,x,x"))]
+ "(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+ || (TARGET_SSE2 && (<MODE>mode == TFmode))"
+ "#")
-(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_split
+ [(set (match_operand:CSGNMODE 0 "register_operand" "")
+ (unspec:CSGNMODE
+ [(match_operand:CSGNMODE 2 "register_operand" "")
+ (match_operand:CSGNMODE 3 "register_operand" "")
+ (match_operand:<CSGNVMODE> 4 "" "")
+ (match_operand:<CSGNVMODE> 5 "" "")]
+ UNSPEC_COPYSIGN))
+ (clobber (match_scratch:<CSGNVMODE> 1 ""))]
+ "((SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+ || (TARGET_SSE2 && (<MODE>mode == TFmode)))
+ && reload_completed"
+ [(const_int 0)]
+{
+ ix86_split_copysign_var (operands);
+ DONE;
+})
+\f
+;; One complement instructions
-(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_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_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)))])]
- "")
+(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" "<MODE>")])
;; %%% 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")))]
[(set_attr "type" "negnot")
(set_attr "mode" "QI,SI")])
-(define_insn "*one_cmplqi2_2"
+;; ??? 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:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
+ (compare (not:SWI (match_operand:SWI 1 "nonimmediate_operand" "0"))
(const_int 0)))
- (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
- (not:QI (match_dup 1)))]
+ (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
+ (not:SWI (match_dup 1)))]
"ix86_match_ccmode (insn, CCNOmode)
- && ix86_unary_operator_ok (NOT, QImode, operands)"
+ && ix86_unary_operator_ok (NOT, <MODE>mode, operands)"
"#"
[(set_attr "type" "alu1")
- (set_attr "mode" "QI")])
+ (set_attr "mode" "<MODE>")])
(define_split
[(set (match_operand 0 "flags_reg_operand" "")
(match_operator 2 "compare_operator"
- [(not:QI (match_operand:QI 3 "nonimmediate_operand" ""))
+ [(not:SWI (match_operand:SWI 3 "nonimmediate_operand" ""))
(const_int 0)]))
- (set (match_operand:QI 1 "nonimmediate_operand" "")
- (not:QI (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:QI (match_dup 3) (const_int -1))
- (const_int 0)]))
+ (match_op_dup 2 [(xor:SWI (match_dup 3) (const_int -1))
+ (const_int 0)]))
(set (match_dup 1)
- (xor:QI (match_dup 3) (const_int -1)))])]
- "")
-\f
-;; Arithmetic shift instructions
-
-;; DImode shifts are implemented using the i386 "shift double" opcode,
-;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count
-;; is variable, then the count is in %cl and the "imm" operand is dropped
-;; from the assembler input.
-;;
-;; This instruction shifts the target reg/mem as usual, but instead of
-;; shifting in zeros, bits are shifted in from reg operand. If the insn
-;; is a left shift double, bits are taken from the high order bits of
-;; reg, else if the insn is a shift right double, bits are taken from the
-;; low order bits of reg. So if %eax is "1234" and %edx is "5678",
-;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
-;;
-;; Since sh[lr]d does not change the `reg' operand, that is done
-;; separately, making all shifts emit pairs of shift double and normal
-;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to
-;; support a 63 bit shift, each shift where the count is in a reg expands
-;; to a pair of shifts, a branch, a shift by 32 and a label.
-;;
-;; If the shift count is a constant, we need never emit more than one
-;; shift pair, instead using moves and sign extension for counts greater
-;; than 31.
-
-(define_expand "ashlti3"
- [(set (match_operand:TI 0 "register_operand" "")
- (ashift:TI (match_operand:TI 1 "reg_or_pm1_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))]
- "TARGET_64BIT"
- "ix86_expand_binary_operator (ASHIFT, TImode, operands); DONE;")
-
-;; This pattern must be defined before *ashlti3_1 to prevent
-;; combine pass from converting sse2_ashlti3 to *ashlti3_1.
-
-(define_insn "*avx_ashlti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (ashift:TI (match_operand:TI 1 "register_operand" "x")
- (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))]
- "TARGET_AVX"
-{
- operands[2] = GEN_INT (INTVAL (operands[2]) / 8);
- return "vpslldq\t{%2, %1, %0|%0, %1, %2}";
-}
- [(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
- (set_attr "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")
- (match_operand:QI 2 "nonmemory_operand" "Oc,Oc")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
- "#"
- [(set_attr "type" "multi")])
-
-(define_peephole2
- [(match_scratch:DI 3 "r")
- (parallel [(set (match_operand:TI 0 "register_operand" "")
- (ashift:TI (match_operand:TI 1 "nonmemory_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC FLAGS_REG))])
- (match_dup 3)]
- "TARGET_64BIT"
- [(const_int 0)]
- "ix86_split_ashl (operands, operands[3], TImode); DONE;")
-
-(define_split
- [(set (match_operand:TI 0 "register_operand" "")
- (ashift:TI (match_operand:TI 1 "nonmemory_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? epilogue_completed : reload_completed)"
- [(const_int 0)]
- "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;")
-
-(define_insn "x86_64_shld"
- [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m")
- (ior:DI (ashift:DI (match_dup 0)
- (match_operand:QI 2 "nonmemory_operand" "Jc"))
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
- (minus:QI (const_int 64) (match_dup 2)))))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
- "shld{q}\t{%s2%1, %0|%0, %1, %2}"
- [(set_attr "type" "ishift")
- (set_attr "prefix_0f" "1")
- (set_attr "mode" "DI")
- (set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "vector")])
-
-(define_expand "x86_64_shift_adj_1"
- [(set (reg:CCZ FLAGS_REG)
- (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
- (const_int 64))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "")
- (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
- (match_operand:DI 1 "register_operand" "")
- (match_dup 0)))
- (set (match_dup 1)
- (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
- (match_operand:DI 3 "register_operand" "r")
- (match_dup 1)))]
- "TARGET_64BIT"
+ (xor:SWI (match_dup 3) (const_int -1)))])]
"")
-(define_expand "x86_64_shift_adj_2"
- [(use (match_operand:DI 0 "register_operand" ""))
- (use (match_operand:DI 1 "register_operand" ""))
- (use (match_operand:QI 2 "register_operand" ""))]
- "TARGET_64BIT"
-{
- rtx label = gen_label_rtx ();
- rtx tmp;
-
- emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (64)));
-
- tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
- tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
- JUMP_LABEL (tmp) = label;
-
- emit_move_insn (operands[0], operands[1]);
- ix86_expand_clear (operands[1]);
-
- emit_label (label);
- LABEL_NUSES (label) = 1;
-
- DONE;
-})
-
-(define_expand "ashldi3"
- [(set (match_operand:DI 0 "shiftdi_operand" "")
- (ashift:DI (match_operand:DI 1 "ashldi_input_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))]
- ""
- "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;")
-
-(define_insn "*ashldi3_1_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
- (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l")
- (match_operand:QI 2 "nonmemory_operand" "cJ,M")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- gcc_assert (rtx_equal_p (operands[0], operands[1]));
- return "add{q}\t%0, %0";
-
- case TYPE_LEA:
- gcc_assert (CONST_INT_P (operands[2]));
- gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3);
- operands[1] = gen_rtx_MULT (DImode, operands[1],
- GEN_INT (1 << INTVAL (operands[2])));
- return "lea{q}\t{%a1, %0|%0, %a1}";
-
- default:
- if (REG_P (operands[2]))
- return "sal{q}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{q}\t%0";
- else
- return "sal{q}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "1")
- (const_string "lea")
- (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set_attr "mode" "DI")])
-
-;; Convert lea to the lea pattern to avoid flags dependency.
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (ashift:DI (match_operand:DI 1 "index_register_operand" "")
- (match_operand:QI 2 "immediate_operand" "")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
- [(set (match_dup 0)
- (mult:DI (match_dup 1)
- (match_dup 2)))]
- "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);")
-
-;; This pattern can't accept a variable shift count, since shifts by
-;; zero don't affect the flags. We assume that shifts by constant
-;; zero are optimized away.
-(define_insn "*ashldi3_cmp_rex64"
+;; ??? Currently never generated - xor is used instead.
+(define_insn "*one_cmplsi2_2_zext"
[(set (reg FLAGS_REG)
- (compare
- (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_63_operand" "J"))
- (const_int 0)))
- (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- (ashift:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT
- && (optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{q}\t%0, %0";
-
- default:
- if (REG_P (operands[2]))
- return "sal{q}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{q}\t%0";
- else
- return "sal{q}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set_attr "mode" "DI")])
+ (compare (not:SI (match_operand:SI 1 "register_operand" "0"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (not:SI (match_dup 1))))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+ && ix86_unary_operator_ok (NOT, SImode, operands)"
+ "#"
+ [(set_attr "type" "alu1")
+ (set_attr "mode" "SI")])
-(define_insn "*ashldi3_cconly_rex64"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_63_operand" "J"))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=r"))]
- "TARGET_64BIT
- && (optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || TARGET_DOUBLE_WITH_ADD)))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{q}\t%0, %0";
+(define_split
+ [(set (match_operand 0 "flags_reg_operand" "")
+ (match_operator 2 "compare_operator"
+ [(not:SI (match_operand:SI 3 "register_operand" ""))
+ (const_int 0)]))
+ (set (match_operand:DI 1 "register_operand" "")
+ (zero_extend:DI (not:SI (match_dup 3))))]
+ "ix86_match_ccmode (insn, CCNOmode)"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
+ (const_int 0)]))
+ (set (match_dup 1)
+ (zero_extend:DI (xor:SI (match_dup 3) (const_int -1))))])]
+ "")
+\f
+;; Arithmetic shift instructions
- default:
- if (REG_P (operands[2]))
- return "sal{q}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{q}\t%0";
- else
- return "sal{q}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set_attr "mode" "DI")])
+;; DImode shifts are implemented using the i386 "shift double" opcode,
+;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count
+;; is variable, then the count is in %cl and the "imm" operand is dropped
+;; from the assembler input.
+;;
+;; This instruction shifts the target reg/mem as usual, but instead of
+;; shifting in zeros, bits are shifted in from reg operand. If the insn
+;; is a left shift double, bits are taken from the high order bits of
+;; reg, else if the insn is a shift right double, bits are taken from the
+;; low order bits of reg. So if %eax is "1234" and %edx is "5678",
+;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
+;;
+;; Since sh[lr]d does not change the `reg' operand, that is done
+;; separately, making all shifts emit pairs of shift double and normal
+;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to
+;; support a 63 bit shift, each shift where the count is in a reg expands
+;; to a pair of shifts, a branch, a shift by 32 and a label.
+;;
+;; If the shift count is a constant, we need never emit more than one
+;; shift pair, instead using moves and sign extension for counts greater
+;; than 31.
+
+(define_expand "ashl<mode>3"
+ [(set (match_operand:SDWIM 0 "<shift_operand>" "")
+ (ashift:SDWIM (match_operand:SDWIM 1 "<ashl_input_operand>" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
+ ""
+ "ix86_expand_binary_operator (ASHIFT, <MODE>mode, operands); DONE;")
-(define_insn "*ashldi3_1"
- [(set (match_operand:DI 0 "register_operand" "=&r,r")
- (ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0")
- (match_operand:QI 2 "nonmemory_operand" "Jc,Jc")))
+(define_insn "*ashl<mode>3_doubleword"
+ [(set (match_operand:DWI 0 "register_operand" "=&r,r")
+ (ashift:DWI (match_operand:DWI 1 "reg_or_pm1_operand" "n,0")
+ (match_operand:QI 2 "nonmemory_operand" "<S>c,<S>c")))
(clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT"
+ ""
"#"
[(set_attr "type" "multi")])
-;; By default we don't ask for a scratch register, because when DImode
+(define_split
+ [(set (match_operand:DWI 0 "register_operand" "")
+ (ashift:DWI (match_operand:DWI 1 "nonmemory_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "(optimize && flag_peephole2) ? epilogue_completed : reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashl (operands, NULL_RTX, <MODE>mode); DONE;")
+
+;; By default we don't ask for a scratch register, because when DWImode
;; values are manipulated, registers are already at a premium. But if
;; we have one handy, we won't turn it away.
+
(define_peephole2
- [(match_scratch:SI 3 "r")
- (parallel [(set (match_operand:DI 0 "register_operand" "")
- (ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
+ [(match_scratch:DWIH 3 "r")
+ (parallel [(set (match_operand:<DWI> 0 "register_operand" "")
+ (ashift:<DWI>
+ (match_operand:<DWI> 1 "nonmemory_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
(clobber (reg:CC FLAGS_REG))])
(match_dup 3)]
- "!TARGET_64BIT && TARGET_CMOVE"
+ "TARGET_CMOVE"
[(const_int 0)]
- "ix86_split_ashl (operands, operands[3], DImode); DONE;")
+ "ix86_split_ashl (operands, operands[3], <DWI>mode); DONE;")
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
+(define_insn "x86_64_shld"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m")
+ (ior:DI (ashift:DI (match_dup 0)
+ (match_operand:QI 2 "nonmemory_operand" "Jc"))
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
+ (minus:QI (const_int 64) (match_dup 2)))))
(clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? epilogue_completed : reload_completed)"
- [(const_int 0)]
- "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;")
+ "TARGET_64BIT"
+ "shld{q}\t{%s2%1, %0|%0, %1, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")
+ (set_attr "athlon_decode" "vector")
+ (set_attr "amdfam10_decode" "vector")])
(define_insn "x86_shld"
[(set (match_operand:SI 0 "nonimmediate_operand" "+r*m")
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "vector")])
-(define_expand "x86_shift_adj_1"
+(define_expand "x86_shift<mode>_adj_1"
[(set (reg:CCZ FLAGS_REG)
(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
- (const_int 32))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "")
- (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
- (match_operand:SI 1 "register_operand" "")
- (match_dup 0)))
- (set (match_dup 1)
- (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
- (match_operand:SI 3 "register_operand" "r")
- (match_dup 1)))]
- "TARGET_CMOVE"
- "")
-
-(define_expand "x86_shift_adj_2"
- [(use (match_operand:SI 0 "register_operand" ""))
- (use (match_operand:SI 1 "register_operand" ""))
- (use (match_operand:QI 2 "register_operand" ""))]
- ""
-{
- rtx label = gen_label_rtx ();
- rtx tmp;
-
- emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
-
- tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
- tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
- JUMP_LABEL (tmp) = label;
-
- emit_move_insn (operands[0], operands[1]);
- ix86_expand_clear (operands[1]);
-
- emit_label (label);
- LABEL_NUSES (label) = 1;
-
- DONE;
-})
-
-(define_expand "ashlsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))]
- ""
- "ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;")
-
-(define_insn "*ashlsi3_1"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l")
- (match_operand:QI 2 "nonmemory_operand" "cI,M")))
- (clobber (reg:CC FLAGS_REG))]
- "ix86_binary_operator_ok (ASHIFT, SImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- gcc_assert (rtx_equal_p (operands[0], operands[1]));
- return "add{l}\t%0, %0";
-
- case TYPE_LEA:
- return "#";
-
- default:
- if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%0";
- else
- return "sal{l}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "1")
- (const_string "lea")
- (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set_attr "mode" "SI")])
-
-;; Convert lea to the lea pattern to avoid flags dependency.
-(define_split
- [(set (match_operand 0 "register_operand" "")
- (ashift (match_operand 1 "index_register_operand" "")
- (match_operand:QI 2 "const_int_operand" "")))
- (clobber (reg:CC FLAGS_REG))]
- "reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])
- && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4"
- [(const_int 0)]
-{
- rtx pat;
- enum machine_mode mode = GET_MODE (operands[0]);
-
- if (GET_MODE_SIZE (mode) < 4)
- operands[0] = gen_lowpart (SImode, operands[0]);
- if (mode != Pmode)
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
-
- pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
- DONE;
-})
-
-;; Rare case of shifting RSP is handled by generating move and shift
-(define_split
- [(set (match_operand 0 "register_operand" "")
- (ashift (match_operand 1 "register_operand" "")
- (match_operand:QI 2 "const_int_operand" "")))
- (clobber (reg:CC FLAGS_REG))]
- "reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
- [(const_int 0)]
-{
- rtx pat, clob;
- emit_move_insn (operands[0], operands[1]);
- pat = gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ASHIFT (GET_MODE (operands[0]),
- operands[0], operands[2]));
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob)));
- DONE;
-})
-
-(define_insn "*ashlsi3_1_zext"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l")
- (match_operand:QI 2 "nonmemory_operand" "cI,M"))))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{l}\t%k0, %k0";
-
- case TYPE_LEA:
- return "#";
-
- default:
- if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %k0|%k0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%k0";
- else
- return "sal{l}\t{%2, %k0|%k0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "1")
- (const_string "lea")
- (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set_attr "mode" "SI")])
+ (match_dup 4))
+ (const_int 0)))
+ (set (match_operand:SWI48 0 "register_operand" "")
+ (if_then_else:SWI48 (ne (reg:CCZ FLAGS_REG) (const_int 0))
+ (match_operand:SWI48 1 "register_operand" "")
+ (match_dup 0)))
+ (set (match_dup 1)
+ (if_then_else:SWI48 (ne (reg:CCZ FLAGS_REG) (const_int 0))
+ (match_operand:SWI48 3 "register_operand" "r")
+ (match_dup 1)))]
+ "TARGET_CMOVE"
+ "operands[4] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));")
-;; Convert lea to the lea pattern to avoid flags dependency.
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (ashift (match_operand 1 "register_operand" "")
- (match_operand:QI 2 "const_int_operand" ""))))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
- [(set (match_dup 0) (zero_extend:DI
- (subreg:SI (mult:SI (match_dup 1)
- (match_dup 2)) 0)))]
+(define_expand "x86_shift<mode>_adj_2"
+ [(use (match_operand:SWI48 0 "register_operand" ""))
+ (use (match_operand:SWI48 1 "register_operand" ""))
+ (use (match_operand:QI 2 "register_operand" ""))]
+ ""
{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
-})
+ rtx label = gen_label_rtx ();
+ rtx tmp;
-;; This pattern can't accept a variable shift count, since shifts by
-;; zero don't affect the flags. We assume that shifts by constant
-;; zero are optimized away.
-(define_insn "*ashlsi3_cmp"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- (ashift:SI (match_dup 1) (match_dup 2)))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{l}\t%0, %0";
+ emit_insn (gen_testqi_ccz_1 (operands[2],
+ GEN_INT (GET_MODE_BITSIZE (<MODE>mode))));
- default:
- if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%0";
- else
- return "sal{l}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set_attr "mode" "SI")])
+ tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
+ tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
+ tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+ gen_rtx_LABEL_REF (VOIDmode, label),
+ pc_rtx);
+ tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ JUMP_LABEL (tmp) = label;
-(define_insn "*ashlsi3_cconly"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || TARGET_DOUBLE_WITH_ADD)))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
+ emit_move_insn (operands[0], operands[1]);
+ ix86_expand_clear (operands[1]);
+
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+
+ DONE;
+})
+
+(define_insn "*ashl<mode>3_1"
+ [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r")
+ (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,l")
+ (match_operand:QI 2 "nonmemory_operand" "c<S>,M")))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
gcc_assert (operands[2] == const1_rtx);
- return "add{l}\t%0, %0";
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
+ return "add{<imodesuffix>}\t%0, %0";
+
+ case TYPE_LEA:
+ return "#";
default:
if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %0|%0, %b2}";
+ return "sal{<imodesuffix>}\t{%b2, %0|%0, %b2}";
else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%0";
+ return "sal{<imodesuffix>}\t%0";
else
- return "sal{l}\t{%2, %0|%0, %2}";
+ return "sal{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (cond [(eq_attr "alternative" "1")
+ (const_string "lea")
+ (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
(const_int 0))
(match_operand 0 "register_operand" ""))
(match_operand 2 "const1_operand" ""))
(const_string "alu")
]
(const_string "ishift")))
- (set_attr "mode" "SI")])
+ (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" "<MODE>")])
-(define_insn "*ashlsi3_cmp_zext"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
- "TARGET_64BIT
- && (optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || TARGET_DOUBLE_WITH_ADD)))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
+(define_insn "*ashlsi3_1_zext"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (zero_extend:DI
+ (ashift:SI (match_operand:SI 1 "register_operand" "0,l")
+ (match_operand:QI 2 "nonmemory_operand" "cI,M"))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
{
switch (get_attr_type (insn))
{
gcc_assert (operands[2] == const1_rtx);
return "add{l}\t%k0, %k0";
- default:
- if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %k0|%k0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%k0";
- else
- return "sal{l}\t{%2, %k0|%k0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set_attr "mode" "SI")])
-
-(define_expand "ashlhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))]
- "TARGET_HIMODE_MATH"
- "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;")
-
-(define_insn "*ashlhi3_1_lea"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l")
- (match_operand:QI 2 "nonmemory_operand" "cI,M")))
- (clobber (reg:CC FLAGS_REG))]
- "!TARGET_PARTIAL_REG_STALL
- && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
-{
- switch (get_attr_type (insn))
- {
case TYPE_LEA:
return "#";
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{w}\t%0, %0";
default:
if (REG_P (operands[2]))
- return "sal{w}\t{%b2, %0|%0, %b2}";
+ return "sal{l}\t{%b2, %k0|%k0, %b2}";
else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{w}\t%0";
+ return "sal{l}\t%k0";
else
- return "sal{w}\t{%2, %0|%0, %2}";
+ return "sal{l}\t{%2, %k0|%k0, %2}";
}
}
[(set (attr "type")
(cond [(eq_attr "alternative" "1")
(const_string "lea")
- (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
+ (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
(match_operand 2 "const1_operand" ""))
(const_string "alu")
]
(const_string "ishift")))
- (set_attr "mode" "HI,SI")])
+ (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 "*ashlhi3_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "HI")])
-;; This pattern can't accept a variable shift count, since shifts by
-;; zero don't affect the flags. We assume that shifts by constant
-;; zero are optimized away.
-(define_insn "*ashlhi3_cmp"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
- (ashift:HI (match_dup 1) (match_dup 2)))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{w}\t%0, %0";
-
- default:
- if (REG_P (operands[2]))
- return "sal{w}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{w}\t%0";
- else
- return "sal{w}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set_attr "mode" "HI")])
-
-(define_insn "*ashlhi3_cconly"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (clobber (match_scratch:HI 0 "=r"))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || TARGET_DOUBLE_WITH_ADD)))
- && ix86_match_ccmode (insn, CCGOCmode)
+(define_insn "*ashlhi3_1_lea"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
+ (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l")
+ (match_operand:QI 2 "nonmemory_operand" "cI,M")))
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (ASHIFT, HImode, operands)"
{
switch (get_attr_type (insn))
{
+ case TYPE_LEA:
+ return "#";
case TYPE_ALU:
gcc_assert (operands[2] == const1_rtx);
return "add{w}\t%0, %0";
}
}
[(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (cond [(eq_attr "alternative" "1")
+ (const_string "lea")
+ (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
(const_int 0))
(match_operand 0 "register_operand" ""))
(match_operand 2 "const1_operand" ""))
(const_string "alu")
]
(const_string "ishift")))
- (set_attr "mode" "HI")])
-
-(define_expand "ashlqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "")
- (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))]
- "TARGET_QIMODE_MATH"
- "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;")
-
-;; %%% Potential partial reg stall on alternative 2. What to do?
+ (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 "*ashlqi3_1_lea"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r")
- (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l")
- (match_operand:QI 2 "nonmemory_operand" "cI,cI,M")))
+(define_insn "*ashlqi3_1"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
+ (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
(clobber (reg:CC FLAGS_REG))]
- "!TARGET_PARTIAL_REG_STALL
+ "TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (ASHIFT, QImode, operands)"
{
switch (get_attr_type (insn))
{
- case TYPE_LEA:
- return "#";
case TYPE_ALU:
gcc_assert (operands[2] == const1_rtx);
if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "2")
- (const_string "lea")
- (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
(const_int 0))
(match_operand 0 "register_operand" ""))
(match_operand 2 "const1_operand" ""))
(const_string "alu")
]
(const_string "ishift")))
- (set_attr "mode" "QI,SI,SI")])
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
+ (set_attr "mode" "QI,SI")])
-(define_insn "*ashlqi3_1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
- (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
+;; %%% Potential partial reg stall on alternative 2. What to do?
+(define_insn "*ashlqi3_1_lea"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r")
+ (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l")
+ (match_operand:QI 2 "nonmemory_operand" "cI,cI,M")))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_PARTIAL_REG_STALL
+ "!TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (ASHIFT, QImode, operands)"
{
switch (get_attr_type (insn))
{
+ case TYPE_LEA:
+ return "#";
case TYPE_ALU:
gcc_assert (operands[2] == const1_rtx);
if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
}
}
[(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (cond [(eq_attr "alternative" "2")
+ (const_string "lea")
+ (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
(const_int 0))
(match_operand 0 "register_operand" ""))
(match_operand 2 "const1_operand" ""))
(const_string "alu")
]
(const_string "ishift")))
- (set_attr "mode" "QI,SI")])
+ (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")])
+
+;; Convert lea to the lea pattern to avoid flags dependency.
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ashift:DI (match_operand:DI 1 "index_register_operand" "")
+ (match_operand:QI 2 "const_int_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed
+ && true_regnum (operands[0]) != true_regnum (operands[1])"
+ [(set (match_dup 0)
+ (mult:DI (match_dup 1)
+ (match_dup 2)))]
+ "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);")
+
+;; Convert lea to the lea pattern to avoid flags dependency.
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (ashift (match_operand 1 "index_register_operand" "")
+ (match_operand:QI 2 "const_int_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4"
+ [(const_int 0)]
+{
+ rtx pat;
+ enum machine_mode mode = GET_MODE (operands[0]);
+
+ if (GET_MODE_SIZE (mode) < 4)
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ if (mode != Pmode)
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
+
+ pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
+ if (Pmode != SImode)
+ pat = gen_rtx_SUBREG (SImode, pat, 0);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+ DONE;
+})
+
+;; Rare case of shifting RSP is handled by generating move and shift
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (ashift (match_operand 1 "register_operand" "")
+ (match_operand:QI 2 "const_int_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed
+ && true_regnum (operands[0]) != true_regnum (operands[1])"
+ [(const_int 0)]
+{
+ rtx pat, clob;
+ emit_move_insn (operands[0], operands[1]);
+ pat = gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_ASHIFT (GET_MODE (operands[0]),
+ operands[0], operands[2]));
+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob)));
+ DONE;
+})
+
+;; Convert lea to the lea pattern to avoid flags dependency.
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:QI 2 "const_int_operand" ""))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed
+ && true_regnum (operands[0]) != true_regnum (operands[1])"
+ [(set (match_dup 0)
+ (zero_extend:DI (subreg:SI (mult:SI (match_dup 1) (match_dup 2)) 0)))]
+{
+ operands[1] = gen_lowpart (Pmode, operands[1]);
+ operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
+})
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
-(define_insn "*ashlqi3_cmp"
+(define_insn "*ashl<mode>3_cmp"
[(set (reg FLAGS_REG)
(compare
- (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (ashift:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "<shift_immediate_operand>" "<S>"))
(const_int 0)))
- (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
- (ashift:QI (match_dup 1) (match_dup 2)))]
+ (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
+ (ashift:SWI (match_dup 1) (match_dup 2)))]
"(optimize_function_for_size_p (cfun)
|| !TARGET_PARTIAL_FLAG_REG_STALL
|| (operands[2] == const1_rtx
&& (TARGET_SHIFT1
|| (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))
&& ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
gcc_assert (operands[2] == const1_rtx);
- return "add{b}\t%0, %0";
+ return "add{<imodesuffix>}\t%0, %0";
default:
- if (REG_P (operands[2]))
- return "sal{b}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{b}\t%0";
+ if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+ return "sal{<imodesuffix>}\t%0";
else
- return "sal{b}\t{%2, %0|%0, %2}";
+ return "sal{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
(const_string "alu")
]
(const_string "ishift")))
- (set_attr "mode" "QI")])
+ (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" "<MODE>")])
-(define_insn "*ashlqi3_cconly"
+(define_insn "*ashlsi3_cmp_zext"
[(set (reg FLAGS_REG)
(compare
- (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
- (clobber (match_scratch:QI 0 "=q"))]
+ (set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
+ "TARGET_64BIT
+ && (optimize_function_for_size_p (cfun)
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))
+ && ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{l}\t%k0, %k0";
+
+ default:
+ if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+ return "sal{l}\t%k0";
+ else
+ return "sal{l}\t{%2, %k0|%k0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashl<mode>3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "<shift_immediate_operand>" "<S>"))
+ (const_int 0)))
+ (clobber (match_scratch:SWI 0 "=<r>"))]
"(optimize_function_for_size_p (cfun)
|| !TARGET_PARTIAL_FLAG_REG_STALL
|| (operands[2] == const1_rtx
&& (TARGET_SHIFT1
|| TARGET_DOUBLE_WITH_ADD)))
&& ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
gcc_assert (operands[2] == const1_rtx);
- return "add{b}\t%0, %0";
+ return "add{<imodesuffix>}\t%0, %0";
default:
- if (REG_P (operands[2]))
- return "sal{b}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{b}\t%0";
+ if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+ return "sal{<imodesuffix>}\t%0";
else
- return "sal{b}\t{%2, %0|%0, %2}";
+ return "sal{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
(const_string "alu")
]
(const_string "ishift")))
- (set_attr "mode" "QI")])
+ (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" "<MODE>")])
;; See comment above `ashldi3' about how this works.
&& 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")
&& 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)
&& 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
&& 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")
&& 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")
&& 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)
&& 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)
&& 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
&& 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")
&& 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)
&& 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
&& 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"))
&& 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")
&& 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)
&& 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
"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")
&& 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")
&& 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)
&& 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
&& 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")
&& 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")
&& 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)
&& 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)
&& 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
&& 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")
&& 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)
&& 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
&& 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"))
&& (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")
&& 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)
&& 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
&& 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")
&& 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")
&& 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")
&& 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")
&& (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")
&& 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"))
&& 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")
&& 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")
&& 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")
&& 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")
&& 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"))
&& (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")
(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")
(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")
(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.
(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)
(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")])
\f
;; 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_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_1"
+(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)]))]
[(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)]))]
"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>"
(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 "length_immediate" "1")
(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>")])
-
\f
;; Basic conditional jump instructions.
;; We ignore the overflow flag for signed branch instructions.
(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 "" ""))
"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)
"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 "" ""))
(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)
(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 "" ""))
(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
(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")])
"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 "" "")
(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 "" "")
(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" "")])
;; %%% 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" "")])
;; checked for calls. This is a bug in the generic code, but it isn't that
;; easy to fix. Ignore it for now and be prepared to fix things up.
+;; P6 processors will jump to the address after the decrement when %esp
+;; is used as a call operand, so they will execute return address as a code.
+;; See Pentium Pro errata 70, Pentium 2 errata A33 and Pentium 3 errata E17.
+
;; Call subroutine returning no value.
(define_expand "call_pop"
(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))
[(set_attr "type" "call")])
(define_insn "*call_pop_1"
- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
+ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
(match_operand:SI 1 "" ""))
- (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
- (match_operand:SI 2 "immediate_operand" "i")))]
- "!TARGET_64BIT"
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[0], Pmode))
- {
- if (SIBLING_CALL_P (insn))
- return "jmp\t%P0";
- else
- return "call\t%P0";
- }
- if (SIBLING_CALL_P (insn))
- return "jmp\t%A0";
- else
- return "call\t%A0";
+ return "call\t%P0";
+ return "call\t%A0";
}
[(set_attr "type" "call")])
+(define_insn "*sibcall_pop_1"
+ [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U"))
+ (match_operand:SI 1 "" ""))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 2 "immediate_operand" "i,i")))]
+ "!TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "@
+ jmp\t%P0
+ jmp\t%A0"
+ [(set_attr "type" "call")])
+
(define_expand "call"
[(call (match_operand:QI 0 "" "")
(match_operand 1 "" ""))
[(set_attr "type" "call")])
(define_insn "*call_1"
- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
+ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
(match_operand 1 "" ""))]
- "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
+ "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[0], Pmode))
return "call\t%P0";
[(set_attr "type" "call")])
(define_insn "*sibcall_1"
- [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,c,d,a"))
+ [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U"))
(match_operand 1 "" ""))]
- "SIBLING_CALL_P (insn) && !TARGET_64BIT"
-{
- if (constant_call_address_operand (operands[0], Pmode))
- return "jmp\t%P0";
- return "jmp\t%A0";
-}
+ "!TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "@
+ jmp\t%P0
+ jmp\t%A0"
[(set_attr "type" "call")])
(define_insn "*call_1_rex64"
[(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
(match_operand 1 "" ""))]
- "!SIBLING_CALL_P (insn) && TARGET_64BIT
+ "TARGET_64BIT && !SIBLING_CALL_P (insn)
&& ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
{
if (constant_call_address_operand (operands[0], Pmode))
(clobber (reg:TI XMM15_REG))
(clobber (reg:DI SI_REG))
(clobber (reg:DI DI_REG))]
- "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+ "TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[0], Pmode))
return "call\t%P0";
(define_insn "*call_1_rex64_large"
[(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm"))
(match_operand 1 "" ""))]
- "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+ "TARGET_64BIT && !SIBLING_CALL_P (insn)"
"call\t%A0"
[(set_attr "type" "call")])
(define_insn "*sibcall_1_rex64"
- [(call (mem:QI (match_operand:DI 0 "constant_call_address_operand" ""))
+ [(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U"))
(match_operand 1 "" ""))]
- "SIBLING_CALL_P (insn) && TARGET_64BIT"
- "jmp\t%P0"
- [(set_attr "type" "call")])
-
-(define_insn "*sibcall_1_rex64_v"
- [(call (mem:QI (reg:DI R11_REG))
- (match_operand 0 "" ""))]
- "SIBLING_CALL_P (insn) && TARGET_64BIT"
- "jmp\t{*%%}r11"
+ "TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "@
+ jmp\t%P0
+ jmp\t%A0"
[(set_attr "type" "call")])
-
;; Call subroutine, returning value in operand 0
-
(define_expand "call_value_pop"
[(parallel [(set (match_operand 0 "" "")
(call (match_operand:QI 1 "" "")
(call (match_operand:QI 1 "" "")
(match_operand:SI 2 "" "")))
(use (match_operand:SI 3 "" ""))]
- ;; Operand 2 not used on the i386.
+ ;; Operand 3 is not used on the i386.
""
{
- ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 0);
+ ix86_expand_call (operands[0], operands[1], operands[2],
+ operands[3], NULL, 0);
DONE;
})
(call (match_operand:QI 1 "" "")
(match_operand:SI 2 "" "")))
(use (match_operand:SI 3 "" ""))]
- ;; Operand 2 not used on the i386.
+ ;; Operand 3 is not used on the i386.
""
{
- ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 1);
+ ix86_expand_call (operands[0], operands[1], operands[2],
+ operands[3], NULL, 1);
DONE;
})
GEN_INT ((TARGET_64BIT
? (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);
(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 "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
"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")
"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")
"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)]
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))]
+(define_insn_and_split "eh_return_internal"
+ [(eh_return)]
""
"#"
- "reload_completed"
+ "epilogue_completed"
[(const_int 0)]
"ix86_expand_epilogue (2); DONE;")
(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))
(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")
(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")
(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
(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"
(bswap:SI (match_operand:SI 1 "register_operand" "")))]
""
{
- if (!TARGET_BSWAP)
+ if (!(TARGET_BSWAP || TARGET_MOVBE))
{
rtx x = operands[0];
}
})
+(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")))]
[(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"
(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"
(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"
(clobber (match_scratch:SI 5 "=c"))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_GNU_TLS"
- "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
+ "lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}\;call\t%P3"
[(set_attr "type" "multi")
(set_attr "length" "12")])
-(define_insn "*tls_global_dynamic_32_sun"
- [(set (match_operand:SI 0 "register_operand" "=a")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "tls_symbolic_operand" "")
- (match_operand:SI 3 "call_insn_operand" "")]
- UNSPEC_TLS_GD))
- (clobber (match_scratch:SI 4 "=d"))
- (clobber (match_scratch:SI 5 "=c"))
- (clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT && TARGET_SUN_TLS"
- "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
- push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
- [(set_attr "type" "multi")
- (set_attr "length" "14")])
-
(define_expand "tls_global_dynamic_32"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(unspec:SI
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
UNSPEC_TLS_GD)]
"TARGET_64BIT"
- ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|rdi, %a1@TLSGD[rip]}\;.word\t0x6666\;rex64\;call\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")])
(clobber (match_scratch:SI 4 "=c"))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_GNU_TLS"
- "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
+ "lea{l}\t{%&@tlsldm(%1), %0|%0, %&@tlsldm[%1]}\;call\t%P2"
[(set_attr "type" "multi")
(set_attr "length" "11")])
-(define_insn "*tls_local_dynamic_base_32_sun"
- [(set (match_operand:SI 0 "register_operand" "=a")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "call_insn_operand" "")]
- UNSPEC_TLS_LD_BASE))
- (clobber (match_scratch:SI 3 "=d"))
- (clobber (match_scratch:SI 4 "=c"))
- (clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT && TARGET_SUN_TLS"
- "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
- push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
- [(set_attr "type" "multi")
- (set_attr "length" "13")])
-
(define_expand "tls_local_dynamic_base_32"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(unspec:SI [(match_dup 1) (match_dup 2)]
(match_operand:DI 2 "" "")))
(unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
"TARGET_64BIT"
- "lea{q}\t{%&@TLSLD(%%rip), %%rdi|rdi, %&@TLSLD[rip]}\;call\t%P1"
+ "lea{q}\t{%&@tlsld(%%rip), %%rdi|rdi, %&@tlsld[rip]}\;call\t%P1"
[(set_attr "type" "multi")
(set_attr "length" "12")])
(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;
})
""
[(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]));
})
(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;
})
""
[(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]));
})
(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)
op1 = gen_reg_rtx (XFmode);
op2 = gen_reg_rtx (XFmode);
- emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
- emit_insn (gen_extend<mode>xf2 (op2, operands[2]));
- emit_insn (gen_scalbxf3 (op0, op1, op2));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_extend<mode>xf2 (op2, operands[2]));
+ emit_insn (gen_scalbxf3 (op0, op1, op2));
+ 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;
})
(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)]
(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)]
(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)]
(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)]
&& flag_unsafe_math_optimizations"
"")
-(define_expand "lfloor<mode>di2"
- [(match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:MODEF 1 "register_operand" "")]
- "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH && TARGET_64BIT
- && !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" "")
+(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
+ "SSE_FLOAT_MODE_P (<MODEF: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;
(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)]
(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)]
&& 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);
(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)]
(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)]
"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>")])
[(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))
"movsb"
[(set_attr "type" "str")
(set_attr "memory" "both")
+ (set_attr "prefix_rex" "0")
(set_attr "mode" "QI")])
(define_expand "rep_mov"
"stosb"
[(set_attr "type" "str")
(set_attr "memory" "store")
+ (set_attr "prefix_rex" "0")
(set_attr "mode" "QI")])
(define_expand "rep_stos"
[(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"
}
else
{
+ rtx (*cmp_insn)(rtx, rtx);
+
if (TARGET_64BIT)
- emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
+ cmp_insn = gen_cmpdi_1;
else
- emit_insn (gen_cmpsi_1 (countreg, countreg));
+ cmp_insn = gen_cmpsi_1;
+ emit_insn (cmp_insn (countreg, countreg));
emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
operands[1], operands[2]));
}
"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.
"repz cmpsb"
[(set_attr "type" "str")
(set_attr "mode" "QI")
+ (set_attr "prefix_rex" "0")
(set_attr "prefix_rep" "1")])
(define_expand "strlensi"
"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
\f
;; 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"
+(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;")
-(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" "")
+;; Data flow gets confused by our desire for `sbbl reg,reg', and clearing
+;; the register first winds up with `sbbl $0,reg', which is also weird.
+;; So just document what we're doing explicitly.
+
+(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))]
- "TARGET_64BIT"
- "sbb{q}\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 "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 "use_carry" "1")
- (set_attr "pent_pair" "pu")
- (set_attr "memory" "none")
- (set_attr "imm_disp" "false")
- (set_attr "mode" "DI")
+ (set_attr "mode" "<MODE>")
(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" "")))]
- ""
- "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;")
-
-;; Data flow gets confused by our desire for `sbbl reg,reg', and clearing
-;; the register first winds up with `sbbl $0,reg', which is also weird.
-;; 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" "")
- (const_int -1)
- (const_int 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{l}\t%0, %0"
- ; Since we don't have the proper number of operands for an alu insn,
- ; fill in all the blanks.
+ "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 "*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))]
+(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{l}\t%0, %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" "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]))"
- "@
- 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]))"
+(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" "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"
(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)
[(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
(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"
(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"
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"
[(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)]))
[(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)]))
[(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))
(define_insn "*call_value_pop_1"
[(set (match_operand 0 "" "")
- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
+ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
(match_operand:SI 2 "" "")))
- (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
- (match_operand:SI 3 "immediate_operand" "i")))]
- "!TARGET_64BIT"
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[1], Pmode))
- {
- if (SIBLING_CALL_P (insn))
- return "jmp\t%P1";
- else
- return "call\t%P1";
- }
- if (SIBLING_CALL_P (insn))
- return "jmp\t%A1";
- else
- return "call\t%A1";
+ return "call\t%P1";
+ return "call\t%A1";
}
[(set_attr "type" "callv")])
+(define_insn "*sibcall_value_pop_1"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U"))
+ (match_operand:SI 2 "" "")))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 3 "immediate_operand" "i,i")))]
+ "!TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "@
+ jmp\t%P1
+ jmp\t%A1"
+ [(set_attr "type" "callv")])
+
(define_insn "*call_value_0"
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
(clobber (reg:TI XMM15_REG))
(clobber (reg:DI SI_REG))
(clobber (reg:DI DI_REG))]
- "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+ "TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (SIBLING_CALL_P (insn))
return "jmp\t%P1";
(define_insn "*call_value_1"
[(set (match_operand 0 "" "")
- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
+ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
(match_operand:SI 2 "" "")))]
- "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
+ "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[1], Pmode))
return "call\t%P1";
(define_insn "*sibcall_value_1"
[(set (match_operand 0 "" "")
- (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,c,d,a"))
+ (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U"))
(match_operand:SI 2 "" "")))]
- "SIBLING_CALL_P (insn) && !TARGET_64BIT"
-{
- if (constant_call_address_operand (operands[1], Pmode))
- return "jmp\t%P1";
- return "jmp\t%A1";
-}
+ "!TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "@
+ jmp\t%P1
+ jmp\t%A1"
[(set_attr "type" "callv")])
(define_insn "*call_value_1_rex64"
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
(match_operand:DI 2 "" "")))]
- "!SIBLING_CALL_P (insn) && TARGET_64BIT
+ "TARGET_64BIT && !SIBLING_CALL_P (insn)
&& ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
{
if (constant_call_address_operand (operands[1], Pmode))
(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";
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm"))
(match_operand:DI 2 "" "")))]
- "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+ "TARGET_64BIT && !SIBLING_CALL_P (insn)"
"call\t%A1"
[(set_attr "type" "callv")])
(define_insn "*sibcall_value_1_rex64"
[(set (match_operand 0 "" "")
- (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
+ (call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U"))
(match_operand:DI 2 "" "")))]
- "SIBLING_CALL_P (insn) && TARGET_64BIT"
- "jmp\t%P1"
- [(set_attr "type" "callv")])
-
-(define_insn "*sibcall_value_1_rex64_v"
- [(set (match_operand 0 "" "")
- (call (mem:QI (reg:DI R11_REG))
- (match_operand:DI 1 "" "")))]
- "SIBLING_CALL_P (insn) && TARGET_64BIT"
- "jmp\t{*%%}r11"
+ "TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "@
+ jmp\t%P1
+ jmp\t%A1"
[(set_attr "type" "callv")])
\f
;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5.
(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 "" "")))])]
(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")))]
}
[(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"
}
[(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"
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"
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"
}
[(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"
[(match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "nonimmediate_operand" "rm")]
UNSPEC_CRC32))]
- "TARGET_SSE4_2 && TARGET_64BIT"
- "crc32q\t{%2, %0|%0, %2}"
+ "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")