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
This commit is contained in:
Jan Hubicka 2003-01-28 12:16:32 +01:00 committed by Jan Hubicka
parent 32214c3253
commit e6e81735cf
4 changed files with 167 additions and 29 deletions

View File

@ -1,3 +1,16 @@
Tue Jan 28 12:15:13 CET 2003 Jan Hubicka <jh@suse.cz>
* 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 <schwab@suse.de>
* cfgloopmanip.c (create_preheader): Initialize src to avoid

View File

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

View File

@ -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}}, \

View File

@ -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))]