Commit c6fb08ad by Paolo Bonzini Committed by Paolo Bonzini

combine.c (combine_simplify_rtx): Adjust call to use simplify_relational_operation.

2004-04-29  Paolo Bonzini  <bonzini@gnu.org>

        * combine.c (combine_simplify_rtx): Adjust call to use
        simplify_relational_operation.  Do not use SELECT_CC_MODE
        when a comparison already has a MODE_CC mode.
        (simplify_set): simplify_relational_operation may now
        return another relational expression.
        * cse.c (fold_rtx): simplify_relational_operation now
        takes of computing the comparison mode.
        * dojump.c (compare_from_rtx): Use simplify_relational_operation,
        remove dead code.
        (do_compare_rtx_and_jump): Likewise.
        * integrate.c (subst_constants): simplify_relational_operation
        may now return another relational expression.
        * simplify-rtx.c (simplify_gen_relational): Move most code to
        the new simplify_relational_operation and
        simplify_relational_operation_1 functions.
        (simplify_relational_operation): Rewritten.
        (simplify_relational_operation_1): New function.
        (simplify_ternary_operation): simplify_relational_operation
        may now return another relational expression.
        (simplify_rtx): Remove unnecessary temp variable.

From-SVN: r81282
parent 6cf1ac42
2004-04-29 Paolo Bonzini <bonzini@gnu.org>
* combine.c (combine_simplify_rtx): Adjust call to use
simplify_relational_operation. Do not use SELECT_CC_MODE
when a comparison already has a MODE_CC mode.
(simplify_set): simplify_relational_operation may now
return another relational expression.
* cse.c (fold_rtx): simplify_relational_operation now
takes of computing the comparison mode.
* dojump.c (compare_from_rtx): Use simplify_relational_operation,
remove dead code.
(do_compare_rtx_and_jump): Likewise.
* integrate.c (subst_constants): simplify_relational_operation
may now return another relational expression.
* simplify-rtx.c (simplify_gen_relational): Move most code to
the new simplify_relational_operation and
simplify_relational_operation_1 functions.
(simplify_relational_operation): Rewritten.
(simplify_relational_operation_1): New function.
(simplify_ternary_operation): simplify_relational_operation
may now return another relational expression.
(simplify_rtx): Remove unnecessary temp variable.
2004-04-29 Uros Bizjak <uros@kss-loka.si>
* reg-stack.c (swap_to_top): New function.
......
......@@ -3924,21 +3924,11 @@ fold_rtx (rtx x, rtx insn)
}
}
new = simplify_relational_operation (code, mode,
(mode_arg0 != VOIDmode
? mode_arg0
: (GET_MODE (const_arg0
? const_arg0
: folded_arg0)
!= VOIDmode)
? GET_MODE (const_arg0
? const_arg0
: folded_arg0)
: GET_MODE (const_arg1
? const_arg1
: folded_arg1)),
const_arg0 ? const_arg0 : folded_arg0,
const_arg1 ? const_arg1 : folded_arg1);
{
rtx op0 = const_arg0 ? const_arg0 : folded_arg0;
rtx op1 = const_arg1 ? const_arg1 : folded_arg1;
new = simplify_relational_operation (code, mode, mode_arg0, op0, op1);
}
break;
case RTX_BIN_ARITH:
......
......@@ -820,7 +820,6 @@ rtx
compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
enum machine_mode mode, rtx size)
{
enum rtx_code ucode;
rtx tem;
/* If one operand is constant, make it the second one. Only do this
......@@ -842,32 +841,19 @@ compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
do_pending_stack_adjust ();
ucode = unsignedp ? unsigned_condition (code) : code;
tem = simplify_const_relational_operation (ucode, mode, op0, op1);
if (tem != 0)
code = unsignedp ? unsigned_condition (code) : code;
if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
op0, op1)))
{
if (CONSTANT_P (tem))
return tem;
#if 0
/* There's no need to do this now that combine.c can eliminate lots of
sign extensions. This can be less efficient in certain cases on other
machines. */
/* If this is a signed equality comparison, we can do it as an
unsigned comparison since zero-extension is cheaper than sign
extension and comparisons with zero are done as unsigned. This is
the case even on machines that can do fast sign extension, since
zero-extension is easier to combine with other operations than
sign-extension is. If we are comparing against a constant, we must
convert it to what it would look like unsigned. */
if ((code == EQ || code == NE) && ! unsignedp
&& GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
{
if (GET_CODE (op1) == CONST_INT
&& (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
unsignedp = 1;
code = GET_CODE (tem);
mode = GET_MODE (tem);
op0 = XEXP (tem, 0);
op1 = XEXP (tem, 1);
unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
}
#endif
emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
......@@ -889,7 +875,6 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
enum machine_mode mode, rtx size, rtx if_false_label,
rtx if_true_label)
{
enum rtx_code ucode;
rtx tem;
int dummy_true_label = 0;
......@@ -921,44 +906,25 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
do_pending_stack_adjust ();
ucode = unsignedp ? unsigned_condition (code) : code;
tem = simplify_const_relational_operation (ucode, mode, op0, op1);
if (tem != 0)
code = unsignedp ? unsigned_condition (code) : code;
if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
op0, op1)))
{
if (tem == const_true_rtx)
if (CONSTANT_P (tem))
{
if (if_true_label)
emit_jump (if_true_label);
}
else
{
if (if_false_label)
emit_jump (if_false_label);
}
rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode))
? if_false_label : if_true_label;
if (label)
emit_jump (label);
return;
}
#if 0
/* There's no need to do this now that combine.c can eliminate lots of
sign extensions. This can be less efficient in certain cases on other
machines. */
/* If this is a signed equality comparison, we can do it as an
unsigned comparison since zero-extension is cheaper than sign
extension and comparisons with zero are done as unsigned. This is
the case even on machines that can do fast sign extension, since
zero-extension is easier to combine with other operations than
sign-extension is. If we are comparing against a constant, we must
convert it to what it would look like unsigned. */
if ((code == EQ || code == NE) && ! unsignedp
&& GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
{
if (GET_CODE (op1) == CONST_INT
&& (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
unsignedp = 1;
code = GET_CODE (tem);
mode = GET_MODE (tem);
op0 = XEXP (tem, 0);
op1 = XEXP (tem, 1);
unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
}
#endif
if (! if_true_label)
{
......
......@@ -2738,6 +2738,7 @@ subst_constants (rtx *loc, rtx insn, struct inline_remap *map, int memonly)
if (op_mode == VOIDmode)
op_mode = GET_MODE (XEXP (x, 1));
new = simplify_relational_operation (code, GET_MODE (x), op_mode,
XEXP (x, 0), XEXP (x, 1));
break;
......@@ -2766,15 +2767,18 @@ subst_constants (rtx *loc, rtx insn, struct inline_remap *map, int memonly)
{
/* We have compare of two VOIDmode constants for which
we recorded the comparison mode. */
rtx temp =
simplify_const_relational_operation (GET_CODE (op0),
map->compare_mode,
XEXP (op0, 0),
rtx tem =
simplify_gen_relational (GET_CODE (op0), GET_MODE (op0),
map->compare_mode, XEXP (op0, 0),
XEXP (op0, 1));
if (temp == const0_rtx)
if (GET_CODE (tem) != CONST_INT)
new = simplify_ternary_operation (code, GET_MODE (x),
op0_mode, tem, XEXP (x, 1),
XEXP (x, 2));
else if (tem == const0_rtx)
new = XEXP (x, 2);
else if (temp == const1_rtx)
else
new = XEXP (x, 1);
}
}
......
......@@ -58,6 +58,8 @@ static rtx simplify_immed_subreg (enum machine_mode, rtx, enum machine_mode,
unsigned int);
static rtx simplify_associative_operation (enum rtx_code, enum machine_mode,
rtx, rtx);
static rtx simplify_relational_operation_1 (enum rtx_code, enum machine_mode,
enum machine_mode, rtx, rtx);
/* Negate a CONST_INT rtx, truncating (because a conversion from a
maximally negative number can overflow). */
......@@ -223,8 +225,7 @@ simplify_gen_ternary (enum rtx_code code, enum machine_mode mode,
}
/* Likewise, for relational operations.
CMP_MODE specifies mode comparison is done in.
*/
CMP_MODE specifies mode comparison is done in. */
rtx
simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
......@@ -232,46 +233,9 @@ simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
{
rtx tem;
if (cmp_mode == VOIDmode)
cmp_mode = GET_MODE (op0);
if (cmp_mode == VOIDmode)
cmp_mode = GET_MODE (op1);
if (cmp_mode != VOIDmode)
{
tem = simplify_relational_operation (code, mode, cmp_mode, op0, op1);
if (tem)
if (0 != (tem = simplify_relational_operation (code, mode, cmp_mode,
op0, op1)))
return tem;
}
/* For the following tests, ensure const0_rtx is op1. */
if (swap_commutative_operands_p (op0, op1)
|| (op0 == const0_rtx && op1 != const0_rtx))
tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
/* If op0 is a compare, extract the comparison arguments from it. */
if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
return simplify_gen_relational (code, mode, VOIDmode,
XEXP (op0, 0), XEXP (op0, 1));
/* If op0 is a comparison, extract the comparison arguments form it. */
if (COMPARISON_P (op0) && op1 == const0_rtx)
{
if (code == NE)
{
if (GET_MODE (op0) == mode)
return op0;
return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode,
XEXP (op0, 0), XEXP (op0, 1));
}
else if (code == EQ)
{
enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
if (new != UNKNOWN)
return simplify_gen_relational (new, mode, VOIDmode,
XEXP (op0, 0), XEXP (op0, 1));
}
}
return gen_rtx_fmt_ee (code, mode, op0, op1);
}
......@@ -1201,7 +1165,6 @@ simplify_associative_operation (enum rtx_code code, enum machine_mode mode,
Don't use this for relational operations such as EQ or LT.
Use simplify_relational_operation instead. */
rtx
simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
rtx op0, rtx op1)
......@@ -2662,10 +2625,102 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
}
/* Like simplify_binary_operation except used for relational operators.
MODE is the mode of the operands, not that of the result. If MODE
is VOIDmode, both operands must also be VOIDmode and we compare the
operands in "infinite precision".
MODE is the mode of the result. If MODE is VOIDmode, both operands must
also be VOIDmode.
CMP_MODE specifies in which mode the comparison is done in, so it is
the mode of the operands. If CMP_MODE is VOIDmode, it is taken from
the operands or, if both are VOIDmode, the operands are compared in
"infinite precision". */
rtx
simplify_relational_operation (enum rtx_code code, enum machine_mode mode,
enum machine_mode cmp_mode, rtx op0, rtx op1)
{
rtx tem, trueop0, trueop1;
if (cmp_mode == VOIDmode)
cmp_mode = GET_MODE (op0);
if (cmp_mode == VOIDmode)
cmp_mode = GET_MODE (op1);
tem = simplify_const_relational_operation (code, cmp_mode, op0, op1);
if (tem)
{
#ifdef FLOAT_STORE_FLAG_VALUE
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
if (tem == const0_rtx)
return CONST0_RTX (mode);
else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
REAL_VALUE_TYPE val;
val = FLOAT_STORE_FLAG_VALUE (mode);
return CONST_DOUBLE_FROM_REAL_VALUE (val, mode);
}
}
#endif
return tem;
}
/* For the following tests, ensure const0_rtx is op1. */
if (swap_commutative_operands_p (op0, op1)
|| (op0 == const0_rtx && op1 != const0_rtx))
tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
/* If op0 is a compare, extract the comparison arguments from it. */
if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
return simplify_relational_operation (code, mode, VOIDmode,
XEXP (op0, 0), XEXP (op0, 1));
if (mode == VOIDmode
|| GET_MODE_CLASS (cmp_mode) == MODE_CC
|| CC0_P (op0))
return NULL_RTX;
trueop0 = avoid_constant_pool_reference (op0);
trueop1 = avoid_constant_pool_reference (op1);
return simplify_relational_operation_1 (code, mode, cmp_mode,
trueop0, trueop1);
}
/* This part of simplify_relational_operation is only used when CMP_MODE
is not in class MODE_CC (i.e. it is a real comparison).
MODE is the mode of the result, while CMP_MODE specifies in which
mode the comparison is done in, so it is the mode of the operands. */
rtx
simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode,
enum machine_mode cmp_mode, rtx op0, rtx op1)
{
if (GET_CODE (op1) == CONST_INT)
{
if (INTVAL (op1) == 0 && COMPARISON_P (op0))
{
/* If op0 is a comparison, extract the comparison arguments form it. */
if (code == NE)
{
if (GET_MODE (op0) == cmp_mode)
return simplify_rtx (op0);
else
return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode,
XEXP (op0, 0), XEXP (op0, 1));
}
else if (code == EQ)
{
enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
if (new != UNKNOWN)
return simplify_gen_relational (new, mode, VOIDmode,
XEXP (op0, 0), XEXP (op0, 1));
}
}
}
return NULL_RTX;
}
/* Check if the given comparison (done in the given MODE) is actually a
tautology or a contradiction.
If no simplification is possible, this function returns zero.
Otherwise, it returns either const_true_rtx or const0_rtx. */
......@@ -2955,36 +3010,6 @@ simplify_const_relational_operation (enum rtx_code code,
}
}
/* Like simplify_binary_operation except used for relational operators.
MODE is the mode of the result, and CMP_MODE is the mode of the operands.
If CMP_MODE is VOIDmode, both operands must also be VOIDmode and we
compare the operands in "infinite precision". */
rtx
simplify_relational_operation (enum rtx_code code,
enum machine_mode mode ATTRIBUTE_UNUSED,
enum machine_mode cmp_mode, rtx op0, rtx op1)
{
rtx tmp;
tmp = simplify_const_relational_operation (code, cmp_mode, op0, op1);
if (tmp)
{
#ifdef FLOAT_STORE_FLAG_VALUE
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
if (tmp == const0_rtx)
return CONST0_RTX (mode);
return CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE (mode),
mode);
}
#endif
return tmp;
}
return NULL_RTX;
}
/* Simplify CODE, an operation with result mode MODE and three operands,
OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became
a constant. Return 0 if no simplifications is possible. */
......@@ -3078,20 +3103,6 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
? GET_MODE (XEXP (op0, 1))
: GET_MODE (XEXP (op0, 0)));
rtx temp;
if (cmp_mode == VOIDmode)
cmp_mode = op0_mode;
temp = simplify_const_relational_operation (GET_CODE (op0),
cmp_mode,
XEXP (op0, 0),
XEXP (op0, 1));
/* See if any simplifications were possible. */
if (temp == const0_rtx)
return op2;
else if (temp == const_true_rtx)
return op1;
else if (temp)
abort ();
/* Look for happy constants in op1 and op2. */
if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
......@@ -3112,7 +3123,23 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
else
break;
return gen_rtx_fmt_ee (code, mode, XEXP (op0, 0), XEXP (op0, 1));
return simplify_gen_relational (code, op0_mode, cmp_mode,
XEXP (op0, 0), XEXP (op0, 1));
}
if (cmp_mode == VOIDmode)
cmp_mode = op0_mode;
temp = simplify_relational_operation (GET_CODE (op0), op0_mode,
cmp_mode, XEXP (op0, 0),
XEXP (op0, 1));
/* See if any simplifications were possible. */
if (temp)
{
if (GET_CODE (temp) == CONST_INT)
return temp == const0_rtx ? op2 : op1;
else if (temp)
return gen_rtx_IF_THEN_ELSE (mode, temp, op1, op2);
}
}
break;
......@@ -3721,7 +3748,6 @@ simplify_rtx (rtx x)
{
enum rtx_code code = GET_CODE (x);
enum machine_mode mode = GET_MODE (x);
rtx temp;
switch (GET_RTX_CLASS (code))
{
......@@ -3745,13 +3771,13 @@ simplify_rtx (rtx x)
case RTX_COMPARE:
case RTX_COMM_COMPARE:
temp = simplify_relational_operation (code, mode,
return simplify_relational_operation (code, mode,
((GET_MODE (XEXP (x, 0))
!= VOIDmode)
? GET_MODE (XEXP (x, 0))
: GET_MODE (XEXP (x, 1))),
XEXP (x, 0), XEXP (x, 1));
return temp;
XEXP (x, 0),
XEXP (x, 1));
case RTX_EXTRA:
if (code == SUBREG)
......
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