Commit 3a3677ff by Richard Henderson

genrecog.c (pred): Update comparison_operator for the unordered operators.

        * genrecog.c (pred): Update comparison_operator for the unordered
        operators.

        * config/i386/i386.c (no_comparison_operator): Disallow unordered
        operators.
        (fcmov_comparison_operator): Allow UNORDERED/ORDERED.
        (uno_comparison_operator): New.
        (put_condition_code): Handle UNORDERED/ORDERED.
        (unsigned_comparison): Likewise.
        (ix86_fp_compare_mode): Broken out of ix86_expand_fp_compare.
        (ix86_use_fcomi_compare, ix86_prepare_fp_compare_args): Likewise.
        (ix86_expand_fp_compare): Use them.  Take scratch as argument,
        update all callers.  Handle all 8 unordered operators.
        (ix86_expand_setcc): Lose the unordered argument, update all callers.
        (ix86_expand_branch): Likewise.  Don't fully expand fp branches.
        * config/i386/i386.h (PREDICATE_CODES): Update.
        * config/i386/i386-protos.h (ix86_expand_fp_compare): Declare.
        (ix86_expand_branch, ix86_expand_setcc): Update.
        * config/i386/i386.md (sunordered, sordered): New.
        (suneq, sunge, sungt, sunle, sunlt, sltgt): New.
        (bunordered, bordered): New.
        (buneq, bunge, bungt, bunle, bunlt, bltgt): New.
        (*fp_jcc_1, *fp_jcc_2, *fp_jcc_3, *fp_jcc_4): New.
        (*fp_jcc_5, *fp_jcc_6, and splitters): New.

From-SVN: r33046
parent 00fdafef
2000-04-09 Richard Henderson <rth@cygnus.com>
* genrecog.c (pred): Update comparison_operator for the unordered
operators.
* config/i386/i386.c (no_comparison_operator): Disallow unordered
operators.
(fcmov_comparison_operator): Allow UNORDERED/ORDERED.
(uno_comparison_operator): New.
(put_condition_code): Handle UNORDERED/ORDERED.
(unsigned_comparison): Likewise.
(ix86_fp_compare_mode): Broken out of ix86_expand_fp_compare.
(ix86_use_fcomi_compare, ix86_prepare_fp_compare_args): Likewise.
(ix86_expand_fp_compare): Use them. Take scratch as argument,
update all callers. Handle all 8 unordered operators.
(ix86_expand_setcc): Lose the unordered argument, update all callers.
(ix86_expand_branch): Likewise. Don't fully expand fp branches.
* config/i386/i386.h (PREDICATE_CODES): Update.
* config/i386/i386-protos.h (ix86_expand_fp_compare): Declare.
(ix86_expand_branch, ix86_expand_setcc): Update.
* config/i386/i386.md (sunordered, sordered): New.
(suneq, sunge, sungt, sunle, sunlt, sltgt): New.
(bunordered, bordered): New.
(buneq, bunge, bungt, bunle, bunlt, bltgt): New.
(*fp_jcc_1, *fp_jcc_2, *fp_jcc_3, *fp_jcc_4): New.
(*fp_jcc_5, *fp_jcc_6, and splitters): New.
2000-04-09 Philip Blundell <philb@gnu.org>
* config/arm/arm.h (ARM_NAME_ENCODING_LENGTHS): Strip `*' too.
......
......@@ -97,8 +97,9 @@ 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 void ix86_expand_branch PARAMS ((enum rtx_code, int, rtx));
extern int ix86_expand_setcc PARAMS ((enum rtx_code, int, rtx));
extern rtx ix86_expand_fp_compare PARAMS ((enum rtx_code, rtx, rtx, 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_int_movcc PARAMS ((rtx[]));
extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
extern int ix86_split_long_move PARAMS ((rtx[]));
......
......@@ -384,8 +384,11 @@ static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
int, int, FILE *));
static enum rtx_code unsigned_comparison PARAMS ((enum rtx_code code));
static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));
static rtx ix86_expand_fp_compare PARAMS ((enum rtx_code, rtx, rtx, int));
static rtx ix86_expand_compare PARAMS ((enum rtx_code, int));
static enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code));
static int ix86_use_fcomi_compare PARAMS ((enum rtx_code));
static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
rtx *, rtx *));
static rtx ix86_expand_compare PARAMS ((enum rtx_code));
static rtx gen_push PARAMS ((rtx));
static int memory_address_length PARAMS ((rtx addr));
static int ix86_flags_dependant PARAMS ((rtx, rtx, enum attr_type));
......@@ -1235,10 +1238,19 @@ no_comparison_operator (op, mode)
register rtx op;
enum machine_mode mode;
{
return ((mode == VOIDmode || GET_MODE (op) == mode)
&& GET_RTX_CLASS (GET_CODE (op)) == '<'
&& GET_CODE (op) != LE
&& GET_CODE (op) != GT);
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
switch (GET_CODE (op))
{
case EQ: case NE:
case LT: case GE:
case LEU: case LTU: case GEU: case GTU:
return 1;
default:
return 0;
}
}
/* Return 1 if OP is a comparison operator that can be issued by fcmov. */
......@@ -1248,9 +1260,42 @@ fcmov_comparison_operator (op, mode)
register rtx op;
enum machine_mode mode;
{
return ((mode == VOIDmode || GET_MODE (op) == mode)
&& GET_RTX_CLASS (GET_CODE (op)) == '<'
&& GET_CODE (op) == unsigned_condition (GET_CODE (op)));
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
switch (GET_CODE (op))
{
case EQ: case NE:
case LEU: case LTU: case GEU: case GTU:
case UNORDERED: case ORDERED:
return 1;
default:
return 0;
}
}
/* Return 1 if OP is any normal comparison operator plus {UN}ORDERED. */
int
uno_comparison_operator (op, mode)
register rtx op;
enum machine_mode mode;
{
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
switch (GET_CODE (op))
{
case EQ: case NE:
case LE: case LT: case GE: case GT:
case LEU: case LTU: case GEU: case GTU:
case UNORDERED: case ORDERED:
return 1;
default:
return 0;
}
}
/* Return 1 if OP is a binary operator that can be promoted to wider mode. */
......@@ -2970,6 +3015,12 @@ put_condition_code (code, mode, reverse, fp, file)
case LEU:
suffix = "be";
break;
case UNORDERED:
suffix = "p";
break;
case ORDERED:
suffix = "np";
break;
default:
abort ();
}
......@@ -4386,6 +4437,8 @@ unsigned_comparison (code)
case LTU:
case GEU:
case GTU:
case UNORDERED:
case ORDERED:
break;
default:
abort ();
......@@ -4416,36 +4469,80 @@ ix86_expand_int_compare (code, op0, op1)
return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
}
/* Generate insn patterns to do a floating point compare of OPERANDS.
If UNORDERED, allow for unordered compares. */
/* Figure out whether to use ordered or unordered fp comparisons.
Return the appropriate mode to use. */
static rtx
ix86_expand_fp_compare (code, op0, op1, unordered)
static enum machine_mode
ix86_fp_compare_mode (code)
enum rtx_code code;
rtx op0, op1;
int unordered;
{
enum machine_mode fpcmp_mode;
enum machine_mode intcmp_mode;
rtx tmp;
int unordered;
/* When not doing IEEE compliant compares, disable unordered. */
if (! TARGET_IEEE_FP)
switch (code)
{
case NE: case EQ:
/* When not doing IEEE compliant compares, fault on NaNs. */
unordered = (TARGET_IEEE_FP != 0);
break;
case LT: case LE: case GT: case GE:
unordered = 0;
fpcmp_mode = unordered ? CCFPUmode : CCFPmode;
break;
case UNORDERED: case ORDERED:
case UNEQ: case UNGE: case UNGT: case UNLE: case UNLT: case LTGT:
unordered = 1;
break;
default:
abort ();
}
/* ??? If we knew whether invalid-operand exceptions were masked,
we could rely on fcom to raise an exception and take care of
NaNs. But we don't. We could know this from c9x math bits. */
NaNs. But we don't. We could know this from c99 math pragmas. */
if (TARGET_IEEE_FP)
unordered = 1;
return unordered ? CCFPUmode : CCFPmode;
}
/* Return true if we should use an FCOMI instruction for this fp comparison. */
static int
ix86_use_fcomi_compare (code)
enum rtx_code code;
{
return (TARGET_CMOVE
&& (code == ORDERED || code == UNORDERED
/* All other unordered compares require checking
multiple sets of bits. */
|| ix86_fp_compare_mode (code) == CCFPmode));
}
/* Swap, force into registers, or otherwise massage the two operands
to a fp comparison. The operands are updated in place; the new
comparsion code is returned. */
static enum rtx_code
ix86_prepare_fp_compare_args (code, pop0, pop1)
enum rtx_code code;
rtx *pop0, *pop1;
{
enum machine_mode fpcmp_mode = ix86_fp_compare_mode (code);
rtx op0 = *pop0, op1 = *pop1;
enum machine_mode op_mode = GET_MODE (op0);
/* All of the unordered compare instructions only work on registers.
The same is true of the XFmode compare instructions. */
if (unordered || GET_MODE (op0) == XFmode)
The same is true of the XFmode compare instructions. The same is
true of the fcomi compare instructions. */
if (fpcmp_mode == CCFPUmode
|| op_mode == XFmode
|| ix86_use_fcomi_compare (code))
{
op0 = force_reg (GET_MODE (op0), op0);
op1 = force_reg (GET_MODE (op1), op1);
op0 = force_reg (op_mode, op0);
op1 = force_reg (op_mode, op1);
}
else
{
......@@ -4464,33 +4561,46 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
}
if (GET_CODE (op0) != REG)
op0 = force_reg (GET_MODE (op0), op0);
op0 = force_reg (op_mode, op0);
if (CONSTANT_P (op1))
{
if (standard_80387_constant_p (op1))
op1 = force_reg (GET_MODE (op1), op1);
op1 = force_reg (op_mode, op1);
else
op1 = validize_mem (force_const_mem (GET_MODE (op1), op1));
op1 = validize_mem (force_const_mem (op_mode, op1));
}
}
*pop0 = op0;
*pop1 = op1;
return code;
}
/* Generate insn patterns to do a floating point compare of OPERANDS. */
rtx
ix86_expand_fp_compare (code, op0, op1, scratch)
enum rtx_code code;
rtx op0, op1, scratch;
{
enum machine_mode fpcmp_mode, intcmp_mode;
rtx tmp;
fpcmp_mode = ix86_fp_compare_mode (code);
code = ix86_prepare_fp_compare_args (code, &op0, &op1);
/* %%% fcomi is probably always faster, even when dealing with memory,
since compare-and-branch would be three insns instead of four. */
if (TARGET_CMOVE && !unordered)
if (ix86_use_fcomi_compare (code))
{
if (GET_CODE (op0) != REG)
op0 = force_reg (GET_MODE (op0), op0);
if (GET_CODE (op1) != REG)
op1 = force_reg (GET_MODE (op1), op1);
tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG), tmp);
emit_insn (tmp);
/* The FP codes work out to act like unsigned. */
code = unsigned_comparison (code);
intcmp_mode = fpcmp_mode;
intcmp_mode = CCmode;
}
else
{
......@@ -4499,10 +4609,11 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
rtx tmp2;
tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9);
tmp = gen_reg_rtx (HImode);
emit_insn (gen_rtx_SET (VOIDmode, tmp, tmp2));
emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
if (! unordered)
if (fpcmp_mode == CCFPmode
|| code == ORDERED
|| code == UNORDERED)
{
/* We have two options here -- use sahf, or testing bits of ah
directly. On PPRO, they are equivalent, sahf being one byte
......@@ -4512,10 +4623,10 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
if (TARGET_USE_SAHF || optimize_size)
{
do_sahf:
emit_insn (gen_x86_sahf_1 (scratch));
/* The FP codes work out to act like unsigned. */
code = unsigned_comparison (code);
emit_insn (gen_x86_sahf_1 (tmp));
intcmp_mode = CCmode;
}
else
......@@ -4559,11 +4670,20 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
mask = 0x40;
code = EQ;
break;
case UNORDERED:
mask = 0x04;
code = NE;
break;
case ORDERED:
mask = 0x04;
code = EQ;
break;
default:
abort ();
}
emit_insn (gen_testqi_ext_ccno_0 (tmp, GEN_INT (mask)));
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (mask)));
intcmp_mode = CCNOmode;
}
}
......@@ -4578,37 +4698,74 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
switch (code)
{
case GT:
emit_insn (gen_testqi_ext_ccno_0 (tmp, GEN_INT (0x45)));
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
code = EQ;
break;
case LT:
emit_insn (gen_andqi_ext_0 (tmp, tmp, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (tmp, GEN_INT (0x01)));
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x01)));
intcmp_mode = CCmode;
code = EQ;
break;
case GE:
emit_insn (gen_testqi_ext_ccno_0 (tmp, GEN_INT (0x05)));
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05)));
code = EQ;
break;
case LE:
emit_insn (gen_andqi_ext_0 (tmp, tmp, GEN_INT (0x45)));
emit_insn (gen_addqi_ext_1 (tmp, tmp, constm1_rtx));
emit_insn (gen_cmpqi_ext_3 (tmp, GEN_INT (0x40)));
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
intcmp_mode = CCmode;
code = LTU;
break;
case EQ:
emit_insn (gen_andqi_ext_0 (tmp, tmp, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (tmp, GEN_INT (0x40)));
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
intcmp_mode = CCmode;
code = EQ;
break;
case NE:
emit_insn (gen_andqi_ext_0 (tmp, tmp, GEN_INT (0x45)));
emit_insn (gen_xorqi_cc_ext_1 (tmp, tmp, GEN_INT (0x40)));
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, GEN_INT (0x40)));
code = NE;
break;
case UNORDERED:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
code = NE;
break;
case ORDERED:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
code = EQ;
break;
case UNEQ:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
code = NE;
break;
case UNGE:
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, GEN_INT (0x01)));
code = NE;
break;
case UNGT:
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
code = GEU;
break;
case UNLE:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
code = NE;
break;
case UNLT:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01)));
code = NE;
break;
case LTGT:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
code = EQ;
break;
default:
abort ();
}
......@@ -4623,16 +4780,15 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
}
static rtx
ix86_expand_compare (code, unordered)
ix86_expand_compare (code)
enum rtx_code code;
int unordered;
{
rtx op0, op1, ret;
op0 = ix86_compare_op0;
op1 = ix86_compare_op1;
if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
ret = ix86_expand_fp_compare (code, op0, op1, unordered);
ret = ix86_expand_fp_compare (code, op0, op1, gen_reg_rtx (HImode));
else
ret = ix86_expand_int_compare (code, op0, op1);
......@@ -4640,25 +4796,63 @@ ix86_expand_compare (code, unordered)
}
void
ix86_expand_branch (code, unordered, label)
ix86_expand_branch (code, label)
enum rtx_code code;
int unordered;
rtx label;
{
rtx tmp, lo[2], hi[2], label2;
enum rtx_code code1, code2, code3;
rtx tmp;
if (GET_MODE (ix86_compare_op0) != DImode)
switch (GET_MODE (ix86_compare_op0))
{
tmp = ix86_expand_compare (code, unordered);
case QImode:
case HImode:
case SImode:
tmp = ix86_expand_compare (code);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
return;
case SFmode:
case DFmode:
case XFmode:
/* Don't expand the comparison early, so that we get better code
when jump or whoever decides to reverse the comparison. */
{
rtvec vec;
int use_fcomi;
code = ix86_prepare_fp_compare_args (code, &ix86_compare_op0,
&ix86_compare_op1);
tmp = gen_rtx_fmt_ee (code, ix86_fp_compare_mode (code),
ix86_compare_op0, ix86_compare_op1);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx);
tmp = gen_rtx_SET (VOIDmode, pc_rtx, tmp);
use_fcomi = ix86_use_fcomi_compare (code);
vec = rtvec_alloc (3 + !use_fcomi);
RTVEC_ELT (vec, 0) = tmp;
RTVEC_ELT (vec, 1)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 18));
RTVEC_ELT (vec, 2)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 17));
if (! use_fcomi)
RTVEC_ELT (vec, 3)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (HImode));
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));
return;
}
case DImode:
/* Expand DImode branch into multiple compare+branch. */
{
rtx lo[2], hi[2], label2;
enum rtx_code code1, code2, code3;
if (CONSTANT_P (ix86_compare_op0) && ! CONSTANT_P (ix86_compare_op1))
{
......@@ -4670,9 +4864,9 @@ ix86_expand_branch (code, unordered, label)
split_di (&ix86_compare_op0, 1, lo+0, hi+0);
split_di (&ix86_compare_op1, 1, lo+1, hi+1);
/* When comparing for equality, we can use (hi0^hi1)|(lo0^lo1) to avoid
two branches. This costs one extra insn, so disable when optimizing
for size. */
/* When comparing for equality, we can use (hi0^hi1)|(lo0^lo1) to
avoid two branches. This costs one extra insn, so disable when
optimizing for size. */
if ((code == EQ || code == NE)
&& (!optimize_size
......@@ -4682,24 +4876,20 @@ ix86_expand_branch (code, unordered, label)
xor1 = hi[0];
if (hi[1] != const0_rtx)
{
xor1 = expand_binop (SImode, xor_optab, xor1, hi[1],
NULL_RTX, 0, OPTAB_WIDEN);
}
xor0 = lo[0];
if (lo[1] != const0_rtx)
{
xor0 = expand_binop (SImode, xor_optab, xor0, lo[1],
NULL_RTX, 0, OPTAB_WIDEN);
}
tmp = expand_binop (SImode, ior_optab, xor1, xor0,
NULL_RTX, 0, OPTAB_WIDEN);
ix86_compare_op0 = tmp;
ix86_compare_op1 = const0_rtx;
ix86_expand_branch (code, unordered, label);
ix86_expand_branch (code, label);
return;
}
......@@ -4711,7 +4901,7 @@ ix86_expand_branch (code, unordered, label)
{
ix86_compare_op0 = hi[0];
ix86_compare_op1 = hi[1];
ix86_expand_branch (code, unordered, label);
ix86_expand_branch (code, label);
return;
}
......@@ -4752,22 +4942,27 @@ ix86_expand_branch (code, unordered, label)
ix86_compare_op1 = hi[1];
if (code1 != NIL)
ix86_expand_branch (code1, unordered, label);
ix86_expand_branch (code1, label);
if (code2 != NIL)
ix86_expand_branch (code2, unordered, label2);
ix86_expand_branch (code2, label2);
ix86_compare_op0 = lo[0];
ix86_compare_op1 = lo[1];
ix86_expand_branch (code3, unordered, label);
ix86_expand_branch (code3, label);
if (code2 != NIL)
emit_label (label2);
return;
}
default:
abort ();
}
}
int
ix86_expand_setcc (code, unordered, dest)
ix86_expand_setcc (code, dest)
enum rtx_code code;
int unordered;
rtx dest;
{
rtx ret, tmp;
......@@ -4796,7 +4991,7 @@ ix86_expand_setcc (code, unordered, dest)
if (type == 0)
emit_move_insn (dest, const0_rtx);
ret = ix86_expand_compare (code, unordered);
ret = ix86_expand_compare (code);
PUT_MODE (ret, QImode);
tmp = dest;
......@@ -4853,8 +5048,9 @@ ix86_expand_int_movcc (operands)
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_op = ix86_expand_compare (code);
compare_seq = gen_sequence ();
end_sequence ();
......@@ -5165,7 +5361,7 @@ ix86_expand_fp_movcc (operands)
case GE:
case GT:
tmp = gen_reg_rtx (QImode);
ix86_expand_setcc (code, 0, tmp);
ix86_expand_setcc (code, tmp);
code = NE;
ix86_compare_op0 = tmp;
ix86_compare_op1 = const0_rtx;
......
......@@ -2508,6 +2508,8 @@ do { long l; \
{"non_q_regs_operand", {SUBREG, REG}}, \
{"no_comparison_operator", {EQ, NE, LT, GE, LTU, GTU, LEU, GEU}}, \
{"fcmov_comparison_operator", {EQ, NE, LTU, GTU, LEU, GEU}}, \
{"uno_comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, \
GTU, UNORDERED, ORDERED}}, \
{"cmp_fp_expander_operand", {CONST_DOUBLE, SUBREG, REG, MEM}}, \
{"ext_register_operand", {SUBREG, REG}}, \
{"binary_fp_operator", {PLUS, MINUS, MULT, DIV}}, \
......
......@@ -6605,61 +6605,109 @@
[(set (match_operand:SI 0 "register_operand" "")
(eq:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (EQ, 1, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
(define_expand "sne"
[(set (match_operand:SI 0 "register_operand" "")
(ne:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (NE, 1, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
(define_expand "sgt"
[(set (match_operand:SI 0 "register_operand" "")
(gt:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (GT, 0, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
(define_expand "sgtu"
[(set (match_operand:SI 0 "register_operand" "")
(gtu:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (GTU, 0, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
(define_expand "slt"
[(set (match_operand:SI 0 "register_operand" "")
(lt:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (LT, 0, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
(define_expand "sltu"
[(set (match_operand:SI 0 "register_operand" "")
(ltu:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (LTU, 0, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
(define_expand "sge"
[(set (match_operand:SI 0 "register_operand" "")
(ge:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (GE, 0, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
(define_expand "sgeu"
[(set (match_operand:SI 0 "register_operand" "")
(geu:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (GEU, 0, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
(define_expand "sle"
[(set (match_operand:SI 0 "register_operand" "")
(le:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (LE, 0, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
(define_expand "sleu"
[(set (match_operand:SI 0 "register_operand" "")
(leu:SI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (LEU, 0, operands[0])) DONE; else FAIL;")
"if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
(define_expand "sunordered"
[(set (match_operand:SI 0 "register_operand" "")
(unordered:SI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
(define_expand "sordered"
[(set (match_operand:SI 0 "register_operand" "")
(ordered:SI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
(define_expand "suneq"
[(set (match_operand:SI 0 "register_operand" "")
(uneq:SI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
(define_expand "sunge"
[(set (match_operand:SI 0 "register_operand" "")
(unge:SI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
(define_expand "sungt"
[(set (match_operand:SI 0 "register_operand" "")
(ungt:SI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
(define_expand "sunle"
[(set (match_operand:SI 0 "register_operand" "")
(unle:SI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
(define_expand "sunlt"
[(set (match_operand:SI 0 "register_operand" "")
(unlt:SI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
(define_expand "sltgt"
[(set (match_operand:SI 0 "register_operand" "")
(ltgt:SI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
(define_insn "*setcc_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
......@@ -6679,7 +6727,7 @@
(define_insn "*setcc_3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(match_operator:QI 1 "comparison_operator"
(match_operator:QI 1 "uno_comparison_operator"
[(reg:CC 17) (const_int 0)]))]
""
"set%C1\\t%0"
......@@ -6687,7 +6735,7 @@
(define_insn "*setcc_4"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
(match_operator:QI 1 "comparison_operator"
(match_operator:QI 1 "uno_comparison_operator"
[(reg:CC 17) (const_int 0)]))]
""
"set%C1\\t%0"
......@@ -6705,7 +6753,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (EQ, 1, operands[0]); DONE;")
"ix86_expand_branch (EQ, operands[0]); DONE;")
(define_expand "bne"
[(set (pc)
......@@ -6713,7 +6761,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (NE, 1, operands[0]); DONE;")
"ix86_expand_branch (NE, operands[0]); DONE;")
(define_expand "bgt"
[(set (pc)
......@@ -6721,7 +6769,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (GT, 0, operands[0]); DONE;")
"ix86_expand_branch (GT, operands[0]); DONE;")
(define_expand "bgtu"
[(set (pc)
......@@ -6729,7 +6777,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (GTU, 0, operands[0]); DONE;")
"ix86_expand_branch (GTU, operands[0]); DONE;")
(define_expand "blt"
[(set (pc)
......@@ -6737,7 +6785,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (LT, 0, operands[0]); DONE;")
"ix86_expand_branch (LT, operands[0]); DONE;")
(define_expand "bltu"
[(set (pc)
......@@ -6745,7 +6793,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (LTU, 0, operands[0]); DONE;")
"ix86_expand_branch (LTU, operands[0]); DONE;")
(define_expand "bge"
[(set (pc)
......@@ -6753,7 +6801,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (GE, 0, operands[0]); DONE;")
"ix86_expand_branch (GE, operands[0]); DONE;")
(define_expand "bgeu"
[(set (pc)
......@@ -6761,7 +6809,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (GEU, 0, operands[0]); DONE;")
"ix86_expand_branch (GEU, operands[0]); DONE;")
(define_expand "ble"
[(set (pc)
......@@ -6769,7 +6817,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (LE, 0, operands[0]); DONE;")
"ix86_expand_branch (LE, operands[0]); DONE;")
(define_expand "bleu"
[(set (pc)
......@@ -6777,7 +6825,71 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (LEU, 0, operands[0]); DONE;")
"ix86_expand_branch (LEU, operands[0]); DONE;")
(define_expand "bunordered"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_80387"
"ix86_expand_branch (UNORDERED, operands[0]); DONE;")
(define_expand "bordered"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_80387"
"ix86_expand_branch (ORDERED, operands[0]); DONE;")
(define_expand "buneq"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_80387"
"ix86_expand_branch (UNEQ, operands[0]); DONE;")
(define_expand "bunge"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_80387"
"ix86_expand_branch (UNGE, operands[0]); DONE;")
(define_expand "bungt"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_80387"
"ix86_expand_branch (UNGT, operands[0]); DONE;")
(define_expand "bunle"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_80387"
"ix86_expand_branch (UNLE, operands[0]); DONE;")
(define_expand "bunlt"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_80387"
"ix86_expand_branch (UNLT, operands[0]); DONE;")
(define_expand "bltgt"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_80387"
"ix86_expand_branch (LTGT, operands[0]); DONE;")
(define_insn "*jcc_1"
[(set (pc)
......@@ -6815,7 +6927,7 @@
(define_insn "*jcc_3"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
(if_then_else (match_operator 0 "uno_comparison_operator"
[(reg:CC 17) (const_int 0)])
(label_ref (match_operand 1 "" ""))
(pc)))]
......@@ -6832,7 +6944,7 @@
(define_insn "*jcc_4"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
(if_then_else (match_operator 0 "uno_comparison_operator"
[(reg:CC 17) (const_int 0)])
(pc)
(label_ref (match_operand 1 "" ""))))]
......@@ -6847,6 +6959,139 @@
(const_int 2)
(const_int 6)))])
;; Define combination compare-and-branch fp compare instructions to use
;; during early optimization. Splitting the operation apart early makes
;; for bad code when we want to reverse the operation.
(define_insn "*fp_jcc_1"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:CCFP 18))
(clobber (reg:CCFP 17))]
"TARGET_CMOVE && TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"#")
(define_insn "*fp_jcc_2"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")])
(pc)
(label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP 18))
(clobber (reg:CCFP 17))]
"TARGET_CMOVE && TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"#")
(define_insn "*fp_jcc_3"
[(set (pc)
(if_then_else (match_operator:CCFP 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "fm")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:CCFP 18))
(clobber (reg:CCFP 17))
(clobber (match_scratch:HI 4 "=a"))]
"TARGET_80387
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"#")
(define_insn "*fp_jcc_4"
[(set (pc)
(if_then_else (match_operator:CCFP 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "fm")])
(pc)
(label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP 18))
(clobber (reg:CCFP 17))
(clobber (match_scratch:HI 4 "=a"))]
"TARGET_80387
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"#")
(define_insn "*fp_jcc_5"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:CCFP 18))
(clobber (reg:CCFP 17))
(clobber (match_scratch:HI 4 "=a"))]
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"#")
(define_insn "*fp_jcc_6"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")])
(pc)
(label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP 18))
(clobber (reg:CCFP 17))
(clobber (match_scratch:HI 4 "=a"))]
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"#")
(define_split
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "")
(match_operand 2 "nonimmediate_operand" "")])
(match_operand 3 "" "")
(match_operand 4 "" "")))
(clobber (reg:CCFP 18))
(clobber (reg:CCFP 17))]
"reload_completed"
[(set (pc)
(if_then_else (match_dup 5)
(match_dup 3)
(match_dup 4)))]
"
{
operands[5] = ix86_expand_fp_compare (GET_CODE (operands[0]), operands[1],
operands[2], NULL_RTX);
}")
(define_split
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "")
(match_operand 2 "nonimmediate_operand" "")])
(match_operand 3 "" "")
(match_operand 4 "" "")))
(clobber (reg:CCFP 18))
(clobber (reg:CCFP 17))
(clobber (match_scratch:HI 5 "=a"))]
"reload_completed"
[(set (pc)
(if_then_else (match_dup 6)
(match_dup 3)
(match_dup 4)))]
"
{
operands[6] = ix86_expand_fp_compare (GET_CODE (operands[0]), operands[1],
operands[2], operands[5]);
}")
;; Unconditional and other jump instructions
(define_insn "jump"
......@@ -8824,7 +9069,7 @@
(define_insn "*movsicc_c"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(if_then_else:SI (match_operator 1 "comparison_operator"
(if_then_else:SI (match_operator 1 "uno_comparison_operator"
[(reg:CC 17) (const_int 0)])
(match_operand:SI 2 "nonimmediate_operand" "rm,0")
(match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
......@@ -8858,7 +9103,7 @@
(define_insn "*movhicc_c"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(if_then_else:HI (match_operator 1 "comparison_operator"
(if_then_else:HI (match_operator 1 "uno_comparison_operator"
[(reg:CC 17) (const_int 0)])
(match_operand:HI 2 "nonimmediate_operand" "rm,0")
(match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
......
......@@ -211,7 +211,9 @@ static struct pred_table
{"pop_operand", {MEM}},
{"memory_operand", {SUBREG, MEM}},
{"indirect_operand", {SUBREG, MEM}},
{"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU}},
{"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU,
UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
UNLT, LTGT}},
{"mode_independent_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
LABEL_REF, SUBREG, REG, MEM}}
};
......
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