Commit 9b70259d by Jan Hubicka Committed by Jan Hubicka

i386.md (cmpdi): Fix operand predicates.


	* i386.md (cmpdi): Fix operand predicates.
	(cmpdi_ccno_1_rex64, cmpdi_minus_1_rex64, cmpdi_1_rex64,
	 cmpdi_1_insn_rex64): New patterns.
	(adddi3): Turn to expander.
	(adddi3_1, adddi3_carry_rex64, adddi3_cc_rex64): New patterns.
	(addsi3_carry_zext): New pattern.
	(adddi_?_rex64): New patterns and splitters.
	(addsi_?_zext): New patterns.
	(subsi3_carry_zext): New pattern.
	(subdi_?_rex64): New patterns and splitters.
	(iorsi_?_zext): New patterns.
	(iordi_?_rex64): New patterns and splitters.
	(iorsi_?_zext): New patterns.
	(iorsi_?_zext_imm): New patterns.
	(xorsi_?_zext): New patterns.
	(xordi_?_rex64): New patterns and splitters.
	(xorsi_?_zext): New patterns.
	(negdi*): New patterns.
	(one_cmpldi*): Likewise.
	(one_cmplsi*_zext, negsi*_zext): Likewise.
	(testqi_ext_3_rex64): New pattern.

From-SVN: r40819
parent 26e5b205
Sat Mar 24 23:15:19 CET 2001 Jan Hubicka <jh@suse.cz>
* i386.md (cmpdi): Fix operand predicates.
(cmpdi_ccno_1_rex64, cmpdi_minus_1_rex64, cmpdi_1_rex64,
cmpdi_1_insn_rex64): New patterns.
(adddi3): Turn to expander.
(adddi3_1, adddi3_carry_rex64, adddi3_cc_rex64): New patterns.
(addsi3_carry_zext): New pattern.
(adddi_?_rex64): New patterns and splitters.
(addsi_?_zext): New patterns.
(subsi3_carry_zext): New pattern.
(subdi_?_rex64): New patterns and splitters.
(iorsi_?_zext): New patterns.
(iordi_?_rex64): New patterns and splitters.
(iorsi_?_zext): New patterns.
(iorsi_?_zext_imm): New patterns.
(xorsi_?_zext): New patterns.
(xordi_?_rex64): New patterns and splitters.
(xorsi_?_zext): New patterns.
(negdi*): New patterns.
(one_cmpldi*): Likewise.
(one_cmplsi*_zext, negsi*_zext): Likewise.
(testqi_ext_3_rex64): New pattern.
Sat Mar 24 21:13:28 CET 2001 Jan Hubicka <jh@suse.cz>
* i386-protos.h (ix86_split_long_move): Return void.
......
......@@ -1002,8 +1002,8 @@
(define_expand "cmpdi"
[(set (reg:CC 17)
(compare:CC (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" "")))]
(compare:CC (match_operand:DI 0 "x86_64_general_operand" "")
(match_operand:DI 1 "x86_64_general_operand" "")))]
""
"
{
......@@ -1060,6 +1060,45 @@
DONE;
}")
(define_insn "cmpdi_ccno_1_rex64"
[(set (reg 17)
(compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
(match_operand:DI 1 "const0_operand" "n,n")))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
"@
test{q}\\t{%0, %0|%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 17)
(compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r")
(match_operand:DI 1 "x86_64_general_operand" "re,mr"))
(const_int 0)))]
"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 17)
(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" "")))]
""
"")
(define_insn "cmpdi_1_insn_rex64"
[(set (reg 17)
(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 17)
(compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
......@@ -5100,12 +5139,20 @@
; (plus:DI (match_operand:DI 1 "general_operand" "")
; (zero_extend:DI (match_operand:SI 2 "general_operand" ""))))]
(define_insn "adddi3"
(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" "")))
(clobber (reg:CC 17))]
""
"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 17))]
""
"!TARGET_64BIT"
"#")
(define_split
......@@ -5125,6 +5172,29 @@
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
(define_insn "*adddi3_carry_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
(match_operand:DI 1 "nonimmediate_operand" "%0,0"))
(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (PLUS, DImode, operands)"
"adc{q}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
(set_attr "mode" "DI")
(set_attr "ppro_uops" "few")])
(define_insn "*adddi3_cc_rex64"
[(set (reg:CC 17) (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rm")] 12))
(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 "*addsi3_carry"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
......@@ -5138,6 +5208,20 @@
(set_attr "mode" "SI")
(set_attr "ppro_uops" "few")])
(define_insn "*addsi3_carry_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
(match_operand:SI 1 "nonimmediate_operand" "%0"))
(match_operand:SI 2 "general_operand" "rim"))))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
"adc{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")
(set_attr "ppro_uops" "few")])
(define_insn "*addsi3_cc"
[(set (reg:CC 17) (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "ri,rm")] 12))
......@@ -5270,29 +5354,29 @@
[(set_attr "type" "lea")
(set_attr "mode" "SI")])
(define_insn "*addsi_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
(match_operand:SI 2 "general_operand" "rmni,rni,rni")))
(define_insn "*adddi_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r")
(match_operand:DI 2 "x86_64_general_operand" "rme,re,re")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (PLUS, SImode, operands)"
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_LEA:
operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
return \"lea{l}\\t{%a2, %0|%0, %a2}\";
return \"lea{q}\\t{%a2, %0|%0, %a2}\";
case TYPE_INCDEC:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (operands[2] == const1_rtx)
return \"inc{l}\\t%0\";
return \"inc{q}\\t%0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%0\";
return \"dec{q}\\t%0\";
else
abort();
abort ();
default:
if (! rtx_equal_p (operands[0], operands[1]))
......@@ -5306,9 +5390,9 @@
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %0|%0, %2}\";
return \"sub{q}\\t{%2, %0|%0, %2}\";
}
return \"add{l}\\t{%2, %0|%0, %2}\";
return \"add{q}\\t{%2, %0|%0, %2}\";
}
}"
[(set (attr "type")
......@@ -5316,51 +5400,37 @@
(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" "")
(match_operand:DI 2 "pic_symbolic_operand" "")
(const_string "lea")
(match_operand:SI 2 "incdec_operand" "")
(match_operand:DI 2 "incdec_operand" "")
(const_string "incdec")
]
(const_string "alu")))
(set_attr "mode" "SI")])
(set_attr "mode" "DI")])
;; 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" "")))
[(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 17))]
"reload_completed
"reload_completed && TARGET_64BIT
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(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;
}")
[(set (match_dup 0)
(plus:DI (match_dup 1)
(match_dup 2)))]
"")
(define_insn "*addsi_2"
(define_insn "*adddi_2_rex64"
[(set (reg 17)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "rmni,rni"))
(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:SI 0 "nonimmediate_operand" "=r,rm")
(plus:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (PLUS, SImode, operands)
(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)"
......@@ -5372,15 +5442,17 @@
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (operands[2] == const1_rtx)
return \"inc{l}\\t%0\";
return \"inc{q}\\t%0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%0\";
return \"dec{q}\\t%0\";
else
abort();
abort ();
default:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
/* ???? We ought to handle there the 32bit case too
- do we need new constrant? */
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
......@@ -5389,22 +5461,22 @@
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %0|%0, %2}\";
return \"sub{q}\\t{%2, %0|%0, %2}\";
}
return \"add{l}\\t{%2, %0|%0, %2}\";
return \"add{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 "mode" "DI")])
(define_insn "*addsi_3"
(define_insn "*adddi_3"
[(set (reg 17)
(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
(match_operand:SI 1 "nonimmediate_operand" "%0")))
(clobber (match_scratch:SI 0 "=r"))]
(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"))]
"ix86_match_ccmode (insn, CCZmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
/* Current assemblers are broken and do not allow @GOTOFF in
......@@ -5418,15 +5490,17 @@
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (operands[2] == const1_rtx)
return \"inc{l}\\t%0\";
return \"inc{q}\\t%0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%0\";
return \"dec{q}\\t%0\";
else
abort();
abort ();
default:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
/* ???? We ought to handle there the 32bit case too
- do we need new constrant? */
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
......@@ -5435,41 +5509,40 @@
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %0|%0, %2}\";
return \"sub{q}\\t{%2, %0|%0, %2}\";
}
return \"add{l}\\t{%2, %0|%0, %2}\";
return \"add{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 "mode" "DI")])
; For comparisons agains 1, -1 and 128, we may generate better code
; 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
; This pattern also don't hold of 0x8000000000000000, since the value overflows
; when negated.
; Also carry flag is reversed compared to cmp, so this converison is valid
; only for comparisons not depending on it.
(define_insn "*addsi_4"
(define_insn "*adddi_4"
[(set (reg 17)
(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"))]
"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 if (operands[2] == const1_rtx)
return \"dec{l}\\t%0\";
return \"dec{q}\\t%0\";
else
abort();
......@@ -5481,24 +5554,24 @@
if ((INTVAL (operands[2]) == -128
|| (INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) != 128)))
return \"sub{l}\\t{%2, %0|%0, %2}\";
return \"sub{q}\\t{%2, %0|%0, %2}\";
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"add{l}\\t{%2, %0|%0, %2}\";
return \"add{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 "mode" "DI")])
(define_insn "*addsi_5"
(define_insn "*adddi_5"
[(set (reg 17)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rmni"))
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "x86_64_general_operand" "rme"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
(clobber (match_scratch:DI 0 "=r"))]
"ix86_match_ccmode (insn, CCGOCmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
/* Current assemblers are broken and do not allow @GOTOFF in
......@@ -5512,9 +5585,9 @@
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (operands[2] == const1_rtx)
return \"inc{l}\\t%0\";
return \"inc{q}\\t%0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%0\";
return \"dec{q}\\t%0\";
else
abort();
......@@ -5529,91 +5602,524 @@
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %0|%0, %2}\";
return \"sub{q}\\t{%2, %0|%0, %2}\";
}
return \"add{l}\\t{%2, %0|%0, %2}\";
return \"add{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")])
(define_expand "addhi3"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "general_operand" "")))
(clobber (reg:CC 17))])]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
(set_attr "mode" "DI")])
;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah
;; type optimizations enabled by define-splits. This is not important
;; for PII, and in fact harmful because of partial register stalls.
(define_insn "*addhi_1_lea"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
(match_operand:HI 2 "general_operand" "ri,rm,rni")))
(define_insn "*addsi_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
(match_operand:SI 2 "general_operand" "rmni,rni,rni")))
(clobber (reg:CC 17))]
"!TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (PLUS, HImode, operands)"
"ix86_binary_operator_ok (PLUS, SImode, operands)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_LEA:
return \"#\";
operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
return \"lea{l}\\t{%a2, %0|%0, %a2}\";
case TYPE_INCDEC:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (operands[2] == const1_rtx)
return \"inc{w}\\t%0\";
else if (operands[2] == constm1_rtx
|| (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 65535))
return \"dec{w}\\t%0\";
abort();
return \"inc{l}\\t%0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%0\";
else
abort();
default:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
&& (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}\";
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %0|%0, %2}\";
}
return \"add{l}\\t{%2, %0|%0, %2}\";
}
}"
[(set (attr "type")
(if_then_else (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")])
(cond [(eq_attr "alternative" "2")
(const_string "lea")
; Current assemblers are broken and do not allow @GOTOFF in
; ought but a memory context.
(match_operand:SI 2 "pic_symbolic_operand" "")
(const_string "lea")
(match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
]
(const_string "alu")))
(set_attr "mode" "SI")])
(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" "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 17))]
"TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (PLUS, HImode, operands)"
"reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(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" "rmni,rni"))))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_LEA:
operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
return \"lea{l}\\t{%a2, %k0|%k0, %a2}\";
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return \"inc{w}\\t%0\";
else if (operands[2] == constm1_rtx
|| (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 65535))
return \"dec{w}\\t%0\";
return \"inc{l}\\t%k0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%k0\";
else
abort();
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 (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %k0|%k0, %2}\";
}
return \"add{l}\\t{%2, %k0|%k0, %2}\";
}
}"
[(set (attr "type")
(cond [(eq_attr "alternative" "1")
(const_string "lea")
; Current assemblers are broken and do not allow @GOTOFF in
; ought but a memory context.
(match_operand:SI 2 "pic_symbolic_operand" "")
(const_string "lea")
(match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
]
(const_string "alu")))
(set_attr "mode" "SI")])
;; Convert lea to the lea pattern to avoid flags dependency.
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" ""))))
(clobber (reg:CC 17))]
"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]);
}")
(define_insn "*addsi_2"
[(set (reg 17)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "rmni,rni"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
(plus:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (PLUS, SImode, operands)
/* Current assemblers are broken and do not allow @GOTOFF in
ought but a memory context. */
&& ! pic_symbolic_operand (operands[2], VOIDmode)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (operands[2] == const1_rtx)
return \"inc{l}\\t%0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%0\";
else
abort();
default:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %0|%0, %2}\";
}
return \"add{l}\\t{%2, %0|%0, %2}\";
}
}"
[(set (attr "type")
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
(set_attr "mode" "SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
(define_insn "*addsi_2_zext"
[(set (reg 17)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rmni"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (PLUS, SImode, operands)
/* Current assemblers are broken and do not allow @GOTOFF in
ought but a memory context. */
&& ! pic_symbolic_operand (operands[2], VOIDmode)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return \"inc{l}\\t%k0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%k0\";
else
abort();
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 (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %k0|%k0, %2}\";
}
return \"add{l}\\t{%2, %k0|%k0, %2}\";
}
}"
[(set (attr "type")
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
(set_attr "mode" "SI")])
(define_insn "*addsi_3"
[(set (reg 17)
(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
(match_operand:SI 1 "nonimmediate_operand" "%0")))
(clobber (match_scratch:SI 0 "=r"))]
"ix86_match_ccmode (insn, CCZmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
/* Current assemblers are broken and do not allow @GOTOFF in
ought but a memory context. */
&& ! pic_symbolic_operand (operands[2], VOIDmode)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (operands[2] == const1_rtx)
return \"inc{l}\\t%0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%0\";
else
abort();
default:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %0|%0, %2}\";
}
return \"add{l}\\t{%2, %0|%0, %2}\";
}
}"
[(set (attr "type")
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
(set_attr "mode" "SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
(define_insn "*addsi_3_zext"
[(set (reg 17)
(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
(match_operand:SI 1 "nonimmediate_operand" "%0")))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCZmode)
&& ix86_binary_operator_ok (PLUS, SImode, operands)
/* Current assemblers are broken and do not allow @GOTOFF in
ought but a memory context. */
&& ! pic_symbolic_operand (operands[2], VOIDmode)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return \"inc{l}\\t%k0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%k0\";
else
abort();
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 (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %k0|%k0, %2}\";
}
return \"add{l}\\t{%2, %k0|%k0, %2}\";
}
}"
[(set (attr "type")
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
(set_attr "mode" "SI")])
; For comparisons agains 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 converison is valid
; only for comparisons not depending on it.
(define_insn "*addsi_4"
[(set (reg 17)
(compare (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))
(clobber (match_scratch:SI 0 "=rm"))]
"ix86_match_ccmode (insn, CCGCmode)
&& (INTVAL (operands[2]) & 0xffffffff) != 0x80000000"
"*
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
if (operands[2] == constm1_rtx)
return \"inc{l}\\t%0\";
else if (operands[2] == const1_rtx)
return \"dec{l}\\t%0\";
else
abort();
default:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if ((INTVAL (operands[2]) == -128
|| (INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) != 128)))
return \"sub{l}\\t{%2, %0|%0, %2}\";
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"add{l}\\t{%2, %0|%0, %2}\";
}
}"
[(set (attr "type")
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
(set_attr "mode" "SI")])
(define_insn "*addsi_5"
[(set (reg 17)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rmni"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"ix86_match_ccmode (insn, CCGOCmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
/* Current assemblers are broken and do not allow @GOTOFF in
ought but a memory context. */
&& ! pic_symbolic_operand (operands[2], VOIDmode)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (operands[2] == const1_rtx)
return \"inc{l}\\t%0\";
else if (operands[2] == constm1_rtx)
return \"dec{l}\\t%0\";
else
abort();
default:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{l}\\t{%2, %0|%0, %2}\";
}
return \"add{l}\\t{%2, %0|%0, %2}\";
}
}"
[(set (attr "type")
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
(set_attr "mode" "SI")])
(define_expand "addhi3"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "general_operand" "")))
(clobber (reg:CC 17))])]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah
;; type optimizations enabled by define-splits. This is not important
;; for PII, and in fact harmful because of partial register stalls.
(define_insn "*addhi_1_lea"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
(match_operand:HI 2 "general_operand" "ri,rm,rni")))
(clobber (reg:CC 17))]
"!TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (PLUS, HImode, operands)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_LEA:
return \"#\";
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return \"inc{w}\\t%0\";
else if (operands[2] == constm1_rtx
|| (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 65535))
return \"dec{w}\\t%0\";
abort();
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 (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"sub{w}\\t{%2, %0|%0, %2}\";
}
return \"add{w}\\t{%2, %0|%0, %2}\";
}
}"
[(set (attr "type")
(if_then_else (eq_attr "alternative" "2")
(const_string "lea")
(if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu"))))
(set_attr "mode" "HI,HI,SI")])
(define_insn "*addhi_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "ri,rm")))
(clobber (reg:CC 17))]
"TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (PLUS, HImode, operands)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return \"inc{w}\\t%0\";
else if (operands[2] == constm1_rtx
|| (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 65535))
return \"dec{w}\\t%0\";
abort();
default:
......@@ -6188,15 +6694,22 @@
;; Subtract instructions
;; %%% define_expand from the very first?
;; %%% splits for subsidi3
(define_insn "subdi3"
(define_expand "subdi3"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "x86_64_general_operand" "")))
(clobber (reg:CC 17))])]
""
"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 17))]
""
"!TARGET_64BIT"
"#")
(define_split
......@@ -6216,6 +6729,56 @@
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
(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 (ltu:DI (reg:CC 17) (const_int 0))
(match_operand:DI 2 "x86_64_general_operand" "re,rm"))))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (MINUS, DImode, operands)"
"sbb{q}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
(set_attr "ppro_uops" "few")
(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 17))]
"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 "*subdi_2_rex64"
[(set (reg 17)
(compare
(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rm"))
(const_int 0)))
(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(minus:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (MINUS, DImode, operands)"
"sub{q}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
(define_insn "*subdi_3_rex63"
[(set (reg 17)
(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 "subsi3_carry"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
......@@ -6229,6 +6792,20 @@
(set_attr "ppro_uops" "few")
(set_attr "mode" "SI")])
(define_insn "subsi3_carry_zext"
[(set (match_operand:DI 0 "register_operand" "=rm,r")
(zero_extend:DI
(minus:SI (match_operand:SI 1 "register_operand" "0,0")
(plus:SI (ltu:SI (reg:CC 17) (const_int 0))
(match_operand:SI 2 "general_operand" "ri,rm")))))
(clobber (reg:CC 17))]
"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 "ppro_uops" "few")
(set_attr "mode" "SI")])
(define_expand "subsi3"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
......@@ -6247,6 +6824,17 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*subsi_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "rim"))))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*subsi_2"
[(set (reg 17)
(compare
......@@ -6261,6 +6849,22 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*subsi_2_zext"
[(set (reg 17)
(compare
(minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "rim"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_dup 1)
(match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*subsi_3"
[(set (reg 17)
(compare (match_operand:SI 1 "nonimmediate_operand" "0,0")
......@@ -6273,6 +6877,20 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*subsi_3_zext"
[(set (reg 17)
(compare (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "general_operand" "rim")))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_dup 1)
(match_dup 2))))]
"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_expand "subhi3"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
......@@ -6393,6 +7011,29 @@
;; Multiply instructions
(define_expand "muldi3"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
(mult:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "x86_64_general_operand" "")))
(clobber (reg:CC 17))])]
"TARGET_64BIT"
"")
(define_insn "*muldi3_1_rex64"
[(set (match_operand:DI 0 "register_operand" "=r,r,r")
(mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,0,0")
(match_operand:DI 2 "x86_64_general_operand" "K,e,mr")))
(clobber (reg:CC 17))]
"(GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
&& TARGET_64BIT"
"@
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 "mode" "DI")])
(define_expand "mulsi3"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(mult:SI (match_operand:SI 1 "register_operand" "")
......@@ -6427,6 +7068,34 @@
(set_attr "prefix_0f" "0,0,1")
(set_attr "mode" "SI")])
(define_insn "*mulsi3_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r,r,r")
(zero_extend:DI
(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,0,0")
(match_operand:SI 2 "general_operand" "K,i,mr"))))
(clobber (reg:CC 17))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
; For the {r,0,i} alternative (i.e., register <- register * immediate),
; there are two ways of writing the exact same machine instruction
; in assembly language. One, for example, is:
;
; imul $12, %eax
;
; while the other is:
;
; imul $12, %eax, %eax
;
; The first is simply short-hand for the latter. But, some assemblers,
; like the SCO OSR5 COFF assembler, don't handle the first form.
"@
imul{l}\\t{%2, %1, %k0|%k0, %1, %2}
imul{l}\\t{%2, %1, %k0|%k0, %1, %2}
imul{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "imul")
(set_attr "prefix_0f" "0,0,1")
(set_attr "mode" "SI")])
(define_expand "mulhi3"
[(parallel [(set (match_operand:HI 0 "register_operand" "")
(mult:HI (match_operand:HI 1 "register_operand" "")
......@@ -6484,18 +7153,17 @@
(set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
(define_insn "umulsi3"
[(set (match_operand:SI 0 "register_operand" "=a")
(mult:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonimmediate_operand" "rm")))
(clobber (match_operand:SI 3 "register_operand" "=d"))
(define_insn "umulditi3"
[(set (match_operand:TI 0 "register_operand" "=A")
(mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "%0"))
(zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
(clobber (reg:CC 17))]
""
"mul{l}\\t%2"
"TARGET_64BIT"
"mul{q}\\t%2"
[(set_attr "type" "imul")
(set_attr "ppro_uops" "few")
(set_attr "length_immediate" "0")
(set_attr "mode" "SI")])
(set_attr "mode" "DI")])
;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers
(define_insn "umulsidi3"
......@@ -6510,6 +7178,17 @@
(set_attr "length_immediate" "0")
(set_attr "mode" "SI")])
(define_insn "mulditi3"
[(set (match_operand:TI 0 "register_operand" "=A")
(mult:TI (sign_extend:TI (match_operand:DI 1 "register_operand" "%0"))
(sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"imul{q}\\t%2"
[(set_attr "type" "imul")
(set_attr "length_immediate" "0")
(set_attr "mode" "DI")])
(define_insn "mulsidi3"
[(set (match_operand:DI 0 "register_operand" "=A")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
......@@ -6521,6 +7200,24 @@
(set_attr "length_immediate" "0")
(set_attr "mode" "SI")])
(define_insn "*umuldi3_highpart_rex64"
[(set (match_operand:DI 0 "register_operand" "=d")
(truncate:DI
(lshiftrt:TI
(mult:TI (zero_extend:TI
(match_operand:DI 1 "register_operand" "%a"))
(zero_extend:TI
(match_operand:DI 2 "nonimmediate_operand" "rm")))
(const_int 64))))
(clobber (match_scratch:DI 3 "=a"))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"mul{q}\\t%2"
[(set_attr "type" "imul")
(set_attr "ppro_uops" "few")
(set_attr "length_immediate" "0")
(set_attr "mode" "DI")])
(define_insn "umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
(truncate:SI
......@@ -6539,6 +7236,23 @@
(set_attr "length_immediate" "0")
(set_attr "mode" "SI")])
(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 "register_operand" "%a"))
(sign_extend:TI
(match_operand:DI 2 "nonimmediate_operand" "rm")))
(const_int 64))))
(clobber (match_scratch:DI 3 "=a"))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"imul{q}\\t%2"
[(set_attr "type" "imul")
(set_attr "ppro_uops" "few")
(set_attr "mode" "DI")])
(define_insn "smulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
(truncate:SI
......@@ -6556,6 +7270,23 @@
(set_attr "ppro_uops" "few")
(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 "register_operand" "%a"))
(sign_extend:DI
(match_operand:SI 2 "nonimmediate_operand" "rm")))
(const_int 32)))))
(clobber (match_scratch:SI 3 "=a"))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"imul{l}\\t%2"
[(set_attr "type" "imul")
(set_attr "ppro_uops" "few")
(set_attr "mode" "SI")])
;; The patterns that match these are at the end of this file.
(define_expand "mulxf3"
......@@ -6641,6 +7372,93 @@
"")
;; 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 17))])]
"TARGET_64BIT"
"")
;; Allow to come the parameter in eax or edx to avoid extra moves.
;; Penalize eax case sligthly 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 17))]
"TARGET_64BIT && !optimize_size && !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 17))]
"TARGET_64BIT && (optimize_size || 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 17))]
"TARGET_64BIT"
"idiv{q}\\t%2"
[(set_attr "type" "idiv")
(set_attr "mode" "DI")
(set_attr "ppro_uops" "few")])
(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 17))]
"TARGET_64BIT && reload_completed"
[(parallel [(set (match_dup 3)
(ashiftrt:DI (match_dup 4) (const_int 63)))
(clobber (reg:CC 17))])
(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 17))])]
"
{
/* Avoid use of cltd in favour of a mov+shift. */
if (!TARGET_USE_CLTD && !optimize_size)
{
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
{
if (true_regnum (operands[1]))
abort();
operands[4] = operands[1];
}
}")
(define_expand "divmodsi4"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(div:SI (match_operand:SI 1 "register_operand" "")
......@@ -6737,7 +7555,51 @@
"cwtd\;idiv{w}\\t%2"
[(set_attr "type" "multi")
(set_attr "length_immediate" "0")
(set_attr "mode" "SI")])
(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 17))]
"TARGET_64BIT"
"xor{q}\\t%3, %3\;div{q}\\t%2"
[(set_attr "type" "multi")
(set_attr "length_immediate" "0")
(set_attr "mode" "DI")])
(define_insn "*udivmoddi4_noext"
[(set (match_operand:DI 0 "register_operand" "=a")
(udiv:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "nonimmediate_operand" "rm")))
(set (match_operand:DI 3 "register_operand" "=d")
(umod:DI (match_dup 1) (match_dup 2)))
(use (match_dup 3))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"div{q}\\t%2"
[(set_attr "type" "idiv")
(set_attr "ppro_uops" "few")
(set_attr "mode" "DI")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(udiv:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "nonimmediate_operand" "")))
(set (match_operand:DI 3 "register_operand" "")
(umod:DI (match_dup 1) (match_dup 2)))
(clobber (reg:CC 17))]
"reload_completed && TARGET_64BIT"
[(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))
(clobber (reg:CC 17))])]
"")
(define_insn "udivmodsi4"
[(set (match_operand:SI 0 "register_operand" "=a")
......@@ -6834,6 +7696,23 @@
;; 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 17)
(compare
(and:DI (match_operand:DI 0 "nonimmediate_operand" "%*a,r,*a,r,rm")
(match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,Z,e,e,re"))
(const_int 0)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
"@
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 17)
......@@ -6990,16 +7869,32 @@
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)
&& (GET_MODE (operands[0]) == SImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
|| GET_MODE (operands[0]) == HImode
|| GET_MODE (operands[0]) == QImode)"
"#")
(define_insn "*testqi_ext_3_rex64"
[(set (reg 17)
(compare (zero_extract:DI
(match_operand 0 "nonimmediate_operand" "rm")
(match_operand:DI 1 "const_int_operand" "")
(match_operand:DI 2 "const_int_operand" ""))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)
&& TARGET_64BIT
&& (GET_MODE (operands[0]) == SImode
|| GET_MODE (operands[0]) == DImode
|| GET_MODE (operands[0]) == HImode
|| GET_MODE (operands[0]) == QImode)"
"#")
(define_split
[(set (reg 17)
(compare (zero_extract:SI
(compare (zero_extract
(match_operand 0 "nonimmediate_operand" "rm")
(match_operand:SI 1 "const_int_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand 1 "const_int_operand" "")
(match_operand 2 "const_int_operand" ""))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)"
[(set (reg:CCNO 17) (compare:CCNO (match_dup 3) (const_int 0)))]
......@@ -7038,6 +7933,73 @@
;; 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" "")))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"ix86_expand_binary_operator (AND, DImode, operands); DONE;")
(define_insn "*anddi_1_rex64"
[(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")))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
"*
{
switch (get_attr_type (insn))
{
case TYPE_IMOVX:
{
enum machine_mode mode;
if (GET_CODE (operands[2]) != CONST_INT)
abort ();
if (INTVAL (operands[2]) == 0xff)
mode = QImode;
else if (INTVAL (operands[2]) == 0xffff)
mode = HImode;
else
abort ();
operands[1] = gen_lowpart (mode, operands[1]);
if (mode == QImode)
return \"movz{bq|x}\\t{%1,%0|%0, %1}\";
else
return \"movz{wq|x}\\t{%1,%0|%0, %1}\";
}
default:
if (! rtx_equal_p (operands[0], operands[1]))
abort ();
if (get_attr_mode (insn) == MODE_SI)
return \"and{l}\\t{%k2, %k0|%k0, %k2}\";
else
return \"and{q}\\t{%2, %0|%0, %2}\";
}
}"
[(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 17)
(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" "")
......@@ -7087,31 +8049,35 @@
(set_attr "mode" "SI")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(and:SI (match_dup 0)
(const_int -65536)))
[(set (match_operand 0 "register_operand" "")
(and (match_dup 0)
(const_int -65536)))
(clobber (reg:CC 17))]
"optimize_size"
"optimize_size
&& (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode))"
[(set (strict_low_part (match_dup 1)) (const_int 0))]
"operands[1] = gen_lowpart (HImode, operands[0]);")
(define_split
[(set (match_operand 0 "q_regs_operand" "")
(and (match_dup 0)
(const_int -256)))
(const_int -256)))
(clobber (reg:CC 17))]
"(optimize_size || !TARGET_PARTIAL_REG_STALL)
&& (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode)"
&& (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode))"
[(set (strict_low_part (match_dup 1)) (const_int 0))]
"operands[1] = gen_lowpart (QImode, operands[0]);")
(define_split
[(set (match_operand 0 "q_regs_operand" "")
[(set (match_operand 0 "register_operand" "")
(and (match_dup 0)
(const_int -65281)))
(clobber (reg:CC 17))]
"(optimize_size || !TARGET_PARTIAL_REG_STALL)
&& (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode)"
&& (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode))"
[(parallel [(set (zero_extract:SI (match_dup 0)
(const_int 8)
(const_int 8))
......@@ -7125,6 +8091,18 @@
(clobber (reg:CC 17))])]
"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" "rim"))))
(clobber (reg:CC 17))]
"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 17)
(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
......@@ -7138,6 +8116,20 @@
[(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 17)
(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))
(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" "")
......@@ -7367,6 +8359,53 @@
;; %%% 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" "")))
(clobber (reg:CC 17))]
"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 17))]
"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 17)
(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 17)
(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" "")
......@@ -7385,6 +8424,28 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
(define_insn "*iorsi_1_zext"
[(set (match_operand:DI 0 "register_operand" "=rm")
(zero_extend:DI
(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
"or{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*iorsi_1_zext_imm"
[(set (match_operand:DI 0 "register_operand" "=rm")
(ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"or{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*iorsi_2"
[(set (reg 17)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
......@@ -7398,6 +8459,34 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
;; ??? Special case for immediate operand is missing - it is tricky.
(define_insn "*iorsi_2_zext"
[(set (reg 17)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))
(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")])
(define_insn "*iorsi_2_zext_imm"
[(set (reg 17)
(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}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*iorsi_3"
[(set (reg 17)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
......@@ -7528,6 +8617,56 @@
;; %%% 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" "")))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"ix86_expand_binary_operator (XOR, DImode, operands); DONE;")
(define_insn "*xordi_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
(clobber (reg:CC 17))]
"TARGET_64BIT
&& ix86_binary_operator_ok (XOR, DImode, operands)"
"@
xor{q}\\t{%2, %0|%0, %2}
xor{q}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "DI,DI")])
(define_insn "*xordi_2_rex64"
[(set (reg 17)
(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}
xor{q}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "DI,DI")])
(define_insn "*xordi_3_rex64"
[(set (reg 17)
(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "x86_64_general_operand" "rem"))
(const_int 0)))
(clobber (match_scratch:DI 0 "=r"))]
"TARGET_64BIT
&& ix86_match_ccmode (insn, CCNOmode)
&& ix86_binary_operator_ok (XOR, DImode, operands)"
"xor{q}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
(define_expand "xorsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(xor:SI (match_operand:SI 1 "nonimmediate_operand" "")
......@@ -7546,6 +8685,29 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
;; Add speccase for immediates
(define_insn "*xorsi_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
"xor{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*xorsi_1_zext_imm"
[(set (match_operand:DI 0 "register_operand" "=r")
(xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
"xor{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*xorsi_2"
[(set (reg 17)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
......@@ -7559,6 +8721,34 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
;; ??? Special case for immediate operand is missing - it is tricky.
(define_insn "*xorsi_2_zext"
[(set (reg 17)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (xor:SI (match_dup 1) (match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
&& ix86_binary_operator_ok (XOR, SImode, operands)"
"xor{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*xorsi_2_zext_imm"
[(set (reg 17)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand 2 "x86_64_zext_immediate_operand" "Z"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(xor:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
&& ix86_binary_operator_ok (XOR, SImode, operands)"
"xor{l}\\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*xorsi_3"
[(set (reg 17)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
......@@ -7785,6 +8975,31 @@
"split_di (operands+1, 1, operands+2, operands+3);
split_di (operands+0, 1, operands+0, operands+1);")
(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 17))]
"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 17)
(compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(neg:DI (match_dup 1)))]
"TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
"neg{q}\\t%0"
[(set_attr "type" "negnot")
(set_attr "mode" "DI")])
(define_expand "negsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))
......@@ -7801,6 +9016,18 @@
[(set_attr "type" "negnot")
(set_attr "mode" "SI")])
;; Combine is quite creative about this pattern.
(define_insn "*negsi2_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0")
(const_int 32)))
(const_int 32)))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
"neg{l}\\t%k0"
[(set_attr "type" "negnot")
(set_attr "mode" "SI")])
;; The problem with neg is that it does not perform (compare x 0),
;; it really performs (compare 0 x), which leaves us with the zero
;; flag being the only useful item.
......@@ -7816,6 +9043,23 @@
[(set_attr "type" "negnot")
(set_attr "mode" "SI")])
(define_insn "*negsi2_cmpz_zext"
[(set (reg:CCZ 17)
(compare:CCZ (lshiftrt:DI
(neg:DI (ashift:DI
(match_operand:DI 1 "register_operand" "0")
(const_int 32)))
(const_int 32))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (neg:DI (ashift:DI (match_dup 1)
(const_int 32)))
(const_int 32)))]
"TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
"neg{l}\\t%k0"
[(set_attr "type" "negnot")
(set_attr "mode" "SI")])
(define_expand "neghi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))
......@@ -8495,6 +9739,46 @@
;; 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 17)
(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 (reg 17)
(compare (not:DI (match_operand:DI 1 "nonimmediate_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "nonimmediate_operand" "")
(not:DI (match_dup 1)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
[(parallel [(set (reg:CCNO 17)
(compare:CCNO (xor:DI (match_dup 1) (const_int -1))
(const_int 0)))
(set (match_dup 0)
(xor:DI (match_dup 1) (const_int -1)))])]
"")
(define_expand "one_cmplsi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
......@@ -8509,6 +9793,15 @@
[(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 17)
(compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
......@@ -8535,6 +9828,33 @@
(xor:SI (match_dup 1) (const_int -1)))])]
"")
;; ??? Currently never generated - xor is used instead.
(define_insn "*one_cmplsi2_2_zext"
[(set (reg 17)
(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 (reg 17)
(compare (not:SI (match_operand:SI 1 "register_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (not:SI (match_dup 1))))]
"ix86_match_ccmode (insn, CCNOmode)"
[(parallel [(set (reg:CCNO 17)
(compare:CCNO (xor:SI (match_dup 1) (const_int -1))
(const_int 0)))
(set (match_dup 0)
(zero_extend:DI (xor:SI (match_dup 1) (const_int -1))))])]
"")
(define_expand "one_cmplhi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment