Commit a1b8572c by Jan Hubicka Committed by Jan Hubicka

i386.c (ix86_expand_compare): Add bypass_test and second_test parameters.


	* i386.c (ix86_expand_compare): Add bypass_test and second_test
	parameters.
	(ix86_expand_branch): Update.
	(ix86_expand_setcc): Update to handle multiple test conditions.
	(expand_int_movcc): Likewise.
	(expand_fp_movcc): Likewise.
	* i386-protos.h (ix86_expand_compare): New.
	* i386.md (andqi_?_slp, orqi_?_slp): New.
	(conditional trap expander): Update call to ix86_expand_compare.

From-SVN: r39005
parent 264ddbaa
Sun Jan 14 10:09:48 MET 2001 Jan hubicka <jh@suse.cz>
* i386.c (ix86_expand_compare): Add bypass_test and second_test
parameters.
(ix86_expand_branch): Update.
(ix86_expand_setcc): Update to handle multiple test conditions.
(expand_int_movcc): Likewise.
(expand_fp_movcc): Likewise.
* i386-protos.h (ix86_expand_compare): New.
* i386.md (andqi_?_slp, orqi_?_slp): New.
(conditional trap expander): Update call to ix86_expand_compare.
2001-01-14 Richard Henderson <rth@redhat.com> 2001-01-14 Richard Henderson <rth@redhat.com>
* config/vax/vax.md: Use nonimmediate_operand instead of * config/vax/vax.md: Use nonimmediate_operand instead of
......
...@@ -101,7 +101,7 @@ extern void ix86_expand_unary_operator PARAMS ((enum rtx_code, enum machine_mode ...@@ -101,7 +101,7 @@ extern void ix86_expand_unary_operator PARAMS ((enum rtx_code, enum machine_mode
extern int ix86_unary_operator_ok PARAMS ((enum rtx_code, enum machine_mode, extern int ix86_unary_operator_ok PARAMS ((enum rtx_code, enum machine_mode,
rtx[])); rtx[]));
extern int ix86_match_ccmode PARAMS ((rtx, enum machine_mode)); extern int ix86_match_ccmode PARAMS ((rtx, enum machine_mode));
extern rtx ix86_expand_compare PARAMS ((enum rtx_code)); extern rtx ix86_expand_compare PARAMS ((enum rtx_code, rtx *, rtx *));
extern int ix86_use_fcomi_compare PARAMS ((enum rtx_code)); extern int ix86_use_fcomi_compare PARAMS ((enum rtx_code));
extern void ix86_expand_branch PARAMS ((enum rtx_code, rtx)); extern void ix86_expand_branch PARAMS ((enum rtx_code, rtx));
extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx)); extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
......
...@@ -5161,16 +5161,22 @@ ix86_expand_fp_compare (code, op0, op1, scratch, second_test, bypass_test) ...@@ -5161,16 +5161,22 @@ ix86_expand_fp_compare (code, op0, op1, scratch, second_test, bypass_test)
} }
rtx rtx
ix86_expand_compare (code) ix86_expand_compare (code, second_test, bypass_test)
enum rtx_code code; enum rtx_code code;
rtx *second_test, *bypass_test;
{ {
rtx op0, op1, ret; rtx op0, op1, ret;
op0 = ix86_compare_op0; op0 = ix86_compare_op0;
op1 = ix86_compare_op1; op1 = ix86_compare_op1;
if (second_test)
*second_test = NULL_RTX;
if (bypass_test)
*bypass_test = NULL_RTX;
if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
ret = ix86_expand_fp_compare (code, op0, op1, gen_reg_rtx (HImode), ret = ix86_expand_fp_compare (code, op0, op1, gen_reg_rtx (HImode),
NULL, NULL); second_test, bypass_test);
else else
ret = ix86_expand_int_compare (code, op0, op1); ret = ix86_expand_int_compare (code, op0, op1);
...@@ -5189,7 +5195,7 @@ ix86_expand_branch (code, label) ...@@ -5189,7 +5195,7 @@ ix86_expand_branch (code, label)
case QImode: case QImode:
case HImode: case HImode:
case SImode: case SImode:
tmp = ix86_expand_compare (code); tmp = ix86_expand_compare (code, NULL, NULL);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label), gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx); pc_rtx);
...@@ -5404,7 +5410,8 @@ ix86_expand_setcc (code, dest) ...@@ -5404,7 +5410,8 @@ ix86_expand_setcc (code, dest)
enum rtx_code code; enum rtx_code code;
rtx dest; rtx dest;
{ {
rtx ret, tmp; rtx ret, tmp, tmpreg;
rtx second_test, bypass_test;
int type; int type;
if (GET_MODE (ix86_compare_op0) == DImode) if (GET_MODE (ix86_compare_op0) == DImode)
...@@ -5430,13 +5437,15 @@ ix86_expand_setcc (code, dest) ...@@ -5430,13 +5437,15 @@ ix86_expand_setcc (code, dest)
if (type == 0) if (type == 0)
emit_move_insn (dest, const0_rtx); emit_move_insn (dest, const0_rtx);
ret = ix86_expand_compare (code); ret = ix86_expand_compare (code, &second_test, &bypass_test);
PUT_MODE (ret, QImode); PUT_MODE (ret, QImode);
tmp = dest; tmp = dest;
tmpreg = dest;
if (type == 0) if (type == 0)
{ {
tmp = gen_lowpart (QImode, dest); tmp = gen_lowpart (QImode, dest);
tmpreg = tmp;
tmp = gen_rtx_STRICT_LOW_PART (VOIDmode, tmp); tmp = gen_rtx_STRICT_LOW_PART (VOIDmode, tmp);
} }
else if (type == 1) else if (type == 1)
...@@ -5445,9 +5454,31 @@ ix86_expand_setcc (code, dest) ...@@ -5445,9 +5454,31 @@ ix86_expand_setcc (code, dest)
tmp = gen_reg_rtx (QImode); tmp = gen_reg_rtx (QImode);
else else
tmp = gen_lowpart (QImode, dest); tmp = gen_lowpart (QImode, dest);
tmpreg = tmp;
} }
emit_insn (gen_rtx_SET (VOIDmode, tmp, ret)); emit_insn (gen_rtx_SET (VOIDmode, tmp, ret));
if (bypass_test || second_test)
{
rtx test = second_test;
int bypass = 0;
rtx tmp2 = gen_reg_rtx (QImode);
if (bypass_test)
{
if (second_test)
abort();
test = bypass_test;
bypass = 1;
PUT_CODE (test, reverse_condition_maybe_unordered (GET_CODE (test)));
}
PUT_MODE (test, QImode);
emit_insn (gen_rtx_SET (VOIDmode, tmp2, test));
if (bypass)
emit_insn (gen_andqi3 (tmp, tmpreg, tmp2));
else
emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2));
}
if (type == 1) if (type == 1)
{ {
...@@ -5469,6 +5500,7 @@ ix86_expand_int_movcc (operands) ...@@ -5469,6 +5500,7 @@ ix86_expand_int_movcc (operands)
{ {
enum rtx_code code = GET_CODE (operands[1]), compare_code; enum rtx_code code = GET_CODE (operands[1]), compare_code;
rtx compare_seq, compare_op; rtx compare_seq, compare_op;
rtx second_test, bypass_test;
/* When the compare code is not LTU or GEU, we can not use sbbl case. /* When the compare code is not LTU or GEU, we can not use sbbl case.
In case comparsion is done with immediate, we can convert it to LTU or In case comparsion is done with immediate, we can convert it to LTU or
...@@ -5489,7 +5521,7 @@ ix86_expand_int_movcc (operands) ...@@ -5489,7 +5521,7 @@ ix86_expand_int_movcc (operands)
} }
start_sequence (); start_sequence ();
compare_op = ix86_expand_compare (code); compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
compare_seq = gen_sequence (); compare_seq = gen_sequence ();
end_sequence (); end_sequence ();
...@@ -5507,7 +5539,8 @@ ix86_expand_int_movcc (operands) ...@@ -5507,7 +5539,8 @@ ix86_expand_int_movcc (operands)
HOST_WIDE_INT cf = INTVAL (operands[3]); HOST_WIDE_INT cf = INTVAL (operands[3]);
HOST_WIDE_INT diff; HOST_WIDE_INT diff;
if (compare_code == LTU || compare_code == GEU) if ((compare_code == LTU || compare_code == GEU)
&& !second_test && !bypass_test)
{ {
/* Detect overlap between destination and compare sources. */ /* Detect overlap between destination and compare sources. */
...@@ -5796,11 +5829,36 @@ ix86_expand_int_movcc (operands) ...@@ -5796,11 +5829,36 @@ ix86_expand_int_movcc (operands)
if (! nonimmediate_operand (operands[3], GET_MODE (operands[0]))) if (! nonimmediate_operand (operands[3], GET_MODE (operands[0])))
operands[3] = force_reg (GET_MODE (operands[0]), operands[3]); operands[3] = force_reg (GET_MODE (operands[0]), operands[3]);
if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
{
rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
emit_move_insn (tmp, operands[3]);
operands[3] = tmp;
}
if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
{
rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
emit_move_insn (tmp, operands[2]);
operands[2] = tmp;
}
emit_insn (compare_seq); emit_insn (compare_seq);
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
compare_op, operands[2], compare_op, operands[2],
operands[3]))); operands[3])));
if (bypass_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
bypass_test,
operands[3],
operands[0])));
if (second_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
second_test,
operands[2],
operands[0])));
return 1; /* DONE */ return 1; /* DONE */
} }
...@@ -5811,25 +5869,39 @@ ix86_expand_fp_movcc (operands) ...@@ -5811,25 +5869,39 @@ ix86_expand_fp_movcc (operands)
{ {
enum rtx_code code; enum rtx_code code;
rtx tmp; rtx tmp;
rtx compare_op; rtx compare_op, second_test, bypass_test;
/* The floating point conditional move instructions don't directly /* The floating point conditional move instructions don't directly
support conditions resulting from a signed integer comparison. */ support conditions resulting from a signed integer comparison. */
code = GET_CODE (operands[1]); code = GET_CODE (operands[1]);
compare_op = ix86_expand_compare (code); compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
/* The floating point conditional move instructions don't directly /* The floating point conditional move instructions don't directly
support signed integer comparisons. */ support signed integer comparisons. */
if (!fcmov_comparison_operator (compare_op, GET_MODE (XEXP (compare_op, 0)))) if (!fcmov_comparison_operator (compare_op, VOIDmode))
{ {
if (second_test != NULL || bypass_test != NULL)
abort();
tmp = gen_reg_rtx (QImode); tmp = gen_reg_rtx (QImode);
ix86_expand_setcc (code, tmp); ix86_expand_setcc (code, tmp);
code = NE; code = NE;
ix86_compare_op0 = tmp; ix86_compare_op0 = tmp;
ix86_compare_op1 = const0_rtx; ix86_compare_op1 = const0_rtx;
compare_op = ix86_expand_compare (code); compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
}
if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
{
tmp = gen_reg_rtx (GET_MODE (operands[0]));
emit_move_insn (tmp, operands[3]);
operands[3] = tmp;
}
if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
{
tmp = gen_reg_rtx (GET_MODE (operands[0]));
emit_move_insn (tmp, operands[2]);
operands[2] = tmp;
} }
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
...@@ -5837,6 +5909,18 @@ ix86_expand_fp_movcc (operands) ...@@ -5837,6 +5909,18 @@ ix86_expand_fp_movcc (operands)
compare_op, compare_op,
operands[2], operands[2],
operands[3]))); operands[3])));
if (bypass_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
bypass_test,
operands[3],
operands[0])));
if (second_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
second_test,
operands[2],
operands[0])));
return 1; return 1;
} }
......
...@@ -6263,6 +6263,16 @@ ...@@ -6263,6 +6263,16 @@
[(set_attr "type" "alu") [(set_attr "type" "alu")
(set_attr "mode" "QI,QI,SI")]) (set_attr "mode" "QI,QI,SI")])
(define_insn "*andqi_1_slp"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
(and:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qi,qmi")))
(clobber (reg:CC 17))]
""
"and{b}\\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
(define_insn "*andqi_2" (define_insn "*andqi_2"
[(set (reg 17) [(set (reg 17)
(compare (and:QI (compare (and:QI
...@@ -6280,6 +6290,19 @@ ...@@ -6280,6 +6290,19 @@
[(set_attr "type" "alu") [(set_attr "type" "alu")
(set_attr "mode" "QI,QI,SI")]) (set_attr "mode" "QI,QI,SI")])
(define_insn "*andqi_2_slp"
[(set (reg 17)
(compare (and:QI
(match_operand:QI 0 "nonimmediate_operand" "+q,qm")
(match_operand:QI 1 "nonimmediate_operand" "qmi,qi"))
(const_int 0)))
(set (strict_low_part (match_dup 0))
(and:QI (match_dup 0) (match_dup 1)))]
"ix86_match_ccmode (insn, CCNOmode)"
"and{b}\\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
;; ??? A bug in recog prevents it from recognizing a const_int as an ;; ??? A bug in recog prevents it from recognizing a const_int as an
;; operand to zero_extend in andqi_ext_1. It was checking explicitly ;; operand to zero_extend in andqi_ext_1. It was checking explicitly
;; for a QImode operand, which of course failed. ;; for a QImode operand, which of course failed.
...@@ -6479,6 +6502,16 @@ ...@@ -6479,6 +6502,16 @@
or{b}\\t{%2, %0|%0, %2} or{b}\\t{%2, %0|%0, %2}
or{l}\\t{%k2, %k0|%k0, %k2}" or{l}\\t{%k2, %k0|%k0, %k2}"
[(set_attr "type" "alu") [(set_attr "type" "alu")
(set_attr "mode" "QI,QI,SI")])
(define_insn "*iorqi_1_slp"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m"))
(ior:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qmi,qi")))
(clobber (reg:CC 17))]
""
"or{b}\\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")]) (set_attr "mode" "QI")])
(define_insn "*iorqi_2" (define_insn "*iorqi_2"
...@@ -6494,6 +6527,18 @@ ...@@ -6494,6 +6527,18 @@
[(set_attr "type" "alu") [(set_attr "type" "alu")
(set_attr "mode" "QI")]) (set_attr "mode" "QI")])
(define_insn "*iorqi_2_slp"
[(set (reg 17)
(compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
(match_operand:QI 1 "general_operand" "qim,qi"))
(const_int 0)))
(set (strict_low_part (match_dup 0))
(ior:QI (match_dup 0) (match_dup 1)))]
"ix86_match_ccmode (insn, CCNOmode)"
"or{b}\\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
(define_insn "*iorqi_3" (define_insn "*iorqi_3"
[(set (reg 17) [(set (reg 17)
(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0") (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
...@@ -12496,7 +12541,8 @@ ...@@ -12496,7 +12541,8 @@
" "
{ {
emit_insn (gen_rtx_TRAP_IF (VOIDmode, emit_insn (gen_rtx_TRAP_IF (VOIDmode,
ix86_expand_compare (GET_CODE (operands[0])), ix86_expand_compare (GET_CODE (operands[0]),
NULL_RTX, NULL_RTX),
operands[1])); operands[1]));
DONE; DONE;
}") }")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment