aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog29
-rw-r--r--gcc/config/i386/i386-protos.h5
-rw-r--r--gcc/config/i386/i386.c502
-rw-r--r--gcc/config/i386/i386.h2
-rw-r--r--gcc/config/i386/i386.md297
-rw-r--r--gcc/genrecog.c4
6 files changed, 656 insertions, 183 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1e058c6..952ba80 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,33 @@
+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.
+ * config/arm/arm.h (ARM_NAME_ENCODING_LENGTHS): Strip `*' too.
Sun Apr 9 15:16:14 EDT 2000 John Wehle (john@feith.com)
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index d73fc5e..557d806 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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[]));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index dcab2be..74de03c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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)
- unordered = 0;
- fpcmp_mode = unordered ? CCFPUmode : CCFPmode;
+ 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;
+ 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,134 +4796,173 @@ 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;
- }
-
- /* Expand DImode branch into multiple compare+branch. */
- if (CONSTANT_P (ix86_compare_op0) && ! CONSTANT_P (ix86_compare_op1))
- {
- tmp = ix86_compare_op0;
- ix86_compare_op0 = ix86_compare_op1;
- ix86_compare_op1 = tmp;
- code = swap_condition (code);
- }
- 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. */
+ 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;
+ }
- if ((code == EQ || code == NE)
- && (!optimize_size
- || hi[1] == const0_rtx || lo[1] == const0_rtx))
- {
- rtx xor0, xor1;
+ case DImode:
+ /* Expand DImode branch into multiple compare+branch. */
+ {
+ rtx lo[2], hi[2], label2;
+ enum rtx_code code1, code2, code3;
- xor1 = hi[0];
- if (hi[1] != const0_rtx)
- {
- xor1 = expand_binop (SImode, xor_optab, xor1, hi[1],
- NULL_RTX, 0, OPTAB_WIDEN);
- }
+ if (CONSTANT_P (ix86_compare_op0) && ! CONSTANT_P (ix86_compare_op1))
+ {
+ tmp = ix86_compare_op0;
+ ix86_compare_op0 = ix86_compare_op1;
+ ix86_compare_op1 = tmp;
+ code = swap_condition (code);
+ }
+ split_di (&ix86_compare_op0, 1, lo+0, hi+0);
+ split_di (&ix86_compare_op1, 1, lo+1, hi+1);
- xor0 = lo[0];
- if (lo[1] != const0_rtx)
- {
- xor0 = expand_binop (SImode, xor_optab, xor0, lo[1],
- NULL_RTX, 0, OPTAB_WIDEN);
- }
+ /* 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. */
- tmp = expand_binop (SImode, ior_optab, xor1, xor0,
- NULL_RTX, 0, OPTAB_WIDEN);
+ if ((code == EQ || code == NE)
+ && (!optimize_size
+ || hi[1] == const0_rtx || lo[1] == const0_rtx))
+ {
+ rtx xor0, xor1;
- ix86_compare_op0 = tmp;
- ix86_compare_op1 = const0_rtx;
- ix86_expand_branch (code, unordered, label);
- return;
- }
+ xor1 = hi[0];
+ if (hi[1] != const0_rtx)
+ xor1 = expand_binop (SImode, xor_optab, xor1, hi[1],
+ NULL_RTX, 0, OPTAB_WIDEN);
- /* Otherwise, if we are doing less-than, op1 is a constant and the
- low word is zero, then we can just examine the high word. */
+ xor0 = lo[0];
+ if (lo[1] != const0_rtx)
+ xor0 = expand_binop (SImode, xor_optab, xor0, lo[1],
+ NULL_RTX, 0, OPTAB_WIDEN);
- if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx
- && (code == LT || code == LTU))
- {
- ix86_compare_op0 = hi[0];
- ix86_compare_op1 = hi[1];
- ix86_expand_branch (code, unordered, label);
- return;
- }
+ tmp = expand_binop (SImode, ior_optab, xor1, xor0,
+ NULL_RTX, 0, OPTAB_WIDEN);
- /* Otherwise, we need two or three jumps. */
+ ix86_compare_op0 = tmp;
+ ix86_compare_op1 = const0_rtx;
+ ix86_expand_branch (code, label);
+ return;
+ }
- label2 = gen_label_rtx ();
+ /* Otherwise, if we are doing less-than, op1 is a constant and the
+ low word is zero, then we can just examine the high word. */
- code1 = code;
- code2 = swap_condition (code);
- code3 = unsigned_condition (code);
+ if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx
+ && (code == LT || code == LTU))
+ {
+ ix86_compare_op0 = hi[0];
+ ix86_compare_op1 = hi[1];
+ ix86_expand_branch (code, label);
+ return;
+ }
- switch (code)
- {
- case LT: case GT: case LTU: case GTU:
- break;
+ /* Otherwise, we need two or three jumps. */
- case LE: code1 = LT; code2 = GT; break;
- case GE: code1 = GT; code2 = LT; break;
- case LEU: code1 = LTU; code2 = GTU; break;
- case GEU: code1 = GTU; code2 = LTU; break;
+ label2 = gen_label_rtx ();
- case EQ: code1 = NIL; code2 = NE; break;
- case NE: code2 = NIL; break;
+ code1 = code;
+ code2 = swap_condition (code);
+ code3 = unsigned_condition (code);
- default:
- abort ();
- }
+ switch (code)
+ {
+ case LT: case GT: case LTU: case GTU:
+ break;
- /*
- * a < b =>
- * if (hi(a) < hi(b)) goto true;
- * if (hi(a) > hi(b)) goto false;
- * if (lo(a) < lo(b)) goto true;
- * false:
- */
+ case LE: code1 = LT; code2 = GT; break;
+ case GE: code1 = GT; code2 = LT; break;
+ case LEU: code1 = LTU; code2 = GTU; break;
+ case GEU: code1 = GTU; code2 = LTU; break;
- ix86_compare_op0 = hi[0];
- ix86_compare_op1 = hi[1];
+ case EQ: code1 = NIL; code2 = NE; break;
+ case NE: code2 = NIL; break;
- if (code1 != NIL)
- ix86_expand_branch (code1, unordered, label);
- if (code2 != NIL)
- ix86_expand_branch (code2, unordered, label2);
+ default:
+ abort ();
+ }
- ix86_compare_op0 = lo[0];
- ix86_compare_op1 = lo[1];
- ix86_expand_branch (code3, unordered, label);
+ /*
+ * a < b =>
+ * if (hi(a) < hi(b)) goto true;
+ * if (hi(a) > hi(b)) goto false;
+ * if (lo(a) < lo(b)) goto true;
+ * false:
+ */
+
+ ix86_compare_op0 = hi[0];
+ ix86_compare_op1 = hi[1];
+
+ if (code1 != NIL)
+ ix86_expand_branch (code1, label);
+ if (code2 != NIL)
+ ix86_expand_branch (code2, label2);
+
+ ix86_compare_op0 = lo[0];
+ ix86_compare_op1 = lo[1];
+ ix86_expand_branch (code3, label);
+
+ if (code2 != NIL)
+ emit_label (label2);
+ return;
+ }
- if (code2 != NIL)
- emit_label (label2);
+ 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;
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index d73e7b0..cde39ce 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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}}, \
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 294493c..98c7616 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -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 "" ""))))]
@@ -6846,6 +6958,139 @@
(const_int 124)))
(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
@@ -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")))]
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index c86b62a..3acf5b1 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -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}}
};