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:
parent
bbc7fda9b0
commit
9a9157721d
@ -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
|
||||
|
174
gcc/combine.c
174
gcc/combine.c
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user