rtlanal.c (commutative_operand_precedence): Correct comments.

* rtlanal.c (commutative_operand_precedence): Correct comments.
	* simplify-rtx.c (simplify_plus_minus_op_data_cmp): Delete forward
	declaration.  Return an int.  Distinguish REG,REG return from
	others.
	(struct simplify_plus_minus_op_data): Make local to function.
	(simplify_plus_minus): Don't set canonicalized if merely sorting
	registers.  Avoid packing ops if nothing changes.  White space fixes.

From-SVN: r224768
This commit is contained in:
Alan Modra 2015-06-23 10:35:04 +09:30 committed by Alan Modra
parent 6536a0a875
commit 350911e651
3 changed files with 78 additions and 47 deletions

View file

@ -1,3 +1,13 @@
2015-06-23 Alan Modra <amodra@gmail.com>
* rtlanal.c (commutative_operand_precedence): Correct comments.
* simplify-rtx.c (simplify_plus_minus_op_data_cmp): Delete forward
declaration. Return an int. Distinguish REG,REG return from
others.
(struct simplify_plus_minus_op_data): Make local to function.
(simplify_plus_minus): Don't set canonicalized if merely sorting
registers. Avoid packing ops if nothing changes. White space fixes.
2015-06-22 Pierre-Marie de Rodat <derodat@adacore.com> 2015-06-22 Pierre-Marie de Rodat <derodat@adacore.com>
* gcc.c (default_compilers): Pass "-o %g.s" to cc1 for headers even if * gcc.c (default_compilers): Pass "-o %g.s" to cc1 for headers even if

View file

@ -3132,17 +3132,16 @@ regno_use_in (unsigned int regno, rtx x)
} }
/* Return a value indicating whether OP, an operand of a commutative /* Return a value indicating whether OP, an operand of a commutative
operation, is preferred as the first or second operand. The higher operation, is preferred as the first or second operand. The more
the value, the stronger the preference for being the first operand. positive the value, the stronger the preference for being the first
We use negative values to indicate a preference for the first operand operand. */
and positive values for the second operand. */
int int
commutative_operand_precedence (rtx op) commutative_operand_precedence (rtx op)
{ {
enum rtx_code code = GET_CODE (op); enum rtx_code code = GET_CODE (op);
/* Constants always come the second operand. Prefer "nice" constants. */ /* Constants always become the second operand. Prefer "nice" constants. */
if (code == CONST_INT) if (code == CONST_INT)
return -8; return -8;
if (code == CONST_WIDE_INT) if (code == CONST_WIDE_INT)

View file

@ -59,7 +59,6 @@ along with GCC; see the file COPYING3. If not see
static rtx neg_const_int (machine_mode, const_rtx); static rtx neg_const_int (machine_mode, const_rtx);
static bool plus_minus_operand_p (const_rtx); static bool plus_minus_operand_p (const_rtx);
static bool simplify_plus_minus_op_data_cmp (rtx, rtx);
static rtx simplify_plus_minus (enum rtx_code, machine_mode, rtx, rtx); static rtx simplify_plus_minus (enum rtx_code, machine_mode, rtx, rtx);
static rtx simplify_immed_subreg (machine_mode, rtx, machine_mode, static rtx simplify_immed_subreg (machine_mode, rtx, machine_mode,
unsigned int); unsigned int);
@ -4049,20 +4048,10 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
/* Simplify a PLUS or MINUS, at least one of whose operands may be another /* Return a positive integer if X should sort after Y. The value
PLUS or MINUS. returned is 1 if and only if X and Y are both regs. */
Rather than test for specific case, we do this by a brute-force method static int
and do all possible simplifications until no more changes occur. Then
we rebuild the operation. */
struct simplify_plus_minus_op_data
{
rtx op;
short neg;
};
static bool
simplify_plus_minus_op_data_cmp (rtx x, rtx y) simplify_plus_minus_op_data_cmp (rtx x, rtx y)
{ {
int result; int result;
@ -4070,20 +4059,33 @@ simplify_plus_minus_op_data_cmp (rtx x, rtx y)
result = (commutative_operand_precedence (y) result = (commutative_operand_precedence (y)
- commutative_operand_precedence (x)); - commutative_operand_precedence (x));
if (result) if (result)
return result > 0; return result + result;
/* Group together equal REGs to do more simplification. */ /* Group together equal REGs to do more simplification. */
if (REG_P (x) && REG_P (y)) if (REG_P (x) && REG_P (y))
return REGNO (x) > REGNO (y); return REGNO (x) > REGNO (y);
else
return false; return 0;
} }
/* Simplify and canonicalize a PLUS or MINUS, at least one of whose
operands may be another PLUS or MINUS.
Rather than test for specific case, we do this by a brute-force method
and do all possible simplifications until no more changes occur. Then
we rebuild the operation.
May return NULL_RTX when no changes were made. */
static rtx static rtx
simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0, simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
rtx op1) rtx op1)
{ {
struct simplify_plus_minus_op_data ops[16]; struct simplify_plus_minus_op_data
{
rtx op;
short neg;
} ops[16];
rtx result, tem; rtx result, tem;
int n_ops = 2; int n_ops = 2;
int changed, n_constants, canonicalized = 0; int changed, n_constants, canonicalized = 0;
@ -4124,7 +4126,18 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
ops[i].op = XEXP (this_op, 0); ops[i].op = XEXP (this_op, 0);
changed = 1; changed = 1;
canonicalized |= this_neg || i != n_ops - 2; /* If this operand was negated then we will potentially
canonicalize the expression. Similarly if we don't
place the operands adjacent we're re-ordering the
expression and thus might be performing a
canonicalization. Ignore register re-ordering.
??? It might be better to shuffle the ops array here,
but then (plus (plus (A, B), plus (C, D))) wouldn't
be seen as non-canonical. */
if (this_neg
|| (i != n_ops - 2
&& !(REG_P (ops[i].op) && REG_P (ops[n_ops - 1].op))))
canonicalized = 1;
break; break;
case NEG: case NEG:
@ -4145,7 +4158,7 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
ops[n_ops].neg = this_neg; ops[n_ops].neg = this_neg;
n_ops++; n_ops++;
changed = 1; changed = 1;
canonicalized = 1; canonicalized = 1;
} }
break; break;
@ -4158,7 +4171,7 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
ops[i].op = XEXP (this_op, 0); ops[i].op = XEXP (this_op, 0);
ops[i].neg = !this_neg; ops[i].neg = !this_neg;
changed = 1; changed = 1;
canonicalized = 1; canonicalized = 1;
} }
break; break;
@ -4169,7 +4182,7 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
ops[i].op = neg_const_int (mode, this_op); ops[i].op = neg_const_int (mode, this_op);
ops[i].neg = 0; ops[i].neg = 0;
changed = 1; changed = 1;
canonicalized = 1; canonicalized = 1;
} }
break; break;
@ -4213,23 +4226,29 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
} }
/* Now simplify each pair of operands until nothing changes. */ /* Now simplify each pair of operands until nothing changes. */
do while (1)
{ {
/* Insertion sort is good enough for a small array. */ /* Insertion sort is good enough for a small array. */
for (i = 1; i < n_ops; i++) for (i = 1; i < n_ops; i++)
{ {
struct simplify_plus_minus_op_data save; struct simplify_plus_minus_op_data save;
j = i - 1; int cmp;
if (!simplify_plus_minus_op_data_cmp (ops[j].op, ops[i].op))
continue;
canonicalized = 1; j = i - 1;
save = ops[i]; cmp = simplify_plus_minus_op_data_cmp (ops[j].op, ops[i].op);
do if (cmp <= 0)
continue;
/* Just swapping registers doesn't count as canonicalization. */
if (cmp != 1)
canonicalized = 1;
save = ops[i];
do
ops[j + 1] = ops[j]; ops[j + 1] = ops[j];
while (j-- && simplify_plus_minus_op_data_cmp (ops[j].op, save.op)); while (j--
ops[j + 1] = save; && simplify_plus_minus_op_data_cmp (ops[j].op, save.op) > 0);
} ops[j + 1] = save;
}
changed = 0; changed = 0;
for (i = n_ops - 1; i > 0; i--) for (i = n_ops - 1; i > 0; i--)
@ -4258,7 +4277,8 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
tem_lhs = GET_CODE (lhs) == CONST ? XEXP (lhs, 0) : lhs; tem_lhs = GET_CODE (lhs) == CONST ? XEXP (lhs, 0) : lhs;
tem_rhs = GET_CODE (rhs) == CONST ? XEXP (rhs, 0) : rhs; tem_rhs = GET_CODE (rhs) == CONST ? XEXP (rhs, 0) : rhs;
tem = simplify_binary_operation (ncode, mode, tem_lhs, tem_rhs); tem = simplify_binary_operation (ncode, mode, tem_lhs,
tem_rhs);
if (tem && !CONSTANT_P (tem)) if (tem && !CONSTANT_P (tem))
tem = gen_rtx_CONST (GET_MODE (tem), tem); tem = gen_rtx_CONST (GET_MODE (tem), tem);
@ -4296,20 +4316,22 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
} }
} }
/* If nothing changed, fail. */ if (!changed)
if (!canonicalized) break;
return NULL_RTX;
/* Pack all the operands to the lower-numbered entries. */ /* Pack all the operands to the lower-numbered entries. */
for (i = 0, j = 0; j < n_ops; j++) for (i = 0, j = 0; j < n_ops; j++)
if (ops[j].op) if (ops[j].op)
{ {
ops[i] = ops[j]; ops[i] = ops[j];
i++; i++;
} }
n_ops = i; n_ops = i;
} }
while (changed);
/* If nothing changed, fail. */
if (!canonicalized)
return NULL_RTX;
/* Create (minus -C X) instead of (neg (const (plus X C))). */ /* Create (minus -C X) instead of (neg (const (plus X C))). */
if (n_ops == 2 if (n_ops == 2