Commit 9b3bd424 by Richard Henderson Committed by Richard Henderson

loop.c (record_giv): Avoid simplifying MULT to ASHIFT.

        * loop.c (record_giv): Avoid simplifying MULT to ASHIFT.
        (express_from_1): Wrap lines.
        * rtlanal.c (commutative_operand_precedence): Rename from
        operand_preference; export.
        * rtl.h: Declare it.
        * simplify-rtx.c (simplify_gen_binary): Tidy +/- const_int handling.
        (simplify_binary_operation): Invoke simplify_plus_minus on
        (CONST (PLUS ...)) as well.
        (struct simplify_plus_minus_op_data): New.
        (simplify_plus_minus_op_data_cmp): New.
        (simplify_plus_minus): Use them.  Avoid infinite recursion with
        simplify_binary_operation wrt CONST.

From-SVN: r45473
parent 99780529
2001-09-07 Richard Henderson <rth@redhat.com>
* loop.c (record_giv): Avoid simplifying MULT to ASHIFT.
(express_from_1): Wrap lines.
* rtlanal.c (commutative_operand_precedence): Rename from
operand_preference; export.
* rtl.h: Declare it.
* simplify-rtx.c (simplify_gen_binary): Tidy +/- const_int handling.
(simplify_binary_operation): Invoke simplify_plus_minus on
(CONST (PLUS ...)) as well.
(struct simplify_plus_minus_op_data): New.
(simplify_plus_minus_op_data_cmp): New.
(simplify_plus_minus): Use them. Avoid infinite recursion with
simplify_binary_operation wrt CONST.
Fri Sep 7 11:52:30 2001 Kazu Hirata <kazu@hxi.com> Fri Sep 7 11:52:30 2001 Kazu Hirata <kazu@hxi.com>
* h8300-protos.h (general_operand_dst_push): Remove. * h8300-protos.h (general_operand_dst_push): Remove.
......
...@@ -4922,9 +4922,12 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val, ...@@ -4922,9 +4922,12 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
rtx set = single_set (insn); rtx set = single_set (insn);
rtx temp; rtx temp;
/* Attempt to prove constantness of the values. */ /* Attempt to prove constantness of the values. Don't let simplity_rtx
undo the MULT canonicalization that we performed earlier. */
temp = simplify_rtx (add_val); temp = simplify_rtx (add_val);
if (temp) if (temp
&& ! (GET_CODE (add_val) == MULT
&& GET_CODE (temp) == ASHIFT))
add_val = temp; add_val = temp;
v->insn = insn; v->insn = insn;
...@@ -6371,7 +6374,10 @@ express_from_1 (a, b, mult) ...@@ -6371,7 +6374,10 @@ express_from_1 (a, b, mult)
} }
else if (CONSTANT_P (a)) else if (CONSTANT_P (a))
{ {
return simplify_gen_binary (MINUS, GET_MODE (b) != VOIDmode ? GET_MODE (b) : GET_MODE (a), b, a); enum machine_mode mode_a = GET_MODE (a);
enum machine_mode mode_b = GET_MODE (b);
enum machine_mode mode = mode_b == VOIDmode ? mode_a : mode_b;
return simplify_gen_binary (MINUS, mode, b, a);
} }
else if (GET_CODE (b) == PLUS) else if (GET_CODE (b) == PLUS)
{ {
......
...@@ -1374,6 +1374,7 @@ extern int reg_used_between_p PARAMS ((rtx, rtx, rtx)); ...@@ -1374,6 +1374,7 @@ extern int reg_used_between_p PARAMS ((rtx, rtx, rtx));
extern int reg_referenced_between_p PARAMS ((rtx, rtx, rtx)); extern int reg_referenced_between_p PARAMS ((rtx, rtx, rtx));
extern int reg_set_between_p PARAMS ((rtx, rtx, rtx)); extern int reg_set_between_p PARAMS ((rtx, rtx, rtx));
extern int regs_set_between_p PARAMS ((rtx, rtx, rtx)); extern int regs_set_between_p PARAMS ((rtx, rtx, rtx));
extern int commutative_operand_precedence PARAMS ((rtx));
extern int swap_commutative_operands_p PARAMS ((rtx, rtx)); extern int swap_commutative_operands_p PARAMS ((rtx, rtx));
extern int modified_between_p PARAMS ((rtx, rtx, rtx)); extern int modified_between_p PARAMS ((rtx, rtx, rtx));
extern int no_labels_between_p PARAMS ((rtx, rtx)); extern int no_labels_between_p PARAMS ((rtx, rtx));
......
...@@ -30,7 +30,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -30,7 +30,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static void set_of_1 PARAMS ((rtx, rtx, void *)); static void set_of_1 PARAMS ((rtx, rtx, void *));
static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *)); static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
static int computed_jump_p_1 PARAMS ((rtx)); static int computed_jump_p_1 PARAMS ((rtx));
static int operand_preference PARAMS ((rtx));
static void parms_set PARAMS ((rtx, rtx, void *)); static void parms_set PARAMS ((rtx, rtx, void *));
/* Bit flags that specify the machine subtype we are compiling for. /* Bit flags that specify the machine subtype we are compiling for.
...@@ -2558,8 +2557,8 @@ regno_use_in (regno, x) ...@@ -2558,8 +2557,8 @@ regno_use_in (regno, x)
We use negative values to indicate a preference for the first operand We use negative values to indicate a preference for the first operand
and positive values for the second operand. */ and positive values for the second operand. */
static int int
operand_preference (op) commutative_operand_precedence (op)
rtx op; rtx op;
{ {
/* Constants always come the second operand. Prefer "nice" constants. */ /* Constants always come the second operand. Prefer "nice" constants. */
...@@ -2597,7 +2596,8 @@ int ...@@ -2597,7 +2596,8 @@ int
swap_commutative_operands_p (x, y) swap_commutative_operands_p (x, y)
rtx x, y; rtx x, y;
{ {
return operand_preference (x) < operand_preference (y); return (commutative_operand_precedence (x)
< commutative_operand_precedence (y));
} }
/* Return 1 if X is an autoincrement side effect and the register is /* Return 1 if X is an autoincrement side effect and the register is
......
...@@ -95,6 +95,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -95,6 +95,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define HWI_SIGN_EXTEND(low) \ #define HWI_SIGN_EXTEND(low) \
((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0)) ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0))
static int simplify_plus_minus_op_data_cmp PARAMS ((const void *,
const void *));
static rtx simplify_plus_minus PARAMS ((enum rtx_code, static rtx simplify_plus_minus PARAMS ((enum rtx_code,
enum machine_mode, rtx, rtx)); enum machine_mode, rtx, rtx));
static void check_fold_consts PARAMS ((PTR)); static void check_fold_consts PARAMS ((PTR));
...@@ -130,12 +132,15 @@ simplify_gen_binary (code, mode, op0, op1) ...@@ -130,12 +132,15 @@ simplify_gen_binary (code, mode, op0, op1)
/* Handle addition and subtraction of CONST_INT specially. Otherwise, /* Handle addition and subtraction of CONST_INT specially. Otherwise,
just form the operation. */ just form the operation. */
if (code == PLUS && GET_CODE (op1) == CONST_INT if (GET_CODE (op1) == CONST_INT
&& GET_MODE (op0) != VOIDmode) && GET_MODE (op0) != VOIDmode
return plus_constant (op0, INTVAL (op1)); && (code == PLUS || code == MINUS))
else if (code == MINUS && GET_CODE (op1) == CONST_INT {
&& GET_MODE (op0) != VOIDmode) HOST_WIDE_INT value = INTVAL (op1);
return plus_constant (op0, - INTVAL (op1)); if (code == MINUS)
value = -value;
return plus_constant (op0, value);
}
else else
return gen_rtx_fmt_ee (code, mode, op0, op1); return gen_rtx_fmt_ee (code, mode, op0, op1);
} }
...@@ -1124,7 +1129,11 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -1124,7 +1129,11 @@ simplify_binary_operation (code, mode, op0, op1)
if (INTEGRAL_MODE_P (mode) if (INTEGRAL_MODE_P (mode)
&& (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
|| GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS) || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS
|| (GET_CODE (op0) == CONST
&& GET_CODE (XEXP (op0, 0)) == PLUS)
|| (GET_CODE (op1) == CONST
&& GET_CODE (XEXP (op1, 0)) == PLUS))
&& (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
return tem; return tem;
break; break;
...@@ -1162,8 +1171,8 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -1162,8 +1171,8 @@ simplify_binary_operation (code, mode, op0, op1)
#endif #endif
return xop00; return xop00;
} }
break; break;
case MINUS: case MINUS:
/* None of these optimizations can be done for IEEE /* None of these optimizations can be done for IEEE
floating point. */ floating point. */
...@@ -1257,7 +1266,11 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -1257,7 +1266,11 @@ simplify_binary_operation (code, mode, op0, op1)
if (INTEGRAL_MODE_P (mode) if (INTEGRAL_MODE_P (mode)
&& (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
|| GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS) || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS
|| (GET_CODE (op0) == CONST
&& GET_CODE (XEXP (op0, 0)) == PLUS)
|| (GET_CODE (op1) == CONST
&& GET_CODE (XEXP (op1, 0)) == PLUS))
&& (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
return tem; return tem;
...@@ -1680,17 +1693,34 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -1680,17 +1693,34 @@ simplify_binary_operation (code, mode, op0, op1)
and do all possible simplifications until no more changes occur. Then and do all possible simplifications until no more changes occur. Then
we rebuild the operation. */ we rebuild the operation. */
struct simplify_plus_minus_op_data
{
rtx op;
int neg;
};
static int
simplify_plus_minus_op_data_cmp (p1, p2)
const void *p1;
const void *p2;
{
const struct simplify_plus_minus_op_data *d1 = p1;
const struct simplify_plus_minus_op_data *d2 = p2;
return (commutative_operand_precedence (d2->op)
- commutative_operand_precedence (d1->op));
}
static rtx static rtx
simplify_plus_minus (code, mode, op0, op1) simplify_plus_minus (code, mode, op0, op1)
enum rtx_code code; enum rtx_code code;
enum machine_mode mode; enum machine_mode mode;
rtx op0, op1; rtx op0, op1;
{ {
rtx ops[8]; struct simplify_plus_minus_op_data ops[8];
int negs[8];
rtx result, tem; rtx result, tem;
int n_ops = 2, input_ops = 2, input_consts = 0, n_consts = 0; int n_ops = 2, input_ops = 2, input_consts = 0, n_consts;
int first = 1, negate = 0, changed; int first, negate, changed;
int i, j; int i, j;
memset ((char *) ops, 0, sizeof ops); memset ((char *) ops, 0, sizeof ops);
...@@ -1699,153 +1729,204 @@ simplify_plus_minus (code, mode, op0, op1) ...@@ -1699,153 +1729,204 @@ simplify_plus_minus (code, mode, op0, op1)
changed. If we run out of room in our array, give up; this should changed. If we run out of room in our array, give up; this should
almost never happen. */ almost never happen. */
ops[0] = op0, ops[1] = op1, negs[0] = 0, negs[1] = (code == MINUS); ops[0].op = op0;
ops[0].neg = 0;
ops[1].op = op1;
ops[1].neg = (code == MINUS);
changed = 1; do
while (changed)
{ {
changed = 0; changed = 0;
for (i = 0; i < n_ops; i++) for (i = 0; i < n_ops; i++)
switch (GET_CODE (ops[i])) {
{ rtx this_op = ops[i].op;
case PLUS: int this_neg = ops[i].neg;
case MINUS: enum rtx_code this_code = GET_CODE (this_op);
if (n_ops == 7)
return 0;
ops[n_ops] = XEXP (ops[i], 1);
negs[n_ops++] = GET_CODE (ops[i]) == MINUS ? !negs[i] : negs[i];
ops[i] = XEXP (ops[i], 0);
input_ops++;
changed = 1;
break;
case NEG:
ops[i] = XEXP (ops[i], 0);
negs[i] = ! negs[i];
changed = 1;
break;
case CONST: switch (this_code)
ops[i] = XEXP (ops[i], 0); {
input_consts++; case PLUS:
changed = 1; case MINUS:
break; if (n_ops == 7)
return 0;
case NOT: ops[n_ops].op = XEXP (this_op, 1);
/* ~a -> (-a - 1) */ ops[n_ops].neg = (this_code == MINUS) ^ this_neg;
if (n_ops != 7) n_ops++;
{
ops[n_ops] = constm1_rtx; ops[i].op = XEXP (this_op, 0);
negs[n_ops++] = negs[i]; input_ops++;
ops[i] = XEXP (ops[i], 0); changed = 1;
negs[i] = ! negs[i]; break;
changed = 1;
} case NEG:
break; ops[i].op = XEXP (this_op, 0);
ops[i].neg = ! this_neg;
changed = 1;
break;
case CONST:
ops[i].op = XEXP (this_op, 0);
input_consts++;
changed = 1;
break;
case NOT:
/* ~a -> (-a - 1) */
if (n_ops != 7)
{
ops[n_ops].op = constm1_rtx;
ops[n_ops].neg = this_neg;
ops[i].op = XEXP (this_op, 0);
ops[i].neg = !this_neg;
changed = 1;
}
break;
case CONST_INT: case CONST_INT:
if (negs[i]) if (this_neg)
ops[i] = GEN_INT (- INTVAL (ops[i])), negs[i] = 0, changed = 1; {
break; ops[i].op = GEN_INT (- INTVAL (this_op));
ops[i].neg = 0;
changed = 1;
}
break;
default: default:
break; break;
} }
}
} }
while (changed);
/* If we only have two operands, we can't do anything. */ /* If we only have two operands, we can't do anything. */
if (n_ops <= 2) if (n_ops <= 2)
return 0; return NULL_RTX;
/* Now simplify each pair of operands until nothing changes. The first /* Now simplify each pair of operands until nothing changes. The first
time through just simplify constants against each other. */ time through just simplify constants against each other. */
changed = 1; first = 1;
while (changed) do
{ {
changed = first; changed = first;
for (i = 0; i < n_ops - 1; i++) for (i = 0; i < n_ops - 1; i++)
for (j = i + 1; j < n_ops; j++) for (j = i + 1; j < n_ops; j++)
if (ops[i] != 0 && ops[j] != 0 {
&& (! first || (CONSTANT_P (ops[i]) && CONSTANT_P (ops[j])))) rtx lhs = ops[i].op, rhs = ops[j].op;
{ int lneg = ops[i].neg, rneg = ops[j].neg;
rtx lhs = ops[i], rhs = ops[j];
enum rtx_code ncode = PLUS;
if (negs[i] && ! negs[j])
lhs = ops[j], rhs = ops[i], ncode = MINUS;
else if (! negs[i] && negs[j])
ncode = MINUS;
tem = simplify_binary_operation (ncode, mode, lhs, rhs);
if (tem)
{
ops[i] = tem, ops[j] = 0;
negs[i] = negs[i] && negs[j];
if (GET_CODE (tem) == NEG)
ops[i] = XEXP (tem, 0), negs[i] = ! negs[i];
if (GET_CODE (ops[i]) == CONST_INT && negs[i]) if (lhs != 0 && rhs != 0
ops[i] = GEN_INT (- INTVAL (ops[i])), negs[i] = 0; && (! first || (CONSTANT_P (lhs) && CONSTANT_P (rhs))))
changed = 1; {
} enum rtx_code ncode = PLUS;
}
if (lneg != rneg)
{
ncode = MINUS;
if (lneg)
tem = lhs, lhs = rhs, rhs = tem;
}
else if (swap_commutative_operands_p (lhs, rhs))
tem = lhs, lhs = rhs, rhs = tem;
tem = simplify_binary_operation (ncode, mode, lhs, rhs);
/* Reject "simplifications" that just wrap the two
arguments in a CONST. Failure to do so can result
in infinite recursion with simplify_binary_operation
when it calls us to simplify CONST operations. */
if (tem
&& ! (GET_CODE (tem) == CONST
&& GET_CODE (XEXP (tem, 0)) == ncode
&& XEXP (XEXP (tem, 0), 0) == lhs
&& XEXP (XEXP (tem, 0), 1) == rhs))
{
lneg &= rneg;
if (GET_CODE (tem) == NEG)
tem = XEXP (tem, 0), lneg = !lneg;
if (GET_CODE (tem) == CONST_INT && lneg)
tem = GEN_INT (- INTVAL (tem)), lneg = 0;
ops[i].op = tem;
ops[i].neg = lneg;
ops[j].op = NULL_RTX;
changed = 1;
}
}
}
first = 0; first = 0;
} }
while (changed);
/* Pack all the operands to the lower-numbered entries and give up if /* Pack all the operands to the lower-numbered entries. */
we didn't reduce the number of operands we had. Make sure we
count a CONST as two operands. If we have the same number of
operands, but have made more CONSTs than we had, this is also
an improvement, so accept it. */
for (i = 0, j = 0; j < n_ops; j++) for (i = 0, j = 0; j < n_ops; j++)
if (ops[j] != 0) if (ops[j].op)
{ ops[i++] = ops[j];
ops[i] = ops[j], negs[i++] = negs[j]; n_ops = i;
if (GET_CODE (ops[j]) == CONST)
n_consts++;
}
if (i + n_consts > input_ops /* Sort the operations based on swap_commutative_operands_p. */
|| (i + n_consts == input_ops && n_consts <= input_consts)) qsort (ops, n_ops, sizeof (*ops), simplify_plus_minus_op_data_cmp);
return 0;
n_ops = i; /* We suppressed creation of trivial CONST expressions in the
combination loop to avoid recursion. Create one manually now.
The combination loop should have ensured that there is exactly
one CONST_INT, and the sort will have ensured that it is last
in the array and that any other constant will be next-to-last. */
/* If we have a CONST_INT, put it last. */ if (n_ops > 1
for (i = 0; i < n_ops - 1; i++) && GET_CODE (ops[n_ops - 1].op) == CONST_INT
if (GET_CODE (ops[i]) == CONST_INT) && CONSTANT_P (ops[n_ops - 2].op))
{ {
tem = ops[n_ops - 1], ops[n_ops - 1] = ops[i] , ops[i] = tem; HOST_WIDE_INT value = INTVAL (ops[n_ops - 1].op);
j = negs[n_ops - 1], negs[n_ops - 1] = negs[i], negs[i] = j; if (ops[n_ops - 1].neg)
} value = -value;
ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, value);
n_ops--;
}
/* Count the number of CONSTs that we generated. */
n_consts = 0;
for (i = 0; i < n_ops; i++)
if (GET_CODE (ops[i].op) == CONST)
n_consts++;
/* Give up if we didn't reduce the number of operands we had. Make
sure we count a CONST as two operands. If we have the same
number of operands, but have made more CONSTs than before, this
is also an improvement, so accept it. */
if (n_ops + n_consts > input_ops
|| (n_ops + n_consts == input_ops && n_consts <= input_consts))
return NULL_RTX;
/* Put a non-negated operand first. If there aren't any, make all /* Put a non-negated operand first. If there aren't any, make all
operands positive and negate the whole thing later. */ operands positive and negate the whole thing later. */
for (i = 0; i < n_ops && negs[i]; i++)
;
negate = 0;
for (i = 0; i < n_ops && ops[i].neg; i++)
continue;
if (i == n_ops) if (i == n_ops)
{ {
for (i = 0; i < n_ops; i++) for (i = 0; i < n_ops; i++)
negs[i] = 0; ops[i].neg = 0;
negate = 1; negate = 1;
} }
else if (i != 0) else if (i != 0)
{ {
tem = ops[0], ops[0] = ops[i], ops[i] = tem; tem = ops[0].op;
j = negs[0], negs[0] = negs[i], negs[i] = j; ops[0] = ops[i];
ops[i].op = tem;
ops[i].neg = 1;
} }
/* Now make the result by performing the requested operations. */ /* Now make the result by performing the requested operations. */
result = ops[0]; result = ops[0].op;
for (i = 1; i < n_ops; i++) for (i = 1; i < n_ops; i++)
result = simplify_gen_binary (negs[i] ? MINUS : PLUS, mode, result, ops[i]); result = gen_rtx_fmt_ee (ops[i].neg ? MINUS : PLUS,
mode, result, ops[i].op);
return negate ? gen_rtx_NEG (mode, result) : result; return negate ? gen_rtx_NEG (mode, result) : result;
} }
......
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