Commit aa166939 by Roger Sayle Committed by Roger Sayle

combine.c (combine_simplify_rtx): Move several NOT and NEG optimizations from here...


	* combine.c (combine_simplify_rtx): Move several NOT and NEG
	optimizations from here...
	* simplify-rtx.c (simplify_unary_operation): to here.  Recursively
	simplify expressions using simplify_gen_*ary instead of gen_rtx_*.

From-SVN: r71300
parent cda85569
2003-09-11 Roger Sayle <roger@eyesopen.com>
* combine.c (combine_simplify_rtx): Move several NOT and NEG
optimizations from here...
* simplify-rtx.c (simplify_unary_operation): to here. Recursively
simplify expressions using simplify_gen_*ary instead of gen_rtx_*.
2003-09-11 Richard Henderson <rth@redhat.com>
* cgraphunit.c (cgraph_finalize_function): Add nested arg.
......
......@@ -3847,33 +3847,6 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
break;
case NOT:
/* (not (plus X -1)) can become (neg X). */
if (GET_CODE (XEXP (x, 0)) == PLUS
&& XEXP (XEXP (x, 0), 1) == constm1_rtx)
return gen_rtx_NEG (mode, XEXP (XEXP (x, 0), 0));
/* Similarly, (not (neg X)) is (plus X -1). */
if (GET_CODE (XEXP (x, 0)) == NEG)
return gen_rtx_PLUS (mode, XEXP (XEXP (x, 0), 0), constm1_rtx);
/* (not (xor X C)) for C constant is (xor X D) with D = ~C. */
if (GET_CODE (XEXP (x, 0)) == XOR
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
&& (temp = simplify_unary_operation (NOT, mode,
XEXP (XEXP (x, 0), 1),
mode)) != 0)
return gen_binary (XOR, mode, XEXP (XEXP (x, 0), 0), temp);
/* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for operands
other than 1, but that is not valid. We could do a similar
simplification for (not (lshiftrt C X)) where C is just the sign bit,
but this doesn't seem common enough to bother with. */
if (GET_CODE (XEXP (x, 0)) == ASHIFT
&& XEXP (XEXP (x, 0), 0) == const1_rtx)
return gen_rtx_ROTATE (mode, simplify_gen_unary (NOT, mode,
const1_rtx, mode),
XEXP (XEXP (x, 0), 1));
if (GET_CODE (XEXP (x, 0)) == SUBREG
&& subreg_lowpart_p (XEXP (x, 0))
&& (GET_MODE_SIZE (GET_MODE (XEXP (x, 0)))
......@@ -3890,24 +3863,6 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
return gen_lowpart_for_combine (mode, x);
}
/* If STORE_FLAG_VALUE is -1, (not (comparison foo bar)) can be done by
reversing the comparison code if valid. */
if (STORE_FLAG_VALUE == -1
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& (reversed = reversed_comparison (x, mode, XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 0), 1))))
return reversed;
/* (not (ashiftrt foo C)) where C is the number of bits in FOO minus 1
is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can
perform the above simplification. */
if (STORE_FLAG_VALUE == -1
&& GET_CODE (XEXP (x, 0)) == ASHIFTRT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
&& INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode) - 1)
return gen_rtx_GE (mode, XEXP (XEXP (x, 0), 0), const0_rtx);
/* Apply De Morgan's laws to reduce number of patterns for machines
with negating logical insns (and-not, nand, etc.). If result has
only one NOT, put it first, since that is how the patterns are
......@@ -3938,63 +3893,12 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
break;
case NEG:
/* (neg (plus X 1)) can become (not X). */
if (GET_CODE (XEXP (x, 0)) == PLUS
&& XEXP (XEXP (x, 0), 1) == const1_rtx)
return gen_rtx_NOT (mode, XEXP (XEXP (x, 0), 0));
/* Similarly, (neg (not X)) is (plus X 1). */
if (GET_CODE (XEXP (x, 0)) == NOT)
return plus_constant (XEXP (XEXP (x, 0), 0), 1);
/* (neg (minus X Y)) can become (minus Y X). This transformation
isn't safe for modes with signed zeros, since if X and Y are
both +0, (minus Y X) is the same as (minus X Y). If the rounding
mode is towards +infinity (or -infinity) then the two expressions
will be rounded differently. */
if (GET_CODE (XEXP (x, 0)) == MINUS
&& !HONOR_SIGNED_ZEROS (mode)
&& !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
XEXP (XEXP (x, 0), 0));
/* (neg (plus A B)) is canonicalized to (minus (neg A) B). */
if (GET_CODE (XEXP (x, 0)) == PLUS
&& !HONOR_SIGNED_ZEROS (mode)
&& !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
{
temp = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 0), 0), mode);
temp = combine_simplify_rtx (temp, mode, last, in_dest);
return gen_binary (MINUS, mode, temp, XEXP (XEXP (x, 0), 1));
}
/* (neg (mult A B)) becomes (mult (neg A) B).
This works even for floating-point values. */
if (GET_CODE (XEXP (x, 0)) == MULT
&& !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
{
temp = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 0), 0), mode);
return gen_binary (MULT, mode, temp, XEXP (XEXP (x, 0), 1));
}
/* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */
if (GET_CODE (XEXP (x, 0)) == XOR
&& XEXP (XEXP (x, 0), 1) == const1_rtx
&& nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1)
return gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), constm1_rtx);
/* NEG commutes with ASHIFT since it is multiplication. Only do this
if we can then eliminate the NEG (e.g.,
if the operand is a constant). */
if (GET_CODE (XEXP (x, 0)) == ASHIFT)
{
temp = simplify_unary_operation (NEG, mode,
XEXP (XEXP (x, 0), 0), mode);
if (temp)
return gen_binary (ASHIFT, mode, temp, XEXP (XEXP (x, 0), 1));
}
temp = expand_compound_operation (XEXP (x, 0));
/* For C equal to the width of MODE minus 1, (neg (ashiftrt X C)) can be
......
......@@ -788,6 +788,8 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
else
{
enum rtx_code reversed;
rtx temp;
/* There are some simplifications we can do even if the operands
aren't constant. */
switch (code)
......@@ -801,14 +803,116 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
if (mode == BImode && GET_RTX_CLASS (GET_CODE (op)) == '<'
&& ((reversed = reversed_comparison_code (op, NULL_RTX))
!= UNKNOWN))
return gen_rtx_fmt_ee (reversed,
op_mode, XEXP (op, 0), XEXP (op, 1));
return simplify_gen_relational (reversed, op_mode, op_mode,
XEXP (op, 0), XEXP (op, 1));
/* (not (plus X -1)) can become (neg X). */
if (GET_CODE (op) == PLUS
&& XEXP (op, 1) == constm1_rtx)
return simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
/* Similarly, (not (neg X)) is (plus X -1). */
if (GET_CODE (op) == NEG)
return plus_constant (XEXP (op, 0), -1);
/* (not (xor X C)) for C constant is (xor X D) with D = ~C. */
if (GET_CODE (op) == XOR
&& GET_CODE (XEXP (op, 1)) == CONST_INT
&& (temp = simplify_unary_operation (NOT, mode,
XEXP (op, 1),
mode)) != 0)
return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp);
/* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for
operands other than 1, but that is not valid. We could do a
similar simplification for (not (lshiftrt C X)) where C is
just the sign bit, but this doesn't seem common enough to
bother with. */
if (GET_CODE (op) == ASHIFT
&& XEXP (op, 0) == const1_rtx)
{
temp = simplify_gen_unary (NOT, mode, const1_rtx, mode);
return simplify_gen_binary (ROTATE, mode, temp, XEXP (op, 1));
}
/* If STORE_FLAG_VALUE is -1, (not (comparison X Y)) can be done
by reversing the comparison code if valid. */
if (STORE_FLAG_VALUE == -1
&& GET_RTX_CLASS (GET_CODE (op)) == '<'
&& (reversed = reversed_comparison_code (op, NULL_RTX))
!= UNKNOWN)
return simplify_gen_relational (reversed, op_mode, op_mode,
XEXP (op, 0), XEXP (op, 1));
/* (not (ashiftrt foo C)) where C is the number of bits in FOO
minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1,
so we can perform the above simplification. */
if (STORE_FLAG_VALUE == -1
&& GET_CODE (op) == ASHIFTRT
&& GET_CODE (XEXP (op, 1)) == CONST_INT
&& INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
return simplify_gen_relational (GE, mode, mode, XEXP (op, 0),
const0_rtx);
break;
case NEG:
/* (neg (neg X)) == X. */
if (GET_CODE (op) == NEG)
return XEXP (op, 0);
/* (neg (plus X 1)) can become (not X). */
if (GET_CODE (op) == PLUS
&& XEXP (op, 1) == const1_rtx)
return simplify_gen_unary (NOT, mode, XEXP (op, 0), mode);
/* Similarly, (neg (not X)) is (plus X 1). */
if (GET_CODE (op) == NOT)
return plus_constant (XEXP (op, 0), 1);
/* (neg (minus X Y)) can become (minus Y X). This transformation
isn't safe for modes with signed zeros, since if X and Y are
both +0, (minus Y X) is the same as (minus X Y). If the
rounding mode is towards +infinity (or -infinity) then the two
expressions will be rounded differently. */
if (GET_CODE (op) == MINUS
&& !HONOR_SIGNED_ZEROS (mode)
&& !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
return simplify_gen_binary (MINUS, mode, XEXP (op, 1),
XEXP (op, 0));
/* (neg (plus A B)) is canonicalized to (minus (neg A) B). */
if (GET_CODE (op) == PLUS
&& !HONOR_SIGNED_ZEROS (mode)
&& !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
{
temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 1));
}
/* (neg (mult A B)) becomes (mult (neg A) B).
This works even for floating-point values. */
if (GET_CODE (op) == MULT
&& !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
{
temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
return simplify_gen_binary (MULT, mode, temp, XEXP (op, 1));
}
/* NEG commutes with ASHIFT since it is multiplication. Only do
this if we can then eliminate the NEG (e.g., if the operand
is a constant). */
if (GET_CODE (op) == ASHIFT)
{
temp = simplify_unary_operation (NEG, mode, XEXP (op, 0),
mode);
if (temp)
return simplify_gen_binary (ASHIFT, mode, temp,
XEXP (op, 1));
}
break;
case SIGN_EXTEND:
......
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