Commit 5109d49f by Richard Kenner

(subst): Move simple operations inside IF_THEN_ELSE if the IF_THEN_ELSE is in…

(subst): Move simple operations inside IF_THEN_ELSE if the IF_THEN_ELSE is in the second operand as well as the first.

(subst): Move simple operations inside IF_THEN_ELSE if the IF_THEN_ELSE is in
the second operand as well as the first.
(subst, case NEG): Use plus_constant to make a PLUS.
(subst, case MINUS): Simplify (minus 1 (comparison foo bar)).
(subst, case EQ): Add a number of missing cases where comparisons may be
replaced with arithmetic or logical ops.
(subst, case IF_THEN_ELSE): Handle (if_then_else COND (OP Z C1) Z) in a more
general manner.
(simplify_and_const_int): Make AND with gen_binary in case we can simplify it.

From-SVN: r5056
parent 5937bc84
......@@ -2898,6 +2898,23 @@ subst (x, from, to, in_dest, unique_copy)
goto restart;
}
else if ((GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
&& GET_CODE (XEXP (x, 1)) == IF_THEN_ELSE)
{
/* Don't do this by using SUBST inside X since we might be messing
up a shared expression. */
rtx cond = XEXP (XEXP (x, 1), 0);
rtx t_arm = subst (gen_binary (code, mode, XEXP (x, 0),
XEXP (XEXP (x, 1), 1)),
pc_rtx, pc_rtx, 0, 0);
rtx f_arm = subst (gen_binary (code, mode, XEXP (x, 0),
XEXP (XEXP (x, 1), 2)),
pc_rtx, pc_rtx, 0, 0);
x = gen_rtx (IF_THEN_ELSE, mode, cond, t_arm, f_arm);
goto restart;
}
else if (GET_RTX_CLASS (code) == '1'
&& GET_CODE (XEXP (x, 0)) == IF_THEN_ELSE
&& GET_MODE (XEXP (x, 0)) == mode)
......@@ -3242,7 +3259,7 @@ subst (x, from, to, in_dest, unique_copy)
/* Similarly, (neg (not X)) is (plus X 1). */
if (GET_CODE (XEXP (x, 0)) == NOT)
{
x = gen_rtx_combine (PLUS, mode, XEXP (XEXP (x, 0), 0), const1_rtx);
x = plus_constant (XEXP (XEXP (x, 0), 0), 1);
goto restart;
}
......@@ -3457,6 +3474,17 @@ subst (x, from, to, in_dest, unique_copy)
break;
case MINUS:
#if STORE_FLAG_VALUE == 1
/* (minus 1 (comparison foo bar)) can be done by reversing the comparison
code if valid. */
if (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));
#endif
/* (minus <foo> (and <foo> (const_int -pow2))) becomes
(and <foo> (const_int pow2-1)) */
if (GET_CODE (XEXP (x, 1)) == AND
......@@ -3551,42 +3579,90 @@ subst (x, from, to, in_dest, unique_copy)
#if STORE_FLAG_VALUE == 1
/* If STORE_FLAG_VALUE is 1, we can convert (ne x 0) to simply X
if only the low-order bit is possibly nonzero in X (such as when
X is a ZERO_EXTRACT of one bit. Similarly, we can convert
EQ to (xor X 1). Remove any ZERO_EXTRACT we made when thinking
this was a comparison. It may now be simpler to use, e.g., an
AND. If a ZERO_EXTRACT is indeed appropriate, it will
be placed back by the call to make_compound_operation in the
SET case. */
X is a ZERO_EXTRACT of one bit). Similarly, we can convert EQ to
(xor X 1) or (minus 1 X); we use the former. Finally, if X is
known to be either 0 or -1, NE becomes a NEG and EQ becomes
(plus X 1).
Remove any ZERO_EXTRACT we made when thinking this was a
comparison. It may now be simpler to use, e.g., an AND. If a
ZERO_EXTRACT is indeed appropriate, it will be placed back by
the call to make_compound_operation in the SET case. */
if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& nonzero_bits (op0, GET_MODE (op0)) == 1)
&& nonzero_bits (op0, mode) == 1)
return gen_lowpart_for_combine (mode,
expand_compound_operation (op0));
else if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& (num_sign_bit_copies (op0, mode)
== GET_MODE_BITSIZE (mode)))
{
op0 = expand_compound_operation (op0);
x = gen_unary (NEG, mode, gen_lowpart_for_combine (mode, op0));
goto restart;
}
else if (new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& nonzero_bits (op0, GET_MODE (op0)) == 1)
&& nonzero_bits (op0, mode) == 1)
{
op0 = expand_compound_operation (op0);
x = gen_binary (XOR, mode,
gen_lowpart_for_combine (mode, op0),
const1_rtx);
goto restart;
}
x = gen_rtx_combine (XOR, mode,
gen_lowpart_for_combine (mode, op0),
const1_rtx);
else if (new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& (num_sign_bit_copies (op0, mode)
== GET_MODE_BITSIZE (mode)))
{
op0 = expand_compound_operation (op0);
x = plus_constant (gen_lowpart_for_combine (mode, op0), 1);
goto restart;
}
#endif
#if STORE_FLAG_VALUE == -1
/* If STORE_FLAG_VALUE is -1, we can convert (ne x 0)
to (neg x) if only the low-order bit of X can be nonzero.
This converts (ne (zero_extract X 1 Y) 0) to
(sign_extract X 1 Y). */
/* If STORE_FLAG_VALUE is -1, we have cases similar to
those above. */
if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& nonzero_bits (op0, GET_MODE (op0)) == 1)
&& (num_sign_bit_copies (op0, mode)
== GET_MODE_BITSIZE (mode)))
return gen_lowpart_for_combine (mode,
expand_compound_operation (op0));
else if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& nonzero_bits (op0, mode) == 1)
{
op0 = expand_compound_operation (op0);
x = gen_unary (NEG, mode, gen_lowpart_for_combine (mode, op0));
goto restart;
}
else if (new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& (num_sign_bit_copies (op0, mode)
== GET_MODE_BITSIZE (mode)))
{
op0 = expand_compound_operation (op0);
x = gen_rtx_combine (NEG, mode,
gen_lowpart_for_combine (mode, op0));
x = gen_unary (NOT, mode, gen_lowpart_for_combine (mode, op0));
goto restart;
}
/* If X is 0/1, (eq X 0) is X-1. */
else if (new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& nonzero_bits (op0, mode) == 1)
{
op0 = expand_compound_operation (op0);
x = plus_constant (gen_lowpart_for_combine (mode, op0), -1);
goto restart;
}
#endif
......@@ -3602,7 +3678,7 @@ subst (x, from, to, in_dest, unique_copy)
== (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
&& op1 == const0_rtx
&& mode == GET_MODE (op0)
&& (i = exact_log2 (nonzero_bits (op0, GET_MODE (op0)))) >= 0)
&& (i = exact_log2 (nonzero_bits (op0, mode))) >= 0)
{
x = simplify_shift_const (NULL_RTX, ASHIFT, mode,
expand_compound_operation (op0),
......@@ -3756,94 +3832,144 @@ subst (x, from, to, in_dest, unique_copy)
goto restart;
}
/* If we have something like (if_then_else (ne A 0) (OP X C) X),
A is known to be either 0 or 1, and OP is an identity when its
second operand is zero, this can be done as (OP X (mult A C)).
Similarly if A is known to be 0 or -1 and also similarly if we have
a ZERO_EXTEND or SIGN_EXTEND as long as X is already extended (so
we don't destroy it). */
if (mode != VOIDmode
&& (GET_CODE (XEXP (x, 0)) == EQ || GET_CODE (XEXP (x, 0)) == NE)
&& XEXP (XEXP (x, 0), 1) == const0_rtx
&& (nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1
|| (num_sign_bit_copies (XEXP (XEXP (x, 0), 0), mode)
== GET_MODE_BITSIZE (mode))))
{
rtx nz = make_compound_operation (GET_CODE (XEXP (x, 0)) == NE
? XEXP (x, 1) : XEXP (x, 2),
SET);
rtx z = GET_CODE (XEXP (x, 0)) == NE ? XEXP (x, 2) : XEXP (x, 1);
rtx dir = (nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1
? const1_rtx : constm1_rtx);
rtx c = 0;
#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
/* If we have (if_then_else COND (OP Z C1) Z) and OP is an identity when
its second operand is zero, this can be done as (OP Z (mult COND C2))
where C2 = C1 * STORE_FLAG_VALUE. Similarly if OP has an outer
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
cases when STORE_FLAG_VALUE is neither of the above, but it isn't
worth checking for. */
if (mode != VOIDmode && ! side_effects_p (x))
{
rtx t = make_compound_operation (XEXP (x, 1), SET);
rtx f = make_compound_operation (XEXP (x, 2), SET);
rtx cond_op0 = XEXP (XEXP (x, 0), 0);
rtx cond_op1 = XEXP (XEXP (x, 0), 1);
enum rtx_code cond_op = GET_CODE (XEXP (x, 0));
enum rtx_code op, extend_op = NIL;
enum machine_mode m = mode;
enum rtx_code op, extend_op = 0;
if ((GET_CODE (nz) == PLUS || GET_CODE (nz) == MINUS
|| GET_CODE (nz) == IOR || GET_CODE (nz) == XOR
|| GET_CODE (nz) == ASHIFT
|| GET_CODE (nz) == LSHIFTRT || GET_CODE (nz) == ASHIFTRT)
&& rtx_equal_p (XEXP (nz, 0), z))
c = XEXP (nz, 1), op = GET_CODE (nz);
else if (GET_CODE (nz) == SIGN_EXTEND
&& (GET_CODE (XEXP (nz, 0)) == PLUS
|| GET_CODE (XEXP (nz, 0)) == MINUS
|| GET_CODE (XEXP (nz, 0)) == IOR
|| GET_CODE (XEXP (nz, 0)) == XOR
|| GET_CODE (XEXP (nz, 0)) == ASHIFT
|| GET_CODE (XEXP (nz, 0)) == LSHIFTRT
|| GET_CODE (XEXP (nz, 0)) == ASHIFTRT)
&& GET_CODE (XEXP (XEXP (nz, 0), 0)) == SUBREG
&& subreg_lowpart_p (XEXP (XEXP (nz, 0), 0))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (nz, 0), 0)), z)
&& (num_sign_bit_copies (z, GET_MODE (z))
>= (GET_MODE_BITSIZE (mode)
- GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (nz, 0), 0))))))
rtx z = 0, c1, c2;
if ((GET_CODE (t) == PLUS || GET_CODE (t) == MINUS
|| GET_CODE (t) == IOR || GET_CODE (t) == XOR
|| GET_CODE (t) == ASHIFT
|| GET_CODE (t) == LSHIFTRT || GET_CODE (t) == ASHIFTRT)
&& rtx_equal_p (XEXP (t, 0), f))
c1 = XEXP (t, 1), op = GET_CODE (t), z = f;
else if (GET_CODE (t) == SIGN_EXTEND
&& (GET_CODE (XEXP (t, 0)) == PLUS
|| GET_CODE (XEXP (t, 0)) == MINUS
|| GET_CODE (XEXP (t, 0)) == IOR
|| GET_CODE (XEXP (t, 0)) == XOR
|| GET_CODE (XEXP (t, 0)) == ASHIFT
|| GET_CODE (XEXP (t, 0)) == LSHIFTRT
|| GET_CODE (XEXP (t, 0)) == ASHIFTRT)
&& GET_CODE (XEXP (XEXP (t, 0), 0)) == SUBREG
&& subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
&& (num_sign_bit_copies (f, GET_MODE (f))
> (GET_MODE_BITSIZE (mode)
- GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0), 0))))))
{
c1 = XEXP (XEXP (t, 0), 1); 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
&& (GET_CODE (XEXP (t, 0)) == PLUS
|| GET_CODE (XEXP (t, 0)) == MINUS
|| GET_CODE (XEXP (t, 0)) == IOR
|| GET_CODE (XEXP (t, 0)) == XOR
|| GET_CODE (XEXP (t, 0)) == ASHIFT
|| GET_CODE (XEXP (t, 0)) == LSHIFTRT
|| GET_CODE (XEXP (t, 0)) == ASHIFTRT)
&& GET_CODE (XEXP (XEXP (t, 0), 0)) == SUBREG
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
&& ((nonzero_bits (f, GET_MODE (f))
& ~ GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 0))))
== 0))
{
c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
extend_op = ZERO_EXTEND;
m = GET_MODE (XEXP (t, 0));
}
if (reversible_comparison_p (XEXP (x, 0))
&& (GET_CODE (f) == PLUS || GET_CODE (f) == MINUS
|| GET_CODE (f) == IOR || GET_CODE (f) == XOR
|| 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))))))
{
c = XEXP (XEXP (nz, 0), 1);
op = GET_CODE (XEXP (nz, 0));
c1 = XEXP (XEXP (f, 0), 1); z = t; op = GET_CODE (XEXP (f, 0));
extend_op = SIGN_EXTEND;
m = GET_MODE (XEXP (nz, 0));
m = GET_MODE (XEXP (f, 0));
cond_op = reverse_condition (cond_op);
}
else if (GET_CODE (nz) == ZERO_EXTEND
&& (GET_CODE (XEXP (nz, 0)) == PLUS
|| GET_CODE (XEXP (nz, 0)) == MINUS
|| GET_CODE (XEXP (nz, 0)) == IOR
|| GET_CODE (XEXP (nz, 0)) == XOR
|| GET_CODE (XEXP (nz, 0)) == ASHIFT
|| GET_CODE (XEXP (nz, 0)) == LSHIFTRT
|| GET_CODE (XEXP (nz, 0)) == ASHIFTRT)
&& GET_CODE (XEXP (XEXP (nz, 0), 0)) == SUBREG
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
&& subreg_lowpart_p (XEXP (XEXP (nz, 0), 0))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (nz, 0), 0)), z)
&& ((nonzero_bits (z, GET_MODE (z))
& ~ GET_MODE_MASK (GET_MODE (XEXP (XEXP (nz, 0), 0))))
&& subreg_lowpart_p (XEXP (XEXP (f, 0), 0))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (f, 0), 0)), t)
&& ((nonzero_bits (t, GET_MODE (t))
& ~ GET_MODE_MASK (GET_MODE (XEXP (XEXP (f, 0), 0))))
== 0))
{
c = XEXP (XEXP (nz, 0), 1);
op = GET_CODE (XEXP (nz, 0));
c1 = XEXP (XEXP (f, 0), 1); z = t; op = GET_CODE (XEXP (f, 0));
extend_op = ZERO_EXTEND;
m = GET_MODE (XEXP (nz, 0));
m = GET_MODE (XEXP (f, 0));
cond_op = reverse_condition (cond_op);
}
if (c && ! side_effects_p (c) && ! side_effects_p (z))
if (z)
{
temp
= gen_binary (MULT, m,
gen_lowpart_for_combine (m,
XEXP (XEXP (x, 0), 0)),
gen_binary (MULT, m, c, dir));
temp = subst (gen_binary (cond_op, m, cond_op0, cond_op1),
pc_rtx, pc_rtx, 0, 0);
temp = gen_binary (MULT, m, temp,
gen_binary (MULT, m, c1,
GEN_INT (STORE_FLAG_VALUE)));
temp = gen_binary (op, m, gen_lowpart_for_combine (m, z), temp);
if (extend_op != 0)
if (extend_op != NIL)
temp = gen_unary (extend_op, mode, temp);
return temp;
}
}
#endif
/* If we have (if_then_else (ne A 0) C1 0) and either A is known to
be 0 or 1 and C1 is a single bit or A is known to be 0 or -1 and
......@@ -6591,9 +6717,9 @@ nonzero_bits (x, mode)
}
/* Return the number of bits at the high-order end of X that are known to
be equal to the sign bit. This number will always be between 1 and
the number of bits in the mode of X. MODE is the mode to be used
if X is VOIDmode. */
be equal to the sign bit. X will be used in mode MODE; if MODE is
VOIDmode, X will be used in its own mode. The returned value will always
be between 1 and the number of bits in MODE. */
static int
num_sign_bit_copies (x, mode)
......
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