aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-01-14 09:14:03 +0000
committerJan Hubicka <hubicka@gcc.gnu.org>2001-01-14 09:14:03 +0000
commita1b8572cac7c96128e10c2e93f8c7ef71d3d6d5d (patch)
treeef4ee7257a074a8c3351697865670bbd0a49b8bd
parent264ddbaa683da65a254b012d178149830339d502 (diff)
downloadgcc-a1b8572cac7c96128e10c2e93f8c7ef71d3d6d5d.zip
gcc-a1b8572cac7c96128e10c2e93f8c7ef71d3d6d5d.tar.gz
gcc-a1b8572cac7c96128e10c2e93f8c7ef71d3d6d5d.tar.bz2
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
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c106
-rw-r--r--gcc/config/i386/i386.md48
4 files changed, 155 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a07f54b..7d82db9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+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>
* config/vax/vax.md: Use nonimmediate_operand instead of
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 3bf2ea8..cd44c4b 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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,
rtx[]));
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 void ix86_expand_branch PARAMS ((enum rtx_code, rtx));
extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index eb8a852..6508478 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -5161,16 +5161,22 @@ ix86_expand_fp_compare (code, op0, op1, scratch, second_test, bypass_test)
}
rtx
-ix86_expand_compare (code)
+ix86_expand_compare (code, second_test, bypass_test)
enum rtx_code code;
+ rtx *second_test, *bypass_test;
{
rtx op0, op1, ret;
op0 = ix86_compare_op0;
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)
ret = ix86_expand_fp_compare (code, op0, op1, gen_reg_rtx (HImode),
- NULL, NULL);
+ second_test, bypass_test);
else
ret = ix86_expand_int_compare (code, op0, op1);
@@ -5189,7 +5195,7 @@ ix86_expand_branch (code, label)
case QImode:
case HImode:
case SImode:
- tmp = ix86_expand_compare (code);
+ tmp = ix86_expand_compare (code, NULL, NULL);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx);
@@ -5404,7 +5410,8 @@ ix86_expand_setcc (code, dest)
enum rtx_code code;
rtx dest;
{
- rtx ret, tmp;
+ rtx ret, tmp, tmpreg;
+ rtx second_test, bypass_test;
int type;
if (GET_MODE (ix86_compare_op0) == DImode)
@@ -5430,13 +5437,15 @@ ix86_expand_setcc (code, dest)
if (type == 0)
emit_move_insn (dest, const0_rtx);
- ret = ix86_expand_compare (code);
+ ret = ix86_expand_compare (code, &second_test, &bypass_test);
PUT_MODE (ret, QImode);
tmp = dest;
+ tmpreg = dest;
if (type == 0)
{
tmp = gen_lowpart (QImode, dest);
+ tmpreg = tmp;
tmp = gen_rtx_STRICT_LOW_PART (VOIDmode, tmp);
}
else if (type == 1)
@@ -5445,9 +5454,31 @@ ix86_expand_setcc (code, dest)
tmp = gen_reg_rtx (QImode);
else
tmp = gen_lowpart (QImode, dest);
+ tmpreg = tmp;
}
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)
{
@@ -5469,6 +5500,7 @@ ix86_expand_int_movcc (operands)
{
enum rtx_code code = GET_CODE (operands[1]), compare_code;
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.
In case comparsion is done with immediate, we can convert it to LTU or
@@ -5489,7 +5521,7 @@ ix86_expand_int_movcc (operands)
}
start_sequence ();
- compare_op = ix86_expand_compare (code);
+ compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
compare_seq = gen_sequence ();
end_sequence ();
@@ -5507,7 +5539,8 @@ ix86_expand_int_movcc (operands)
HOST_WIDE_INT cf = INTVAL (operands[3]);
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. */
@@ -5796,11 +5829,36 @@ ix86_expand_int_movcc (operands)
if (! nonimmediate_operand (operands[3], GET_MODE (operands[0])))
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 (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
compare_op, operands[2],
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 */
}
@@ -5811,25 +5869,39 @@ ix86_expand_fp_movcc (operands)
{
enum rtx_code code;
rtx tmp;
- rtx compare_op;
+ rtx compare_op, second_test, bypass_test;
/* The floating point conditional move instructions don't directly
support conditions resulting from a signed integer comparison. */
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
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);
ix86_expand_setcc (code, tmp);
code = NE;
ix86_compare_op0 = tmp;
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],
@@ -5837,6 +5909,18 @@ ix86_expand_fp_movcc (operands)
compare_op,
operands[2],
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;
}
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 12d7e39..5e53f14 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -6263,6 +6263,16 @@
[(set_attr "type" "alu")
(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"
[(set (reg 17)
(compare (and:QI
@@ -6280,6 +6290,19 @@
[(set_attr "type" "alu")
(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
;; operand to zero_extend in andqi_ext_1. It was checking explicitly
;; for a QImode operand, which of course failed.
@@ -6479,6 +6502,16 @@
or{b}\\t{%2, %0|%0, %2}
or{l}\\t{%k2, %k0|%k0, %k2}"
[(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")])
(define_insn "*iorqi_2"
@@ -6494,6 +6527,18 @@
[(set_attr "type" "alu")
(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"
[(set (reg 17)
(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
@@ -12496,7 +12541,8 @@
"
{
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]));
DONE;
}")