;; 9 This is an `fnstsw' operation.
;; 10 This is a `sahf' operation.
;; 11 This is a `fstcw' operation
+;; 12 This is behaviour of add when setting carry flag.
;; For SSE/MMX support:
;; 30 This is `fix', guaranteed to be truncating.
(match_operand:DI 2 "general_operand" "")))
(clobber (reg:CC 17))]
"reload_completed"
- [(parallel [(set (reg:CCRC 17)
- (compare:CCRC (match_dup 1) (neg:SI (match_dup 2))))
+ [(parallel [(set (reg:CC 17) (unspec:CC [(match_dup 1) (match_dup 2)] 12))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
(parallel [(set (match_dup 3)
- (plus:SI (plus:SI (gtu:SI (reg:CCRC 17) (const_int 0))
+ (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
(match_dup 4))
(match_dup 5)))
(clobber (reg:CC 17))])]
(set_attr "mode" "SI")
(set_attr "ppro_uops" "few")])
-(define_insn "*addsi3_carry_rc"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
- (plus:SI (plus:SI (gtu:SI (reg:CCRC 17) (const_int 0))
- (match_operand:SI 1 "nonimmediate_operand" "%0,0"))
- (match_operand:SI 2 "general_operand" "ri,rm")))
- (clobber (reg:CC 17))]
+(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))
+ (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
+ (plus:SI (match_dup 1) (match_dup 2)))]
"ix86_binary_operator_ok (PLUS, SImode, operands)"
- "adc{l}\\t{%2, %0|%0, %2}"
+ "add{l}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
- (set_attr "pent_pair" "pu")
- (set_attr "mode" "SI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "SI")])
+
+(define_insn "addqi3_cc"
+ [(set (reg:CC 17) (unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "qi,qm")] 12))
+ (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
+ (plus:QI (match_dup 1) (match_dup 2)))]
+ "ix86_binary_operator_ok (PLUS, QImode, operands)"
+ "add{b}\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "QI")])
(define_expand "addsi3"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(define_insn "*addsi_3"
[(set (reg 17)
- (compare (match_operand:SI 1 "nonimmediate_operand" "%0")
- (neg:SI (match_operand:SI 2 "general_operand" "rmni"))))
+ (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, CCGCmode)
+ "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. */
(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,0")
- (neg:SI (match_operand:SI 2 "general_operand" "rmni,rni"))))
- (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "ix86_binary_operator_ok (PLUS, SImode, operands)
- && ix86_match_ccmode (insn, CCRCmode)
- /* Current assemblers are broken and do not allow @GOTOFF in
- ought but a memory context. */
- && ! pic_symbolic_operand (operands[2], VOIDmode)"
- "add{l}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "SI")])
+ (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();
-(define_insn "*addsi_5"
- [(set (reg 17)
- (compare (match_operand:SI 1 "nonimmediate_operand" "%0")
- (neg:SI (match_operand:SI 2 "general_operand" "rmni"))))
- (clobber (match_scratch:SI 0 "=r"))]
- "(GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
- && ix86_match_ccmode (insn, CCRCmode)
- /* Current assemblers are broken and do not allow @GOTOFF in
- ought but a memory context. */
- && ! pic_symbolic_operand (operands[2], VOIDmode)"
- "add{l}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
+ 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_6"
+(define_insn "*addsi_5"
[(set (reg 17)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(define_insn "*addhi_3"
[(set (reg 17)
- (compare (match_operand:HI 1 "nonimmediate_operand" "%0")
- (neg:HI (match_operand:HI 2 "general_operand" "rmni"))))
+ (compare (neg:HI (match_operand:HI 2 "general_operand" "rmni"))
+ (match_operand:HI 1 "nonimmediate_operand" "%0")))
(clobber (match_scratch:HI 0 "=r"))]
- "ix86_match_ccmode (insn, CCGCmode)
+ "ix86_match_ccmode (insn, CCZmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"*
{
(const_string "alu")))
(set_attr "mode" "HI")])
+; See comments above addsi_3_imm for details.
(define_insn "*addhi_4"
[(set (reg 17)
- (compare (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (neg:HI (match_operand:HI 2 "general_operand" "rmni,rni"))))
- (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
- (plus:HI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCRCmode)
- && ix86_binary_operator_ok (PLUS, HImode, operands)"
- "add{w}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "HI")])
+ (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
+ || (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 65535))
+ return \"inc{w}\\t%0\";
+ else if (operands[2] == const1_rtx)
+ return \"dec{w}\\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{w}\\t{%2, %0|%0, %2}\";
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
+ return \"add{w}\\t{%2, %0|%0, %2}\";
+ }
+}"
+ [(set (attr "type")
+ (if_then_else (match_operand:HI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
+ (set_attr "mode" "SI")])
-(define_insn "*addhi_5"
- [(set (reg 17)
- (compare (match_operand:HI 1 "nonimmediate_operand" "%0")
- (neg:HI (match_operand:HI 2 "general_operand" "rmni"))))
- (clobber (match_scratch:HI 0 "=r"))]
- "ix86_match_ccmode (insn, CCRCmode)
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "add{w}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "HI")])
-(define_insn "*addhi_6"
+(define_insn "*addhi_5"
[(set (reg 17)
(compare
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
(define_insn "*addqi_3"
[(set (reg 17)
- (compare (match_operand:QI 1 "nonimmediate_operand" "%0")
- (neg:QI (match_operand:QI 2 "general_operand" "qmni"))))
- (clobber (match_scratch:QI 0 "=r"))]
- "ix86_match_ccmode (insn, CCGCmode)
+ (compare (neg:QI (match_operand:QI 2 "general_operand" "qmni"))
+ (match_operand:QI 1 "nonimmediate_operand" "%0")))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCZmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"*
{
(const_string "alu")))
(set_attr "mode" "QI")])
+; See comments above addsi_3_imm for details.
(define_insn "*addqi_4"
[(set (reg 17)
- (compare (match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (neg:QI (match_operand:QI 2 "general_operand" "qmni,qni"))))
- (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
- (plus:QI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCRCmode)
- && ix86_binary_operator_ok (PLUS, QImode, operands)"
- "add{b}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
+ (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
+ || (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 255))
+ return \"inc{b}\\t%0\";
+ else if (operands[2] == const1_rtx)
+ return \"dec{b}\\t%0\";
+ else
+ abort();
+
+ default:
+ if (! rtx_equal_p (operands[0], operands[1]))
+ abort ();
+ 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_expand "addqi3_ccrc"
- [(parallel [
- (set (reg:CCRC 17)
- (compare:CCRC (match_operand:QI 1 "nonimmediate_operand" "")
- (neg:QI (match_operand:QI 2 "general_operand" ""))))
- (clobber (match_scratch:QI 0 ""))])]
- ""
- "")
(define_insn "*addqi_5"
[(set (reg 17)
- (compare (match_operand:QI 1 "nonimmediate_operand" "%0")
- (neg:QI (match_operand:QI 2 "general_operand" "qmni"))))
- (clobber (match_scratch:QI 0 "=r"))]
- "ix86_match_ccmode (insn, CCRCmode)
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "add{b}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "QI")])
-
-(define_insn "*addqi_6"
- [(set (reg 17)
(compare
(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
(match_operand:QI 2 "general_operand" "qmni"))
(const_int 0)))
- (clobber (match_scratch:QI 0 "=r"))]
+ (clobber (match_scratch:QI 0 "=q"))]
"ix86_match_ccmode (insn, CCGOCmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"*
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
-(define_insn "*subsi3_carry"
+(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 (ltu:SI (reg:CC 17) (const_int 0))
(set_attr "ppro_uops" "few")
(set_attr "mode" "SI")])
-(define_insn "subsi3_carry_rc"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
- (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
- (plus:SI (gtu:SI (reg:CCRC 17) (const_int 0))
- (match_operand:SI 2 "general_operand" "ri,rm"))))
- (clobber (reg:CC 17))]
- "ix86_binary_operator_ok (MINUS, SImode, operands)"
- "sbb{l}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "pent_pair" "pu")
- (set_attr "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" "")
(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
(match_operand:QI 2 "general_operand" "qim"))
(const_int 0)))
- (clobber (match_scratch:QI 0 "=r"))]
+ (clobber (match_scratch:QI 0 "=q"))]
"ix86_match_ccmode (insn, CCNOmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"or{b}\\t{%2, %0|%0, %2}"
(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
(match_operand:QI 2 "general_operand" "qim"))
(const_int 0)))
- (clobber (match_scratch:QI 0 "=r"))]
+ (clobber (match_scratch:QI 0 "=q"))]
"ix86_match_ccmode (insn, CCNOmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"xor{b}\\t{%2, %0|%0, %2}"
(set (match_dup 0) (neg:SI (match_dup 2)))])
(parallel
[(set (match_dup 1)
- (plus:SI (plus:SI (gtu:SI (reg:CCRC 17) (const_int 0))
+ (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
(match_dup 3))
(const_int 0)))
(clobber (reg:CC 17))])
(set_attr "mode" "SI")
(set_attr "length_immediate" "0")])
-(define_insn "x86_movsicc_0_m1_rc"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (if_then_else:SI (gtu (reg:CCRC 17) (const_int 0))
- (const_int -1)
- (const_int 0)))
- (clobber (reg:CC 17))]
- ""
- "sbb{l}\\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 "memory" "none")
- (set_attr "imm_disp" "false")
- (set_attr "mode" "SI")
- (set_attr "length_immediate" "0")])
-
(define_insn "*movsicc_noc"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(if_then_else:SI (match_operator 1 "ix86_comparison_operator"
&& find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
[(parallel [(set (reg:CCGC 17)
(compare:CCGC (match_dup 0)
- (neg:SI (match_dup 1))))
+ (match_dup 1)))
(clobber (match_dup 0))])]
- "operands[1] = (operands[1] == const1_rtx) ? constm1_rtx : const1_rtx;")
+ "")
(define_peephole2
[(set (reg 17)
&& find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
[(parallel [(set (reg:CCGC 17)
(compare:CCGC (match_dup 0)
- (neg:HI (match_dup 1))))
+ (match_dup 1)))
(clobber (match_dup 0))])]
- "operands[1] = (operands[1] == const1_rtx) ? constm1_rtx : const1_rtx;")
+ "")
(define_peephole2
[(set (reg 17)
&& find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
[(parallel [(set (reg:CCGC 17)
(compare:CCGC (match_dup 0)
- (neg:QI (match_dup 1))))
+ (match_dup 1)))
(clobber (match_dup 0))])]
- "operands[1] = (operands[1] == const1_rtx) ? constm1_rtx : const1_rtx;")
+ "")
;; Convert compares with 128 to shorter add -128
(define_peephole2
[(set (reg 17)
(compare (match_operand:SI 0 "register_operand" "")
(const_int 128)))]
- "ix86_match_ccmode (insn, CCRCmode)
+ "ix86_match_ccmode (insn, CCGCmode)
&& find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
- [(parallel [(set (reg:CCRC 17)
- (compare:CCRC (match_dup 0)
- (neg:SI (const_int -128))))
+ [(parallel [(set (reg:CCGC 17)
+ (compare:CCGC (match_dup 0)
+ (const_int 128)))
(clobber (match_dup 0))])]
"")
[(set (reg 17)
(compare (match_operand:HI 0 "register_operand" "")
(const_int 128)))]
- "ix86_match_ccmode (insn, CCRCmode)
+ "ix86_match_ccmode (insn, CCGCmode)
&& find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
- [(parallel [(set (reg:CCRC 17)
- (compare:CCRC (match_dup 0)
- (neg:HI (const_int -128))))
+ [(parallel [(set (reg:CCGC 17)
+ (compare:CCGC (match_dup 0)
+ (const_int 128)))
(clobber (match_dup 0))])]
"")
\f