--- 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));