Commit 9a915772 by Jan Hubicka Committed by Jan Hubicka

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
parent bbc7fda9
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> 2001-01-11 Alan Lehotsky <lehotsky@tiac.net>
* builtins.c (std_expand_builtin_va_start): Handle varargs when * builtins.c (std_expand_builtin_va_start): Handle varargs when
......
...@@ -131,12 +131,6 @@ static int combine_successes; ...@@ -131,12 +131,6 @@ static int combine_successes;
static int total_attempts, total_merges, total_extras, total_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. /* Vector mapping INSN_UIDs to cuids.
The cuids are like uids but increase monotonically always. The cuids are like uids but increase monotonically always.
...@@ -414,7 +408,6 @@ static rtx gen_binary PARAMS ((enum rtx_code, enum machine_mode, ...@@ -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, static rtx gen_unary PARAMS ((enum rtx_code, enum machine_mode,
enum machine_mode, rtx)); enum machine_mode, rtx));
static enum rtx_code simplify_comparison PARAMS ((enum rtx_code, rtx *, 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 update_table_tick PARAMS ((rtx));
static void record_value_for_reg PARAMS ((rtx, rtx, rtx)); static void record_value_for_reg PARAMS ((rtx, rtx, rtx));
static void check_promoted_subreg PARAMS ((rtx, rtx)); static void check_promoted_subreg PARAMS ((rtx, rtx));
...@@ -432,6 +425,8 @@ static void distribute_links PARAMS ((rtx)); ...@@ -432,6 +425,8 @@ static void distribute_links PARAMS ((rtx));
static void mark_used_regs_combine PARAMS ((rtx)); static void mark_used_regs_combine PARAMS ((rtx));
static int insn_cuid PARAMS ((rtx)); static int insn_cuid PARAMS ((rtx));
static void record_promoted_value PARAMS ((rtx, 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 /* Substitute NEWVAL, an rtx expression, into INTO, a place in some
insn. The substitution can be undone by undo_all. If INTO is already 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) ...@@ -3501,6 +3496,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
enum rtx_code code = GET_CODE (x); enum rtx_code code = GET_CODE (x);
enum machine_mode mode = GET_MODE (x); enum machine_mode mode = GET_MODE (x);
rtx temp; rtx temp;
rtx reversed;
int i; int i;
/* If this is a commutative operation, put a constant last and a complex /* 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) ...@@ -3922,10 +3918,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
reversing the comparison code if valid. */ reversing the comparison code if valid. */
if (STORE_FLAG_VALUE == -1 if (STORE_FLAG_VALUE == -1
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& reversible_comparison_p (XEXP (x, 0))) && (reversed = reversed_comparison (x, mode, XEXP (XEXP (x, 0), 0),
return gen_rtx_combine (reverse_condition (GET_CODE (XEXP (x, 0))), XEXP (XEXP (x, 0), 1))))
mode, XEXP (XEXP (x, 0), 0), return reversed;
XEXP (XEXP (x, 0), 1));
/* (ashiftrt foo C) where C is the number of bits in FOO minus 1 /* (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 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) ...@@ -4218,14 +4213,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
is 1. This produces better code than the alternative immediately is 1. This produces better code than the alternative immediately
below. */ below. */
if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' 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) == 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 return
gen_unary (NEG, mode, mode, gen_unary (NEG, mode, mode, reversed);
gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))),
mode, XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 0), 1)));
/* If only the low-order bit of X is possibly nonzero, (plus x -1) /* 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 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) ...@@ -4270,10 +4264,10 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (STORE_FLAG_VALUE == 1 if (STORE_FLAG_VALUE == 1
&& XEXP (x, 0) == const1_rtx && XEXP (x, 0) == const1_rtx
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<' && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<'
&& reversible_comparison_p (XEXP (x, 1))) && (reversed = reversed_comparison (XEXP (x, 1), mode,
return gen_binary (reverse_condition (GET_CODE (XEXP (x, 1))), mode,
XEXP (XEXP (x, 1), 0), XEXP (XEXP (x, 1), 0),
XEXP (XEXP (x, 1), 1)); XEXP (XEXP (x, 1), 1))))
return reversed;
/* (minus <foo> (and <foo> (const_int -pow2))) becomes /* (minus <foo> (and <foo> (const_int -pow2))) becomes
(and <foo> (const_int pow2-1)) */ (and <foo> (const_int pow2-1)) */
...@@ -4626,27 +4620,31 @@ simplify_if_then_else (x) ...@@ -4626,27 +4620,31 @@ simplify_if_then_else (x)
int comparison_p = GET_RTX_CLASS (true_code) == '<'; int comparison_p = GET_RTX_CLASS (true_code) == '<';
rtx temp; rtx temp;
int i; int i;
enum rtx_code false_code;
rtx reversed;
/* Simplify storing of the truth value. */ /* Simplify storing of the truth value. */
if (comparison_p && true == const_true_rtx && false == const0_rtx) if (comparison_p && true == const_true_rtx && false == const0_rtx)
return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1)); return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1));
/* Also when the truth value has to be reversed. */ /* Also when the truth value has to be reversed. */
if (comparison_p && reversible_comparison_p (cond) if (comparison_p
&& true == const0_rtx && false == const_true_rtx) && true == const0_rtx && false == const_true_rtx
return gen_binary (reverse_condition (true_code), && (reversed = reversed_comparison (cond, mode, XEXP (cond, 0),
mode, XEXP (cond, 0), XEXP (cond, 1)); XEXP (cond, 1))))
return reversed;
/* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register used /* 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 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. */ 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) && GET_CODE (XEXP (cond, 0)) == REG)
{ {
HOST_WIDE_INT nzb; HOST_WIDE_INT nzb;
rtx from = XEXP (cond, 0); rtx from = XEXP (cond, 0);
enum rtx_code false_code = reverse_condition (true_code);
rtx true_val = XEXP (cond, 1); rtx true_val = XEXP (cond, 1);
rtx false_val = true_val; rtx false_val = true_val;
int swapped = 0; int swapped = 0;
...@@ -4695,7 +4693,8 @@ simplify_if_then_else (x) ...@@ -4695,7 +4693,8 @@ simplify_if_then_else (x)
arm, the false arm is the same as the first operand of the comparison, or 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. */ 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 && (true == pc_rtx
|| (CONSTANT_P (true) || (CONSTANT_P (true)
&& GET_CODE (false) != CONST_INT && false != pc_rtx) && GET_CODE (false) != CONST_INT && false != pc_rtx)
...@@ -4708,9 +4707,9 @@ simplify_if_then_else (x) ...@@ -4708,9 +4707,9 @@ simplify_if_then_else (x)
|| reg_mentioned_p (true, false) || reg_mentioned_p (true, false)
|| rtx_equal_p (false, XEXP (cond, 0)))) || rtx_equal_p (false, XEXP (cond, 0))))
{ {
true_code = reverse_condition (true_code); true_code = reversed_comparison_code (cond, NULL);
SUBST (XEXP (x, 0), SUBST (XEXP (x, 0),
gen_binary (true_code, GET_MODE (cond), XEXP (cond, 0), reversed_comparison (cond, GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1))); XEXP (cond, 1)));
SUBST (XEXP (x, 1), false); SUBST (XEXP (x, 1), false);
...@@ -5211,6 +5210,7 @@ simplify_set (x) ...@@ -5211,6 +5210,7 @@ simplify_set (x)
rtx cond = XEXP (src, 0); rtx cond = XEXP (src, 0);
rtx true_val = const1_rtx; rtx true_val = const1_rtx;
rtx false_arm, true_arm; rtx false_arm, true_arm;
rtx reversed;
if (GET_CODE (cond) == MULT) if (GET_CODE (cond) == MULT)
{ {
...@@ -5236,16 +5236,16 @@ simplify_set (x) ...@@ -5236,16 +5236,16 @@ simplify_set (x)
/* Canonicalize if true_arm is the simpler one. */ /* Canonicalize if true_arm is the simpler one. */
if (GET_RTX_CLASS (GET_CODE (true_arm)) == 'o' if (GET_RTX_CLASS (GET_CODE (true_arm)) == 'o'
&& GET_RTX_CLASS (GET_CODE (false_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; rtx temp = true_arm;
true_arm = false_arm; true_arm = false_arm;
false_arm = temp; false_arm = temp;
cond = gen_rtx_combine (reverse_condition (GET_CODE (cond)), cond = reversed;
GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1));
} }
src = gen_rtx_combine (IF_THEN_ELSE, GET_MODE (src), src = gen_rtx_combine (IF_THEN_ELSE, GET_MODE (src),
...@@ -5279,6 +5279,7 @@ simplify_logical (x, last) ...@@ -5279,6 +5279,7 @@ simplify_logical (x, last)
enum machine_mode mode = GET_MODE (x); enum machine_mode mode = GET_MODE (x);
rtx op0 = XEXP (x, 0); rtx op0 = XEXP (x, 0);
rtx op1 = XEXP (x, 1); rtx op1 = XEXP (x, 1);
rtx reversed;
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
...@@ -5530,9 +5531,9 @@ simplify_logical (x, last) ...@@ -5530,9 +5531,9 @@ simplify_logical (x, last)
if (STORE_FLAG_VALUE == 1 if (STORE_FLAG_VALUE == 1
&& op1 == const1_rtx && op1 == const1_rtx
&& GET_RTX_CLASS (GET_CODE (op0)) == '<' && GET_RTX_CLASS (GET_CODE (op0)) == '<'
&& reversible_comparison_p (op0)) && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
return gen_rtx_combine (reverse_condition (GET_CODE (op0)), XEXP (op0, 1))))
mode, XEXP (op0, 0), XEXP (op0, 1)); return reversed;
/* (lshiftrt foo C) where C is the number of bits in FOO minus 1 /* (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 is (lt foo (const_int 0)), so we can perform the above
...@@ -5552,9 +5553,9 @@ simplify_logical (x, last) ...@@ -5552,9 +5553,9 @@ simplify_logical (x, last)
== (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
&& op1 == const_true_rtx && op1 == const_true_rtx
&& GET_RTX_CLASS (GET_CODE (op0)) == '<' && GET_RTX_CLASS (GET_CODE (op0)) == '<'
&& reversible_comparison_p (op0)) && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
return gen_rtx_combine (reverse_condition (GET_CODE (op0)), XEXP (op0, 1))))
mode, XEXP (op0, 0), XEXP (op0, 1)); return reversed;
break; break;
...@@ -7344,12 +7345,11 @@ if_then_else_cond (x, ptrue, pfalse) ...@@ -7344,12 +7345,11 @@ if_then_else_cond (x, ptrue, pfalse)
if (GET_RTX_CLASS (GET_CODE (cond0)) == '<' if (GET_RTX_CLASS (GET_CODE (cond0)) == '<'
&& GET_RTX_CLASS (GET_CODE (cond1)) == '<' && GET_RTX_CLASS (GET_CODE (cond1)) == '<'
&& reversible_comparison_p (cond1) && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1)
&& ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1))
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0)) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1))) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
|| ((swap_condition (GET_CODE (cond0)) || ((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, 0), XEXP (cond1, 1))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0)))) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x)) && ! side_effects_p (x))
...@@ -7374,12 +7374,11 @@ if_then_else_cond (x, ptrue, pfalse) ...@@ -7374,12 +7374,11 @@ if_then_else_cond (x, ptrue, pfalse)
if (GET_RTX_CLASS (GET_CODE (cond0)) == '<' if (GET_RTX_CLASS (GET_CODE (cond0)) == '<'
&& GET_RTX_CLASS (GET_CODE (cond1)) == '<' && GET_RTX_CLASS (GET_CODE (cond1)) == '<'
&& reversible_comparison_p (cond1) && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1)
&& ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1))
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0)) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1))) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
|| ((swap_condition (GET_CODE (cond0)) || ((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, 0), XEXP (cond1, 1))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0)))) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x)) && ! side_effects_p (x))
...@@ -7527,7 +7526,7 @@ known_cond (x, cond, reg, val) ...@@ -7527,7 +7526,7 @@ known_cond (x, cond, reg, val)
if (comparison_dominates_p (cond, code)) if (comparison_dominates_p (cond, code))
return const_true_rtx; return const_true_rtx;
code = reverse_condition (code); code = combine_reversed_comparison_code (x);
if (code != UNKNOWN if (code != UNKNOWN
&& comparison_dominates_p (cond, code)) && comparison_dominates_p (cond, code))
return const0_rtx; return const0_rtx;
...@@ -10705,21 +10704,22 @@ simplify_comparison (code, pop0, pop1) ...@@ -10705,21 +10704,22 @@ simplify_comparison (code, pop0, pop1)
/* Check for the cases where we simply want the result of the /* Check for the cases where we simply want the result of the
earlier test or the opposite of that result. */ earlier test or the opposite of that result. */
if (code == NE if (code == NE || code == EQ
|| (code == EQ && reversible_comparison_p (op0))
|| (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT || (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
&& (STORE_FLAG_VALUE && (STORE_FLAG_VALUE
& (((HOST_WIDE_INT) 1 & (((HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (op0)) - 1)))) << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
&& (code == LT && (code == LT || (code == GE))))
|| (code == GE && reversible_comparison_p (op0)))))
{ {
code = (code == LT || code == NE code = (code == LT || code == NE
? GET_CODE (op0) : reverse_condition (GET_CODE (op0))); ? GET_CODE (op0) : combine_reversed_comparison_code (op0));
if (code != UNKNOWN)
{
op0 = tem, op1 = tem1; op0 = tem, op1 = tem1;
continue; continue;
} }
}
break; break;
case IOR: case IOR:
...@@ -11121,42 +11121,38 @@ simplify_comparison (code, pop0, pop1) ...@@ -11121,42 +11121,38 @@ simplify_comparison (code, pop0, pop1)
return code; return code;
} }
/* Return 1 if we know that X, a comparison operation, is not operating /* Like jump.c' reversed_comparison_code, but use combine infrastructure for
on a floating-point value or is EQ or NE, meaning that we can safely searching backward. */
reverse it. */ enum rtx_code
combine_reversed_comparison_code (exp)
static int rtx exp;
reversible_comparison_p (x)
rtx x;
{ {
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT enum rtx_code code1 = reversed_comparison_code (exp, NULL);
|| flag_fast_math rtx x;
|| GET_CODE (x) == NE || GET_CODE (x) == EQ
|| GET_CODE (x) == UNORDERED || GET_CODE (x) == ORDERED)
return 1;
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;
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 /* Otherwise try and find where the condition codes were last set and
use that. */ use that. */
x = get_last_value (XEXP (x, 0)); x = get_last_value (XEXP (x, 0));
return (x && GET_CODE (x) == COMPARE if (GET_CODE (x) != COMPARE)
&& ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))); return UNKNOWN;
return reversed_comparison_code_parts (GET_CODE (exp),
default: XEXP (x, 0), XEXP (x, 1), NULL);
return 0; }
} /* 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 /* 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)); ...@@ -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 nonmemory_no_elim_operand PARAMS ((rtx, enum machine_mode));
extern int q_regs_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 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 sse_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int fcmov_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)); extern int cmp_fp_expander_operand PARAMS ((rtx, enum machine_mode));
......
...@@ -386,7 +386,6 @@ int ix86_align_jumps; ...@@ -386,7 +386,6 @@ int ix86_align_jumps;
static void output_pic_addr_const PARAMS ((FILE *, rtx, int)); static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode, static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
int, int, FILE *)); 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_int_compare PARAMS ((enum rtx_code, rtx, rtx));
static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code, static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
rtx *, rtx *)); rtx *, rtx *));
...@@ -1267,30 +1266,6 @@ non_q_regs_operand (op, mode) ...@@ -1267,30 +1266,6 @@ non_q_regs_operand (op, mode)
return NON_QI_REG_P (op); 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 /* Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS
insns. */ insns. */
int int
...@@ -1308,25 +1283,33 @@ ix86_comparison_operator (op, mode) ...@@ -1308,25 +1283,33 @@ ix86_comparison_operator (op, mode)
enum machine_mode mode; enum machine_mode mode;
{ {
enum machine_mode inmode; enum machine_mode inmode;
enum rtx_code code = GET_CODE (op);
if (mode != VOIDmode && GET_MODE (op) != mode) if (mode != VOIDmode && GET_MODE (op) != mode)
return 0; 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: case EQ: case NE:
return 1; return 1;
case LT: case GE: case LT: case GE:
inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode || inmode == CCGCmode if (inmode == CCmode || inmode == CCGCmode
|| inmode == CCGOCmode || inmode == CCNOmode) || inmode == CCGOCmode || inmode == CCNOmode)
return 1; return 1;
return 0; return 0;
case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU: case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode) if (inmode == CCmode)
return 1; return 1;
return 0; return 0;
case GT: case LE: case GT: case LE:
inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode || inmode == CCGCmode || inmode == CCNOmode) if (inmode == CCmode || inmode == CCGCmode || inmode == CCNOmode)
return 1; return 1;
return 0; return 0;
...@@ -1343,16 +1326,30 @@ fcmov_comparison_operator (op, mode) ...@@ -1343,16 +1326,30 @@ fcmov_comparison_operator (op, mode)
enum machine_mode mode; enum machine_mode mode;
{ {
enum machine_mode inmode = GET_MODE (XEXP (op, 0)); enum machine_mode inmode = GET_MODE (XEXP (op, 0));
enum rtx_code code = GET_CODE (op);
if (mode != VOIDmode && GET_MODE (op) != mode) if (mode != VOIDmode && GET_MODE (op) != mode)
return 0; return 0;
switch (GET_CODE (op)) if (GET_RTX_CLASS (code) != '<')
{ return 0;
case EQ: case NE: inmode = GET_MODE (XEXP (op, 0));
return 1;
case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
if (inmode == CCFPmode || inmode == CCFPUmode) 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 1;
return 0; return 0;
case ORDERED: case UNORDERED:
case EQ: case NE:
return 1;
default: default:
return 0; return 0;
} }
...@@ -3102,6 +3099,15 @@ put_condition_code (code, mode, reverse, fp, file) ...@@ -3102,6 +3099,15 @@ put_condition_code (code, mode, reverse, fp, file)
{ {
const char *suffix; 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) if (reverse)
code = reverse_condition (code); code = reverse_condition (code);
...@@ -4611,41 +4617,6 @@ ix86_match_ccmode (insn, req_mode) ...@@ -4611,41 +4617,6 @@ ix86_match_ccmode (insn, req_mode)
return (GET_MODE (SET_SRC (set)) == set_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. */ /* Generate insn patterns to do an integer compare of OPERANDS. */
static rtx static rtx
...@@ -4960,8 +4931,7 @@ ix86_expand_fp_compare (code, op0, op1, scratch) ...@@ -4960,8 +4931,7 @@ ix86_expand_fp_compare (code, op0, op1, scratch)
} }
/* The FP codes work out to act like unsigned. */ /* The FP codes work out to act like unsigned. */
code = ix86_fp_compare_code_to_integer (first_code); intcmp_mode = fpcmp_mode;
intcmp_mode = CCmode;
} }
else else
{ {
...@@ -4970,72 +4940,6 @@ ix86_expand_fp_compare (code, op0, op1, scratch) ...@@ -4970,72 +4940,6 @@ ix86_expand_fp_compare (code, op0, op1, scratch)
tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9); tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9);
emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2)); emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
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
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:
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 /* In the unordered case, we have to check C2 for NaN's, which
doesn't happen to work out to anything nice combination-wise. 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 So do some bit twiddling on the value we've got in AH to come
...@@ -5045,36 +4949,97 @@ ix86_expand_fp_compare (code, op0, op1, scratch) ...@@ -5045,36 +4949,97 @@ ix86_expand_fp_compare (code, op0, op1, scratch)
switch (code) switch (code)
{ {
case GT: case GT:
case UNGT:
if (code == GT || !TARGET_IEEE_FP)
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45))); emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
code = EQ; code = EQ;
}
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; break;
case LT: case LT:
case UNLT:
if (code == LT && TARGET_IEEE_FP)
{
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x01))); emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x01)));
intcmp_mode = CCmode; intcmp_mode = CCmode;
code = EQ; code = EQ;
}
else
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01)));
code = NE;
}
break; break;
case GE: case GE:
case UNGE:
if (code == GE || !TARGET_IEEE_FP)
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05))); emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05)));
code = EQ; 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; break;
case LE: case LE:
case UNLE:
if (code == LE && TARGET_IEEE_FP)
{
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx)); emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40))); emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
intcmp_mode = CCmode; intcmp_mode = CCmode;
code = LTU; code = LTU;
}
else
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
code = NE;
}
break; break;
case EQ: case EQ:
case UNEQ:
if (code == EQ && TARGET_IEEE_FP)
{
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40))); emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
intcmp_mode = CCmode; intcmp_mode = CCmode;
code = EQ; code = EQ;
}
else
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
code = NE;
break;
}
break; break;
case NE: case NE:
case LTGT:
if (code == NE && TARGET_IEEE_FP)
{
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45))); emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, GEN_INT (0x40))); emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch,
GEN_INT (0x40)));
code = NE; code = NE;
}
else
{
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
code = EQ;
}
break; break;
case UNORDERED: case UNORDERED:
...@@ -5085,40 +5050,11 @@ ix86_expand_fp_compare (code, op0, op1, scratch) ...@@ -5085,40 +5050,11 @@ ix86_expand_fp_compare (code, op0, op1, scratch)
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04))); emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
code = EQ; code = EQ;
break; 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)));
intcmp_mode = CCmode;
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: default:
abort (); abort ();
} }
} }
}
/* Return the test that should be put into the flags user, i.e. /* Return the test that should be put into the flags user, i.e.
the bcc, scc, or cmov instruction. */ the bcc, scc, or cmov instruction. */
......
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