simplify-rtx.c (associative_constant_p): New function to test whether an RTX expression is an immediate constant.

* simplify-rtx.c (associative_constant_p): New function to test
	whether an RTX expression is an immediate constant.
	(simplify_associative_operation): New function to perform some
	reassociation optimizations of associative binary expressions.
	(simplify_binary_operation): Use simplify_associative_operation
	to simplify PLUS, MULT, AND, IOR, XOR, SMIN, SMAX, UMIN and UMAX.
	Floating point expressions are only reassociated when unsafe
	math optimizations are permitted.

From-SVN: r70521
This commit is contained in:
Roger Sayle 2003-08-17 19:24:09 +00:00 committed by Roger Sayle
parent fde46628fa
commit dd61aa98ca
2 changed files with 129 additions and 6 deletions

View File

@ -1,3 +1,14 @@
2003-08-17 Roger Sayle <roger@eyesopen.com>
* simplify-rtx.c (associative_constant_p): New function to test
whether an RTX expression is an immediate constant.
(simplify_associative_operation): New function to perform some
reassociation optimizations of associative binary expressions.
(simplify_binary_operation): Use simplify_associative_operation
to simplify PLUS, MULT, AND, IOR, XOR, SMIN, SMAX, UMIN and UMAX.
Floating point expressions are only reassociated when unsafe
math optimizations are permitted.
2003-08-17 Andreas Jaeger <aj@suse.de>
* config/alpha/alpha.md: Remove usage of PARAMS.

View File

@ -53,6 +53,9 @@ static rtx neg_const_int (enum machine_mode, rtx);
static int simplify_plus_minus_op_data_cmp (const void *, const void *);
static rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx,
rtx, int);
static bool associative_constant_p (rtx);
static rtx simplify_associative_operation (enum rtx_code, enum machine_mode,
rtx, rtx);
/* Negate a CONST_INT rtx, truncating (because a conversion from a
maximally negative number can overflow). */
@ -854,6 +857,72 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
}
}
/* Subroutine of simplify_associative_operation. Return true if rtx OP
is a suitable integer or floating point immediate constant. */
static bool
associative_constant_p (rtx op)
{
if (GET_CODE (op) == CONST_INT
|| GET_CODE (op) == CONST_DOUBLE)
return true;
op = avoid_constant_pool_reference (op);
return GET_CODE (op) == CONST_INT
|| GET_CODE (op) == CONST_DOUBLE;
}
/* Subroutine of simplify_binary_operation to simplify an associative
binary operation CODE with result mode MODE, operating on OP0 and OP1.
Return 0 if no simplification is possible. */
static rtx
simplify_associative_operation (enum rtx_code code, enum machine_mode mode,
rtx op0, rtx op1)
{
rtx tem;
/* Simplify (x op c1) op c2 as x op (c1 op c2). */
if (GET_CODE (op0) == code
&& associative_constant_p (op1)
&& associative_constant_p (XEXP (op0, 1)))
{
tem = simplify_binary_operation (code, mode, XEXP (op0, 1), op1);
if (! tem)
return tem;
return simplify_gen_binary (code, mode, XEXP (op0, 0), tem);
}
/* Simplify (x op c1) op (y op c2) as (x op y) op (c1 op c2). */
if (GET_CODE (op0) == code
&& GET_CODE (op1) == code
&& associative_constant_p (XEXP (op0, 1))
&& associative_constant_p (XEXP (op1, 1)))
{
rtx c = simplify_binary_operation (code, mode,
XEXP (op0, 1), XEXP (op1, 1));
if (! c)
return 0;
tem = simplify_gen_binary (code, mode, XEXP (op0, 0), XEXP (op1, 0));
return simplify_gen_binary (code, mode, tem, c);
}
/* Canonicalize (x op c) op y as (x op y) op c. */
if (GET_CODE (op0) == code
&& associative_constant_p (XEXP (op0, 1)))
{
tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1);
return simplify_gen_binary (code, mode, tem, XEXP (op0, 1));
}
/* Canonicalize x op (y op c) as (x op y) op c. */
if (GET_CODE (op1) == code
&& associative_constant_p (XEXP (op1, 1)))
{
tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0));
return simplify_gen_binary (code, mode, tem, XEXP (op1, 1));
}
return 0;
}
/* Simplify a binary operation CODE with result mode MODE, operating on OP0
and OP1. Return 0 if no simplification is possible.
@ -1179,6 +1248,16 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
&& GET_CODE (XEXP (op1, 0)) == PLUS))
&& (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
return tem;
/* Reassociate floating point addition only when the user
specifies unsafe math optimizations. */
if (FLOAT_MODE_P (mode)
&& flag_unsafe_math_optimizations)
{
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
}
break;
case COMPARE:
@ -1388,6 +1467,16 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
if (REAL_VALUES_EQUAL (d, dconstm1))
return simplify_gen_unary (NEG, mode, op0, mode);
}
/* Reassociate multiplication, but for floating point MULTs
only when the user specifies unsafe math optimizations. */
if (! FLOAT_MODE_P (mode)
|| flag_unsafe_math_optimizations)
{
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
}
break;
case IOR:
@ -1405,6 +1494,9 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
&& ! side_effects_p (op0)
&& GET_MODE_CLASS (mode) != MODE_CC)
return constm1_rtx;
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
break;
case XOR:
@ -1417,6 +1509,9 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
if (trueop0 == trueop1 && ! side_effects_p (op0)
&& GET_MODE_CLASS (mode) != MODE_CC)
return const0_rtx;
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
break;
case AND:
@ -1435,6 +1530,9 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
&& ! side_effects_p (op0)
&& GET_MODE_CLASS (mode) != MODE_CC)
return const0_rtx;
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
break;
case UDIV:
@ -1524,36 +1622,50 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
break;
case SMIN:
if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
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 (trueop0, trueop1) && ! side_effects_p (op0))
if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
break;
case SMAX:
if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
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 (trueop0, trueop1) && ! side_effects_p (op0))
if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
break;
case UMIN:
if (trueop1 == const0_rtx && ! side_effects_p (op0))
return op1;
else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
break;
case UMAX:
if (trueop1 == constm1_rtx && ! side_effects_p (op0))
return op1;
else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
break;
case SS_PLUS: