i386.c (ix86_comparison_operator, [...]): Convert fp comparison codes to integer before handling.

* i386.c (ix86_comparison_operator, fcmov_comparison_operator,
	put_condition_code): Convert fp comparison codes to integer
	before handling.
	(ix86_expand_fp_compare): Postnote the fp comparison code converison
	to final.

	* i386.c (unsigned_comparison, no_comparison_operator): Kill.
	* i386-protos.h (no_comparison_operator): Kill.

	* i386.c (ix86_expand_fp_compare): Fix ordered/unordered confussion.

	* combine.c (REVERSIBLE_CC_MODE): Remove.
	(reversible_comparison_p): Remove.
	(combine_reversed_comparison_code): New.
	(reversed_comparison): New.
	(combine_simplify_rtx): Use
	combine_reversed_comparison_code/reversed_comparison instead
	of reversible_comparison_p.
	(simplify_if_then_else): Likewise.
	(simplify_set): Likewise.
	(simplify_logical): Likewise.
	(if_then_else_cond): Likewise.
	(known_cond): Likewise.
	(simplify_comparison): Likewise.

From-SVN: r38930
This commit is contained in:
Jan Hubicka 2001-01-12 00:10:30 +01:00 committed by Jan Hubicka
parent bbc7fda9b0
commit 9a9157721d
4 changed files with 251 additions and 293 deletions

View File

@ -1,3 +1,30 @@
Fri Jan 12 00:04:00 MET 2001 Jan Hubicka <jh@suse.cz>
* i386.c (ix86_comparison_operator, fcmov_comparison_operator,
put_condition_code): Convert fp comparison codes to integer
before handling.
(ix86_expand_fp_compare): Postnote the fp comparison code converison
to final.
* i386.c (unsigned_comparison, no_comparison_operator): Kill.
* i386-protos.h (no_comparison_operator): Kill.
* i386.c (ix86_expand_fp_compare): Fix ordered/unordered confussion.
* combine.c (REVERSIBLE_CC_MODE): Remove.
(reversible_comparison_p): Remove.
(combine_reversed_comparison_code): New.
(reversed_comparison): New.
(combine_simplify_rtx): Use
combine_reversed_comparison_code/reversed_comparison instead
of reversible_comparison_p.
(simplify_if_then_else): Likewise.
(simplify_set): Likewise.
(simplify_logical): Likewise.
(if_then_else_cond): Likewise.
(known_cond): Likewise.
(simplify_comparison): Likewise.
2001-01-11 Alan Lehotsky <lehotsky@tiac.net>
* builtins.c (std_expand_builtin_va_start): Handle varargs when

View File

@ -131,12 +131,6 @@ static int combine_successes;
static int total_attempts, total_merges, total_extras, total_successes;
/* Define a default value for REVERSIBLE_CC_MODE.
We can never assume that a condition code mode is safe to reverse unless
the md tells us so. */
#ifndef REVERSIBLE_CC_MODE
#define REVERSIBLE_CC_MODE(MODE) 0
#endif
/* Vector mapping INSN_UIDs to cuids.
The cuids are like uids but increase monotonically always.
@ -414,7 +408,6 @@ static rtx gen_binary PARAMS ((enum rtx_code, enum machine_mode,
static rtx gen_unary PARAMS ((enum rtx_code, enum machine_mode,
enum machine_mode, rtx));
static enum rtx_code simplify_comparison PARAMS ((enum rtx_code, rtx *, rtx *));
static int reversible_comparison_p PARAMS ((rtx));
static void update_table_tick PARAMS ((rtx));
static void record_value_for_reg PARAMS ((rtx, rtx, rtx));
static void check_promoted_subreg PARAMS ((rtx, rtx));
@ -432,6 +425,8 @@ static void distribute_links PARAMS ((rtx));
static void mark_used_regs_combine PARAMS ((rtx));
static int insn_cuid PARAMS ((rtx));
static void record_promoted_value PARAMS ((rtx, rtx));
static rtx reversed_comparison PARAMS ((rtx, enum machine_mode, rtx, rtx));
static enum rtx_code combine_reversed_comparison_code PARAMS ((rtx));
/* Substitute NEWVAL, an rtx expression, into INTO, a place in some
insn. The substitution can be undone by undo_all. If INTO is already
@ -3501,6 +3496,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
enum rtx_code code = GET_CODE (x);
enum machine_mode mode = GET_MODE (x);
rtx temp;
rtx reversed;
int i;
/* If this is a commutative operation, put a constant last and a complex
@ -3922,10 +3918,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
reversing the comparison code if valid. */
if (STORE_FLAG_VALUE == -1
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& reversible_comparison_p (XEXP (x, 0)))
return gen_rtx_combine (reverse_condition (GET_CODE (XEXP (x, 0))),
mode, XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 0), 1));
&& (reversed = reversed_comparison (x, mode, XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 0), 1))))
return reversed;
/* (ashiftrt foo C) where C is the number of bits in FOO minus 1
is (lt foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can
@ -4218,14 +4213,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
is 1. This produces better code than the alternative immediately
below. */
if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& reversible_comparison_p (XEXP (x, 0))
&& ((STORE_FLAG_VALUE == -1 && XEXP (x, 1) == const1_rtx)
|| (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx)))
|| (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx))
&& (reversed = reversed_comparison (XEXP (x, 0), mode,
XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 0), 1))))
return
gen_unary (NEG, mode, mode,
gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))),
mode, XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 0), 1)));
gen_unary (NEG, mode, mode, reversed);
/* If only the low-order bit of X is possibly nonzero, (plus x -1)
can become (ashiftrt (ashift (xor x 1) C) C) where C is
@ -4270,10 +4264,10 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (STORE_FLAG_VALUE == 1
&& XEXP (x, 0) == const1_rtx
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<'
&& reversible_comparison_p (XEXP (x, 1)))
return gen_binary (reverse_condition (GET_CODE (XEXP (x, 1))), mode,
XEXP (XEXP (x, 1), 0),
XEXP (XEXP (x, 1), 1));
&& (reversed = reversed_comparison (XEXP (x, 1), mode,
XEXP (XEXP (x, 1), 0),
XEXP (XEXP (x, 1), 1))))
return reversed;
/* (minus <foo> (and <foo> (const_int -pow2))) becomes
(and <foo> (const_int pow2-1)) */
@ -4626,27 +4620,31 @@ simplify_if_then_else (x)
int comparison_p = GET_RTX_CLASS (true_code) == '<';
rtx temp;
int i;
enum rtx_code false_code;
rtx reversed;
/* Simplify storing of the truth value. */
if (comparison_p && true == const_true_rtx && false == const0_rtx)
return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1));
/* Also when the truth value has to be reversed. */
if (comparison_p && reversible_comparison_p (cond)
&& true == const0_rtx && false == const_true_rtx)
return gen_binary (reverse_condition (true_code),
mode, XEXP (cond, 0), XEXP (cond, 1));
if (comparison_p
&& true == const0_rtx && false == const_true_rtx
&& (reversed = reversed_comparison (cond, mode, XEXP (cond, 0),
XEXP (cond, 1))))
return reversed;
/* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register used
in it is being compared against certain values. Get the true and false
comparisons and see if that says anything about the value of each arm. */
if (comparison_p && reversible_comparison_p (cond)
if (comparison_p
&& ((false_code = combine_reversed_comparison_code (cond))
!= UNKNOWN)
&& GET_CODE (XEXP (cond, 0)) == REG)
{
HOST_WIDE_INT nzb;
rtx from = XEXP (cond, 0);
enum rtx_code false_code = reverse_condition (true_code);
rtx true_val = XEXP (cond, 1);
rtx false_val = true_val;
int swapped = 0;
@ -4695,7 +4693,8 @@ simplify_if_then_else (x)
arm, the false arm is the same as the first operand of the comparison, or
the false arm is more complicated than the true arm. */
if (comparison_p && reversible_comparison_p (cond)
if (comparison_p
&& combine_reversed_comparison_code (cond) != UNKNOWN
&& (true == pc_rtx
|| (CONSTANT_P (true)
&& GET_CODE (false) != CONST_INT && false != pc_rtx)
@ -4708,10 +4707,10 @@ simplify_if_then_else (x)
|| reg_mentioned_p (true, false)
|| rtx_equal_p (false, XEXP (cond, 0))))
{
true_code = reverse_condition (true_code);
true_code = reversed_comparison_code (cond, NULL);
SUBST (XEXP (x, 0),
gen_binary (true_code, GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1)));
reversed_comparison (cond, GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1)));
SUBST (XEXP (x, 1), false);
SUBST (XEXP (x, 2), true);
@ -5211,6 +5210,7 @@ simplify_set (x)
rtx cond = XEXP (src, 0);
rtx true_val = const1_rtx;
rtx false_arm, true_arm;
rtx reversed;
if (GET_CODE (cond) == MULT)
{
@ -5236,16 +5236,16 @@ simplify_set (x)
/* Canonicalize if true_arm is the simpler one. */
if (GET_RTX_CLASS (GET_CODE (true_arm)) == 'o'
&& GET_RTX_CLASS (GET_CODE (false_arm)) != 'o'
&& reversible_comparison_p (cond))
&& (reversed = reversed_comparison_code (cond, GET_MODE (cond),
XEXP (cond, 0),
XEXP (cond, 1))))
{
rtx temp = true_arm;
true_arm = false_arm;
false_arm = temp;
cond = gen_rtx_combine (reverse_condition (GET_CODE (cond)),
GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1));
cond = reversed;
}
src = gen_rtx_combine (IF_THEN_ELSE, GET_MODE (src),
@ -5279,6 +5279,7 @@ simplify_logical (x, last)
enum machine_mode mode = GET_MODE (x);
rtx op0 = XEXP (x, 0);
rtx op1 = XEXP (x, 1);
rtx reversed;
switch (GET_CODE (x))
{
@ -5530,9 +5531,9 @@ simplify_logical (x, last)
if (STORE_FLAG_VALUE == 1
&& op1 == const1_rtx
&& GET_RTX_CLASS (GET_CODE (op0)) == '<'
&& reversible_comparison_p (op0))
return gen_rtx_combine (reverse_condition (GET_CODE (op0)),
mode, XEXP (op0, 0), XEXP (op0, 1));
&& (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
XEXP (op0, 1))))
return reversed;
/* (lshiftrt foo C) where C is the number of bits in FOO minus 1
is (lt foo (const_int 0)), so we can perform the above
@ -5552,9 +5553,9 @@ simplify_logical (x, last)
== (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
&& op1 == const_true_rtx
&& GET_RTX_CLASS (GET_CODE (op0)) == '<'
&& reversible_comparison_p (op0))
return gen_rtx_combine (reverse_condition (GET_CODE (op0)),
mode, XEXP (op0, 0), XEXP (op0, 1));
&& (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
XEXP (op0, 1))))
return reversed;
break;
@ -7344,12 +7345,11 @@ if_then_else_cond (x, ptrue, pfalse)
if (GET_RTX_CLASS (GET_CODE (cond0)) == '<'
&& GET_RTX_CLASS (GET_CODE (cond1)) == '<'
&& reversible_comparison_p (cond1)
&& ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1))
&& ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1)
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
|| ((swap_condition (GET_CODE (cond0))
== reverse_condition (GET_CODE (cond1)))
== combine_reversed_comparison_code (cond1))
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x))
@ -7374,12 +7374,11 @@ if_then_else_cond (x, ptrue, pfalse)
if (GET_RTX_CLASS (GET_CODE (cond0)) == '<'
&& GET_RTX_CLASS (GET_CODE (cond1)) == '<'
&& reversible_comparison_p (cond1)
&& ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1))
&& ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1)
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
|| ((swap_condition (GET_CODE (cond0))
== reverse_condition (GET_CODE (cond1)))
== combine_reversed_comparison_code (cond1))
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x))
@ -7527,7 +7526,7 @@ known_cond (x, cond, reg, val)
if (comparison_dominates_p (cond, code))
return const_true_rtx;
code = reverse_condition (code);
code = combine_reversed_comparison_code (x);
if (code != UNKNOWN
&& comparison_dominates_p (cond, code))
return const0_rtx;
@ -10705,20 +10704,21 @@ simplify_comparison (code, pop0, pop1)
/* Check for the cases where we simply want the result of the
earlier test or the opposite of that result. */
if (code == NE
|| (code == EQ && reversible_comparison_p (op0))
if (code == NE || code == EQ
|| (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
&& (STORE_FLAG_VALUE
& (((HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
&& (code == LT
|| (code == GE && reversible_comparison_p (op0)))))
&& (code == LT || (code == GE))))
{
code = (code == LT || code == NE
? GET_CODE (op0) : reverse_condition (GET_CODE (op0)));
op0 = tem, op1 = tem1;
continue;
? GET_CODE (op0) : combine_reversed_comparison_code (op0));
if (code != UNKNOWN)
{
op0 = tem, op1 = tem1;
continue;
}
}
break;
@ -11121,42 +11121,38 @@ simplify_comparison (code, pop0, pop1)
return code;
}
/* Return 1 if we know that X, a comparison operation, is not operating
on a floating-point value or is EQ or NE, meaning that we can safely
reverse it. */
static int
reversible_comparison_p (x)
rtx x;
/* Like jump.c' reversed_comparison_code, but use combine infrastructure for
searching backward. */
enum rtx_code
combine_reversed_comparison_code (exp)
rtx exp;
{
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| flag_fast_math
|| GET_CODE (x) == NE || GET_CODE (x) == EQ
|| GET_CODE (x) == UNORDERED || GET_CODE (x) == ORDERED)
return 1;
enum rtx_code code1 = reversed_comparison_code (exp, NULL);
rtx x;
switch (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))))
{
case MODE_INT:
case MODE_PARTIAL_INT:
case MODE_COMPLEX_INT:
return 1;
case MODE_CC:
/* If the mode of the condition codes tells us that this is safe,
we need look no further. */
if (REVERSIBLE_CC_MODE (GET_MODE (XEXP (x, 0))))
return 1;
/* Otherwise try and find where the condition codes were last set and
use that. */
x = get_last_value (XEXP (x, 0));
return (x && GET_CODE (x) == COMPARE
&& ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0))));
default:
return 0;
}
if (code1 != UNKNOWN
|| GET_MODE_CLASS (GET_MODE (XEXP (exp, 0))) != MODE_CC)
return code1;
/* Otherwise try and find where the condition codes were last set and
use that. */
x = get_last_value (XEXP (x, 0));
if (GET_CODE (x) != COMPARE)
return UNKNOWN;
return reversed_comparison_code_parts (GET_CODE (exp),
XEXP (x, 0), XEXP (x, 1), NULL);
}
/* Return comparison with reversed code of EXP and operands OP0 and OP1.
Return NULL_RTX in case we fail to do the reversal. */
static rtx
reversed_comparison (exp, mode, op0, op1)
rtx exp, op0, op1;
enum machine_mode mode;
{
enum rtx_code reversed_code = combine_reversed_comparison_code (exp);
if (reversed_code == UNKNOWN)
return NULL_RTX;
else
return gen_binary (reversed_code, mode, op0, op1);
}
/* Utility function for following routine. Called when X is part of a value

View File

@ -56,7 +56,6 @@ extern int general_no_elim_operand PARAMS ((rtx, enum machine_mode));
extern int nonmemory_no_elim_operand PARAMS ((rtx, enum machine_mode));
extern int q_regs_operand PARAMS ((rtx, enum machine_mode));
extern int non_q_regs_operand PARAMS ((rtx, enum machine_mode));
extern int no_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int sse_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int fcmov_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int cmp_fp_expander_operand PARAMS ((rtx, enum machine_mode));

View File

@ -386,7 +386,6 @@ int ix86_align_jumps;
static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
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 enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
rtx *, rtx *));
@ -1267,30 +1266,6 @@ non_q_regs_operand (op, mode)
return NON_QI_REG_P (op);
}
/* Return 1 if OP is a comparison operator that can use the condition code
generated by a logical operation, which characteristicly does not set
overflow or carry. To be used with CCNOmode. */
int
no_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 LT: case GE:
case LEU: case LTU: case GEU: case GTU:
return 1;
default:
return 0;
}
}
/* Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS
insns. */
int
@ -1308,25 +1283,33 @@ ix86_comparison_operator (op, mode)
enum machine_mode mode;
{
enum machine_mode inmode;
enum rtx_code code = GET_CODE (op);
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
switch (GET_CODE (op))
if (GET_RTX_CLASS (code) != '<')
return 0;
inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCFPmode || inmode == CCFPUmode)
{
enum rtx_code second_code, bypass_code;
ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
return (bypass_code == NIL && second_code == NIL);
}
switch (code)
{
case EQ: case NE:
return 1;
case LT: case GE:
inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode || inmode == CCGCmode
|| inmode == CCGOCmode || inmode == CCNOmode)
return 1;
return 0;
case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode)
return 1;
return 0;
case GT: case LE:
inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode || inmode == CCGCmode || inmode == CCNOmode)
return 1;
return 0;
@ -1343,16 +1326,30 @@ fcmov_comparison_operator (op, mode)
enum machine_mode mode;
{
enum machine_mode inmode = GET_MODE (XEXP (op, 0));
enum rtx_code code = GET_CODE (op);
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
switch (GET_CODE (op))
if (GET_RTX_CLASS (code) != '<')
return 0;
inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCFPmode || inmode == CCFPUmode)
{
case EQ: case NE:
return 1;
case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
if (inmode == CCFPmode || inmode == CCFPUmode)
enum rtx_code second_code, bypass_code;
ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
if (bypass_code != NIL || second_code != NIL)
return 0;
code = ix86_fp_compare_code_to_integer (code);
}
/* i387 supports just limited amount of conditional codes. */
switch (code)
{
case LTU: case GTU: case LEU: case GEU:
if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode)
return 1;
return 0;
case ORDERED: case UNORDERED:
case EQ: case NE:
return 1;
default:
return 0;
}
@ -3102,6 +3099,15 @@ put_condition_code (code, mode, reverse, fp, file)
{
const char *suffix;
if (mode == CCFPmode || mode == CCFPUmode)
{
enum rtx_code second_code, bypass_code;
ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
if (bypass_code != NIL || second_code != NIL)
abort();
code = ix86_fp_compare_code_to_integer (code);
mode = CCmode;
}
if (reverse)
code = reverse_condition (code);
@ -4611,41 +4617,6 @@ ix86_match_ccmode (insn, req_mode)
return (GET_MODE (SET_SRC (set)) == set_mode);
}
/* Produce an unsigned comparison for a given signed comparison. */
static enum rtx_code
unsigned_comparison (code)
enum rtx_code code;
{
switch (code)
{
case GT:
code = GTU;
break;
case LT:
code = LTU;
break;
case GE:
code = GEU;
break;
case LE:
code = LEU;
break;
case EQ:
case NE:
case LEU:
case LTU:
case GEU:
case GTU:
case UNORDERED:
case ORDERED:
break;
default:
abort ();
}
return code;
}
/* Generate insn patterns to do an integer compare of OPERANDS. */
static rtx
@ -4960,8 +4931,7 @@ ix86_expand_fp_compare (code, op0, op1, scratch)
}
/* The FP codes work out to act like unsigned. */
code = ix86_fp_compare_code_to_integer (first_code);
intcmp_mode = CCmode;
intcmp_mode = fpcmp_mode;
}
else
{
@ -4970,153 +4940,119 @@ ix86_expand_fp_compare (code, op0, op1, scratch)
tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9);
emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
if (fpcmp_mode == CCFPmode
|| code == ORDERED
|| code == UNORDERED)
/* In the unordered case, we have to check C2 for NaN's, which
doesn't happen to work out to anything nice combination-wise.
So do some bit twiddling on the value we've got in AH to come
up with an appropriate set of condition codes. */
intcmp_mode = CCNOmode;
switch (code)
{
/* We have two options here -- use sahf, or testing bits of ah
directly. On PPRO, they are equivalent, sahf being one byte
smaller. On Pentium, sahf is non-pairable while test is UV
pairable. */
/*
* The numbers below correspond to the bits of the FPSW in AH.
* C3, C2, and C0 are in bits 0x40, 0x4, and 0x01 respectively.
*
* cmp C3 C2 C0
* > 0 0 0
* < 0 0 1
* = 1 0 0
* un 1 1 1
*/
int mask;
switch (code)
case GT:
case UNGT:
if (code == GT || !TARGET_IEEE_FP)
{
case GT:
mask = 0x41;
code = EQ;
break;
case LT:
mask = 0x01;
code = NE;
break;
case GE:
/* We'd have to use `xorb 1,ah; andb 0x41,ah', so it's
faster in all cases to just fall back on sahf. */
goto do_sahf;
case LE:
mask = 0x41;
code = NE;
break;
case EQ:
mask = 0x40;
code = NE;
break;
case NE:
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 (scratch, GEN_INT (mask)));
intcmp_mode = CCNOmode;
}
else
{
/* In the unordered case, we have to check C2 for NaN's, which
doesn't happen to work out to anything nice combination-wise.
So do some bit twiddling on the value we've got in AH to come
up with an appropriate set of condition codes. */
intcmp_mode = CCNOmode;
switch (code)
{
case GT:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
code = EQ;
break;
case LT:
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 (scratch, GEN_INT (0x05)));
code = EQ;
break;
case LE:
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 (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 (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:
}
else
{
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)));
intcmp_mode = CCmode;
code = GEU;
break;
case UNLE:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
code = NE;
break;
case UNLT:
}
break;
case LT:
case UNLT:
if (code == LT && TARGET_IEEE_FP)
{
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;
}
else
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01)));
code = NE;
}
break;
case GE:
case UNGE:
if (code == GE || !TARGET_IEEE_FP)
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05)));
code = EQ;
}
else
{
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 LE:
case UNLE:
if (code == LE && TARGET_IEEE_FP)
{
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;
}
else
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
code = NE;
}
break;
case EQ:
case UNEQ:
if (code == EQ && TARGET_IEEE_FP)
{
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;
}
else
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
code = NE;
break;
case LTGT:
}
break;
case NE:
case LTGT:
if (code == NE && TARGET_IEEE_FP)
{
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;
}
else
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
code = EQ;
break;
default:
abort ();
}
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;
default:
abort ();
}
}