aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/simplify-rtx.c93
2 files changed, 58 insertions, 48 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 098829c..71eb203 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,15 @@
-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.).
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 8c437e4..3b12b20 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -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