aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@freesoft.cz>1999-10-01 03:22:24 +0200
committerRichard Henderson <rth@gcc.gnu.org>1999-09-30 18:22:24 -0700
commit36583feac4bd37503c798dc3d32652258ba14d76 (patch)
tree1a201cfa5751bcf37231d07b076c2ada52393145 /gcc
parentca285e0794fc71079acf77d743b44f4a7a5aa12a (diff)
downloadgcc-36583feac4bd37503c798dc3d32652258ba14d76.zip
gcc-36583feac4bd37503c798dc3d32652258ba14d76.tar.gz
gcc-36583feac4bd37503c798dc3d32652258ba14d76.tar.bz2
Jan Hubicka <hubicka@freesoft.cz>
* i386.c (ix86_expand_int_movcc): Convert LEU and GTU comparisons to LTU and GEU. Handle more cases using sbb. From-SVN: r29743
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/i386/i386.c98
2 files changed, 85 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b38ff43..2a61039 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+Thu Sep 30 18:21:30 1999 Jan Hubicka <hubicka@freesoft.cz>
+
+ * i386.c (ix86_expand_int_movcc): Convert LEU and GTU comparisons
+ to LTU and GEU. Handle more cases using sbb.
+
Thu Sep 30 18:18:39 1999 Jan Hubicka <hubicka@freesoft.cz>
* i386.md (truncatexfdf splitters): Do not use subreg.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f654db6..34a68a7 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -4288,6 +4288,23 @@ ix86_expand_int_movcc (operands)
enum rtx_code code = GET_CODE (operands[1]), compare_code;
rtx compare_seq, compare_op;
+ /* 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
+ GEU by altering the integer. */
+
+ if ((code == LEU || code == GTU)
+ && GET_CODE (ix86_compare_op1) == CONST_INT
+ && GET_MODE (operands[0]) != HImode
+ && (unsigned int)INTVAL (ix86_compare_op1) != 0xffffffff
+ && GET_CODE (operands[2]) == CONST_INT
+ && GET_CODE (operands[3]) == CONST_INT)
+ {
+ if (code == LEU)
+ code = LTU;
+ else
+ code = GEU;
+ ix86_compare_op1 = GEN_INT (INTVAL (ix86_compare_op1) + 1);
+ }
start_sequence ();
compare_op = ix86_expand_compare (code, code == EQ || code == NE);
compare_seq = gen_sequence ();
@@ -4307,27 +4324,23 @@ ix86_expand_int_movcc (operands)
HOST_WIDE_INT cf = INTVAL (operands[3]);
HOST_WIDE_INT diff;
- /* Special cases: */
- if (ct == 0)
+ if (compare_code == LTU || compare_code == GEU)
{
- ct = cf;
- cf = 0;
- compare_code = reverse_condition (compare_code);
- code = reverse_condition (code);
- }
- if (cf == 0 && ct == -1 && (compare_code == LTU || compare_code == GEU))
- {
- /*
- * xorl dest,dest
- * cmpl op0,op1
- * sbbl dest,dest
- *
- * Size 6.
- */
/* Detect overlap between destination and compare sources. */
rtx tmp = out;
+ /* To simplify rest of code, restrict to the GEU case. */
+ if (compare_code == LTU)
+ {
+ int tmp = ct;
+ ct = cf;
+ cf = tmp;
+ compare_code = reverse_condition (compare_code);
+ code = reverse_condition (code);
+ }
+ diff = ct - cf;
+
if (reg_overlap_mentioned_p (out, ix86_compare_op0)
|| reg_overlap_mentioned_p (out, ix86_compare_op0))
tmp = gen_reg_rtx (SImode);
@@ -4335,8 +4348,57 @@ ix86_expand_int_movcc (operands)
emit_insn (compare_seq);
emit_insn (gen_x86_movsicc_0_m1 (tmp));
- if (compare_code == GEU)
- emit_insn (gen_one_cmplsi2 (tmp, tmp));
+ if (diff == 1)
+ {
+ /*
+ * cmpl op0,op1
+ * sbbl dest,dest
+ * [addl dest, ct]
+ *
+ * Size 5 - 8.
+ */
+ if (ct)
+ emit_insn (gen_addsi3 (out, out, GEN_INT (ct)));
+ }
+ else if (cf == -1)
+ {
+ /*
+ * cmpl op0,op1
+ * sbbl dest,dest
+ * orl $ct, dest
+ *
+ * Size 8.
+ */
+ emit_insn (gen_iorsi3 (out, out, GEN_INT (ct)));
+ }
+ else if (diff == -1 && ct)
+ {
+ /*
+ * cmpl op0,op1
+ * sbbl dest,dest
+ * xorl $-1, dest
+ * [addl dest, cf]
+ *
+ * Size 8 - 11.
+ */
+ emit_insn (gen_one_cmplsi2 (tmp, tmp));
+ if (cf)
+ emit_insn (gen_addsi3 (out, out, GEN_INT (cf)));
+ }
+ else
+ {
+ /*
+ * cmpl op0,op1
+ * sbbl dest,dest
+ * andl cf - ct, dest
+ * [addl dest, ct]
+ *
+ * Size 8 - 11.
+ */
+ emit_insn (gen_andsi3 (out, out, GEN_INT (cf - ct)));
+ if (ct)
+ emit_insn (gen_addsi3 (out, out, GEN_INT (ct)));
+ }
if (tmp != out)
emit_move_insn (out, tmp);