aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-09-07 11:14:32 -0700
committerRichard Henderson <rth@gcc.gnu.org>2001-09-07 11:14:32 -0700
commit9b3bd4249d2e0e46d4bec0909e626543bbd14d3b (patch)
treefdd0e020da43b19ca8c6fe9ea8eb332cf71d6eba /gcc
parent9978052974a84e9666af3c1f69bdf599c43cd5d0 (diff)
downloadgcc-9b3bd4249d2e0e46d4bec0909e626543bbd14d3b.zip
gcc-9b3bd4249d2e0e46d4bec0909e626543bbd14d3b.tar.gz
gcc-9b3bd4249d2e0e46d4bec0909e626543bbd14d3b.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/loop.c12
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/rtlanal.c8
-rw-r--r--gcc/simplify-rtx.c309
5 files changed, 224 insertions, 121 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0403c8f..c3e93f6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+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>
* h8300-protos.h (general_operand_dst_push): Remove.
diff --git a/gcc/loop.c b/gcc/loop.c
index e72f421..990826a 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -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 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);
- if (temp)
+ if (temp
+ && ! (GET_CODE (add_val) == MULT
+ && GET_CODE (temp) == ASHIFT))
add_val = temp;
v->insn = insn;
@@ -6371,7 +6374,10 @@ express_from_1 (a, b, mult)
}
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)
{
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 3a0a019..75204b6 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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_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 modified_between_p PARAMS ((rtx, rtx, rtx));
extern int no_labels_between_p PARAMS ((rtx, rtx));
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 5ac2c74..9c8830d 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -30,7 +30,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static void set_of_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 operand_preference PARAMS ((rtx));
static void parms_set PARAMS ((rtx, rtx, void *));
/* Bit flags that specify the machine subtype we are compiling for.
@@ -2558,8 +2557,8 @@ regno_use_in (regno, x)
We use negative values to indicate a preference for the first operand
and positive values for the second operand. */
-static int
-operand_preference (op)
+int
+commutative_operand_precedence (op)
rtx op;
{
/* Constants always come the second operand. Prefer "nice" constants. */
@@ -2597,7 +2596,8 @@ int
swap_commutative_operands_p (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
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index ea1cc6d..5e869bd 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -95,6 +95,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define HWI_SIGN_EXTEND(low) \
((((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,
enum machine_mode, rtx, rtx));
static void check_fold_consts PARAMS ((PTR));
@@ -130,12 +132,15 @@ simplify_gen_binary (code, mode, op0, op1)
/* Handle addition and subtraction of CONST_INT specially. Otherwise,
just form the operation. */
- if (code == PLUS && GET_CODE (op1) == CONST_INT
- && GET_MODE (op0) != VOIDmode)
- return plus_constant (op0, INTVAL (op1));
- else if (code == MINUS && GET_CODE (op1) == CONST_INT
- && GET_MODE (op0) != VOIDmode)
- return plus_constant (op0, - INTVAL (op1));
+ if (GET_CODE (op1) == CONST_INT
+ && GET_MODE (op0) != VOIDmode
+ && (code == PLUS || code == MINUS))
+ {
+ HOST_WIDE_INT value = INTVAL (op1);
+ if (code == MINUS)
+ value = -value;
+ return plus_constant (op0, value);
+ }
else
return gen_rtx_fmt_ee (code, mode, op0, op1);
}
@@ -1124,7 +1129,11 @@ simplify_binary_operation (code, mode, op0, op1)
if (INTEGRAL_MODE_P (mode)
&& (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)
return tem;
break;
@@ -1162,8 +1171,8 @@ simplify_binary_operation (code, mode, op0, op1)
#endif
return xop00;
}
-
break;
+
case MINUS:
/* None of these optimizations can be done for IEEE
floating point. */
@@ -1257,7 +1266,11 @@ simplify_binary_operation (code, mode, op0, op1)
if (INTEGRAL_MODE_P (mode)
&& (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)
return tem;
@@ -1680,17 +1693,34 @@ simplify_binary_operation (code, mode, op0, op1)
and do all possible simplifications until no more changes occur. Then
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
simplify_plus_minus (code, mode, op0, op1)
enum rtx_code code;
enum machine_mode mode;
rtx op0, op1;
{
- rtx ops[8];
- int negs[8];
+ struct simplify_plus_minus_op_data ops[8];
rtx result, tem;
- int n_ops = 2, input_ops = 2, input_consts = 0, n_consts = 0;
- int first = 1, negate = 0, changed;
+ int n_ops = 2, input_ops = 2, input_consts = 0, n_consts;
+ int first, negate, changed;
int i, j;
memset ((char *) ops, 0, sizeof ops);
@@ -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
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;
- while (changed)
+ do
{
changed = 0;
for (i = 0; i < n_ops; i++)
- switch (GET_CODE (ops[i]))
- {
- case PLUS:
- case MINUS:
- 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;
+ {
+ rtx this_op = ops[i].op;
+ int this_neg = ops[i].neg;
+ enum rtx_code this_code = GET_CODE (this_op);
- case CONST:
- ops[i] = XEXP (ops[i], 0);
- input_consts++;
- changed = 1;
- break;
+ switch (this_code)
+ {
+ case PLUS:
+ case MINUS:
+ if (n_ops == 7)
+ return 0;
- case NOT:
- /* ~a -> (-a - 1) */
- if (n_ops != 7)
- {
- ops[n_ops] = constm1_rtx;
- negs[n_ops++] = negs[i];
- ops[i] = XEXP (ops[i], 0);
- negs[i] = ! negs[i];
- changed = 1;
- }
- break;
+ ops[n_ops].op = XEXP (this_op, 1);
+ ops[n_ops].neg = (this_code == MINUS) ^ this_neg;
+ n_ops++;
+
+ ops[i].op = XEXP (this_op, 0);
+ input_ops++;
+ changed = 1;
+ break;
+
+ case NEG:
+ 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:
- if (negs[i])
- ops[i] = GEN_INT (- INTVAL (ops[i])), negs[i] = 0, changed = 1;
- break;
+ case CONST_INT:
+ if (this_neg)
+ {
+ ops[i].op = GEN_INT (- INTVAL (this_op));
+ ops[i].neg = 0;
+ changed = 1;
+ }
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
+ }
}
+ while (changed);
/* If we only have two operands, we can't do anything. */
if (n_ops <= 2)
- return 0;
+ return NULL_RTX;
/* Now simplify each pair of operands until nothing changes. The first
time through just simplify constants against each other. */
- changed = 1;
- while (changed)
+ first = 1;
+ do
{
changed = first;
for (i = 0; i < n_ops - 1; i++)
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], 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];
+ {
+ rtx lhs = ops[i].op, rhs = ops[j].op;
+ int lneg = ops[i].neg, rneg = ops[j].neg;
- if (GET_CODE (ops[i]) == CONST_INT && negs[i])
- ops[i] = GEN_INT (- INTVAL (ops[i])), negs[i] = 0;
- changed = 1;
- }
- }
+ if (lhs != 0 && rhs != 0
+ && (! first || (CONSTANT_P (lhs) && CONSTANT_P (rhs))))
+ {
+ 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;
}
+ while (changed);
- /* Pack all the operands to the lower-numbered entries and 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 we had, this is also
- an improvement, so accept it. */
-
+ /* Pack all the operands to the lower-numbered entries. */
for (i = 0, j = 0; j < n_ops; j++)
- if (ops[j] != 0)
- {
- ops[i] = ops[j], negs[i++] = negs[j];
- if (GET_CODE (ops[j]) == CONST)
- n_consts++;
- }
+ if (ops[j].op)
+ ops[i++] = ops[j];
+ n_ops = i;
- if (i + n_consts > input_ops
- || (i + n_consts == input_ops && n_consts <= input_consts))
- return 0;
+ /* Sort the operations based on swap_commutative_operands_p. */
+ qsort (ops, n_ops, sizeof (*ops), simplify_plus_minus_op_data_cmp);
- 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. */
- for (i = 0; i < n_ops - 1; i++)
- if (GET_CODE (ops[i]) == CONST_INT)
- {
- tem = ops[n_ops - 1], ops[n_ops - 1] = ops[i] , ops[i] = tem;
- j = negs[n_ops - 1], negs[n_ops - 1] = negs[i], negs[i] = j;
- }
+ if (n_ops > 1
+ && GET_CODE (ops[n_ops - 1].op) == CONST_INT
+ && CONSTANT_P (ops[n_ops - 2].op))
+ {
+ HOST_WIDE_INT value = INTVAL (ops[n_ops - 1].op);
+ 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
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)
{
for (i = 0; i < n_ops; i++)
- negs[i] = 0;
+ ops[i].neg = 0;
negate = 1;
}
else if (i != 0)
{
- tem = ops[0], ops[0] = ops[i], ops[i] = tem;
- j = negs[0], negs[0] = negs[i], negs[i] = j;
+ tem = ops[0].op;
+ ops[0] = ops[i];
+ ops[i].op = tem;
+ ops[i].neg = 1;
}
/* Now make the result by performing the requested operations. */
- result = ops[0];
+ result = ops[0].op;
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;
}