Commit 9210df58 by Richard Kenner

(REVERSIBLE_CC_MODE): Add default definition.

(reversible_comparison_p): REVERSIBLE_CC_MODE.

(subst): Always simplify true and false arms if if_then_else_cond succeeds.
(subst, case IF_THEN_ELSE): More canonicalizations; delete some redundant
tests.
(if_then_else_cond): Canonicalize (OP (mult COMP A) (mult REV_COMP B)).
(gen_binary): Simplify (REL_OP (compare X Y) 0) here.

From-SVN: r6540
parent be8fe470
...@@ -119,6 +119,13 @@ static int combine_successes; ...@@ -119,6 +119,13 @@ static int combine_successes;
/* Totals over entire compilation. */ /* Totals over entire compilation. */
static int total_attempts, total_merges, total_extras, total_successes; static int total_attempts, total_merges, total_extras, total_successes;
/* Define a defulat 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.
...@@ -2989,6 +2996,14 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -2989,6 +2996,14 @@ subst (x, from, to, in_dest, unique_copy)
rtx cop1 = const0_rtx; rtx cop1 = const0_rtx;
enum rtx_code cond_code = simplify_comparison (NE, &cond, &cop1); enum rtx_code cond_code = simplify_comparison (NE, &cond, &cop1);
/* Simplify the alternative arms; this may collapse the true and
false arms to store-flag values. */
true = subst (true, pc_rtx, pc_rtx, 0, 0);
false = subst (false, pc_rtx, pc_rtx, 0, 0);
/* Restarting if we generate a store-flag expression will cause
us to loop. Just drop through in this case. */
/* If the result values are STORE_FLAG_VALUE and zero, we can /* If the result values are STORE_FLAG_VALUE and zero, we can
just make the comparison operation. */ just make the comparison operation. */
if (true == const_true_rtx && false == const0_rtx) if (true == const_true_rtx && false == const0_rtx)
...@@ -3010,12 +3025,15 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -3010,12 +3025,15 @@ subst (x, from, to, in_dest, unique_copy)
gen_binary (reverse_condition (cond_code), gen_binary (reverse_condition (cond_code),
mode, cond, cop1)); mode, cond, cop1));
else else
x = gen_rtx (IF_THEN_ELSE, mode, {
gen_binary (cond_code, VOIDmode, cond, cop1), x = gen_rtx (IF_THEN_ELSE, mode,
subst (true, pc_rtx, pc_rtx, 0, 0), gen_binary (cond_code, VOIDmode, cond, cop1),
subst (false, pc_rtx, pc_rtx, 0, 0)); true, false);
goto restart;
}
goto restart; code = GET_CODE (x);
op0_mode = VOIDmode;
} }
} }
...@@ -3815,6 +3833,21 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -3815,6 +3833,21 @@ subst (x, from, to, in_dest, unique_copy)
break; break;
case IF_THEN_ELSE: case IF_THEN_ELSE:
/* Simplify storing of the truth value. */
if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& XEXP (x, 1) == const_true_rtx
&& XEXP (x, 2) == const0_rtx)
return gen_binary (GET_CODE (XEXP (x, 0)), mode, XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 0), 1));
/* Also when the truth value has to be reversed. */
if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& reversible_comparison_p (XEXP (x, 0))
&& XEXP (x, 1) == const0_rtx
&& XEXP (x, 2) == const_true_rtx)
return gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))),
mode, XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 0), 1));
/* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register /* 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 used in it is being compared against certain values. Get the
true and false comparisons and see if that says anything about the true and false comparisons and see if that says anything about the
...@@ -3874,13 +3907,24 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -3874,13 +3907,24 @@ subst (x, from, to, in_dest, unique_copy)
/* If we have (if_then_else FOO (pc) (label_ref BAR)) and FOO can be /* If we have (if_then_else FOO (pc) (label_ref BAR)) and FOO can be
reversed, do so to avoid needing two sets of patterns for reversed, do so to avoid needing two sets of patterns for
subtract-and-branch insns. Similarly if we have a constant in that subtract-and-branch insns. Similarly if we have a constant in the
position or if the third operand is the same as the first operand true arm, the false arm is the same as the first operand of the
of the comparison. */ comparison, or the false arm is more complicated than the true
arm. */
if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& reversible_comparison_p (XEXP (x, 0)) && reversible_comparison_p (XEXP (x, 0))
&& (XEXP (x, 1) == pc_rtx || GET_CODE (XEXP (x, 1)) == CONST_INT && (XEXP (x, 1) == pc_rtx
|| (CONSTANT_P (XEXP (x, 1))
&& GET_CODE (XEXP (x, 2)) != CONST_INT
&& XEXP (x, 2) != pc_rtx)
|| XEXP (x, 1) == const0_rtx
|| (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o'
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 2))) != 'o')
|| (GET_CODE (XEXP (x, 1)) == SUBREG
&& GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 1)))) == 'o'
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 2))) != 'o')
|| reg_mentioned_p (XEXP (x, 1), XEXP (x, 2))
|| rtx_equal_p (XEXP (x, 2), XEXP (XEXP (x, 0), 0)))) || rtx_equal_p (XEXP (x, 2), XEXP (XEXP (x, 0), 0))))
{ {
SUBST (XEXP (x, 0), SUBST (XEXP (x, 0),
...@@ -3954,7 +3998,10 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -3954,7 +3998,10 @@ subst (x, from, to, in_dest, unique_copy)
ZERO_EXTEND or SIGN_EXTEND as long as Z is already extended (so ZERO_EXTEND or SIGN_EXTEND as long as Z is already extended (so
we don't destroy it). We can do this kind of thing in some we don't destroy it). We can do this kind of thing in some
cases when STORE_FLAG_VALUE is neither of the above, but it isn't cases when STORE_FLAG_VALUE is neither of the above, but it isn't
worth checking for. */ worth checking for.
Similarly, (if_then_else COND Z 0) can be replaced by
(mult COND (mult Z STORE_FLAG_VALUE)). */
if (mode != VOIDmode && ! side_effects_p (x)) if (mode != VOIDmode && ! side_effects_p (x))
{ {
...@@ -3967,12 +4014,24 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -3967,12 +4014,24 @@ subst (x, from, to, in_dest, unique_copy)
enum machine_mode m = mode; enum machine_mode m = mode;
rtx z = 0, c1, c2; rtx z = 0, c1, c2;
if (f == const0_rtx)
return gen_binary (MULT, mode, gen_binary (cond_op, mode, cond_op0,
cond_op1),
gen_binary (MULT, mode, t, const_true_rtx));
if ((GET_CODE (t) == PLUS || GET_CODE (t) == MINUS if ((GET_CODE (t) == PLUS || GET_CODE (t) == MINUS
|| GET_CODE (t) == IOR || GET_CODE (t) == XOR || GET_CODE (t) == IOR || GET_CODE (t) == XOR
|| GET_CODE (t) == ASHIFT || GET_CODE (t) == ASHIFT
|| GET_CODE (t) == LSHIFTRT || GET_CODE (t) == ASHIFTRT) || GET_CODE (t) == LSHIFTRT || GET_CODE (t) == ASHIFTRT)
&& rtx_equal_p (XEXP (t, 0), f)) && rtx_equal_p (XEXP (t, 0), f))
c1 = XEXP (t, 1), op = GET_CODE (t), z = f; c1 = XEXP (t, 1), op = GET_CODE (t), z = f;
/* If an identity-zero op is commutative, check whether there
would be a match if we swapped the operands. */
else if ((GET_CODE (t) == PLUS || GET_CODE (t) == IOR
|| GET_CODE (t) == XOR)
&& rtx_equal_p (XEXP (t, 1), f))
c1 = XEXP (t, 0), op = GET_CODE (t), z = f;
else if (GET_CODE (t) == SIGN_EXTEND else if (GET_CODE (t) == SIGN_EXTEND
&& (GET_CODE (XEXP (t, 0)) == PLUS && (GET_CODE (XEXP (t, 0)) == PLUS
|| GET_CODE (XEXP (t, 0)) == MINUS || GET_CODE (XEXP (t, 0)) == MINUS
...@@ -3986,12 +4045,29 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -3986,12 +4045,29 @@ subst (x, from, to, in_dest, unique_copy)
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f) && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
&& (num_sign_bit_copies (f, GET_MODE (f)) && (num_sign_bit_copies (f, GET_MODE (f))
> (GET_MODE_BITSIZE (mode) > (GET_MODE_BITSIZE (mode)
- GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0), 0)))))) - GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0),
0))))))
{ {
c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0)); c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
extend_op = SIGN_EXTEND; extend_op = SIGN_EXTEND;
m = GET_MODE (XEXP (t, 0)); m = GET_MODE (XEXP (t, 0));
} }
else if (GET_CODE (t) == SIGN_EXTEND
&& (GET_CODE (XEXP (t, 0)) == PLUS
|| GET_CODE (XEXP (t, 0)) == IOR
|| GET_CODE (XEXP (t, 0)) == XOR)
&& GET_CODE (XEXP (XEXP (t, 0), 1)) == SUBREG
&& subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
&& (num_sign_bit_copies (f, GET_MODE (f))
> (GET_MODE_BITSIZE (mode)
- GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0),
1))))))
{
c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
extend_op = SIGN_EXTEND;
m = GET_MODE (XEXP (t, 0));
}
else if (GET_CODE (t) == ZERO_EXTEND else if (GET_CODE (t) == ZERO_EXTEND
&& (GET_CODE (XEXP (t, 0)) == PLUS && (GET_CODE (XEXP (t, 0)) == PLUS
|| GET_CODE (XEXP (t, 0)) == MINUS || GET_CODE (XEXP (t, 0)) == MINUS
...@@ -4012,58 +4088,21 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -4012,58 +4088,21 @@ subst (x, from, to, in_dest, unique_copy)
extend_op = ZERO_EXTEND; extend_op = ZERO_EXTEND;
m = GET_MODE (XEXP (t, 0)); m = GET_MODE (XEXP (t, 0));
} }
else if (GET_CODE (t) == ZERO_EXTEND
else if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' && (GET_CODE (XEXP (t, 0)) == PLUS
&& reversible_comparison_p (XEXP (x, 0)) || GET_CODE (XEXP (t, 0)) == IOR
&& (GET_CODE (f) == PLUS || GET_CODE (f) == MINUS || GET_CODE (XEXP (t, 0)) == XOR)
|| GET_CODE (f) == IOR || GET_CODE (f) == XOR && GET_CODE (XEXP (XEXP (t, 0), 1)) == SUBREG
|| GET_CODE (f) == ASHIFT
|| GET_CODE (f) == LSHIFTRT || GET_CODE (f) == ASHIFTRT)
&& rtx_equal_p (XEXP (f, 0), t))
{
c1 = XEXP (f, 1), op = GET_CODE (f), z = t;
cond_op = reverse_condition (cond_op);
}
else if (GET_CODE (f) == SIGN_EXTEND
&& (GET_CODE (XEXP (f, 0)) == PLUS
|| GET_CODE (XEXP (f, 0)) == MINUS
|| GET_CODE (XEXP (f, 0)) == IOR
|| GET_CODE (XEXP (f, 0)) == XOR
|| GET_CODE (XEXP (f, 0)) == ASHIFT
|| GET_CODE (XEXP (f, 0)) == LSHIFTRT
|| GET_CODE (XEXP (f, 0)) == ASHIFTRT)
&& GET_CODE (XEXP (XEXP (f, 0), 0)) == SUBREG
&& subreg_lowpart_p (XEXP (XEXP (f, 0), 0))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (f, 0), 0)), f)
&& (num_sign_bit_copies (t, GET_MODE (t))
> (GET_MODE_BITSIZE (mode)
- GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (f, 0), 0))))))
{
c1 = XEXP (XEXP (f, 0), 1); z = t; op = GET_CODE (XEXP (f, 0));
extend_op = SIGN_EXTEND;
m = GET_MODE (XEXP (f, 0));
cond_op = reverse_condition (cond_op);
}
else if (GET_CODE (f) == ZERO_EXTEND
&& (GET_CODE (XEXP (f, 0)) == PLUS
|| GET_CODE (XEXP (f, 0)) == MINUS
|| GET_CODE (XEXP (f, 0)) == IOR
|| GET_CODE (XEXP (f, 0)) == XOR
|| GET_CODE (XEXP (f, 0)) == ASHIFT
|| GET_CODE (XEXP (f, 0)) == LSHIFTRT
|| GET_CODE (XEXP (f, 0)) == ASHIFTRT)
&& GET_CODE (XEXP (XEXP (f, 0), 0)) == SUBREG
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& subreg_lowpart_p (XEXP (XEXP (f, 0), 0)) && subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (f, 0), 0)), t) && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
&& ((nonzero_bits (t, GET_MODE (t)) && ((nonzero_bits (f, GET_MODE (f))
& ~ GET_MODE_MASK (GET_MODE (XEXP (XEXP (f, 0), 0)))) & ~ GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 1))))
== 0)) == 0))
{ {
c1 = XEXP (XEXP (f, 0), 1); z = t; op = GET_CODE (XEXP (f, 0)); c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
extend_op = ZERO_EXTEND; extend_op = ZERO_EXTEND;
m = GET_MODE (XEXP (f, 0)); m = GET_MODE (XEXP (t, 0));
cond_op = reverse_condition (cond_op);
} }
if (z) if (z)
...@@ -4073,8 +4112,7 @@ subst (x, from, to, in_dest, unique_copy) ...@@ -4073,8 +4112,7 @@ subst (x, from, to, in_dest, unique_copy)
temp = gen_binary (MULT, m, temp, temp = gen_binary (MULT, m, temp,
gen_binary (MULT, m, c1, gen_binary (MULT, m, c1, const_true_rtx));
GEN_INT (STORE_FLAG_VALUE)));
temp = subst (temp, pc_rtx, pc_rtx, 0, 0); temp = subst (temp, pc_rtx, pc_rtx, 0, 0);
...@@ -6110,6 +6148,68 @@ if_then_else_cond (x, ptrue, pfalse) ...@@ -6110,6 +6148,68 @@ if_then_else_cond (x, ptrue, pfalse)
*pfalse = gen_binary (code, mode, false0, false1); *pfalse = gen_binary (code, mode, false0, false1);
return cond0 ? cond0 : cond1; return cond0 ? cond0 : cond1;
} }
#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
/* See if we have PLUS, IOR, XOR, MINUS or UMAX, where one of the
operands is zero when the other is non-zero, and vice-versa. */
if ((code == PLUS || code == IOR || code == XOR || code == MINUS
|| code == UMAX)
&& GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == MULT)
{
rtx op0 = XEXP (XEXP (x, 0), 1);
rtx op1 = XEXP (XEXP (x, 1), 1);
cond0 = XEXP (XEXP (x, 0), 0);
cond1 = XEXP (XEXP (x, 1), 0);
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))
&& 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)))
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x))
{
*ptrue = gen_binary (MULT, mode, op0, const_true_rtx);
*pfalse = gen_binary (MULT, mode,
(code == MINUS
? gen_unary (NEG, mode, op1) : op1),
const_true_rtx);
return cond0;
}
}
/* Similarly for MULT, AND and UMIN, execpt that for these the result
is always zero. */
if ((code == MULT || code == AND || code == UMIN)
&& GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == MULT)
{
cond0 = XEXP (XEXP (x, 0), 0);
cond1 = XEXP (XEXP (x, 1), 0);
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))
&& 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)))
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x))
{
*ptrue = *pfalse = const0_rtx;
return cond0;
}
}
#endif
} }
else if (code == IF_THEN_ELSE) else if (code == IF_THEN_ELSE)
...@@ -8383,6 +8483,16 @@ gen_binary (code, mode, op0, op1) ...@@ -8383,6 +8483,16 @@ gen_binary (code, mode, op0, op1)
if (GET_RTX_CLASS (code) == '<') if (GET_RTX_CLASS (code) == '<')
{ {
enum machine_mode op_mode = GET_MODE (op0); enum machine_mode op_mode = GET_MODE (op0);
/* Strip the COMPARE from (REL_OP (compare X Y) 0) to get
just (REL_OP X Y). */
if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
{
op1 = XEXP (op0, 1);
op0 = XEXP (op0, 0);
op_mode = GET_MODE (op0);
}
if (op_mode == VOIDmode) if (op_mode == VOIDmode)
op_mode = GET_MODE (op1); op_mode = GET_MODE (op1);
result = simplify_relational_operation (code, op_mode, op0, op1); result = simplify_relational_operation (code, op_mode, op0, op1);
...@@ -9404,6 +9514,13 @@ reversible_comparison_p (x) ...@@ -9404,6 +9514,13 @@ reversible_comparison_p (x)
return 1; return 1;
case MODE_CC: 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)); x = get_last_value (XEXP (x, 0));
return (x && GET_CODE (x) == COMPARE return (x && GET_CODE (x) == COMPARE
&& ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))); && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0))));
......
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