combine.c (combine_simplify_rtx): Attempt to simplify a*(b/c) as (a*b)/c for floats in unsafe_math mode.

* combine.c (combine_simplify_rtx): Attempt to simplify
	a*(b/c) as (a*b)/c for floats in unsafe_math mode.

	* simplify-rtx.c (avoid_constatn_pool_reference): New static function.
	(simplify_binary_operation, simplify_unary_operation,
	 simplify_relational_operation): Use it.

	* combine.c (combine_simplify_rtx): Don't do associative law
	on divisions; allow associative law on floats.

From-SVN: r44073
This commit is contained in:
Jan Hubicka 2001-07-17 17:11:56 +02:00 committed by Jan Hubicka
parent 3aa8ab7bfa
commit 4ba5f92543
3 changed files with 184 additions and 120 deletions

View File

@ -1,3 +1,15 @@
Tue Jul 17 16:56:05 CEST 2001 Jan Hubicka <jh@suse.cz>
* combine.c (combine_simplify_rtx): Attempt to simplify
a*(b/c) as (a*b)/c for floats in unsafe_math mode.
* simplify-rtx.c (avoid_constatn_pool_reference): New static function.
(simplify_binary_operation, simplify_unary_operation,
simplify_relational_operation): Use it.
* combine.c (combine_simplify_rtx): Don't do associative law
on divisions; allow associative law on floats.
2001-07-17 H.J. Lu <hjl@gnu.org>
Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>

View File

@ -3724,9 +3724,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if they are logically related (i.e. (a & b) & a). */
if ((code == PLUS || code == MINUS
|| code == MULT || code == AND || code == IOR || code == XOR
|| code == DIV || code == UDIV
|| code == SMAX || code == SMIN || code == UMAX || code == UMIN)
&& INTEGRAL_MODE_P (mode))
&& (INTEGRAL_MODE_P (mode)
|| (flag_unsafe_math_optimizations && FLOAT_MODE_P (mode))))
{
if (GET_CODE (XEXP (x, 0)) == code)
{
@ -4231,6 +4231,16 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (GET_CODE (x) != MULT)
return x;
}
/* Try simplify a*(b/c) as (a*b)/c. */
if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations
&& GET_CODE (XEXP (x, 0)) == DIV)
{
rtx tem = simplify_binary_operation (MULT, mode,
XEXP (XEXP (x, 0), 0),
XEXP (x, 1));
if (tem)
return gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1));
}
break;
case UDIV:

View File

@ -99,6 +99,7 @@ Boston, MA 02111-1307, USA. */
static rtx simplify_plus_minus PARAMS ((enum rtx_code,
enum machine_mode, rtx, rtx));
static void check_fold_consts PARAMS ((PTR));
static rtx avoid_constant_pool_reference PARAMS ((rtx));
/* Make a binary operation by properly ordering the operands and
seeing if the expression folds. */
@ -135,6 +136,20 @@ simplify_gen_binary (code, mode, op0, op1)
return gen_rtx_fmt_ee (code, mode, op0, op1);
}
/* In case X is MEM referencing constant pool, return the real value.
Otherwise return X. */
static rtx
avoid_constant_pool_reference (x)
rtx x;
{
if (GET_CODE (x) != MEM)
return x;
if (GET_CODE (XEXP (x, 0)) != SYMBOL_REF
|| !CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
return x;
return get_pool_constant (XEXP (x, 0));
}
/* Make a unary operation by first seeing if it folds and otherwise making
the specified operation. */
@ -287,6 +302,7 @@ simplify_unary_operation (code, mode, op, op_mode)
enum machine_mode op_mode;
{
unsigned int width = GET_MODE_BITSIZE (mode);
rtx trueop = avoid_constant_pool_reference (op);
/* The order of these tests is critical so that, for example, we don't
check the wrong mode (input vs. output) for a conversion operation,
@ -294,16 +310,16 @@ simplify_unary_operation (code, mode, op, op_mode)
#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
if (code == FLOAT && GET_MODE (op) == VOIDmode
&& (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
if (code == FLOAT && GET_MODE (trueop) == VOIDmode
&& (GET_CODE (trueop) == CONST_DOUBLE || GET_CODE (trueop) == CONST_INT))
{
HOST_WIDE_INT hv, lv;
REAL_VALUE_TYPE d;
if (GET_CODE (op) == CONST_INT)
lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv);
if (GET_CODE (trueop) == CONST_INT)
lv = INTVAL (trueop), hv = HWI_SIGN_EXTEND (lv);
else
lv = CONST_DOUBLE_LOW (op), hv = CONST_DOUBLE_HIGH (op);
lv = CONST_DOUBLE_LOW (trueop), hv = CONST_DOUBLE_HIGH (trueop);
#ifdef REAL_ARITHMETIC
REAL_VALUE_FROM_INT (d, lv, hv, mode);
@ -327,16 +343,17 @@ simplify_unary_operation (code, mode, op, op_mode)
d = real_value_truncate (mode, d);
return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
}
else if (code == UNSIGNED_FLOAT && GET_MODE (op) == VOIDmode
&& (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
else if (code == UNSIGNED_FLOAT && GET_MODE (trueop) == VOIDmode
&& (GET_CODE (trueop) == CONST_DOUBLE
|| GET_CODE (trueop) == CONST_INT))
{
HOST_WIDE_INT hv, lv;
REAL_VALUE_TYPE d;
if (GET_CODE (op) == CONST_INT)
lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv);
if (GET_CODE (trueop) == CONST_INT)
lv = INTVAL (trueop), hv = HWI_SIGN_EXTEND (lv);
else
lv = CONST_DOUBLE_LOW (op), hv = CONST_DOUBLE_HIGH (op);
lv = CONST_DOUBLE_LOW (trueop), hv = CONST_DOUBLE_HIGH (trueop);
if (op_mode == VOIDmode)
{
@ -364,10 +381,10 @@ simplify_unary_operation (code, mode, op, op_mode)
}
#endif
if (GET_CODE (op) == CONST_INT
if (GET_CODE (trueop) == CONST_INT
&& width <= HOST_BITS_PER_WIDE_INT && width > 0)
{
register HOST_WIDE_INT arg0 = INTVAL (op);
register HOST_WIDE_INT arg0 = INTVAL (trueop);
register HOST_WIDE_INT val;
switch (code)
@ -453,16 +470,17 @@ simplify_unary_operation (code, mode, op, op_mode)
/* We can do some operations on integer CONST_DOUBLEs. Also allow
for a DImode operation on a CONST_INT. */
else if (GET_MODE (op) == VOIDmode && width <= HOST_BITS_PER_INT * 2
&& (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
else if (GET_MODE (trueop) == VOIDmode && width <= HOST_BITS_PER_INT * 2
&& (GET_CODE (trueop) == CONST_DOUBLE
|| GET_CODE (trueop) == CONST_INT))
{
unsigned HOST_WIDE_INT l1, lv;
HOST_WIDE_INT h1, hv;
if (GET_CODE (op) == CONST_DOUBLE)
l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op);
if (GET_CODE (trueop) == CONST_DOUBLE)
l1 = CONST_DOUBLE_LOW (trueop), h1 = CONST_DOUBLE_HIGH (trueop);
else
l1 = INTVAL (op), h1 = HWI_SIGN_EXTEND (l1);
l1 = INTVAL (trueop), h1 = HWI_SIGN_EXTEND (l1);
switch (code)
{
@ -531,7 +549,7 @@ simplify_unary_operation (code, mode, op, op_mode)
}
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
else if (GET_CODE (op) == CONST_DOUBLE
else if (GET_CODE (trueop) == CONST_DOUBLE
&& GET_MODE_CLASS (mode) == MODE_FLOAT)
{
REAL_VALUE_TYPE d;
@ -546,7 +564,7 @@ simplify_unary_operation (code, mode, op, op_mode)
set_float_handler (handler);
REAL_VALUE_FROM_CONST_DOUBLE (d, op);
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
switch (code)
{
@ -587,8 +605,8 @@ simplify_unary_operation (code, mode, op, op_mode)
return x;
}
else if (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
else if (GET_CODE (trueop) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (trueop)) == MODE_FLOAT
&& GET_MODE_CLASS (mode) == MODE_INT
&& width <= HOST_BITS_PER_WIDE_INT && width > 0)
{
@ -601,7 +619,7 @@ simplify_unary_operation (code, mode, op, op_mode)
set_float_handler (handler);
REAL_VALUE_FROM_CONST_DOUBLE (d, op);
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
switch (code)
{
@ -713,6 +731,8 @@ simplify_binary_operation (code, mode, op0, op1)
HOST_WIDE_INT val;
unsigned int width = GET_MODE_BITSIZE (mode);
rtx tem;
rtx trueop0 = avoid_constant_pool_reference (op0);
rtx trueop1 = avoid_constant_pool_reference (op1);
/* Relational operations don't work here. We must know the mode
of the operands in order to do the comparison correctly.
@ -722,9 +742,18 @@ simplify_binary_operation (code, mode, op0, op1)
if (GET_RTX_CLASS (code) == '<')
abort ();
/* Make sure the constant is second. */
if (GET_RTX_CLASS (code) == 'c'
&& swap_commutative_operands_p (trueop0, trueop1))
{
tem = op0, op0 = op1, op1 = tem;
tem = trueop0, trueop0 = trueop1, trueop1 = tem;
}
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_CODE (op0) == CONST_DOUBLE && GET_CODE (op1) == CONST_DOUBLE
&& GET_CODE (trueop0) == CONST_DOUBLE
&& GET_CODE (trueop1) == CONST_DOUBLE
&& mode == GET_MODE (op0) && mode == GET_MODE (op1))
{
REAL_VALUE_TYPE f0, f1, value;
@ -735,8 +764,8 @@ simplify_binary_operation (code, mode, op0, op1)
set_float_handler (handler);
REAL_VALUE_FROM_CONST_DOUBLE (f0, op0);
REAL_VALUE_FROM_CONST_DOUBLE (f1, op1);
REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
f0 = real_value_truncate (mode, f0);
f1 = real_value_truncate (mode, f1);
@ -785,21 +814,23 @@ simplify_binary_operation (code, mode, op0, op1)
/* We can fold some multi-word operations. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& width == HOST_BITS_PER_WIDE_INT * 2
&& (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT)
&& (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT))
&& (GET_CODE (trueop0) == CONST_DOUBLE
|| GET_CODE (trueop0) == CONST_INT)
&& (GET_CODE (trueop1) == CONST_DOUBLE
|| GET_CODE (trueop1) == CONST_INT))
{
unsigned HOST_WIDE_INT l1, l2, lv;
HOST_WIDE_INT h1, h2, hv;
if (GET_CODE (op0) == CONST_DOUBLE)
l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0);
if (GET_CODE (trueop0) == CONST_DOUBLE)
l1 = CONST_DOUBLE_LOW (trueop0), h1 = CONST_DOUBLE_HIGH (trueop0);
else
l1 = INTVAL (op0), h1 = HWI_SIGN_EXTEND (l1);
l1 = INTVAL (trueop0), h1 = HWI_SIGN_EXTEND (l1);
if (GET_CODE (op1) == CONST_DOUBLE)
l2 = CONST_DOUBLE_LOW (op1), h2 = CONST_DOUBLE_HIGH (op1);
if (GET_CODE (trueop1) == CONST_DOUBLE)
l2 = CONST_DOUBLE_LOW (trueop1), h2 = CONST_DOUBLE_HIGH (trueop1);
else
l2 = INTVAL (op1), h2 = HWI_SIGN_EXTEND (l2);
l2 = INTVAL (trueop1), h2 = HWI_SIGN_EXTEND (l2);
switch (code)
{
@ -919,7 +950,7 @@ simplify_binary_operation (code, mode, op0, op1)
&& FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations)
break;
if (op1 == CONST0_RTX (mode))
if (trueop1 == CONST0_RTX (mode))
return op0;
/* ((-a) + b) -> (b - a) and similarly for (a + (-b)) */
@ -931,8 +962,7 @@ simplify_binary_operation (code, mode, op0, op1)
/* (~a) + 1 -> -a */
if (INTEGRAL_MODE_P (mode)
&& GET_CODE (op0) == NOT
&& GET_CODE (op1) == CONST_INT
&& INTVAL (op1) == 1)
&& trueop1 == const1_rtx)
return gen_rtx_NEG (mode, XEXP (op0, 0));
/* Handle both-operands-constant cases. We can only add
@ -1025,7 +1055,7 @@ simplify_binary_operation (code, mode, op0, op1)
if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
&& op1 == CONST0_RTX (mode))
&& trueop1 == CONST0_RTX (mode))
return op0;
#endif
@ -1060,21 +1090,21 @@ simplify_binary_operation (code, mode, op0, op1)
/* We can't assume x-x is 0 even with non-IEEE floating point,
but since it is zero except in very strange circumstances, we
will treat it as zero with -funsafe-math-optimizations. */
if (rtx_equal_p (op0, op1)
if (rtx_equal_p (trueop0, trueop1)
&& ! side_effects_p (op0)
&& (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
return CONST0_RTX (mode);
/* Change subtraction from zero into negation. */
if (op0 == CONST0_RTX (mode))
if (trueop0 == CONST0_RTX (mode))
return gen_rtx_NEG (mode, op1);
/* (-1 - a) is ~a. */
if (op0 == constm1_rtx)
if (trueop0 == constm1_rtx)
return gen_rtx_NOT (mode, op1);
/* Subtracting 0 has no effect. */
if (op1 == CONST0_RTX (mode))
if (trueop1 == CONST0_RTX (mode))
return op0;
/* See if this is something like X * C - X or vice versa or
@ -1164,7 +1194,7 @@ simplify_binary_operation (code, mode, op0, op1)
break;
case MULT:
if (op1 == constm1_rtx)
if (trueop1 == constm1_rtx)
{
tem = simplify_unary_operation (NEG, mode, op0, mode);
@ -1174,20 +1204,20 @@ simplify_binary_operation (code, mode, op0, op1)
/* In IEEE floating point, x*0 is not always 0. */
if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
&& op1 == CONST0_RTX (mode)
&& trueop1 == CONST0_RTX (mode)
&& ! side_effects_p (op0))
return op1;
/* In IEEE floating point, x*1 is not equivalent to x for nans.
However, ANSI says we can drop signals,
so we can do this anyway. */
if (op1 == CONST1_RTX (mode))
if (trueop1 == CONST1_RTX (mode))
return op0;
/* Convert multiply by constant power of two into shift unless
we are still generating RTL. This test is a kludge. */
if (GET_CODE (op1) == CONST_INT
&& (val = exact_log2 (INTVAL (op1))) >= 0
if (GET_CODE (trueop1) == CONST_INT
&& (val = exact_log2 (INTVAL (trueop1))) >= 0
/* If the mode is larger than the host word size, and the
uppermost bit is set, then this isn't a power of two due
to implicit sign extension. */
@ -1196,8 +1226,8 @@ simplify_binary_operation (code, mode, op0, op1)
&& ! rtx_equal_function_value_matters)
return gen_rtx_ASHIFT (mode, op0, GEN_INT (val));
if (GET_CODE (op1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT)
if (GET_CODE (trueop1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT)
{
REAL_VALUE_TYPE d;
jmp_buf handler;
@ -1207,7 +1237,7 @@ simplify_binary_operation (code, mode, op0, op1)
return 0;
set_float_handler (handler);
REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
op1is2 = REAL_VALUES_EQUAL (d, dconst2);
op1ism1 = REAL_VALUES_EQUAL (d, dconstm1);
set_float_handler (NULL);
@ -1222,12 +1252,13 @@ simplify_binary_operation (code, mode, op0, op1)
break;
case IOR:
if (op1 == const0_rtx)
if (trueop1 == const0_rtx)
return op0;
if (GET_CODE (op1) == CONST_INT
&& (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
if (GET_CODE (trueop1) == CONST_INT
&& ((INTVAL (trueop1) & GET_MODE_MASK (mode))
== GET_MODE_MASK (mode)))
return op1;
if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
/* A | (~A) -> -1 */
if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
@ -1238,23 +1269,25 @@ simplify_binary_operation (code, mode, op0, op1)
break;
case XOR:
if (op1 == const0_rtx)
if (trueop1 == const0_rtx)
return op0;
if (GET_CODE (op1) == CONST_INT
&& (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
if (GET_CODE (trueop1) == CONST_INT
&& ((INTVAL (trueop1) & GET_MODE_MASK (mode))
== GET_MODE_MASK (mode)))
return gen_rtx_NOT (mode, op0);
if (op0 == op1 && ! side_effects_p (op0)
if (trueop0 == trueop1 && ! side_effects_p (op0)
&& GET_MODE_CLASS (mode) != MODE_CC)
return const0_rtx;
break;
case AND:
if (op1 == const0_rtx && ! side_effects_p (op0))
if (trueop1 == const0_rtx && ! side_effects_p (op0))
return const0_rtx;
if (GET_CODE (op1) == CONST_INT
&& (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
if (GET_CODE (trueop1) == CONST_INT
&& ((INTVAL (trueop1) & GET_MODE_MASK (mode))
== GET_MODE_MASK (mode)))
return op0;
if (op0 == op1 && ! side_effects_p (op0)
if (trueop0 == trueop1 && ! side_effects_p (op0)
&& GET_MODE_CLASS (mode) != MODE_CC)
return op0;
/* A & (~A) -> 0 */
@ -1268,33 +1301,33 @@ simplify_binary_operation (code, mode, op0, op1)
case UDIV:
/* Convert divide by power of two into shift (divide by 1 handled
below). */
if (GET_CODE (op1) == CONST_INT
&& (arg1 = exact_log2 (INTVAL (op1))) > 0)
if (GET_CODE (trueop1) == CONST_INT
&& (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
return gen_rtx_LSHIFTRT (mode, op0, GEN_INT (arg1));
/* ... fall through ... */
case DIV:
if (op1 == CONST1_RTX (mode))
if (trueop1 == CONST1_RTX (mode))
return op0;
/* In IEEE floating point, 0/x is not always 0. */
if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
&& op0 == CONST0_RTX (mode)
&& trueop0 == CONST0_RTX (mode)
&& ! side_effects_p (op1))
return op0;
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
/* Change division by a constant into multiplication. Only do
this with -funsafe-math-optimizations. */
else if (GET_CODE (op1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT
&& op1 != CONST0_RTX (mode)
else if (GET_CODE (trueop1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
&& trueop1 != CONST0_RTX (mode)
&& flag_unsafe_math_optimizations)
{
REAL_VALUE_TYPE d;
REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
if (! REAL_VALUES_EQUAL (d, dconst0))
{
@ -1314,14 +1347,14 @@ simplify_binary_operation (code, mode, op0, op1)
case UMOD:
/* Handle modulus by power of two (mod with 1 handled below). */
if (GET_CODE (op1) == CONST_INT
&& exact_log2 (INTVAL (op1)) > 0)
if (GET_CODE (trueop1) == CONST_INT
&& exact_log2 (INTVAL (trueop1)) > 0)
return gen_rtx_AND (mode, op0, GEN_INT (INTVAL (op1) - 1));
/* ... fall through ... */
case MOD:
if ((op0 == const0_rtx || op1 == const1_rtx)
if ((trueop0 == const0_rtx || trueop1 == const1_rtx)
&& ! side_effects_p (op0) && ! side_effects_p (op1))
return const0_rtx;
break;
@ -1329,8 +1362,8 @@ simplify_binary_operation (code, mode, op0, op1)
case ROTATERT:
case ROTATE:
/* Rotating ~0 always results in ~0. */
if (GET_CODE (op0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT
&& (unsigned HOST_WIDE_INT) INTVAL (op0) == GET_MODE_MASK (mode)
if (GET_CODE (trueop0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT
&& (unsigned HOST_WIDE_INT) INTVAL (trueop0) == GET_MODE_MASK (mode)
&& ! side_effects_p (op1))
return op0;
@ -1339,42 +1372,42 @@ simplify_binary_operation (code, mode, op0, op1)
case ASHIFT:
case ASHIFTRT:
case LSHIFTRT:
if (op1 == const0_rtx)
if (trueop1 == const0_rtx)
return op0;
if (op0 == const0_rtx && ! side_effects_p (op1))
if (trueop0 == const0_rtx && ! side_effects_p (op1))
return op0;
break;
case SMIN:
if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT
&& INTVAL (op1) == (HOST_WIDE_INT) 1 << (width -1)
if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
&& INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1)
&& ! side_effects_p (op0))
return op1;
else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
break;
case SMAX:
if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (op1)
if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (trueop1)
== (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1)
&& ! side_effects_p (op0))
return op1;
else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
break;
case UMIN:
if (op1 == const0_rtx && ! side_effects_p (op0))
if (trueop1 == const0_rtx && ! side_effects_p (op0))
return op1;
else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
break;
case UMAX:
if (op1 == constm1_rtx && ! side_effects_p (op0))
if (trueop1 == constm1_rtx && ! side_effects_p (op0))
return op1;
else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
break;
@ -1388,8 +1421,8 @@ simplify_binary_operation (code, mode, op0, op1)
/* Get the integer argument values in two forms:
zero-extended in ARG0, ARG1 and sign-extended in ARG0S, ARG1S. */
arg0 = INTVAL (op0);
arg1 = INTVAL (op1);
arg0 = INTVAL (trueop0);
arg1 = INTVAL (trueop1);
if (width < HOST_BITS_PER_WIDE_INT)
{
@ -1785,6 +1818,8 @@ simplify_relational_operation (code, mode, op0, op1)
{
int equal, op0lt, op0ltu, op1lt, op1ltu;
rtx tem;
rtx trueop0;
rtx trueop1;
if (mode == VOIDmode
&& (GET_MODE (op0) != VOIDmode
@ -1795,6 +1830,9 @@ simplify_relational_operation (code, mode, op0, op1)
if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
trueop0 = avoid_constant_pool_reference (op0);
trueop1 = avoid_constant_pool_reference (op1);
/* We can't simplify MODE_CC values since we don't know what the
actual comparison is. */
if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC
@ -1805,9 +1843,10 @@ simplify_relational_operation (code, mode, op0, op1)
return 0;
/* Make sure the constant is second. */
if (swap_commutative_operands_p (op0, op1))
if (swap_commutative_operands_p (trueop0, trueop1))
{
tem = op0, op0 = op1, op1 = tem;
tem = trueop0, trueop0 = trueop1, trueop1 = tem;
code = swap_condition (code);
}
@ -1821,9 +1860,9 @@ simplify_relational_operation (code, mode, op0, op1)
ANSI C defines unsigned operations such that they never overflow, and
thus such cases can not be ignored. */
if (INTEGRAL_MODE_P (mode) && op1 != const0_rtx
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == CONST_INT)
&& (GET_CODE (op1) == REG || GET_CODE (op1) == CONST_INT))
if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx
&& ! ((GET_CODE (op0) == REG || GET_CODE (trueop0) == CONST_INT)
&& (GET_CODE (op1) == REG || GET_CODE (trueop1) == CONST_INT))
&& 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
&& code != GTU && code != GEU && code != LTU && code != LEU)
return simplify_relational_operation (signed_condition (code),
@ -1837,23 +1876,24 @@ simplify_relational_operation (code, mode, op0, op1)
/* For non-IEEE floating-point, if the two operands are equal, we know the
result. */
if (rtx_equal_p (op0, op1)
if (rtx_equal_p (trueop0, trueop1)
&& (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| ! FLOAT_MODE_P (GET_MODE (op0))
|| ! FLOAT_MODE_P (GET_MODE (trueop0))
|| flag_unsafe_math_optimizations))
equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
/* If the operands are floating-point constants, see if we can fold
the result. */
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
else if (GET_CODE (op0) == CONST_DOUBLE && GET_CODE (op1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
else if (GET_CODE (trueop0) == CONST_DOUBLE
&& GET_CODE (trueop1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (trueop0)) == MODE_FLOAT)
{
struct cfc_args args;
/* Setup input for check_fold_consts() */
args.op0 = op0;
args.op1 = op1;
args.op0 = trueop0;
args.op1 = trueop1;
if (!do_float_handler (check_fold_consts, (PTR) &args))
@ -1891,33 +1931,35 @@ simplify_relational_operation (code, mode, op0, op1)
/* Otherwise, see if the operands are both integers. */
else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode)
&& (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT)
&& (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT))
&& (GET_CODE (trueop0) == CONST_DOUBLE
|| GET_CODE (trueop0) == CONST_INT)
&& (GET_CODE (trueop1) == CONST_DOUBLE
|| GET_CODE (trueop1) == CONST_INT))
{
int width = GET_MODE_BITSIZE (mode);
HOST_WIDE_INT l0s, h0s, l1s, h1s;
unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u;
/* Get the two words comprising each integer constant. */
if (GET_CODE (op0) == CONST_DOUBLE)
if (GET_CODE (trueop0) == CONST_DOUBLE)
{
l0u = l0s = CONST_DOUBLE_LOW (op0);
h0u = h0s = CONST_DOUBLE_HIGH (op0);
l0u = l0s = CONST_DOUBLE_LOW (trueop0);
h0u = h0s = CONST_DOUBLE_HIGH (trueop0);
}
else
{
l0u = l0s = INTVAL (op0);
l0u = l0s = INTVAL (trueop0);
h0u = h0s = HWI_SIGN_EXTEND (l0s);
}
if (GET_CODE (op1) == CONST_DOUBLE)
if (GET_CODE (trueop1) == CONST_DOUBLE)
{
l1u = l1s = CONST_DOUBLE_LOW (op1);
h1u = h1s = CONST_DOUBLE_HIGH (op1);
l1u = l1s = CONST_DOUBLE_LOW (trueop1);
h1u = h1s = CONST_DOUBLE_HIGH (trueop1);
}
else
{
l1u = l1s = INTVAL (op1);
l1u = l1s = INTVAL (trueop1);
h1u = h1s = HWI_SIGN_EXTEND (l1s);
}
@ -1952,8 +1994,8 @@ simplify_relational_operation (code, mode, op0, op1)
case EQ:
/* References to the frame plus a constant or labels cannot
be zero, but a SYMBOL_REF can due to #pragma weak. */
if (((NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx)
|| GET_CODE (op0) == LABEL_REF)
if (((NONZERO_BASE_PLUS_P (op0) && trueop1 == const0_rtx)
|| GET_CODE (trueop0) == LABEL_REF)
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* On some machines, the ap reg can be 0 sometimes. */
&& op0 != arg_pointer_rtx
@ -1963,8 +2005,8 @@ simplify_relational_operation (code, mode, op0, op1)
break;
case NE:
if (((NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx)
|| GET_CODE (op0) == LABEL_REF)
if (((NONZERO_BASE_PLUS_P (op0) && trueop1 == const0_rtx)
|| GET_CODE (trueop0) == LABEL_REF)
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& op0 != arg_pointer_rtx
#endif
@ -1974,27 +2016,27 @@ simplify_relational_operation (code, mode, op0, op1)
case GEU:
/* Unsigned values are never negative. */
if (op1 == const0_rtx)
if (trueop1 == const0_rtx)
return const_true_rtx;
break;
case LTU:
if (op1 == const0_rtx)
if (trueop1 == const0_rtx)
return const0_rtx;
break;
case LEU:
/* Unsigned values are never greater than the largest
unsigned value. */
if (GET_CODE (op1) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (op1) == GET_MODE_MASK (mode)
if (GET_CODE (trueop1) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (trueop1) == GET_MODE_MASK (mode)
&& INTEGRAL_MODE_P (mode))
return const_true_rtx;
break;
case GTU:
if (GET_CODE (op1) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (op1) == GET_MODE_MASK (mode)
if (GET_CODE (trueop1) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (trueop1) == GET_MODE_MASK (mode)
&& INTEGRAL_MODE_P (mode))
return const0_rtx;
break;