Commit d26cef13 by Paolo Bonzini

re PR rtl-optimization/26847 (Missed optimization in simplify_plus_minus)

2006-09-05  Paolo Bonzini  <bonzini@gnu.org>

	PR rtl-optimization/26847
	* simplify-rtx.c (struct simplify_plus_minus_op_data): Remove ix.
	(simplify_plus_minus_op_data_cmp): For REGs, break ties on the regno.
	(simplify_plus_minus): Count n_constants while filling ops.  Replace
	qsort with insertion sort.  Before going through the array to simplify
	pairs, sort it.  Delay early exit until after the first sort, exiting
	only if no swaps occurred.  Simplify pairs in reversed order, without
	special-casing the first iteration.  Pack ops after simplifying pairs.

From-SVN: r116701
parent 5527be59
2006-09-02 Anatoly Sokolov <aesok@post.ru>
2006-09-05 Paolo Bonzini <bonzini@gnu.org>
PR rtl-optimization/26847
* simplify-rtx.c (struct simplify_plus_minus_op_data): Remove ix.
(simplify_plus_minus_op_data_cmp): For REGs, break ties on the regno.
(simplify_plus_minus): Count n_constants while filling ops. Replace
qsort with insertion sort. Before going through the array to simplify
pairs, sort it. Delay early exit until after the first sort, exiting
only if no swaps occurred. Simplify pairs in reversed order, without
special-casing the first iteration. Pack ops after simplifying pairs.
2006-09-05 Anatoly Sokolov <aesok@post.ru>
* config/avr/avr.c (avr_mcu_types): Add support for at90pwm1 device.
* config/avr/t-avr (MULTILIB_MATCHES): (Ditto.).
......
......@@ -3185,7 +3185,6 @@ struct simplify_plus_minus_op_data
{
rtx op;
short neg;
short ix;
};
static int
......@@ -3199,7 +3198,12 @@ simplify_plus_minus_op_data_cmp (const void *p1, const void *p2)
- commutative_operand_precedence (d1->op));
if (result)
return result;
return d1->ix - d2->ix;
/* Group together equal REGs to do more simplification. */
if (REG_P (d1->op) && REG_P (d2->op))
return REGNO (d1->op) - REGNO (d2->op);
else
return 0;
}
static rtx
......@@ -3209,7 +3213,7 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
struct simplify_plus_minus_op_data ops[8];
rtx result, tem;
int n_ops = 2, input_ops = 2;
int first, changed, canonicalized = 0;
int changed, n_constants = 0, canonicalized = 0;
int i, j;
memset (ops, 0, sizeof ops);
......@@ -3286,6 +3290,7 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
break;
case CONST_INT:
n_constants++;
if (this_neg)
{
ops[i].op = neg_const_int (mode, this_op);
......@@ -3302,18 +3307,10 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
}
while (changed);
gcc_assert (n_ops >= 2);
if (!canonicalized)
{
int n_constants = 0;
for (i = 0; i < n_ops; i++)
if (GET_CODE (ops[i].op) == CONST_INT)
n_constants++;
if (n_constants > 1)
canonicalized = 1;
if (n_constants <= 1)
return NULL_RTX;
}
gcc_assert (n_ops >= 2);
/* If we only have two operands, we can avoid the loops. */
if (n_ops == 2)
......@@ -3342,22 +3339,37 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
return simplify_const_binary_operation (code, mode, lhs, rhs);
}
/* Now simplify each pair of operands until nothing changes. The first
time through just simplify constants against each other. */
first = 1;
/* Now simplify each pair of operands until nothing changes. */
do
{
changed = first;
/* Insertion sort is good enough for an eight-element array. */
for (i = 1; i < n_ops; i++)
{
struct simplify_plus_minus_op_data save;
j = i - 1;
if (simplify_plus_minus_op_data_cmp (&ops[j], &ops[i]) < 0)
continue;
canonicalized = 1;
save = ops[i];
do
ops[j + 1] = ops[j];
while (j-- && simplify_plus_minus_op_data_cmp (&ops[j], &save) > 0);
ops[j + 1] = save;
}
for (i = 0; i < n_ops - 1; i++)
for (j = i + 1; j < n_ops; j++)
/* This is only useful the first time through. */
if (!canonicalized)
return NULL_RTX;
changed = 0;
for (i = n_ops - 1; i > 0; i--)
for (j = i - 1; j >= 0; j--)
{
rtx lhs = ops[i].op, rhs = ops[j].op;
int lneg = ops[i].neg, rneg = ops[j].neg;
rtx lhs = ops[j].op, rhs = ops[i].op;
int lneg = ops[j].neg, rneg = ops[i].neg;
if (lhs != 0 && rhs != 0
&& (! first || (CONSTANT_P (lhs) && CONSTANT_P (rhs))))
if (lhs != 0 && rhs != 0)
{
enum rtx_code ncode = PLUS;
......@@ -3393,13 +3405,7 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
&& ! (GET_CODE (tem) == CONST
&& GET_CODE (XEXP (tem, 0)) == ncode
&& XEXP (XEXP (tem, 0), 0) == lhs
&& XEXP (XEXP (tem, 0), 1) == rhs)
/* Don't allow -x + -1 -> ~x simplifications in the
first pass. This allows us the chance to combine
the -1 with other constants. */
&& ! (first
&& GET_CODE (tem) == NOT
&& XEXP (tem, 0) == rhs))
&& XEXP (XEXP (tem, 0), 1) == rhs))
{
lneg &= rneg;
if (GET_CODE (tem) == NEG)
......@@ -3415,24 +3421,17 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
}
}
first = 0;
/* Pack all the operands to the lower-numbered entries. */
for (i = 0, j = 0; j < n_ops; j++)
if (ops[j].op)
{
ops[i] = ops[j];
i++;
}
n_ops = i;
}
while (changed);
/* Pack all the operands to the lower-numbered entries. */
for (i = 0, j = 0; j < n_ops; j++)
if (ops[j].op)
{
ops[i] = ops[j];
/* Stabilize sort. */
ops[i].ix = i;
i++;
}
n_ops = i;
/* Sort the operations based on swap_commutative_operands_p. */
qsort (ops, n_ops, sizeof (*ops), simplify_plus_minus_op_data_cmp);
/* Create (minus -C X) instead of (neg (const (plus X C))). */
if (n_ops == 2
&& GET_CODE (ops[1].op) == CONST_INT
......
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