From e6e81735cf3f35f4ee3fd5e70abc000b45d5bff7 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 28 Jan 2003 12:16:32 +0100 Subject: [PATCH] i386.c (ix86_carry_flag_operator): New predicate. * i386.c (ix86_carry_flag_operator): New predicate. (fcmov_operator): Fix whitespace. (ix86_expand_carry_flag_compare): Deal with floating point. (ix86_expand_int_movcc): Deal with fp; update insn expansion (ix86_expand_int_addcc): Likewise. (ix86_expand_strlensi_unroll_1): likewsie. * i386.h (PREDICATE_CODES): Add ix86_carry_flag_operator. * i386.md (add?i_carry_rex64): Use new predicate. (sub?i3_carry_rex64): Likewise. (x86_mov?icc_0_m1*): Likewise. From-SVN: r61963 --- gcc/ChangeLog | 13 ++++ gcc/config/i386/i386.c | 155 +++++++++++++++++++++++++++++++++++----- gcc/config/i386/i386.h | 2 + gcc/config/i386/i386.md | 26 +++---- 4 files changed, 167 insertions(+), 29 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b79a4862224..24d5cd1bfff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +Tue Jan 28 12:15:13 CET 2003 Jan Hubicka + + * i386.c (ix86_carry_flag_operator): New predicate. + (fcmov_operator): Fix whitespace. + (ix86_expand_carry_flag_compare): Deal with floating point. + (ix86_expand_int_movcc): Deal with fp; update insn expansion + (ix86_expand_int_addcc): Likewise. + (ix86_expand_strlensi_unroll_1): likewsie. + * i386.h (PREDICATE_CODES): Add ix86_carry_flag_operator. + * i386.md (add?i_carry_rex64): Use new predicate. + (sub?i3_carry_rex64): Likewise. + (x86_mov?icc_0_m1*): Likewise. + 2003-01-28 Andreas Schwab * cfgloopmanip.c (create_preheader): Initialize src to avoid diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 0f0a3a76282..bb8091dfcb4 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3797,6 +3797,40 @@ ix86_comparison_operator (op, mode) } } +/* Return 1 if OP is a valid comparison operator testing carry flag + to be set. */ +int +ix86_carry_flag_operator (op, mode) + register rtx op; + enum machine_mode mode; +{ + enum machine_mode inmode; + enum rtx_code code = GET_CODE (op); + + if (mode != VOIDmode && GET_MODE (op) != mode) + return 0; + if (GET_RTX_CLASS (code) != '<') + return 0; + inmode = GET_MODE (XEXP (op, 0)); + if (GET_CODE (XEXP (op, 0)) != REG + || REGNO (XEXP (op, 0)) != 17 + || XEXP (op, 1) != const0_rtx) + return 0; + + if (inmode == CCFPmode || inmode == CCFPUmode) + { + enum rtx_code second_code, bypass_code; + + ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); + if (bypass_code != NIL || second_code != NIL) + return 0; + code = ix86_fp_compare_code_to_integer (code); + } + else if (inmode != CCmode) + return 0; + return code == LTU; +} + /* Return 1 if OP is a comparison operator that can be issued by fcmov. */ int @@ -3806,6 +3840,7 @@ fcmov_comparison_operator (op, mode) { enum machine_mode inmode; enum rtx_code code = GET_CODE (op); + if (mode != VOIDmode && GET_MODE (op) != mode) return 0; if (GET_RTX_CLASS (code) != '<') @@ -3814,6 +3849,7 @@ fcmov_comparison_operator (op, mode) if (inmode == CCFPmode || inmode == CCFPUmode) { enum rtx_code second_code, bypass_code; + ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code); if (bypass_code != NIL || second_code != NIL) return 0; @@ -9316,7 +9352,51 @@ ix86_expand_carry_flag_compare (code, op0, op1, pop) /* Do not handle DImode compares that go trought special path. Also we can't deal with FP compares yet. This is possible to add. */ - if ((mode == DImode && !TARGET_64BIT) || !INTEGRAL_MODE_P (mode)) + if ((mode == DImode && !TARGET_64BIT)) + return false; + if (FLOAT_MODE_P (mode)) + { + rtx second_test = NULL, bypass_test = NULL; + rtx compare_op, compare_seq; + + /* Shortcut: following common codes never translate into carry flag compares. */ + if (code == EQ || code == NE || code == UNEQ || code == LTGT + || code == ORDERED || code == UNORDERED) + return false; + + /* These comparisons require zero flag; swap operands so they won't. */ + if ((code == GT || code == UNLE || code == LE || code == UNGT) + && !TARGET_IEEE_FP) + { + rtx tmp = op0; + op0 = op1; + op1 = tmp; + code = swap_condition (code); + } + + /* Try to expand the comparsion and verify that we end up with carry flag + based comparsion. This is fails to be true only when we decide to expand + comparsion using arithmetic that is not too common scenario. */ + start_sequence (); + compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX, + &second_test, &bypass_test); + compare_seq = get_insns (); + end_sequence (); + + if (second_test || bypass_test) + return false; + if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode + || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode) + code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op)); + else + code = GET_CODE (compare_op); + if (code != LTU && code != GEU) + return false; + emit_insn (compare_seq); + *pop = compare_op; + return true; + } + if (!INTEGRAL_MODE_P (mode)) return false; switch (code) { @@ -9428,8 +9508,17 @@ ix86_expand_int_movcc (operands) if (!sign_bit_compare_p) { + bool fpcmp = false; + compare_code = GET_CODE (compare_op); + if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode + || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode) + { + fpcmp = true; + compare_code = ix86_fp_compare_code_to_integer (compare_code); + } + /* To simplify rest of code, restrict to the GEU case. */ if (compare_code == LTU) { @@ -9439,6 +9528,15 @@ ix86_expand_int_movcc (operands) compare_code = reverse_condition (compare_code); code = reverse_condition (code); } + else + { + if (fpcmp) + PUT_CODE (compare_op, + reverse_condition_maybe_unordered + (GET_CODE (compare_op))); + else + PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op))); + } diff = ct - cf; if (reg_overlap_mentioned_p (out, ix86_compare_op0) @@ -9446,9 +9544,9 @@ ix86_expand_int_movcc (operands) tmp = gen_reg_rtx (mode); if (mode == DImode) - emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp)); + emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp, compare_op)); else - emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp))); + emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp), compare_op)); } else { @@ -10051,6 +10149,9 @@ ix86_expand_int_addcc (operands) enum rtx_code code = GET_CODE (operands[1]); rtx compare_op; rtx val = const0_rtx; + bool fpcmp = false; + rtx pat, clob; + enum machine_mode mode = GET_MODE (operands[0]); if (operands[3] != const1_rtx && operands[3] != constm1_rtx) @@ -10058,23 +10159,43 @@ ix86_expand_int_addcc (operands) if (!ix86_expand_carry_flag_compare (code, ix86_compare_op0, ix86_compare_op1, &compare_op)) return 0; - if (GET_CODE (compare_op) != LTU) - val = constm1_rtx; - if ((GET_CODE (compare_op) == LTU) == (operands[3] == constm1_rtx)) + code = GET_CODE (compare_op); + + if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode + || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode) + { + fpcmp = true; + code = ix86_fp_compare_code_to_integer (code); + } + + if (code != LTU) + { + val = constm1_rtx; + if (fpcmp) + PUT_CODE (compare_op, + reverse_condition_maybe_unordered + (GET_CODE (compare_op))); + else + PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op))); + } + PUT_MODE (compare_op, mode); + + /* Construct either adc or sbb insn. */ + if ((code == LTU) == (operands[3] == constm1_rtx)) { switch (GET_MODE (operands[0])) { case QImode: - emit_insn (gen_subqi3_carry (operands[0], operands[2], val)); + emit_insn (gen_subqi3_carry (operands[0], operands[2], val, compare_op)); break; case HImode: - emit_insn (gen_subhi3_carry (operands[0], operands[2], val)); + emit_insn (gen_subhi3_carry (operands[0], operands[2], val, compare_op)); break; case SImode: - emit_insn (gen_subsi3_carry (operands[0], operands[2], val)); + emit_insn (gen_subsi3_carry (operands[0], operands[2], val, compare_op)); break; case DImode: - emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val)); + emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val, compare_op)); break; default: abort (); @@ -10085,16 +10206,16 @@ ix86_expand_int_addcc (operands) switch (GET_MODE (operands[0])) { case QImode: - emit_insn (gen_addqi3_carry (operands[0], operands[2], val)); + emit_insn (gen_addqi3_carry (operands[0], operands[2], val, compare_op)); break; case HImode: - emit_insn (gen_addhi3_carry (operands[0], operands[2], val)); + emit_insn (gen_addhi3_carry (operands[0], operands[2], val, compare_op)); break; case SImode: - emit_insn (gen_addsi3_carry (operands[0], operands[2], val)); + emit_insn (gen_addsi3_carry (operands[0], operands[2], val, compare_op)); break; case DImode: - emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val)); + emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val, compare_op)); break; default: abort (); @@ -11181,6 +11302,7 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx) rtx mem; rtx tmpreg = gen_reg_rtx (SImode); rtx scratch = gen_reg_rtx (SImode); + rtx cmp; align = 0; if (GET_CODE (align_rtx) == CONST_INT) @@ -11339,10 +11461,11 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx) /* Avoid branch in fixing the byte. */ tmpreg = gen_lowpart (QImode, tmpreg); emit_insn (gen_addqi3_cc (tmpreg, tmpreg, tmpreg)); + cmp = gen_rtx_LTU (Pmode, gen_rtx_REG (CCmode, 17), const0_rtx); if (TARGET_64BIT) - emit_insn (gen_subdi3_carry_rex64 (out, out, GEN_INT (3))); + emit_insn (gen_subdi3_carry_rex64 (out, out, GEN_INT (3), cmp)); else - emit_insn (gen_subsi3_carry (out, out, GEN_INT (3))); + emit_insn (gen_subsi3_carry (out, out, GEN_INT (3), cmp)); emit_label (end_0_label); } diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 32eb8ad6f6f..6543ab018a4 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -3048,6 +3048,8 @@ do { \ {"ix86_comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, \ GTU, UNORDERED, ORDERED, UNLE, UNLT, \ UNGE, UNGT, LTGT, UNEQ }}, \ + {"ix86_carry_flag_operator", {LTU, LT, UNLT, GT, UNGT, LE, UNLE, \ + GE, UNGE, LTGT, UNEQ}}, \ {"cmp_fp_expander_operand", {CONST_DOUBLE, SUBREG, REG, MEM}}, \ {"ext_register_operand", {SUBREG, REG}}, \ {"binary_fp_operator", {PLUS, MINUS, MULT, DIV}}, \ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b17579fbf8a..e58f3e07d34 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -4969,7 +4969,7 @@ (define_insn "adddi3_carry_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0)) + (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") (match_operand:DI 1 "nonimmediate_operand" "%0,0")) (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) (clobber (reg:CC 17))] @@ -4994,7 +4994,7 @@ (define_insn "addqi3_carry" [(set (match_operand:QI 0 "nonimmediate_operand" "=rm,r") - (plus:QI (plus:QI (ltu:QI (reg:CC 17) (const_int 0)) + (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") (match_operand:QI 1 "nonimmediate_operand" "%0,0")) (match_operand:QI 2 "general_operand" "ri,rm"))) (clobber (reg:CC 17))] @@ -5007,7 +5007,7 @@ (define_insn "addhi3_carry" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (plus:HI (plus:HI (ltu:HI (reg:CC 17) (const_int 0)) + (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") (match_operand:HI 1 "nonimmediate_operand" "%0,0")) (match_operand:HI 2 "general_operand" "ri,rm"))) (clobber (reg:CC 17))] @@ -5020,7 +5020,7 @@ (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)) + (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 1 "nonimmediate_operand" "%0,0")) (match_operand:SI 2 "general_operand" "ri,rm"))) (clobber (reg:CC 17))] @@ -5034,7 +5034,7 @@ (define_insn "*addsi3_carry_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 1 "nonimmediate_operand" "%0")) (match_operand:SI 2 "general_operand" "rim")))) (clobber (reg:CC 17))] @@ -6649,7 +6649,7 @@ (define_insn "subdi3_carry_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (plus:DI (ltu:DI (reg:CC 17) (const_int 0)) + (plus:DI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:DI 2 "x86_64_general_operand" "re,rm")))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" @@ -6698,7 +6698,7 @@ (define_insn "subqi3_carry" [(set (match_operand:QI 0 "nonimmediate_operand" "=rm,r") (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (plus:QI (ltu:QI (reg:CC 17) (const_int 0)) + (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") (match_operand:QI 2 "general_operand" "ri,rm")))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (MINUS, QImode, operands)" @@ -6711,7 +6711,7 @@ (define_insn "subhi3_carry" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (plus:HI (ltu:HI (reg:CC 17) (const_int 0)) + (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") (match_operand:HI 2 "general_operand" "ri,rm")))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (MINUS, HImode, operands)" @@ -6724,7 +6724,7 @@ (define_insn "subsi3_carry" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 2 "general_operand" "ri,rm")))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (MINUS, SImode, operands)" @@ -6738,7 +6738,7 @@ [(set (match_operand:DI 0 "register_operand" "=rm,r") (zero_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "0,0") - (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 2 "general_operand" "ri,rm"))))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" @@ -16289,7 +16289,7 @@ (define_insn "x86_movdicc_0_m1_rex64" [(set (match_operand:DI 0 "register_operand" "=r") - (if_then_else:DI (ltu (reg:CC 17) (const_int 0)) + (if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "") (const_int -1) (const_int 0))) (clobber (reg:CC 17))] @@ -16304,7 +16304,7 @@ (set_attr "mode" "DI") (set_attr "length_immediate" "0")]) -(define_insn "*movdicc_c_rex64" +(define_insn "movdicc_c_rex64" [(set (match_operand:DI 0 "register_operand" "=r,r") (if_then_else:DI (match_operator 1 "ix86_comparison_operator" [(reg 17) (const_int 0)]) @@ -16332,7 +16332,7 @@ (define_insn "x86_movsicc_0_m1" [(set (match_operand:SI 0 "register_operand" "=r") - (if_then_else:SI (ltu (reg:CC 17) (const_int 0)) + (if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "") (const_int -1) (const_int 0))) (clobber (reg:CC 17))] -- 2.30.2