--- gcc/config/i386/i386.c Mon Oct 23 22:51:33 2000
+++ gcc/config/i386/i386.c Fri Oct 27 17:41:12 2000
@@ -1272,47 +1272,58 @@ no_comparison_operator (op, mode)
return 0;
}
}
-
-/* Return 1 if OP is a comparison operator that can be issued by fcmov. */
-
+/* Return 1 if OP is a valid comparison operator in valid mode. */
int
-fcmov_comparison_operator (op, mode)
- register rtx op;
- enum machine_mode mode;
+ix86_comparison_operator (op, mode)
+ register rtx op;
+ enum machine_mode mode;
{
+ enum machine_mode inmode;
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
-
switch (GET_CODE (op))
{
case EQ: case NE:
- case LEU: case LTU: case GEU: case GTU:
- case UNORDERED: case ORDERED:
return 1;
-
+ case LT: case GE:
+ inmode = GET_MODE (XEXP (op, 0));
+ if (inmode == CCmode || inmode == CCGCmode
+ || inmode == CCGOCmode || inmode == CCNOmode)
+ return 1;
+ return 0;
+ case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
+ inmode = GET_MODE (XEXP (op, 0));
+ if (inmode == CCmode)
+ return 1;
+ return 0;
+ case GT: case LE:
+ inmode = GET_MODE (XEXP (op, 0));
+ if (inmode == CCmode || inmode == CCGCmode || inmode == CCNOmode)
+ return 1;
+ return 0;
default:
return 0;
}
}
-/* Return 1 if OP is any normal comparison operator plus {UN}ORDERED. */
+/* Return 1 if OP is a comparison operator that can be issued by fcmov. */
-int
-uno_comparison_operator (op, mode)
+int
+fcmov_comparison_operator (op, mode)
register rtx op;
enum machine_mode mode;
{
+ enum machine_mode inmode = GET_MODE (XEXP (op, 0));
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
-
switch (GET_CODE (op))
{
case EQ: case NE:
- case LE: case LT: case GE: case GT:
- case LEU: case LTU: case GEU: case GTU:
- case UNORDERED: case ORDERED:
return 1;
-
+ case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
+ if (inmode == CCmode)
+ return 1;
+ return 0;
default:
return 0;
}
@@ -3035,40 +3046,52 @@ put_condition_code (code, mode, reverse,
suffix = "ne";
break;
case GT:
- if (mode == CCNOmode)
+ if (mode != CCmode && mode != CCNOmode && mode != CCGCmode)
abort ();
suffix = "g";
break;
case GTU:
/* ??? Use "nbe" instead of "a" for fcmov losage on some assemblers.
Those same assemblers have the same but opposite losage on cmov. */
+ if (mode != CCmode)
+ abort();
suffix = fp ? "nbe" : "a";
break;
case LT:
- if (mode == CCNOmode)
+ if (mode == CCNOmode || mode == CCGOCmode)
suffix = "s";
- else
+ else if (mode == CCmode || mode == CCGCmode)
suffix = "l";
+ else
+ abort();
break;
case LTU:
+ if (mode != CCmode)
+ abort();
suffix = "b";
break;
case GE:
- if (mode == CCNOmode)
+ if (mode == CCNOmode || mode == CCGOCmode)
suffix = "ns";
- else
+ else if (mode == CCmode || mode == CCGCmode)
suffix = "ge";
+ else
+ abort();
break;
case GEU:
/* ??? As above. */
+ if (mode != CCmode)
+ abort();
suffix = fp ? "nb" : "ae";
break;
case LE:
- if (mode == CCNOmode)
+ if (mode != CCmode && mode != CCGCmode && mode != CCNOmode)
abort ();
suffix = "le";
break;
case LEU:
+ if (mode != CCmode)
+ abort ();
suffix = "be";
break;
case UNORDERED:
@@ -4454,15 +4477,27 @@ ix86_match_ccmode (insn, req_mode)
set = XVECEXP (set, 0, 0);
if (GET_CODE (set) != SET)
abort ();
+ if (GET_CODE (SET_SRC (set)) != COMPARE)
+ abort ();
set_mode = GET_MODE (SET_DEST (set));
switch (set_mode)
{
+ case CCNOmode:
+ if (req_mode != CCNOmode
+ && (req_mode != CCmode
+ || XEXP (SET_SRC (set), 1) != const0_rtx))
+ return 0;
+ break;
case CCmode:
- if (req_mode == CCNOmode)
+ if (req_mode == CCGCmode)
return 0;
/* FALLTHRU */
- case CCNOmode:
+ case CCGCmode:
+ if (req_mode == CCGOCmode || req_mode == CCNOmode)
+ return 0;
+ /* FALLTHRU */
+ case CCGOCmode:
if (req_mode == CCZmode)
return 0;
/* FALLTHRU */
@@ -4572,6 +4607,49 @@ ix86_fp_compare_mode (code)
return unordered ? CCFPUmode : CCFPmode;
}
+enum machine_mode
+ix86_cc_mode (code, op0, op1)
+ enum rtx_code code;
+ rtx op0, op1;
+{
+ if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
+ return ix86_fp_compare_mode (code);
+ switch (code)
+ {
+ /* Only zero flag is needed. */
+ case EQ: /* ZF=0 */
+ case NE: /* ZF!=0 */
+ return CCZmode;
+ /* Codes needing carry flag. */
+ case GEU: /* CF=0 */
+ case GTU: /* CF=0 & ZF=0 */
+ case LTU: /* CF=1 */
+ case LEU: /* CF=1 | ZF=1 */
+ return CCmode;
+ /* Codes possibly doable only with sign flag when
+ comparing against zero. */
+ case GE: /* SF=OF or SF=0 */
+ case LT: /* SF<>OF or SF=0 */
+ if (op1 == const0_rtx)
+ return CCGOCmode;
+ else
+ /* For other cases Carry flag is not required. */
+ return CCGCmode;
+ /* Codes doable only with sign flag when comparing
+ against zero, but we miss jump instruction for it
+ so we need to use relational tests agains overflow
+ that thus needs to be zero. */
+ case GT: /* ZF=0 & SF=OF */
+ case LE: /* ZF=1 | SF<>OF */
+ if (op1 == const0_rtx)
+ return CCNOmode;
+ else
+ return CCGCmode;
+ default:
+ abort();
+ }
+}
+
/* Return true if we should use an FCOMI instruction for this fp comparison. */
int
@@ -4816,6 +4894,7 @@ ix86_expand_fp_compare (code, op0, op1,
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
+ intcmp_mode = CCmode;
code = GEU;
break;
case UNLE:
@@ -5865,8 +5944,6 @@ ix86_expand_strlensi_unroll_1 (out, alig
rtx align_4_label = gen_label_rtx ();
rtx end_0_label = gen_label_rtx ();
rtx mem;
- rtx no_flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
- rtx z_flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
rtx tmpreg = gen_reg_rtx (SImode);
align = 0;
@@ -5888,30 +5965,12 @@ ix86_expand_strlensi_unroll_1 (out, alig
align_rtx = expand_binop (SImode, and_optab, scratch, GEN_INT (3),
NULL_RTX, 0, OPTAB_WIDEN);
- emit_insn (gen_cmpsi_ccz_1 (align_rtx, const0_rtx));
-
- tmp = gen_rtx_EQ (VOIDmode, z_flags, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode,
- align_4_label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
-
- emit_insn (gen_cmpsi_ccno_1 (align_rtx, GEN_INT (2)));
-
- tmp = gen_rtx_EQ (VOIDmode, no_flags, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode,
- align_2_label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
-
- tmp = gen_rtx_GTU (VOIDmode, no_flags, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode,
- align_3_label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
+ SImode, 1, 0, align_4_label);
+ emit_cmp_and_jump_insns (align_rtx, GEN_INT (2), EQ, NULL,
+ SImode, 1, 0, align_2_label);
+ emit_cmp_and_jump_insns (align_rtx, GEN_INT (2), GTU, NULL,
+ SImode, 1, 0, align_3_label);
}
else
{
@@ -5921,14 +5980,8 @@ ix86_expand_strlensi_unroll_1 (out, alig
align_rtx = expand_binop (SImode, and_optab, scratch, GEN_INT (2),
NULL_RTX, 0, OPTAB_WIDEN);
- emit_insn (gen_cmpsi_ccz_1 (align_rtx, const0_rtx));
-
- tmp = gen_rtx_EQ (VOIDmode, z_flags, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode,
- align_4_label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
+ SImode, 1, 0, align_4_label);
}
mem = gen_rtx_MEM (QImode, out);
@@ -5936,13 +5989,8 @@ ix86_expand_strlensi_unroll_1 (out, alig
/* Now compare the bytes. */
/* Compare the first n unaligned byte on a byte per byte basis. */
- emit_insn (gen_cmpqi_ccz_1 (mem, const0_rtx));
-
- tmp = gen_rtx_EQ (VOIDmode, z_flags, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, end_0_label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
+ QImode, 1, 0, end_0_label);
/* Increment the address. */
emit_insn (gen_addsi3 (out, out, const1_rtx));
@@ -5952,27 +6000,16 @@ ix86_expand_strlensi_unroll_1 (out, alig
{
emit_label (align_2_label);
- emit_insn (gen_cmpqi_ccz_1 (mem, const0_rtx));
-
- tmp = gen_rtx_EQ (VOIDmode, z_flags, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode,
- end_0_label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
+ QImode, 1, 0, end_0_label);
emit_insn (gen_addsi3 (out, out, const1_rtx));
emit_label (align_3_label);
}
- emit_insn (gen_cmpqi_ccz_1 (mem, const0_rtx));
-
- tmp = gen_rtx_EQ (VOIDmode, z_flags, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, end_0_label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
+ QImode, 1, 0, end_0_label);
emit_insn (gen_addsi3 (out, out, const1_rtx));
}
@@ -5993,7 +6030,8 @@ ix86_expand_strlensi_unroll_1 (out, alig
emit_insn (gen_one_cmplsi2 (scratch, scratch));
emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
emit_insn (gen_andsi3 (tmpreg, tmpreg, GEN_INT (0x80808080)));
- emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1, 0, align_4_label);
+ emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0,
+ SImode, 1, 0, align_4_label);
if (TARGET_CMOVE)
{
--- gcc/config/i386/i386.h Mon Oct 30 15:33:07 2000
+++ gcc/config/i386/i386.h Mon Oct 30 16:28:01 2000
@@ -2253,14 +2254,25 @@ while (0)
For the i386, we need separate modes when floating-point
equality comparisons are being done.
-
- Add CCNO to indicate No Overflow, which is often also includes
- No Carry. This is typically used on the output of logicals,
- and is only valid in comparisons against zero.
+
+ Add CCNO to indicate comparisons against zero that requires
+ No Overflow. Sign bit test is used instead and thus
+ can be used to form "a&b>0" type of tests.
+
+ Add CCGC to indicate comparisons agains zero that allows
+ unspecified garbage in the Carry flag. This mode is used
+ by inc/dec instructions.
+
+ Add CCGCO to indicate comparisons agains zero that allows
+ unspecified garbage in the Carry and Overflow flag. This
+ mode is used to simulate comparisons of (a-b) and (a+b)
+ against zero using sub/cmp/add operations.
Add CCZ to indicate that only the Zero flag is valid. */
#define EXTRA_CC_MODES \
+ CC(CCGCmode, "CCGC") \
+ CC(CCGOCmode, "CCGOC") \
CC(CCNOmode, "CCNO") \
CC(CCZmode, "CCZ") \
CC(CCFPmode, "CCFP") \
@@ -2275,12 +2287,7 @@ while (0)
For integer comparisons against zero, reduce to CCNOmode or CCZmode if
possible, to allow for more combinations. */
-#define SELECT_CC_MODE(OP,X,Y) \
- (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
- ? (OP) == EQ || (OP) == NE ? CCFPUmode : CCFPmode \
- : (OP) == LE || (OP) == GT ? CCmode \
- : (Y) != const0_rtx ? CCmode \
- : (OP) == EQ || (OP) == NE ? CCZmode : CCNOmode)
+#define SELECT_CC_MODE(OP,X,Y) ix86_cc_mode (OP, X, Y)
/* Control the assembler format that we output, to the extent
this does not vary between assemblers. */
@@ -2588,8 +2595,8 @@ do { long l; \
{"non_q_regs_operand", {SUBREG, REG}}, \
{"no_comparison_operator", {EQ, NE, LT, GE, LTU, GTU, LEU, GEU}}, \
{"fcmov_comparison_operator", {EQ, NE, LTU, GTU, LEU, GEU}}, \
- {"uno_comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, \
- GTU, UNORDERED, ORDERED}}, \
+ {"ix86_comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, \
+ GTU, UNORDERED, ORDERED}}, \
{"cmp_fp_expander_operand", {CONST_DOUBLE, SUBREG, REG, MEM}}, \
{"ext_register_operand", {SUBREG, REG}}, \
{"binary_fp_operator", {PLUS, MINUS, MULT, DIV}}, \
--- gcc/config/i386/i386.md Mon Oct 30 15:33:04 2000
+++ gcc/config/i386/i386.md Mon Oct 30 16:23:52 2000
@@ -71,6 +71,7 @@
;; 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.
;;
;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
;; from i386.c.
@@ -1043,11 +1044,11 @@
DONE;
}")
-(define_insn "cmpsi_ccz_1"
- [(set (reg:CCZ 17)
- (compare:CCZ (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
- (match_operand:SI 1 "const0_operand" "n,n")))]
- ""
+(define_insn "*cmpsi_ccno_1"
+ [(set (reg 17)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
+ (match_operand:SI 1 "const0_operand" "n,n")))]
+ "ix86_match_ccmode (insn, CCNOmode)"
"@
test{l}\\t{%0, %0|%0, %0}
cmp{l}\\t{%1, %0|%0, %1}"
@@ -1055,28 +1056,34 @@
(set_attr "length_immediate" "0,1")
(set_attr "mode" "SI")])
-(define_insn "cmpsi_ccno_1"
- [(set (reg:CCNO 17)
- (compare:CCNO (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
- (match_operand:SI 1 "const0_operand" "n,n")))]
- ""
- "@
- test{l}\\t{%0, %0|%0, %0}
- cmp{l}\\t{%1, %0|%0, %1}"
- [(set_attr "type" "test,icmp")
- (set_attr "length_immediate" "0,1")
+(define_insn "*cmpsi_minus_1"
+ [(set (reg 17)
+ (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_insn "cmpsi_1"
+(define_expand "cmpsi_1"
[(set (reg:CC 17)
(compare:CC (match_operand:SI 0 "nonimmediate_operand" "rm,r")
(match_operand:SI 1 "general_operand" "ri,mr")))]
- "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+ ""
+ "")
+
+(define_insn "*cmpsi_1_insn"
+ [(set (reg 17)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "rm,r")
+ (match_operand:SI 1 "general_operand" "ri,mr")))]
+ "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ && ix86_match_ccmode (insn, CCmode)"
"cmp{l}\\t{%1, %0|%0, %1}"
[(set_attr "type" "icmp")
(set_attr "mode" "SI")])
-(define_insn "*cmphi_0"
+(define_insn "*cmphi_ccno_1"
[(set (reg 17)
(compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr")
(match_operand:HI 1 "const0_operand" "n,n")))]
@@ -1088,32 +1095,31 @@
(set_attr "length_immediate" "0,1")
(set_attr "mode" "HI")])
-(define_insn "*cmphi_1"
- [(set (reg:CC 17)
- (compare:CC (match_operand:HI 0 "nonimmediate_operand" "rm,r")
- (match_operand:HI 1 "general_operand" "ri,mr")))]
- "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+(define_insn "*cmphi_minus_1"
+ [(set (reg 17)
+ (compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r")
+ (match_operand:HI 1 "general_operand" "ri,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 "cmpqi_ccz_1"
- [(set (reg:CCZ 17)
- (compare:CCZ (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
- (match_operand:QI 1 "const0_operand" "n,n")))]
- ""
- "@
- test{b}\\t{%0, %0|%0, %0}
- cmp{b}\\t{$0, %0|%0, 0}"
- [(set_attr "type" "test,icmp")
- (set_attr "length_immediate" "0,1")
- (set_attr "mode" "QI")])
+(define_insn "*cmphi_1"
+ [(set (reg 17)
+ (compare (match_operand:HI 0 "nonimmediate_operand" "rm,r")
+ (match_operand:HI 1 "general_operand" "ri,mr")))]
+ "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ && 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"
- [(set (reg:CCNO 17)
- (compare:CCNO (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
- (match_operand:QI 1 "const0_operand" "n,n")))]
- ""
+ [(set (reg 17)
+ (compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
+ (match_operand:QI 1 "const0_operand" "n,n")))]
+ "ix86_match_ccmode (insn, CCNOmode)"
"@
test{b}\\t{%0, %0|%0, %0}
cmp{b}\\t{$0, %0|%0, 0}"
@@ -1122,24 +1128,35 @@
(set_attr "mode" "QI")])
(define_insn "*cmpqi_1"
- [(set (reg:CC 17)
- (compare:CC (match_operand:QI 0 "nonimmediate_operand" "qm,q")
- (match_operand:QI 1 "general_operand" "qi,mq")))]
- "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+ [(set (reg 17)
+ (compare (match_operand:QI 0 "nonimmediate_operand" "qm,q")
+ (match_operand:QI 1 "general_operand" "qi,mq")))]
+ "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ && ix86_match_ccmode (insn, CCmode)"
"cmp{b}\\t{%1, %0|%0, %1}"
[(set_attr "type" "icmp")
(set_attr "mode" "QI")])
+(define_insn "*cmpqi_minus_1"
+ [(set (reg 17)
+ (compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "rm,r")
+ (match_operand:QI 1 "general_operand" "ri,mr"))
+ (const_int 0)))]
+ "ix86_match_ccmode (insn, CCGOCmode)"
+ "cmp{w}\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "icmp")
+ (set_attr "mode" "QI")])
+
(define_insn "*cmpqi_ext_1"
- [(set (reg:CC 17)
- (compare:CC
+ [(set (reg 17)
+ (compare
(match_operand:QI 0 "general_operand" "qm")
(subreg:QI
(zero_extract:SI
(match_operand 1 "ext_register_operand" "q")
(const_int 8)
(const_int 8)) 0)))]
- ""
+ "ix86_match_ccmode (insn, CCmode)"
"cmp{b}\\t{%h1, %0|%0, %h1}"
[(set_attr "type" "icmp")
(set_attr "mode" "QI")])
@@ -1159,7 +1176,7 @@
(set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
-(define_insn "cmpqi_ext_3"
+(define_expand "cmpqi_ext_3"
[(set (reg:CC 17)
(compare:CC
(subreg:QI
@@ -1169,13 +1186,25 @@
(const_int 8)) 0)
(match_operand:QI 1 "general_operand" "qmn")))]
""
+ "")
+
+(define_insn "cmpqi_ext_3_insn"
+ [(set (reg 17)
+ (compare
+ (subreg:QI
+ (zero_extract:SI
+ (match_operand 0 "ext_register_operand" "q")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand:QI 1 "general_operand" "qmn")))]
+ "ix86_match_ccmode (insn, CCmode)"
"cmp{b}\\t{%1, %h0|%h0, %1}"
[(set_attr "type" "icmp")
(set_attr "mode" "QI")])
(define_insn "*cmpqi_ext_4"
- [(set (reg:CC 17)
- (compare:CC
+ [(set (reg 17)
+ (compare
(subreg:QI
(zero_extract:SI
(match_operand 0 "ext_register_operand" "q")
@@ -1186,7 +1215,7 @@
(match_operand 1 "ext_register_operand" "q")
(const_int 8)
(const_int 8)) 0)))]
- ""
+ "ix86_match_ccmode (insn, CCmode)"
"cmp{b}\\t{%h1, %h0|%h0, %h1}"
[(set_attr "type" "icmp")
(set_attr "mode" "QI")])
@@ -3680,20 +3709,33 @@
(match_operand:DI 2 "general_operand" "")))
(clobber (reg:CC 17))]
"reload_completed"
- [(parallel [(set (reg:CC 17) (plus:CC (match_dup 1) (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 (match_dup 4)
- (plus:SI (match_dup 5)
- (ltu:SI (reg:CC 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))])]
"split_di (operands+0, 1, operands+0, operands+3);
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
+(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))
+ (match_operand:SI 1 "nonimmediate_operand" "%0,0"))
+ (match_operand:SI 2 "general_operand" "ri,rm")))
+ (clobber (reg:CC 17))]
+ "ix86_binary_operator_ok (PLUS, SImode, operands)"
+ "adc{l}\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "pent_pair" "pu")
+ (set_attr "mode" "SI")
+ (set_attr "ppro_uops" "few")])
+
(define_insn "*addsi3_cc"
- [(set (reg:CC 17) (plus:CC (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "ri,rm")))
+ [(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)"
@@ -3702,8 +3744,8 @@
(set_attr "mode" "SI")])
(define_insn "addqi3_cc"
- [(set (reg:CC 17) (plus:CC (match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "qi,qm")))
+ [(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)"
@@ -3711,19 +3753,6 @@
[(set_attr "type" "alu")
(set_attr "mode" "QI")])
-(define_insn "*addsi3_carry"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
- (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (plus:SI (match_operand:SI 2 "general_operand" "ri,rm")
- (ltu:SI (reg:CC 17) (const_int 0)))))
- (clobber (reg:CC 17))]
- "ix86_binary_operator_ok (PLUS, SImode, operands)"
- "adc{l}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "pent_pair" "pu")
- (set_attr "mode" "SI")
- (set_attr "ppro_uops" "few")])
-
(define_expand "addsi3"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
@@ -3925,7 +3954,7 @@
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
(plus:SI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "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. */
@@ -3971,7 +4000,7 @@
(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, CCNOmode)
+ "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. */
@@ -4012,31 +4041,98 @@
(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:CC 17)
- (compare:CC (neg:SI (match_operand:SI 2 "general_operand" "rmni,rni"))
- (match_operand:SI 1 "nonimmediate_operand" "%0,0")))
- (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "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)"
- "add{l}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
+ [(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:CC 17)
- (compare:CC (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
- (match_operand:SI 1 "nonimmediate_operand" "%0")))
+ [(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"))]
- "(GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
+ "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)"
- "add{l}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
+ "*
+{
+ 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"
@@ -4143,7 +4239,7 @@
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
(plus:HI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (PLUS, HImode, operands)"
"*
{
@@ -4183,7 +4279,7 @@
(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, CCNOmode)
+ "ix86_match_ccmode (insn, CCZmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"*
{
@@ -4218,25 +4314,88 @@
(const_string "alu")))
(set_attr "mode" "HI")])
+; See comments above addsi_3_imm for details.
(define_insn "*addhi_4"
- [(set (reg:CC 17)
- (compare:CC (neg:HI (match_operand:HI 2 "general_operand" "rmni,rni"))
- (match_operand:HI 1 "nonimmediate_operand" "%0,0")))
- (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
- (plus:HI (match_dup 1) (match_dup 2)))]
- "ix86_binary_operator_ok (PLUS, HImode, operands)"
- "add{w}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "HI")])
+ [(set (reg 17)
+ (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:CC 17)
- (compare:CC (neg:HI (match_operand:HI 2 "general_operand" "rmni"))
- (match_operand:HI 1 "nonimmediate_operand" "%0")))
+ [(set (reg 17)
+ (compare
+ (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
+ (match_operand:HI 2 "general_operand" "rmni"))
+ (const_int 0)))
(clobber (match_scratch:HI 0 "=r"))]
- "(GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "add{w}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "*
+{
+ 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:
+ /* 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 (match_operand:HI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
(set_attr "mode" "HI")])
(define_expand "addqi3"
@@ -4354,7 +4513,7 @@
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
(plus:QI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (PLUS, QImode, operands)"
"*
{
@@ -4390,8 +4549,8 @@
[(set (reg 17)
(compare (neg:QI (match_operand:QI 2 "general_operand" "qmni"))
(match_operand:QI 1 "nonimmediate_operand" "%0")))
- (clobber (match_scratch:QI 0 "=r"))]
- "ix86_match_ccmode (insn, CCNOmode)
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCZmode)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"*
{
@@ -4423,25 +4582,82 @@
(const_string "alu")))
(set_attr "mode" "QI")])
+; See comments above addsi_3_imm for details.
(define_insn "*addqi_4"
- [(set (reg:CC 17)
- (compare:CC (neg:QI (match_operand:QI 2 "general_operand" "qmni,qni"))
- (match_operand:QI 1 "nonimmediate_operand" "%0,0")))
- (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
- (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 (reg 17)
+ (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_insn "*addqi_5"
- [(set (reg:CC 17)
- (compare:CC (neg:QI (match_operand:QI 2 "general_operand" "qmni"))
- (match_operand:QI 1 "nonimmediate_operand" "%0")))
- (clobber (match_scratch:QI 0 "=r"))]
- "(GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "add{b}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
+ [(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 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "*
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_INCDEC:
+ if (operands[2] == const1_rtx)
+ return \"inc{b}\\t%0\";
+ else if (operands[2] == constm1_rtx
+ || (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 255))
+ return \"dec{b}\\t%0\";
+ abort();
+
+ default:
+ /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */
+ if (GET_CODE (operands[2]) == CONST_INT
+ && 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")])
@@ -4541,32 +4757,22 @@
(match_operand:DI 2 "general_operand" "")))
(clobber (reg:CC 17))]
"reload_completed"
- [(parallel [(set (reg:CC 17) (minus:CC (match_dup 1) (match_dup 2)))
+ [(parallel [(set (reg:CC 17) (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 (match_dup 5)
- (ltu:SI (reg:CC 17) (const_int 0)))))
+ (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+ (match_dup 5))))
(clobber (reg:CC 17))])]
"split_di (operands+0, 1, operands+0, operands+3);
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
-(define_insn "*subsi3_cc"
- [(set (reg:CC 17) (minus:CC (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)))]
- "ix86_binary_operator_ok (MINUS, SImode, operands)"
- "sub{l}\\t{%2, %0|%0, %2}"
- [(set_attr "type" "alu")
- (set_attr "mode" "SI")])
-
(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 2 "general_operand" "ri,rm")
- (ltu:SI (reg:CC 17) (const_int 0)))))
+ (plus:SI (ltu:SI (reg:CC 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}"
@@ -4601,7 +4807,7 @@
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(minus:SI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
@@ -4645,7 +4851,7 @@
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
(minus:HI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (MINUS, HImode, operands)"
"sub{w}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
@@ -4689,7 +4895,7 @@
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
(minus:HI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (MINUS, QImode, operands)"
"sub{b}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
@@ -5145,31 +5351,28 @@
;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al.
;; Note that this excludes ah.
-(define_insn "*testsi_ccz_1"
- [(set (reg:CCZ 17)
- (compare:CCZ
+
+(define_insn "testsi_1"
+ [(set (reg 17)
+ (compare
(and:SI (match_operand:SI 0 "nonimmediate_operand" "%*a,r,rm")
(match_operand:SI 1 "nonmemory_operand" "in,in,rin"))
(const_int 0)))]
- ""
+ "ix86_match_ccmode (insn, CCNOmode)"
"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_insn "testsi_ccno_1"
+(define_expand "testsi_ccno_1"
[(set (reg:CCNO 17)
(compare:CCNO
- (and:SI (match_operand:SI 0 "nonimmediate_operand" "%*a,r,rm")
- (match_operand:SI 1 "nonmemory_operand" "in,in,rin"))
+ (and:SI (match_operand:SI 0 "nonimmediate_operand" "")
+ (match_operand:SI 1 "nonmemory_operand" ""))
(const_int 0)))]
""
- "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_insn "*testhi_1"
[(set (reg 17)
@@ -5183,55 +5386,46 @@
(set_attr "mode" "HI")
(set_attr "pent_pair" "uv,np,uv")])
-(define_insn "testqi_ccz_1"
+(define_expand "testqi_ccz_1"
[(set (reg:CCZ 17)
- (compare:CCZ
- (and:QI (match_operand:QI 0 "nonimmediate_operand" "%*a,q,qm")
- (match_operand:QI 1 "nonmemory_operand" "n,n,qn"))
- (const_int 0)))]
+ (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "")
+ (match_operand:QI 1 "nonmemory_operand" ""))
+ (const_int 0)))]
""
- "test{b}\\t{%1, %0|%0, %1}"
- [(set_attr "type" "test")
- (set_attr "modrm" "0,1,1")
- (set_attr "mode" "QI")
- (set_attr "pent_pair" "uv,np,uv")])
+ "")
-(define_insn "testqi_ccno_1"
- [(set (reg:CCNO 17)
- (compare:CCNO (and:QI (match_operand:QI 0 "nonimmediate_operand" "%*a,q,qm,r")
- (match_operand:QI 1 "nonmemory_operand" "n,n,qn,n"))
- (const_int 0)))]
- ""
+(define_insn "*testqi_1"
+ [(set (reg 17)
+ (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%*a,q,qm,r")
+ (match_operand:QI 1 "nonmemory_operand" "n,n,qn,n"))
+ (const_int 0)))]
+ "ix86_match_ccmode (insn, CCNOmode)"
"@
test{b}\\t{%1, %0|%0, %1}
test{b}\\t{%1, %0|%0, %1}
test{b}\\t{%1, %0|%0, %1}
- test{l}\\t{%1, %0|%0, %1}"
+ test{l}\\t{%1, %k0|%k0, %1}"
[(set_attr "type" "test")
(set_attr "modrm" "0,1,1,1")
(set_attr "mode" "QI,QI,QI,SI")
(set_attr "pent_pair" "uv,np,uv,np")])
-(define_insn "*testqi_ext_ccz_0"
- [(set (reg:CCZ 17)
- (compare:CCZ
+(define_expand "testqi_ext_ccno_0"
+ [(set (reg:CCNO 17)
+ (compare:CCNO
(and:SI
(zero_extract:SI
- (match_operand 0 "ext_register_operand" "q")
+ (match_operand 0 "ext_register_operand" "")
(const_int 8)
(const_int 8))
- (match_operand 1 "const_int_operand" "n"))
+ (match_operand 1 "const_int_operand" ""))
(const_int 0)))]
- "(unsigned HOST_WIDE_INT) INTVAL (operands[1]) <= 0xff"
- "test{b}\\t{%1, %h0|%h0, %1}"
- [(set_attr "type" "test")
- (set_attr "mode" "QI")
- (set_attr "length_immediate" "1")
- (set_attr "pent_pair" "np")])
+ ""
+ "")
-(define_insn "testqi_ext_ccno_0"
- [(set (reg:CCNO 17)
- (compare:CCNO
+(define_insn "*testqi_ext_0"
+ [(set (reg 17)
+ (compare
(and:SI
(zero_extract:SI
(match_operand 0 "ext_register_operand" "q")
@@ -5239,7 +5433,8 @@
(const_int 8))
(match_operand 1 "const_int_operand" "n"))
(const_int 0)))]
- "(unsigned HOST_WIDE_INT) INTVAL (operands[1]) <= 0xff"
+ "(unsigned HOST_WIDE_INT) INTVAL (operands[1]) <= 0xff
+ && ix86_match_ccmode (insn, CCNOmode)"
"test{b}\\t{%1, %h0|%h0, %1}"
[(set_attr "type" "test")
(set_attr "mode" "QI")
@@ -5745,7 +5940,7 @@
(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}"
@@ -5904,16 +6099,16 @@
(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_attr "type" "alu")
(set_attr "mode" "QI")])
-(define_insn "xorqi_cc_ext_1"
- [(set (reg:CCNO 17)
- (compare:CCNO
+(define_insn "*xorqi_cc_ext_1"
+ [(set (reg 17)
+ (compare
(xor:SI
(zero_extract:SI
(match_operand 1 "ext_register_operand" "0")
@@ -5927,10 +6122,30 @@
(xor:SI
(zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
(match_dup 2)))]
- ""
+ "ix86_match_ccmode (insn, CCNOmode)"
"xor{b}\\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "QI")])
+
+(define_expand "xorqi_cc_ext_1"
+ [(parallel [
+ (set (reg:CCNO 17)
+ (compare:CCNO
+ (xor:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "")
+ (const_int 8)
+ (const_int 8))
+ (match_operand:QI 2 "general_operand" ""))
+ (const_int 0)))
+ (set (zero_extract:SI (match_operand 0 "ext_register_operand" "")
+ (const_int 8)
+ (const_int 8))
+ (xor:SI
+ (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
+ (match_dup 2)))])]
+ ""
+ "")
;; Negation instructions
@@ -5961,9 +6176,9 @@
(set (match_dup 0) (neg:SI (match_dup 2)))])
(parallel
[(set (match_dup 1)
- (plus:SI (match_dup 3)
- (plus:SI (const_int 0)
- (ltu:SI (reg:CC 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))])
(parallel
[(set (match_dup 1)
@@ -6780,7 +6995,7 @@
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(ashift:SI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (ASHIFT, SImode, operands)"
"*
{
@@ -6909,7 +7124,7 @@
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashift:HI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (ASHIFT, HImode, operands)"
"*
{
@@ -7076,7 +7291,7 @@
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashift:QI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (ASHIFT, QImode, operands)"
"*
{
@@ -7546,7 +7761,7 @@
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(lshiftrt:SI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& (TARGET_PENTIUM || TARGET_PENTIUMPRO)
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{l}\\t%0"
@@ -7567,7 +7782,7 @@
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(lshiftrt:SI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"@
shr{l}\\t{%2, %0|%0, %2}"
@@ -7619,7 +7834,7 @@
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(lshiftrt:HI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& (TARGET_PENTIUM || TARGET_PENTIUMPRO)
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{w}\\t%0"
@@ -7640,7 +7855,7 @@
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(lshiftrt:HI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"@
shr{w}\\t{%2, %0|%0, %2}"
@@ -7692,7 +7907,7 @@
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(lshiftrt:QI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& (TARGET_PENTIUM || TARGET_PENTIUMPRO)
&& ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
"shr{b}\\t%0"
@@ -7713,7 +7928,7 @@
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(lshiftrt:QI (match_dup 1) (match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
+ "ix86_match_ccmode (insn, CCGOCmode)
&& ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
"shr{b}\\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
@@ -8102,7 +8317,7 @@
(define_insn "*setcc_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
- (match_operator:QI 1 "no_comparison_operator"
+ (match_operator:QI 1 "ix86_comparison_operator"
[(reg 17) (const_int 0)]))]
""
"set%C1\\t%0"
@@ -8111,30 +8326,12 @@
(define_insn "*setcc_2"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
- (match_operator:QI 1 "no_comparison_operator"
+ (match_operator:QI 1 "ix86_comparison_operator"
[(reg 17) (const_int 0)]))]
""
"set%C1\\t%0"
[(set_attr "type" "setcc")
(set_attr "mode" "QI")])
-
-(define_insn "*setcc_3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
- (match_operator:QI 1 "uno_comparison_operator"
- [(reg:CC 17) (const_int 0)]))]
- ""
- "set%C1\\t%0"
- [(set_attr "type" "setcc")
- (set_attr "mode" "QI")])
-
-(define_insn "*setcc_4"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
- (match_operator:QI 1 "uno_comparison_operator"
- [(reg:CC 17) (const_int 0)]))]
- ""
- "set%C1\\t%0"
- [(set_attr "type" "setcc")
- (set_attr "mode" "QI")])
;; Basic conditional jump instructions.
;; We ignore the overflow flag for signed branch instructions.
@@ -8288,7 +8485,7 @@
(define_insn "*jcc_1"
[(set (pc)
- (if_then_else (match_operator 1 "no_comparison_operator"
+ (if_then_else (match_operator 1 "ix86_comparison_operator"
[(reg 17) (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
@@ -8305,7 +8502,7 @@
(define_insn "*jcc_2"
[(set (pc)
- (if_then_else (match_operator 1 "no_comparison_operator"
+ (if_then_else (match_operator 1 "ix86_comparison_operator"
[(reg 17) (const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
@@ -8320,40 +8517,6 @@
(const_int 0)
(const_int 1)))])
-(define_insn "*jcc_3"
- [(set (pc)
- (if_then_else (match_operator 1 "uno_comparison_operator"
- [(reg:CC 17) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "j%C1\\t%l0"
- [(set_attr "type" "ibr")
- (set (attr "prefix_0f")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -128))
- (lt (minus (match_dup 0) (pc))
- (const_int 124)))
- (const_int 0)
- (const_int 1)))])
-
-(define_insn "*jcc_4"
- [(set (pc)
- (if_then_else (match_operator 1 "uno_comparison_operator"
- [(reg:CC 17) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "j%c1\\t%l0"
- [(set_attr "type" "ibr")
- (set (attr "prefix_0f")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -128))
- (lt (minus (match_dup 0) (pc))
- (const_int 124)))
- (const_int 0)
- (const_int 1)))])
-
;; 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.
@@ -10436,7 +10599,7 @@
(define_insn "*movsicc_noc"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "no_comparison_operator"
+ (if_then_else:SI (match_operator 1 "ix86_comparison_operator"
[(reg 17) (const_int 0)])
(match_operand:SI 2 "nonimmediate_operand" "rm,0")
(match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
@@ -10448,20 +10611,6 @@
[(set_attr "type" "icmov")
(set_attr "mode" "SI")])
-(define_insn "*movsicc_c"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "uno_comparison_operator"
- [(reg:CC 17) (const_int 0)])
- (match_operand:SI 2 "nonimmediate_operand" "rm,0")
- (match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
- "TARGET_CMOVE
- && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
- "@
- cmov%C1\\t{%2, %0|%0, %2}
- cmov%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" "")
@@ -10472,7 +10621,7 @@
(define_insn "*movhicc_noc"
[(set (match_operand:HI 0 "register_operand" "=r,r")
- (if_then_else:HI (match_operator 1 "no_comparison_operator"
+ (if_then_else:HI (match_operator 1 "ix86_comparison_operator"
[(reg 17) (const_int 0)])
(match_operand:HI 2 "nonimmediate_operand" "rm,0")
(match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
@@ -10484,20 +10633,6 @@
[(set_attr "type" "icmov")
(set_attr "mode" "HI")])
-(define_insn "*movhicc_c"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (if_then_else:HI (match_operator 1 "uno_comparison_operator"
- [(reg:CC 17) (const_int 0)])
- (match_operand:HI 2 "nonimmediate_operand" "rm,0")
- (match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
- "TARGET_CMOVE
- && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
- "@
- cmov%C1\\t{%2, %0|%0, %2}
- cmov%c1\\t{%3, %0|%0, %3}"
- [(set_attr "type" "icmov")
- (set_attr "mode" "HI")])
-
(define_expand "movsfcc"
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
@@ -11290,6 +11425,68 @@
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
"")
+;; Convert compares with 1 to shorter inc/dec operations when CF is not
+;; required and register dies.
+(define_peephole2
+ [(set (reg 17)
+ (compare (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "incdec_operand" "")))]
+ "ix86_match_ccmode (insn, CCGCmode)
+ && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
+ [(parallel [(set (reg:CCGC 17)
+ (compare:CCGC (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 0))])]
+ "")
+
+(define_peephole2
+ [(set (reg 17)
+ (compare (match_operand:HI 0 "register_operand" "")
+ (match_operand:HI 1 "incdec_operand" "")))]
+ "ix86_match_ccmode (insn, CCGCmode)
+ && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
+ [(parallel [(set (reg:CCGC 17)
+ (compare:CCGC (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 0))])]
+ "")
+
+(define_peephole2
+ [(set (reg 17)
+ (compare (match_operand:QI 0 "register_operand" "")
+ (match_operand:QI 1 "incdec_operand" "")))]
+ "ix86_match_ccmode (insn, CCGCmode)
+ && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
+ [(parallel [(set (reg:CCGC 17)
+ (compare:CCGC (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 0))])]
+ "")
+
+;; 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, CCGCmode)
+ && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
+ [(parallel [(set (reg:CCGC 17)
+ (compare:CCGC (match_dup 0)
+ (const_int 128)))
+ (clobber (match_dup 0))])]
+ "")
+
+(define_peephole2
+ [(set (reg 17)
+ (compare (match_operand:HI 0 "register_operand" "")
+ (const_int 128)))]
+ "ix86_match_ccmode (insn, CCGCmode)
+ && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
+ [(parallel [(set (reg:CCGC 17)
+ (compare:CCGC (match_dup 0)
+ (const_int 128)))
+ (clobber (match_dup 0))])]
+ "")
;; Call-value patterns last so that the wildcard operand does not
;; disrupt insn-recog's switch tables.
--- gcc/config/i386/i386-protos.h Sun Jul 2 10:37:12 2000
+++ gcc/config/i386/i386-protos.h Wed Oct 18 13:27:27 2000
@@ -57,7 +57,7 @@ extern int q_regs_operand PARAMS ((rtx,
extern int non_q_regs_operand PARAMS ((rtx, enum machine_mode));
extern int no_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int fcmov_comparison_operator PARAMS ((rtx, enum machine_mode));
-extern int uno_comparison_operator PARAMS ((rtx, enum machine_mode));
+extern int ix86_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int cmp_fp_expander_operand PARAMS ((rtx, enum machine_mode));
extern int ext_register_operand PARAMS ((rtx, enum machine_mode));
extern int binary_fp_operator PARAMS ((rtx, enum machine_mode));
@@ -121,6 +121,7 @@ extern int ix86_adjust_cost PARAMS ((rtx
extern void ix86_sched_init PARAMS ((FILE *, int));
extern int ix86_sched_reorder PARAMS ((FILE *, int, rtx *, int, int));
extern int ix86_variable_issue PARAMS ((FILE *, int, rtx, int));
+extern enum machine_mode ix86_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
#ifdef TREE_CODE
extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx));