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> 2004-04-29 Uros Bizjak <uros@kss-loka.si>
* reg-stack.c (swap_to_top): New function. * reg-stack.c (swap_to_top): New function.
......
...@@ -3924,21 +3924,11 @@ fold_rtx (rtx x, rtx insn) ...@@ -3924,21 +3924,11 @@ fold_rtx (rtx x, rtx insn)
} }
} }
new = simplify_relational_operation (code, mode, {
(mode_arg0 != VOIDmode rtx op0 = const_arg0 ? const_arg0 : folded_arg0;
? mode_arg0 rtx op1 = const_arg1 ? const_arg1 : folded_arg1;
: (GET_MODE (const_arg0 new = simplify_relational_operation (code, mode, mode_arg0, op0, op1);
? 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);
break; break;
case RTX_BIN_ARITH: case RTX_BIN_ARITH:
......
...@@ -820,7 +820,6 @@ rtx ...@@ -820,7 +820,6 @@ rtx
compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp, compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
enum machine_mode mode, rtx size) enum machine_mode mode, rtx size)
{ {
enum rtx_code ucode;
rtx tem; rtx tem;
/* If one operand is constant, make it the second one. Only do this /* 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, ...@@ -842,32 +841,19 @@ compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
do_pending_stack_adjust (); do_pending_stack_adjust ();
ucode = unsignedp ? unsigned_condition (code) : code; code = unsignedp ? unsigned_condition (code) : code;
tem = simplify_const_relational_operation (ucode, mode, op0, op1); if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
if (tem != 0) op0, op1)))
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 if (CONSTANT_P (tem))
&& (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1)) return tem;
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); 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, ...@@ -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, enum machine_mode mode, rtx size, rtx if_false_label,
rtx if_true_label) rtx if_true_label)
{ {
enum rtx_code ucode;
rtx tem; rtx tem;
int dummy_true_label = 0; int dummy_true_label = 0;
...@@ -921,44 +906,25 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, ...@@ -921,44 +906,25 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
do_pending_stack_adjust (); do_pending_stack_adjust ();
ucode = unsignedp ? unsigned_condition (code) : code; code = unsignedp ? unsigned_condition (code) : code;
tem = simplify_const_relational_operation (ucode, mode, op0, op1); if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
if (tem != 0) op0, op1)))
{ {
if (tem == const_true_rtx) if (CONSTANT_P (tem))
{ {
if (if_true_label) rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode))
emit_jump (if_true_label); ? if_false_label : if_true_label;
} if (label)
else emit_jump (label);
{ return;
if (if_false_label) }
emit_jump (if_false_label);
}
return;
}
#if 0 code = GET_CODE (tem);
/* There's no need to do this now that combine.c can eliminate lots of mode = GET_MODE (tem);
sign extensions. This can be less efficient in certain cases on other op0 = XEXP (tem, 0);
machines. */ op1 = XEXP (tem, 1);
unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
/* 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;
} }
#endif
if (! if_true_label) if (! if_true_label)
{ {
......
...@@ -2738,6 +2738,7 @@ subst_constants (rtx *loc, rtx insn, struct inline_remap *map, int memonly) ...@@ -2738,6 +2738,7 @@ subst_constants (rtx *loc, rtx insn, struct inline_remap *map, int memonly)
if (op_mode == VOIDmode) if (op_mode == VOIDmode)
op_mode = GET_MODE (XEXP (x, 1)); op_mode = GET_MODE (XEXP (x, 1));
new = simplify_relational_operation (code, GET_MODE (x), op_mode, new = simplify_relational_operation (code, GET_MODE (x), op_mode,
XEXP (x, 0), XEXP (x, 1)); XEXP (x, 0), XEXP (x, 1));
break; break;
...@@ -2766,15 +2767,18 @@ subst_constants (rtx *loc, rtx insn, struct inline_remap *map, int memonly) ...@@ -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 have compare of two VOIDmode constants for which
we recorded the comparison mode. */ we recorded the comparison mode. */
rtx temp = rtx tem =
simplify_const_relational_operation (GET_CODE (op0), simplify_gen_relational (GET_CODE (op0), GET_MODE (op0),
map->compare_mode, map->compare_mode, XEXP (op0, 0),
XEXP (op0, 0), XEXP (op0, 1));
XEXP (op0, 1));
if (GET_CODE (tem) != CONST_INT)
if (temp == const0_rtx) 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); new = XEXP (x, 2);
else if (temp == const1_rtx) else
new = XEXP (x, 1); new = XEXP (x, 1);
} }
} }
......
...@@ -58,6 +58,8 @@ static rtx simplify_immed_subreg (enum machine_mode, rtx, enum machine_mode, ...@@ -58,6 +58,8 @@ static rtx simplify_immed_subreg (enum machine_mode, rtx, enum machine_mode,
unsigned int); unsigned int);
static rtx simplify_associative_operation (enum rtx_code, enum machine_mode, static rtx simplify_associative_operation (enum rtx_code, enum machine_mode,
rtx, rtx); 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 /* Negate a CONST_INT rtx, truncating (because a conversion from a
maximally negative number can overflow). */ maximally negative number can overflow). */
...@@ -221,10 +223,9 @@ simplify_gen_ternary (enum rtx_code code, enum machine_mode mode, ...@@ -221,10 +223,9 @@ simplify_gen_ternary (enum rtx_code code, enum machine_mode mode,
return gen_rtx_fmt_eee (code, mode, op0, op1, op2); return gen_rtx_fmt_eee (code, mode, op0, op1, op2);
} }
/* Likewise, for relational operations. /* Likewise, for relational operations.
CMP_MODE specifies mode comparison is done in. CMP_MODE specifies mode comparison is done in. */
*/
rtx rtx
simplify_gen_relational (enum rtx_code code, enum machine_mode mode, 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, ...@@ -232,46 +233,9 @@ simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
{ {
rtx tem; rtx tem;
if (cmp_mode == VOIDmode) if (0 != (tem = simplify_relational_operation (code, mode, cmp_mode,
cmp_mode = GET_MODE (op0); op0, op1)))
if (cmp_mode == VOIDmode) return tem;
cmp_mode = GET_MODE (op1);
if (cmp_mode != VOIDmode)
{
tem = simplify_relational_operation (code, mode, cmp_mode, op0, op1);
if (tem)
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); return gen_rtx_fmt_ee (code, mode, op0, op1);
} }
...@@ -1201,7 +1165,6 @@ simplify_associative_operation (enum rtx_code code, enum machine_mode mode, ...@@ -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. Don't use this for relational operations such as EQ or LT.
Use simplify_relational_operation instead. */ Use simplify_relational_operation instead. */
rtx rtx
simplify_binary_operation (enum rtx_code code, enum machine_mode mode, simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
rtx op0, rtx op1) rtx op0, rtx op1)
...@@ -2662,10 +2625,102 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0, ...@@ -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. /* Like simplify_binary_operation except used for relational operators.
MODE is the mode of the operands, not that of the result. If MODE MODE is the mode of the result. If MODE is VOIDmode, both operands must
is VOIDmode, both operands must also be VOIDmode and we compare the also be VOIDmode.
operands in "infinite precision".
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. If no simplification is possible, this function returns zero.
Otherwise, it returns either const_true_rtx or const0_rtx. */ Otherwise, it returns either const_true_rtx or const0_rtx. */
...@@ -2954,36 +3009,6 @@ simplify_const_relational_operation (enum rtx_code code, ...@@ -2954,36 +3009,6 @@ simplify_const_relational_operation (enum rtx_code code,
abort (); abort ();
} }
} }
/* 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, /* 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 OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became
...@@ -3078,20 +3103,6 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode, ...@@ -3078,20 +3103,6 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
? GET_MODE (XEXP (op0, 1)) ? GET_MODE (XEXP (op0, 1))
: GET_MODE (XEXP (op0, 0))); : GET_MODE (XEXP (op0, 0)));
rtx temp; 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. */ /* Look for happy constants in op1 and op2. */
if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT) 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, ...@@ -3112,7 +3123,23 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
else else
break; 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; break;
...@@ -3721,7 +3748,6 @@ simplify_rtx (rtx x) ...@@ -3721,7 +3748,6 @@ simplify_rtx (rtx x)
{ {
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;
switch (GET_RTX_CLASS (code)) switch (GET_RTX_CLASS (code))
{ {
...@@ -3745,13 +3771,13 @@ simplify_rtx (rtx x) ...@@ -3745,13 +3771,13 @@ simplify_rtx (rtx x)
case RTX_COMPARE: case RTX_COMPARE:
case RTX_COMM_COMPARE: case RTX_COMM_COMPARE:
temp = simplify_relational_operation (code, mode, return simplify_relational_operation (code, mode,
((GET_MODE (XEXP (x, 0)) ((GET_MODE (XEXP (x, 0))
!= VOIDmode) != VOIDmode)
? GET_MODE (XEXP (x, 0)) ? GET_MODE (XEXP (x, 0))
: GET_MODE (XEXP (x, 1))), : GET_MODE (XEXP (x, 1))),
XEXP (x, 0), XEXP (x, 1)); XEXP (x, 0),
return temp; XEXP (x, 1));
case RTX_EXTRA: case RTX_EXTRA:
if (code == SUBREG) 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